From 12ca577a65d7ea896b3a7005dd1d1e29dc6fe47c Mon Sep 17 00:00:00 2001 From: Dreaded_X Date: Mon, 14 Aug 2023 02:58:13 +0200 Subject: [PATCH] Added trait for devices that can turn off a given timeout --- src/devices/ikea_outlet.rs | 53 +++++++++++++++++++++----------------- src/devices/mod.rs | 3 ++- src/lib.rs | 2 ++ src/traits.rs | 8 ++++++ 4 files changed, 42 insertions(+), 24 deletions(-) create mode 100644 src/traits.rs diff --git a/src/devices/ikea_outlet.rs b/src/devices/ikea_outlet.rs index 89f941e..59cbfb2 100644 --- a/src/devices/ikea_outlet.rs +++ b/src/devices/ikea_outlet.rs @@ -20,6 +20,7 @@ use crate::event::EventChannel; use crate::event::OnMqtt; use crate::event::OnPresence; use crate::messages::OnOffMessage; +use crate::traits::Timeout; #[derive(Debug, Clone, Deserialize, PartialEq, Eq, Copy)] pub enum OutletType { @@ -50,7 +51,7 @@ pub struct IkeaOutlet { info: InfoConfig, mqtt: MqttDeviceConfig, outlet_type: OutletType, - timeout: Option, + timeout: Option, client: AsyncClient, last_known_state: bool, @@ -81,7 +82,7 @@ impl CreateDevice for IkeaOutlet { info: config.info, mqtt: config.mqtt, outlet_type: config.outlet_type, - timeout: config.timeout, + timeout: config.timeout.map(Duration::from_secs), client: client.clone(), last_known_state: false, handle: None, @@ -142,27 +143,8 @@ impl OnMqtt for IkeaOutlet { self.last_known_state = state; // If this is a kettle start a timeout for turning it of again - if state { - let timeout = match self.timeout { - Some(timeout) => Duration::from_secs(timeout), - None => return, - }; - - // Turn the kettle of after the specified timeout - // TODO: Impl Drop for IkeaOutlet that will abort the handle if the IkeaOutlet - // get dropped - let client = self.client.clone(); - let topic = self.mqtt.topic.clone(); - let id = self.identifier.clone(); - self.handle = Some(tokio::spawn(async move { - debug!(id, "Starting timeout ({timeout:?})..."); - tokio::time::sleep(timeout).await; - debug!(id, "Turning outlet off!"); - // TODO: Idealy we would call self.set_on(false), however since we want to do - // it after a timeout we have to put it in a seperate task. - // I don't think we can really get around calling outside function - set_on(client, &topic, false).await; - })); + if state && let Some(timeout) = self.timeout { + self.start_timeout(timeout); } } } @@ -222,3 +204,28 @@ impl traits::OnOff for IkeaOutlet { Ok(()) } } + +impl crate::traits::Timeout for IkeaOutlet { + fn start_timeout(&mut self, timeout: Duration) { + // Abort any timer that is currently running + if let Some(handle) = self.handle.take() { + handle.abort(); + } + + // Turn the kettle of after the specified timeout + // TODO: Impl Drop for IkeaOutlet that will abort the handle if the IkeaOutlet + // get dropped + let client = self.client.clone(); + let topic = self.mqtt.topic.clone(); + let id = self.identifier.clone(); + self.handle = Some(tokio::spawn(async move { + debug!(id, "Starting timeout ({timeout:?})..."); + tokio::time::sleep(timeout).await; + debug!(id, "Turning outlet off!"); + // TODO: Idealy we would call self.set_on(false), however since we want to do + // it after a timeout we have to put it in a seperate task. + // I don't think we can really get around calling outside function + set_on(client, &topic, false).await; + })); + } +} diff --git a/src/devices/mod.rs b/src/devices/mod.rs index e146106..6cd05ec 100644 --- a/src/devices/mod.rs +++ b/src/devices/mod.rs @@ -22,9 +22,10 @@ pub use self::wake_on_lan::WakeOnLAN; use google_home::{device::AsGoogleHomeDevice, traits::OnOff}; +use crate::traits::Timeout; use crate::{event::OnDarkness, event::OnMqtt, event::OnNotification, event::OnPresence}; -#[impl_cast::device(As: OnMqtt + OnPresence + OnDarkness + OnNotification + OnOff)] +#[impl_cast::device(As: OnMqtt + OnPresence + OnDarkness + OnNotification + OnOff + Timeout)] pub trait Device: AsGoogleHomeDevice + std::fmt::Debug + Sync + Send { fn get_id(&self) -> &str; } diff --git a/src/lib.rs b/src/lib.rs index d4a3720..3c12fc4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,6 @@ #![allow(incomplete_features)] #![feature(specialization)] +#![feature(let_chains)] pub mod auth; pub mod config; pub mod device_manager; @@ -8,3 +9,4 @@ pub mod error; pub mod event; pub mod messages; pub mod mqtt; +pub mod traits; diff --git a/src/traits.rs b/src/traits.rs new file mode 100644 index 0000000..b359b2d --- /dev/null +++ b/src/traits.rs @@ -0,0 +1,8 @@ +use std::time::Duration; + +use impl_cast::device_trait; + +#[device_trait] +pub trait Timeout { + fn start_timeout(&mut self, _timeout: Duration) {} +}