From 4e28ad0f856e9bbc22202e23aa17d883f43ee3cf Mon Sep 17 00:00:00 2001 From: Dreaded_X Date: Wed, 10 Sep 2025 02:59:32 +0200 Subject: [PATCH] feat!: Improve device type registration Instead of one function that contains all the device types available in `automation_devices` a global registry is used were each device can register itself. --- automation_devices/src/air_filter.rs | 1 + automation_devices/src/contact_sensor.rs | 1 + automation_devices/src/hue_bridge.rs | 1 + automation_devices/src/hue_group.rs | 1 + automation_devices/src/hue_switch.rs | 1 + automation_devices/src/ikea_remote.rs | 1 + automation_devices/src/kasa_outlet.rs | 1 + automation_devices/src/lib.rs | 71 ++++++++++++------------ automation_devices/src/light_sensor.rs | 1 + automation_devices/src/ntfy.rs | 1 + automation_devices/src/presence.rs | 1 + automation_devices/src/wake_on_lan.rs | 1 + automation_devices/src/washer.rs | 1 + automation_devices/src/zigbee/light.rs | 5 ++ automation_devices/src/zigbee/outlet.rs | 3 + automation_lib/src/lib.rs | 3 +- 16 files changed, 58 insertions(+), 36 deletions(-) diff --git a/automation_devices/src/air_filter.rs b/automation_devices/src/air_filter.rs index 7038223..5cfe965 100644 --- a/automation_devices/src/air_filter.rs +++ b/automation_devices/src/air_filter.rs @@ -24,6 +24,7 @@ pub struct Config { pub struct AirFilter { config: Config, } +crate::register_device!(AirFilter); #[derive(Debug, Error)] pub enum Error { diff --git a/automation_devices/src/contact_sensor.rs b/automation_devices/src/contact_sensor.rs index 809fcc1..3da27ae 100644 --- a/automation_devices/src/contact_sensor.rs +++ b/automation_devices/src/contact_sensor.rs @@ -54,6 +54,7 @@ pub struct ContactSensor { config: Config, state: Arc>, } +crate::register_device!(ContactSensor); impl ContactSensor { async fn state(&self) -> RwLockReadGuard<'_, State> { diff --git a/automation_devices/src/hue_bridge.rs b/automation_devices/src/hue_bridge.rs index f4f9d38..d7d2e25 100644 --- a/automation_devices/src/hue_bridge.rs +++ b/automation_devices/src/hue_bridge.rs @@ -35,6 +35,7 @@ pub struct Config { pub struct HueBridge { config: Config, } +crate::register_device!(HueBridge); #[derive(Debug, Serialize)] struct FlagMessage { diff --git a/automation_devices/src/hue_group.rs b/automation_devices/src/hue_group.rs index 8483e23..a6cdad8 100644 --- a/automation_devices/src/hue_group.rs +++ b/automation_devices/src/hue_group.rs @@ -24,6 +24,7 @@ pub struct Config { pub struct HueGroup { config: Config, } +crate::register_device!(HueGroup); // Couple of helper function to get the correct urls #[async_trait] diff --git a/automation_devices/src/hue_switch.rs b/automation_devices/src/hue_switch.rs index e1f62cc..e52a1e9 100644 --- a/automation_devices/src/hue_switch.rs +++ b/automation_devices/src/hue_switch.rs @@ -59,6 +59,7 @@ struct State { pub struct HueSwitch { config: Config, } +crate::register_device!(HueSwitch); impl Device for HueSwitch { fn get_id(&self) -> String { diff --git a/automation_devices/src/ikea_remote.rs b/automation_devices/src/ikea_remote.rs index b03eedb..2359a52 100644 --- a/automation_devices/src/ikea_remote.rs +++ b/automation_devices/src/ikea_remote.rs @@ -33,6 +33,7 @@ pub struct Config { pub struct IkeaRemote { config: Config, } +crate::register_device!(IkeaRemote); impl Device for IkeaRemote { fn get_id(&self) -> String { diff --git a/automation_devices/src/kasa_outlet.rs b/automation_devices/src/kasa_outlet.rs index 3e02bdf..e812cb1 100644 --- a/automation_devices/src/kasa_outlet.rs +++ b/automation_devices/src/kasa_outlet.rs @@ -26,6 +26,7 @@ pub struct Config { pub struct KasaOutlet { config: Config, } +crate::register_device!(KasaOutlet); #[async_trait] impl LuaDeviceCreate for KasaOutlet { diff --git a/automation_devices/src/lib.rs b/automation_devices/src/lib.rs index b8526f2..80f3f17 100644 --- a/automation_devices/src/lib.rs +++ b/automation_devices/src/lib.rs @@ -14,48 +14,51 @@ mod zigbee; use automation_lib::Module; use automation_lib::device::{Device, LuaDeviceCreate}; -use zigbee::light::{LightBrightness, LightColorTemperature, LightOnOff}; -use zigbee::outlet::{OutletOnOff, OutletPower}; - -pub use self::air_filter::AirFilter; -pub use self::contact_sensor::ContactSensor; -pub use self::hue_bridge::HueBridge; -pub use self::hue_group::HueGroup; -pub use self::hue_switch::HueSwitch; -pub use self::ikea_remote::IkeaRemote; -pub use self::kasa_outlet::KasaOutlet; -pub use self::light_sensor::LightSensor; -pub use self::ntfy::*; -pub use self::presence::Presence; -pub use self::wake_on_lan::WakeOnLAN; -pub use self::washer::Washer; +use tracing::debug; macro_rules! register_device { - ($lua:expr, $table:expr, $device:ty) => { - $table.set(stringify!($device), $lua.create_proxy::<$device>()?)?; + ($device:ty) => { + ::inventory::submit!(crate::RegisteredDevice::new( + stringify!($device), + ::mlua::Lua::create_proxy::<$device> + )); }; } +pub(crate) use register_device; + +type RegisterFn = fn(lua: &mlua::Lua) -> mlua::Result; + +pub struct RegisteredDevice { + name: &'static str, + register_fn: RegisterFn, +} + +impl RegisteredDevice { + pub const fn new(name: &'static str, register_fn: RegisterFn) -> Self { + Self { name, register_fn } + } + + pub const fn get_name(&self) -> &'static str { + self.name + } + + pub fn register(&self, lua: &mlua::Lua) -> mlua::Result { + (self.register_fn)(lua) + } +} + +inventory::collect!(RegisteredDevice); + pub fn create_module(lua: &mlua::Lua) -> mlua::Result { let devices = lua.create_table()?; - register_device!(lua, devices, AirFilter); - register_device!(lua, devices, ContactSensor); - register_device!(lua, devices, HueBridge); - register_device!(lua, devices, HueGroup); - register_device!(lua, devices, HueSwitch); - register_device!(lua, devices, IkeaRemote); - register_device!(lua, devices, KasaOutlet); - register_device!(lua, devices, LightBrightness); - register_device!(lua, devices, LightColorTemperature); - register_device!(lua, devices, LightOnOff); - register_device!(lua, devices, LightSensor); - register_device!(lua, devices, Ntfy); - register_device!(lua, devices, OutletOnOff); - register_device!(lua, devices, OutletPower); - register_device!(lua, devices, Presence); - register_device!(lua, devices, WakeOnLAN); - register_device!(lua, devices, Washer); + debug!("Loading devices..."); + for device in inventory::iter:: { + debug!(name = device.get_name(), "Registering device"); + let proxy = device.register(lua)?; + devices.set(device.get_name(), proxy)?; + } Ok(devices) } diff --git a/automation_devices/src/light_sensor.rs b/automation_devices/src/light_sensor.rs index 4ef85ab..d241c79 100644 --- a/automation_devices/src/light_sensor.rs +++ b/automation_devices/src/light_sensor.rs @@ -39,6 +39,7 @@ pub struct LightSensor { config: Config, state: Arc>, } +crate::register_device!(LightSensor); impl LightSensor { async fn state(&self) -> RwLockReadGuard<'_, State> { diff --git a/automation_devices/src/ntfy.rs b/automation_devices/src/ntfy.rs index b177a4b..7b82c8a 100644 --- a/automation_devices/src/ntfy.rs +++ b/automation_devices/src/ntfy.rs @@ -97,6 +97,7 @@ pub struct Config { pub struct Ntfy { config: Config, } +crate::register_device!(Ntfy); impl Ntfy { fn add_methods>(methods: &mut M) { diff --git a/automation_devices/src/presence.rs b/automation_devices/src/presence.rs index e78cfcc..a765284 100644 --- a/automation_devices/src/presence.rs +++ b/automation_devices/src/presence.rs @@ -39,6 +39,7 @@ pub struct Presence { config: Config, state: Arc>, } +crate::register_device!(Presence); impl Presence { async fn state(&self) -> RwLockReadGuard<'_, State> { diff --git a/automation_devices/src/wake_on_lan.rs b/automation_devices/src/wake_on_lan.rs index a73c3cf..0282111 100644 --- a/automation_devices/src/wake_on_lan.rs +++ b/automation_devices/src/wake_on_lan.rs @@ -32,6 +32,7 @@ pub struct Config { pub struct WakeOnLAN { config: Config, } +crate::register_device!(WakeOnLAN); #[async_trait] impl LuaDeviceCreate for WakeOnLAN { diff --git a/automation_devices/src/washer.rs b/automation_devices/src/washer.rs index c135b81..bf821a0 100644 --- a/automation_devices/src/washer.rs +++ b/automation_devices/src/washer.rs @@ -38,6 +38,7 @@ pub struct Washer { config: Config, state: Arc>, } +crate::register_device!(Washer); impl Washer { async fn state(&self) -> RwLockReadGuard<'_, State> { diff --git a/automation_devices/src/zigbee/light.rs b/automation_devices/src/zigbee/light.rs index a41aa4e..730dafa 100644 --- a/automation_devices/src/zigbee/light.rs +++ b/automation_devices/src/zigbee/light.rs @@ -99,8 +99,13 @@ pub struct Light { } pub type LightOnOff = Light; +crate::register_device!(LightOnOff); + pub type LightBrightness = Light; +crate::register_device!(LightBrightness); + pub type LightColorTemperature = Light; +crate::register_device!(LightColorTemperature); impl Light { async fn state(&self) -> RwLockReadGuard<'_, T> { diff --git a/automation_devices/src/zigbee/outlet.rs b/automation_devices/src/zigbee/outlet.rs index 2d10759..220418e 100644 --- a/automation_devices/src/zigbee/outlet.rs +++ b/automation_devices/src/zigbee/outlet.rs @@ -89,7 +89,10 @@ pub struct Outlet { } pub type OutletOnOff = Outlet; +crate::register_device!(OutletOnOff); + pub type OutletPower = Outlet; +crate::register_device!(OutletPower); impl Outlet { async fn state(&self) -> RwLockReadGuard<'_, T> { diff --git a/automation_lib/src/lib.rs b/automation_lib/src/lib.rs index 59d2769..9ce4337 100644 --- a/automation_lib/src/lib.rs +++ b/automation_lib/src/lib.rs @@ -37,9 +37,8 @@ impl Module { } pub fn load_modules(lua: &mlua::Lua) -> mlua::Result<()> { - debug!("Loading modules..."); for module in inventory::iter:: { - debug!(name = module.get_name(), "Registering"); + debug!(name = module.get_name(), "Loading module"); let table = module.register(lua)?; lua.register_module(module.get_name(), table)?; }