From be77711caf8324eb1bd414ad4444b4077458183f Mon Sep 17 00:00:00 2001 From: Dreaded_X Date: Mon, 20 Oct 2025 04:08:55 +0200 Subject: [PATCH] feat(config)!: Device creation function is now named entry It now has to be called 'setup', this makes it possible to just include the table as a whole in devices and it will automatically call the correct function. --- config/config.lua | 4 +-- definitions/config.lua | 6 +++-- src/bin/automation.rs | 4 +-- src/bin/generate_definitions.rs | 4 +-- src/config.rs | 47 ++++++++++++++++++++------------- src/lib.rs | 2 ++ 6 files changed, 40 insertions(+), 27 deletions(-) diff --git a/config/config.lua b/config/config.lua index f683ccf..aad7046 100644 --- a/config/config.lua +++ b/config/config.lua @@ -749,8 +749,8 @@ return { openid_url = "https://login.huizinga.dev/api/oidc", }, mqtt = mqtt_config, - devices = { - create_devs, + modules = { + setup = create_devs, ntfy, hue_bridge, kitchen_lights, diff --git a/definitions/config.lua b/definitions/config.lua index ad89353..dbe0077 100644 --- a/definitions/config.lua +++ b/definitions/config.lua @@ -9,12 +9,14 @@ local FulfillmentConfig ---@class Config ---@field fulfillment FulfillmentConfig ----@field devices Devices? +---@field modules Modules? ---@field mqtt MqttConfig ---@field schedule table? local Config ----@alias Devices (DeviceInterface | fun(client: AsyncClient): Devices)[] +---@alias SetupFunction fun(mqtt_client: AsyncClient): SetupTable? +---@alias SetupTable (DeviceInterface | { setup: SetupFunction? } | SetupTable)[] +---@alias Modules SetupFunction | SetupTable ---@class MqttConfig ---@field host string diff --git a/src/bin/automation.rs b/src/bin/automation.rs index 5e1bb5f..4120120 100644 --- a/src/bin/automation.rs +++ b/src/bin/automation.rs @@ -140,8 +140,8 @@ async fn app() -> anyhow::Result<()> { let mqtt_client = mqtt::start(config.mqtt, &device_manager.event_channel()); - if let Some(devices) = config.devices { - for device in devices.get(&lua, &mqtt_client).await? { + if let Some(modules) = config.modules { + for device in modules.setup(&lua, &mqtt_client).await? { device_manager.add(device).await; } } diff --git a/src/bin/generate_definitions.rs b/src/bin/generate_definitions.rs index ac6a3de..a2348f9 100644 --- a/src/bin/generate_definitions.rs +++ b/src/bin/generate_definitions.rs @@ -1,7 +1,7 @@ use std::fs::{self, File}; use std::io::Write; -use automation::config::{Config, Devices, FulfillmentConfig}; +use automation::config::{Config, FulfillmentConfig, Modules}; use automation_lib::Module; use automation_lib::mqtt::{MqttConfig, WrappedAsyncClient}; use lua_typed::Typed; @@ -35,7 +35,7 @@ fn config_definitions() -> String { output += "\n"; output += &Config::generate_full().expect("Config should have a definition"); output += "\n"; - output += &Devices::generate_full().expect("Devices should have a definition"); + output += &Modules::generate_full().expect("Setups should have a definition"); output += "\n"; output += &MqttConfig::generate_full().expect("MqttConfig should have a definition"); output += "\n"; diff --git a/src/config.rs b/src/config.rs index 93bd2fb..0c537f8 100644 --- a/src/config.rs +++ b/src/config.rs @@ -35,10 +35,10 @@ pub struct FulfillmentConfig { } #[derive(Debug, Default)] -pub struct Devices(mlua::Value); +pub struct Modules(mlua::Value); -impl Devices { - pub async fn get( +impl Modules { + pub async fn setup( self, lua: &mlua::Lua, client: &WrappedAsyncClient, @@ -60,17 +60,22 @@ impl Devices { }; for pair in table.pairs() { - let (_, value): (mlua::Value, _) = pair?; + let (name, value): (String, _) = pair?; match value { - mlua::Value::UserData(_) => devices.push(Box::from_lua(value, lua)?), - mlua::Value::Function(f) => { - queue.push_back(f.call_async(client.clone()).await?); + mlua::Value::Table(table) => queue.push_back(table), + mlua::Value::UserData(_) + if let Ok(device) = Box::from_lua(value.clone(), lua) => + { + devices.push(device); } - _ => Err(mlua::Error::runtime(format!( - "Expected a device, table, or function, instead found: {}", - value.type_name() - )))?, + mlua::Value::Function(f) if name == "setup" => { + let value: mlua::Value = f.call_async(client.clone()).await?; + if let Some(table) = value.as_table() { + queue.push_back(table.clone()); + } + } + _ => {} } } } @@ -79,22 +84,26 @@ impl Devices { } } -impl FromLua for Devices { +impl FromLua for Modules { fn from_lua(value: mlua::Value, _lua: &mlua::Lua) -> mlua::Result { - Ok(Devices(value)) + Ok(Modules(value)) } } -impl Typed for Devices { +impl Typed for Modules { fn type_name() -> String { - "Devices".into() + "Modules".into() } fn generate_header() -> Option { + let type_name = Self::type_name(); + let client_type = WrappedAsyncClient::type_name(); + Some(format!( - "---@alias {} (DeviceInterface | fun(client: {}): Devices)[]\n", - ::type_name(), - ::type_name() + r#"---@alias SetupFunction fun(mqtt_client: {client_type}): SetupTable? +---@alias SetupTable (DeviceInterface | {{ setup: SetupFunction? }} | SetupTable)[] +---@alias {type_name} SetupFunction | SetupTable +"#, )) } } @@ -103,7 +112,7 @@ impl Typed for Devices { pub struct Config { pub fulfillment: FulfillmentConfig, #[device_config(from_lua, default)] - pub devices: Option, + pub modules: Option, #[device_config(from_lua)] pub mqtt: MqttConfig, #[device_config(from_lua, default)] diff --git a/src/lib.rs b/src/lib.rs index f1e947d..dbfca74 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,5 @@ +#![feature(if_let_guard)] + pub mod config; pub mod schedule; pub mod secret;