Converted google home traits to be async
Some checks failed
continuous-integration/drone/push Build is failing
Some checks failed
continuous-integration/drone/push Build is failing
This commit is contained in:
parent
a67e47997b
commit
522fe27f11
4
Cargo.lock
generated
4
Cargo.lock
generated
|
@ -1682,11 +1682,11 @@ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wakey"
|
name = "wakey"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/DreadedX/wakey#a982950203aa56a93a7ba7a63062eccdd24046c5"
|
||||||
checksum = "dedab5a691c0d33bcfb5c1ed6bb17265e531ed3392282eed9b20063a0f23e9f5"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayvec",
|
"arrayvec",
|
||||||
"hex",
|
"hex",
|
||||||
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -39,5 +39,8 @@ console-subscriber = "0.1.8"
|
||||||
tracing-subscriber = "0.3.16"
|
tracing-subscriber = "0.3.16"
|
||||||
serde-tuple-vec-map = "1.0.1"
|
serde-tuple-vec-map = "1.0.1"
|
||||||
|
|
||||||
|
[patch.crates-io]
|
||||||
|
wakey = { git = "https://github.com/DreadedX/wakey" }
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
lto = true
|
lto = true
|
||||||
|
|
|
@ -104,7 +104,11 @@ pub trait GoogleHomeDevice: AsGoogleHomeDevice + Sync + Send + 'static {
|
||||||
|
|
||||||
// OnOff
|
// OnOff
|
||||||
if let Some(on_off) = As::<dyn OnOff>::cast(self) {
|
if let Some(on_off) = As::<dyn OnOff>::cast(self) {
|
||||||
device.state.on = on_off.is_on().map_err(|err| device.set_error(err)).ok();
|
device.state.on = on_off
|
||||||
|
.is_on()
|
||||||
|
.await
|
||||||
|
.map_err(|err| device.set_error(err))
|
||||||
|
.ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
device
|
device
|
||||||
|
@ -114,14 +118,14 @@ pub trait GoogleHomeDevice: AsGoogleHomeDevice + Sync + Send + 'static {
|
||||||
match command {
|
match command {
|
||||||
CommandType::OnOff { on } => {
|
CommandType::OnOff { on } => {
|
||||||
if let Some(on_off) = As::<dyn OnOff>::cast_mut(self) {
|
if let Some(on_off) = As::<dyn OnOff>::cast_mut(self) {
|
||||||
on_off.set_on(*on)?;
|
on_off.set_on(*on).await?;
|
||||||
} else {
|
} else {
|
||||||
return Err(DeviceError::ActionNotAvailable.into());
|
return Err(DeviceError::ActionNotAvailable.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CommandType::ActivateScene { deactivate } => {
|
CommandType::ActivateScene { deactivate } => {
|
||||||
if let Some(scene) = As::<dyn Scene>::cast(self) {
|
if let Some(scene) = As::<dyn Scene>::cast(self) {
|
||||||
scene.set_active(!deactivate)?;
|
scene.set_active(!deactivate).await?;
|
||||||
} else {
|
} else {
|
||||||
return Err(DeviceError::ActionNotAvailable.into());
|
return Err(DeviceError::ActionNotAvailable.into());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use async_trait::async_trait;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
use crate::errors::ErrorCode;
|
use crate::errors::ErrorCode;
|
||||||
|
@ -10,6 +11,7 @@ pub enum Trait {
|
||||||
Scene,
|
Scene,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
#[impl_cast::device_trait]
|
#[impl_cast::device_trait]
|
||||||
pub trait OnOff {
|
pub trait OnOff {
|
||||||
fn is_command_only(&self) -> Option<bool> {
|
fn is_command_only(&self) -> Option<bool> {
|
||||||
|
@ -21,15 +23,16 @@ pub trait OnOff {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Implement correct error so we can handle them properly
|
// TODO: Implement correct error so we can handle them properly
|
||||||
fn is_on(&self) -> Result<bool, ErrorCode>;
|
async fn is_on(&self) -> Result<bool, ErrorCode>;
|
||||||
fn set_on(&mut self, on: bool) -> Result<(), ErrorCode>;
|
async fn set_on(&mut self, on: bool) -> Result<(), ErrorCode>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
#[impl_cast::device_trait]
|
#[impl_cast::device_trait]
|
||||||
pub trait Scene {
|
pub trait Scene {
|
||||||
fn is_scene_reversible(&self) -> Option<bool> {
|
fn is_scene_reversible(&self) -> Option<bool> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_active(&self, activate: bool) -> Result<(), ErrorCode>;
|
async fn set_active(&self, activate: bool) -> Result<(), ErrorCode>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,21 +87,21 @@ impl OnMqtt for AudioSetup {
|
||||||
|
|
||||||
match action {
|
match action {
|
||||||
RemoteAction::On => {
|
RemoteAction::On => {
|
||||||
if self.mixer.is_on().unwrap() {
|
if self.mixer.is_on().await.unwrap() {
|
||||||
self.speakers.set_on(false).unwrap();
|
self.speakers.set_on(false).await.unwrap();
|
||||||
self.mixer.set_on(false).unwrap();
|
self.mixer.set_on(false).await.unwrap();
|
||||||
} else {
|
} else {
|
||||||
self.speakers.set_on(true).unwrap();
|
self.speakers.set_on(true).await.unwrap();
|
||||||
self.mixer.set_on(true).unwrap();
|
self.mixer.set_on(true).await.unwrap();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
RemoteAction::BrightnessMoveUp => {
|
RemoteAction::BrightnessMoveUp => {
|
||||||
if !self.mixer.is_on().unwrap() {
|
if !self.mixer.is_on().await.unwrap() {
|
||||||
self.mixer.set_on(true).unwrap();
|
self.mixer.set_on(true).await.unwrap();
|
||||||
} else if self.speakers.is_on().unwrap() {
|
} else if self.speakers.is_on().await.unwrap() {
|
||||||
self.speakers.set_on(false).unwrap();
|
self.speakers.set_on(false).await.unwrap();
|
||||||
} else {
|
} else {
|
||||||
self.speakers.set_on(true).unwrap();
|
self.speakers.set_on(true).await.unwrap();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
RemoteAction::BrightnessStop => { /* Ignore this action */ },
|
RemoteAction::BrightnessStop => { /* Ignore this action */ },
|
||||||
|
@ -116,8 +116,8 @@ impl OnPresence for AudioSetup {
|
||||||
// Turn off the audio setup when we leave the house
|
// Turn off the audio setup when we leave the house
|
||||||
if !presence {
|
if !presence {
|
||||||
debug!(id = self.identifier, "Turning devices off");
|
debug!(id = self.identifier, "Turning devices off");
|
||||||
self.speakers.set_on(false).unwrap();
|
self.speakers.set_on(false).await.unwrap();
|
||||||
self.mixer.set_on(false).unwrap();
|
self.mixer.set_on(false).await.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@ use google_home::{
|
||||||
types::Type,
|
types::Type,
|
||||||
GoogleHomeDevice,
|
GoogleHomeDevice,
|
||||||
};
|
};
|
||||||
use pollster::FutureExt as _;
|
|
||||||
use rumqttc::{AsyncClient, Publish};
|
use rumqttc::{AsyncClient, Publish};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
@ -170,7 +169,7 @@ impl OnPresence for IkeaOutlet {
|
||||||
// Turn off the outlet when we leave the house (Not if it is a battery charger)
|
// Turn off the outlet when we leave the house (Not if it is a battery charger)
|
||||||
if !presence && self.outlet_type != OutletType::Charger {
|
if !presence && self.outlet_type != OutletType::Charger {
|
||||||
debug!(id = self.identifier, "Turning device off");
|
debug!(id = self.identifier, "Turning device off");
|
||||||
self.set_on(false).ok();
|
self.set_on(false).await.ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -206,13 +205,14 @@ impl GoogleHomeDevice for IkeaOutlet {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
impl traits::OnOff for IkeaOutlet {
|
impl traits::OnOff for IkeaOutlet {
|
||||||
fn is_on(&self) -> Result<bool, ErrorCode> {
|
async fn is_on(&self) -> Result<bool, ErrorCode> {
|
||||||
Ok(self.last_known_state)
|
Ok(self.last_known_state)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_on(&mut self, on: bool) -> Result<(), ErrorCode> {
|
async fn set_on(&mut self, on: bool) -> Result<(), ErrorCode> {
|
||||||
set_on(self.client.clone(), &self.mqtt.topic, on).block_on();
|
set_on(self.client.clone(), &self.mqtt.topic, on).await;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use std::{
|
use std::{
|
||||||
io::{Read, Write},
|
net::{Ipv4Addr, SocketAddr},
|
||||||
net::{Ipv4Addr, SocketAddr, TcpStream},
|
|
||||||
str::Utf8Error,
|
str::Utf8Error,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use async_trait::async_trait;
|
||||||
use bytes::{Buf, BufMut};
|
use bytes::{Buf, BufMut};
|
||||||
use google_home::{
|
use google_home::{
|
||||||
errors::{self, DeviceError},
|
errors::{self, DeviceError},
|
||||||
|
@ -12,6 +12,10 @@ use google_home::{
|
||||||
use rumqttc::AsyncClient;
|
use rumqttc::AsyncClient;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
use tokio::{
|
||||||
|
io::{AsyncReadExt, AsyncWriteExt},
|
||||||
|
net::TcpStream,
|
||||||
|
};
|
||||||
use tracing::trace;
|
use tracing::trace;
|
||||||
|
|
||||||
use crate::{config::CreateDevice, error::CreateDeviceError, event::EventChannel};
|
use crate::{config::CreateDevice, error::CreateDeviceError, event::EventChannel};
|
||||||
|
@ -215,15 +219,18 @@ impl Response {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
impl traits::OnOff for KasaOutlet {
|
impl traits::OnOff for KasaOutlet {
|
||||||
fn is_on(&self) -> Result<bool, errors::ErrorCode> {
|
async fn is_on(&self) -> Result<bool, errors::ErrorCode> {
|
||||||
let mut stream =
|
let mut stream = TcpStream::connect(self.addr)
|
||||||
TcpStream::connect(self.addr).or::<DeviceError>(Err(DeviceError::DeviceOffline))?;
|
.await
|
||||||
|
.or::<DeviceError>(Err(DeviceError::DeviceOffline))?;
|
||||||
|
|
||||||
let body = Request::get_sysinfo().encrypt();
|
let body = Request::get_sysinfo().encrypt();
|
||||||
stream
|
stream
|
||||||
.write_all(&body)
|
.write_all(&body)
|
||||||
.and(stream.flush())
|
.await
|
||||||
|
.and(stream.flush().await)
|
||||||
.or::<DeviceError>(Err(DeviceError::TransientError))?;
|
.or::<DeviceError>(Err(DeviceError::TransientError))?;
|
||||||
|
|
||||||
let mut received = Vec::new();
|
let mut received = Vec::new();
|
||||||
|
@ -231,6 +238,7 @@ impl traits::OnOff for KasaOutlet {
|
||||||
loop {
|
loop {
|
||||||
let read = stream
|
let read = stream
|
||||||
.read(&mut rx_bytes)
|
.read(&mut rx_bytes)
|
||||||
|
.await
|
||||||
.or::<errors::ErrorCode>(Err(DeviceError::TransientError.into()))?;
|
.or::<errors::ErrorCode>(Err(DeviceError::TransientError.into()))?;
|
||||||
|
|
||||||
received.extend_from_slice(&rx_bytes[..read]);
|
received.extend_from_slice(&rx_bytes[..read]);
|
||||||
|
@ -247,20 +255,22 @@ impl traits::OnOff for KasaOutlet {
|
||||||
.or(Err(DeviceError::TransientError.into()))
|
.or(Err(DeviceError::TransientError.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_on(&mut self, on: bool) -> Result<(), errors::ErrorCode> {
|
async fn set_on(&mut self, on: bool) -> Result<(), errors::ErrorCode> {
|
||||||
let mut stream =
|
let mut stream = TcpStream::connect(self.addr)
|
||||||
TcpStream::connect(self.addr).or::<DeviceError>(Err(DeviceError::DeviceOffline))?;
|
.await
|
||||||
|
.or::<DeviceError>(Err(DeviceError::DeviceOffline))?;
|
||||||
|
|
||||||
let body = Request::set_relay_state(on).encrypt();
|
let body = Request::set_relay_state(on).encrypt();
|
||||||
stream
|
stream
|
||||||
.write_all(&body)
|
.write_all(&body)
|
||||||
.and(stream.flush())
|
.await
|
||||||
|
.and(stream.flush().await)
|
||||||
.or::<DeviceError>(Err(DeviceError::TransientError))?;
|
.or::<DeviceError>(Err(DeviceError::TransientError))?;
|
||||||
|
|
||||||
let mut received = Vec::new();
|
let mut received = Vec::new();
|
||||||
let mut rx_bytes = [0; 1024];
|
let mut rx_bytes = [0; 1024];
|
||||||
loop {
|
loop {
|
||||||
let read = match stream.read(&mut rx_bytes) {
|
let read = match stream.read(&mut rx_bytes).await {
|
||||||
Ok(read) => read,
|
Ok(read) => read,
|
||||||
Err(_) => return Err(DeviceError::TransientError.into()),
|
Err(_) => return Err(DeviceError::TransientError.into()),
|
||||||
};
|
};
|
||||||
|
|
|
@ -95,7 +95,7 @@ impl OnMqtt for WakeOnLAN {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
self.set_active(activate).ok();
|
self.set_active(activate).await.ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,8 +124,9 @@ impl GoogleHomeDevice for WakeOnLAN {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
impl traits::Scene for WakeOnLAN {
|
impl traits::Scene for WakeOnLAN {
|
||||||
fn set_active(&self, activate: bool) -> Result<(), ErrorCode> {
|
async fn set_active(&self, activate: bool) -> Result<(), ErrorCode> {
|
||||||
if activate {
|
if activate {
|
||||||
debug!(
|
debug!(
|
||||||
id = self.identifier,
|
id = self.identifier,
|
||||||
|
@ -138,6 +139,7 @@ impl traits::Scene for WakeOnLAN {
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
wol.send_magic_to((Ipv4Addr::new(0, 0, 0, 0), 0), (self.broadcast_ip, 9))
|
wol.send_magic_to((Ipv4Addr::new(0, 0, 0, 0), 0), (self.broadcast_ip, 9))
|
||||||
|
.await
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
error!(id = self.identifier, "Failed to activate computer: {err}");
|
error!(id = self.identifier, "Failed to activate computer: {err}");
|
||||||
google_home::errors::DeviceError::TransientError.into()
|
google_home::errors::DeviceError::TransientError.into()
|
||||||
|
|
Loading…
Reference in New Issue
Block a user