From c9bbc35f7412c98e535e25e69348da4db19f8a85 Mon Sep 17 00:00:00 2001 From: Dreaded_X Date: Sat, 10 Dec 2022 18:45:46 +0100 Subject: [PATCH] Simplified device conversions and switched device list to hashmap to allow lookup by name --- src/devices.rs | 46 +++++++++++++++++++++++++++----------- src/devices/ikea_outlet.rs | 8 ------- src/main.rs | 9 +++----- 3 files changed, 36 insertions(+), 27 deletions(-) diff --git a/src/devices.rs b/src/devices.rs index 3994bb8..c6a42e0 100644 --- a/src/devices.rs +++ b/src/devices.rs @@ -1,36 +1,56 @@ mod ikea_outlet; +use std::collections::HashMap; + use crate::{mqtt::Listener, state::StateOnOff}; pub use self::ikea_outlet::IkeaOutlet; -pub trait Device { +pub trait AsListener { + fn from(&mut self) -> Option<&mut dyn Listener> { + None + } +} +impl AsListener for T { + fn from(&mut self) -> Option<&mut dyn Listener> { + Some(self) + } +} + +pub trait AsStateOnOff { + fn from(&mut self) -> Option<&mut dyn StateOnOff> { + None + } +} +impl AsStateOnOff for T { + fn from(&mut self) -> Option<&mut dyn StateOnOff> { + Some(self) + } +} + +pub trait Device: AsListener + AsStateOnOff { fn get_identifier(&self) -> &str; - - fn as_state_on_off(&mut self) -> Option<&mut dyn StateOnOff>; - - fn as_listener(&mut self) -> Option<&mut dyn Listener>; } pub struct Devices { - devices: Vec>, + devices: HashMap>, } impl Devices { pub fn new() -> Self { - Self { devices: Vec::new() } + Self { devices: HashMap::new() } } pub fn add_device(&mut self, device: T) { - self.devices.push(Box::new(device)); + self.devices.insert(device.get_identifier().to_owned(), Box::new(device)); } - pub fn as_listeners(&mut self) -> Vec<&mut dyn Listener> { - self.devices.iter_mut().filter_map(|device| device.as_listener()).collect() + pub fn get_listeners(&mut self) -> Vec<&mut dyn Listener> { + self.devices.iter_mut().filter_map(|(_, device)| AsListener::from(device.as_mut())).collect() } - pub fn get_device(&mut self, index: usize) -> Option<&mut dyn Device> { - if let Some(device) = self.devices.get_mut(index) { + pub fn get_device(&mut self, name: &str) -> Option<&mut dyn Device> { + if let Some(device) = self.devices.get_mut(name) { return Some(device.as_mut()); } return None; @@ -39,7 +59,7 @@ impl Devices { impl Listener for Devices { fn notify(&mut self, message: &rumqttc::Publish) { - self.as_listeners().iter_mut().for_each(|listener| { + self.get_listeners().iter_mut().for_each(|listener| { listener.notify(message); }) } diff --git a/src/devices/ikea_outlet.rs b/src/devices/ikea_outlet.rs index 8e3ff9b..dc1ccfb 100644 --- a/src/devices/ikea_outlet.rs +++ b/src/devices/ikea_outlet.rs @@ -23,14 +23,6 @@ impl Device for IkeaOutlet { fn get_identifier(& self) -> &str { &self.zigbee.get_friendly_name() } - - fn as_state_on_off(&mut self) -> Option<&mut dyn StateOnOff> { - Some(self) - } - - fn as_listener(&mut self) -> Option<&mut dyn Listener> { - Some(self) - } } #[derive(Debug, Serialize, Deserialize)] diff --git a/src/main.rs b/src/main.rs index 51d2195..ee4ec5f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,7 +2,7 @@ use std::{time::Duration, rc::Rc, cell::RefCell, process::exit}; use dotenv::dotenv; -use automation::{devices::{Devices, IkeaOutlet}, zigbee::Zigbee, mqtt::Notifier}; +use automation::{devices::{Devices, IkeaOutlet, AsStateOnOff}, zigbee::Zigbee, mqtt::Notifier}; use rumqttc::{MqttOptions, Transport, Client}; fn get_required_env(name: &str) -> String { @@ -34,11 +34,8 @@ fn main() { let mut notifier = Notifier::new(); - { - let mut temp = devices.borrow_mut(); - let a = temp.get_device(0); - a.unwrap().as_state_on_off().unwrap().set_state(false); - } + // Update the state of the kettle + AsStateOnOff::from(devices.borrow_mut().get_device("kitchen/kettle").unwrap()).unwrap().set_state(false); notifier.add_listener(Rc::downgrade(&devices));