diff --git a/Cargo.lock b/Cargo.lock index 6099456..5b14ab7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -100,6 +100,7 @@ dependencies = [ "git-version", "google_home", "hostname", + "inventory", "mlua", "reqwest", "rumqttc", @@ -128,6 +129,7 @@ dependencies = [ "dyn-clone", "eui48", "google_home", + "inventory", "mlua", "reqwest", "rumqttc", @@ -151,6 +153,7 @@ dependencies = [ "futures", "google_home", "indexmap", + "inventory", "mlua", "rumqttc", "serde", @@ -967,6 +970,15 @@ dependencies = [ "serde", ] +[[package]] +name = "inventory" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc61209c082fbeb19919bee74b176221b27223e27b65d781eb91af24eb1fb46e" +dependencies = [ + "rustversion", +] + [[package]] name = "io-uring" version = "0.7.10" diff --git a/Cargo.toml b/Cargo.toml index 13c9440..b099d60 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,6 +34,7 @@ google_home = { path = "./google_home/google_home" } google_home_macro = { path = "./google_home/google_home_macro" } hostname = "0.4.1" indexmap = { version = "2.11.0", features = ["serde"] } +inventory = "0.3.21" itertools = "0.14.0" json_value_merge = "2.0.1" mlua = { version = "0.11.3", features = [ @@ -77,6 +78,7 @@ dotenvy = { workspace = true } git-version = "0.3.9" google_home = { workspace = true } hostname = { workspace = true } +inventory = { workspace = true } mlua = { workspace = true } reqwest = { workspace = true } rumqttc = { workspace = true } diff --git a/automation_devices/Cargo.toml b/automation_devices/Cargo.toml index 0012ce0..4bfee79 100644 --- a/automation_devices/Cargo.toml +++ b/automation_devices/Cargo.toml @@ -13,6 +13,7 @@ bytes = { workspace = true } dyn-clone = { workspace = true } eui48 = { workspace = true } google_home = { workspace = true } +inventory = { workspace = true } mlua = { workspace = true } reqwest = { workspace = true } rumqttc = { workspace = true } diff --git a/automation_devices/src/lib.rs b/automation_devices/src/lib.rs index 6d32b82..fecf7d6 100644 --- a/automation_devices/src/lib.rs +++ b/automation_devices/src/lib.rs @@ -12,6 +12,7 @@ mod wake_on_lan; mod washer; mod zigbee; +use automation_lib::Module; use automation_lib::device::{Device, LuaDeviceCreate}; use zigbee::light::{LightBrightness, LightColorTemperature, LightOnOff}; use zigbee::outlet::{OutletOnOff, OutletPower}; @@ -36,7 +37,7 @@ macro_rules! register_device { }; } -pub fn register_with_lua(lua: &mlua::Lua) -> mlua::Result<()> { +pub fn create_module(lua: &mlua::Lua) -> mlua::Result { register_device!(lua, AirFilter); register_device!(lua, ContactSensor); register_device!(lua, HueBridge); @@ -55,5 +56,8 @@ pub fn register_with_lua(lua: &mlua::Lua) -> mlua::Result<()> { register_device!(lua, WakeOnLAN); register_device!(lua, Washer); - Ok(()) + // For now return an empty table and keep the devices in the global table + lua.create_table() } + +inventory::submit! {Module::new("devices", create_module)} diff --git a/automation_lib/Cargo.toml b/automation_lib/Cargo.toml index e493005..066acab 100644 --- a/automation_lib/Cargo.toml +++ b/automation_lib/Cargo.toml @@ -11,6 +11,7 @@ dyn-clone = { workspace = true } futures = { workspace = true } google_home = { workspace = true } indexmap = { workspace = true } +inventory = { workspace = true } mlua = { workspace = true } rumqttc = { workspace = true } serde = { workspace = true } diff --git a/automation_lib/src/lib.rs b/automation_lib/src/lib.rs index 771da64..06c6081 100644 --- a/automation_lib/src/lib.rs +++ b/automation_lib/src/lib.rs @@ -12,3 +12,26 @@ pub mod lua; pub mod messages; pub mod mqtt; pub mod schedule; + +type RegisterFn = fn(lua: &mlua::Lua) -> mlua::Result; + +pub struct Module { + name: &'static str, + register_fn: RegisterFn, +} + +impl Module { + 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!(Module); diff --git a/src/main.rs b/src/main.rs index 4eb3bb9..9dcd1c2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,8 +12,8 @@ use std::time::{SystemTime, UNIX_EPOCH}; use ::config::{Environment, File}; use automation_lib::config::{FulfillmentConfig, MqttConfig}; use automation_lib::device_manager::DeviceManager; -use automation_lib::helpers; use automation_lib::mqtt::{self, WrappedAsyncClient}; +use automation_lib::{Module, helpers}; use axum::extract::{FromRef, State}; use axum::http::StatusCode; use axum::routing::post; @@ -30,6 +30,9 @@ use web::{ApiError, User}; use crate::secret::EnvironmentSecretFile; use crate::version::VERSION; +// Force automation_devices to link so that it gets registered as a module +extern crate automation_devices; + #[derive(Clone)] struct AppState { pub openid_url: String, @@ -138,6 +141,13 @@ async fn app() -> anyhow::Result<()> { })?; lua.globals().set("print", print)?; + debug!("Loading modules..."); + for module in inventory::iter:: { + debug!(name = module.get_name(), "Registering"); + let table = module.register(&lua)?; + lua.register_module(module.get_name(), table)?; + } + let mqtt = lua.create_table()?; let event_channel = device_manager.event_channel(); let mqtt_new = lua.create_function(move |lua, config: mlua::Value| { @@ -174,7 +184,6 @@ async fn app() -> anyhow::Result<()> { utils.set("get_epoch", get_epoch)?; lua.register_module("utils", utils)?; - automation_devices::register_with_lua(&lua)?; helpers::register_with_lua(&lua)?; let entrypoint = Path::new(&config.entrypoint);