Compare commits

..

9 Commits

Author SHA1 Message Date
60bf0f236c refactor(config)!: Move device proxies into module
All checks were successful
Build and deploy / build (push) Successful in 10m0s
Build and deploy / Deploy container (push) Successful in 43s
Instead of registering the device proxies in the global namespace they
are now registered in a module called `devices`.
2025-09-10 01:46:17 +02:00
07e2d18a28 feat!: Improve lua module registration
Instead of having to call all the module registration functions in one
place it is possible for each module to register itself in a global registry.
During startup all the all the modules will be registered
automatically.

This does currently have one weakness, to need to ensure that the crate
is linked.
2025-09-10 01:46:17 +02:00
d008bb0786 feat!: Removed AddAdditionalMethods
It has been replaced with the add_methods device attribute.
2025-09-10 01:46:17 +02:00
43cb1b31fd feat: Added attribute to easily register additional lua methods
Previously this could only be done by implementing a trait, like
`AddAdditionalMethods`, that that has an add_methods function where you
can put your custom methods. With this new attribute you can pass in a
register function directly!
2025-09-10 01:46:16 +02:00
ff78ac0c76 refactor!: Rewrote device implementation macro once again
This time with a bit more though put into the design of the code, as a
result the macro should be a lot more robust.

This did result in the macro getting renamed from LuaDevice to Device as
this should be _the_ Device macro.
The attribute also got renamed from traits() to device(traits()) and the
syntax got overhauled to allow for a bit more expression.
2025-09-10 01:46:16 +02:00
aad089aa10 chore: Removed old leftover contact sensor presence config 2025-09-10 01:46:16 +02:00
18e40726fe refactor: Remove unneeded wrapper functions when specifying callbacks
These wrappers can be moved up to where the callback itself is defined
instead of having to wrap the call manually. This also works a lot nicer
now that it is possible to provide multiple callback functions.
2025-09-10 01:46:16 +02:00
1925bac73c fix: Front door presence does not get cleared properly 2025-09-10 01:46:16 +02:00
5383e7265d feat!: ActionCallback can now receive any amount of arguments
ActionCallback now only has one generics argument that has to implement
IntoLuaMulti, this makes ActionCallback much more flexible as it no
longer always requires two arguments.
2025-09-10 01:46:12 +02:00
8 changed files with 117 additions and 64 deletions

12
Cargo.lock generated
View File

@@ -100,6 +100,7 @@ dependencies = [
"git-version", "git-version",
"google_home", "google_home",
"hostname", "hostname",
"inventory",
"mlua", "mlua",
"reqwest", "reqwest",
"rumqttc", "rumqttc",
@@ -128,6 +129,7 @@ dependencies = [
"dyn-clone", "dyn-clone",
"eui48", "eui48",
"google_home", "google_home",
"inventory",
"mlua", "mlua",
"reqwest", "reqwest",
"rumqttc", "rumqttc",
@@ -151,6 +153,7 @@ dependencies = [
"futures", "futures",
"google_home", "google_home",
"indexmap", "indexmap",
"inventory",
"mlua", "mlua",
"rumqttc", "rumqttc",
"serde", "serde",
@@ -967,6 +970,15 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "inventory"
version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc61209c082fbeb19919bee74b176221b27223e27b65d781eb91af24eb1fb46e"
dependencies = [
"rustversion",
]
[[package]] [[package]]
name = "io-uring" name = "io-uring"
version = "0.7.10" version = "0.7.10"

View File

@@ -34,6 +34,7 @@ google_home = { path = "./google_home/google_home" }
google_home_macro = { path = "./google_home/google_home_macro" } google_home_macro = { path = "./google_home/google_home_macro" }
hostname = "0.4.1" hostname = "0.4.1"
indexmap = { version = "2.11.0", features = ["serde"] } indexmap = { version = "2.11.0", features = ["serde"] }
inventory = "0.3.21"
itertools = "0.14.0" itertools = "0.14.0"
json_value_merge = "2.0.1" json_value_merge = "2.0.1"
mlua = { version = "0.11.3", features = [ mlua = { version = "0.11.3", features = [
@@ -77,6 +78,7 @@ dotenvy = { workspace = true }
git-version = "0.3.9" git-version = "0.3.9"
google_home = { workspace = true } google_home = { workspace = true }
hostname = { workspace = true } hostname = { workspace = true }
inventory = { workspace = true }
mlua = { workspace = true } mlua = { workspace = true }
reqwest = { workspace = true } reqwest = { workspace = true }
rumqttc = { workspace = true } rumqttc = { workspace = true }

View File

@@ -13,6 +13,7 @@ bytes = { workspace = true }
dyn-clone = { workspace = true } dyn-clone = { workspace = true }
eui48 = { workspace = true } eui48 = { workspace = true }
google_home = { workspace = true } google_home = { workspace = true }
inventory = { workspace = true }
mlua = { workspace = true } mlua = { workspace = true }
reqwest = { workspace = true } reqwest = { workspace = true }
rumqttc = { workspace = true } rumqttc = { workspace = true }

View File

@@ -12,6 +12,7 @@ mod wake_on_lan;
mod washer; mod washer;
mod zigbee; mod zigbee;
use automation_lib::Module;
use automation_lib::device::{Device, LuaDeviceCreate}; use automation_lib::device::{Device, LuaDeviceCreate};
use zigbee::light::{LightBrightness, LightColorTemperature, LightOnOff}; use zigbee::light::{LightBrightness, LightColorTemperature, LightOnOff};
use zigbee::outlet::{OutletOnOff, OutletPower}; use zigbee::outlet::{OutletOnOff, OutletPower};
@@ -30,30 +31,33 @@ pub use self::wake_on_lan::WakeOnLAN;
pub use self::washer::Washer; pub use self::washer::Washer;
macro_rules! register_device { macro_rules! register_device {
($lua:expr, $device:ty) => { ($lua:expr, $table:expr, $device:ty) => {
$lua.globals() $table.set(stringify!($device), $lua.create_proxy::<$device>()?)?;
.set(stringify!($device), $lua.create_proxy::<$device>()?)?;
}; };
} }
pub fn register_with_lua(lua: &mlua::Lua) -> mlua::Result<()> { pub fn register_with_lua(lua: &mlua::Lua) -> mlua::Result<mlua::Table> {
register_device!(lua, AirFilter); let devices = lua.create_table()?;
register_device!(lua, ContactSensor);
register_device!(lua, HueBridge);
register_device!(lua, HueGroup);
register_device!(lua, HueSwitch);
register_device!(lua, IkeaRemote);
register_device!(lua, KasaOutlet);
register_device!(lua, LightBrightness);
register_device!(lua, LightColorTemperature);
register_device!(lua, LightOnOff);
register_device!(lua, LightSensor);
register_device!(lua, Ntfy);
register_device!(lua, OutletOnOff);
register_device!(lua, OutletPower);
register_device!(lua, Presence);
register_device!(lua, WakeOnLAN);
register_device!(lua, Washer);
Ok(()) 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);
Ok(devices)
} }
inventory::submit! {Module::new("devices", register_with_lua)}

View File

@@ -11,6 +11,7 @@ dyn-clone = { workspace = true }
futures = { workspace = true } futures = { workspace = true }
google_home = { workspace = true } google_home = { workspace = true }
indexmap = { workspace = true } indexmap = { workspace = true }
inventory = { workspace = true }
mlua = { workspace = true } mlua = { workspace = true }
rumqttc = { workspace = true } rumqttc = { workspace = true }
serde = { workspace = true } serde = { workspace = true }

View File

@@ -12,3 +12,26 @@ pub mod lua;
pub mod messages; pub mod messages;
pub mod mqtt; pub mod mqtt;
pub mod schedule; pub mod schedule;
type RegisterFn = fn(lua: &mlua::Lua) -> mlua::Result<mlua::Table>;
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<mlua::Table> {
(self.register_fn)(lua)
}
}
inventory::collect!(Module);

View File

@@ -1,3 +1,4 @@
local devices = require("devices")
local device_manager = require("device_manager") local device_manager = require("device_manager")
local utils = require("utils") local utils = require("utils")
local secrets = require("secrets") local secrets = require("secrets")
@@ -29,7 +30,7 @@ local mqtt_client = require("mqtt").new({
tls = host == "zeus" or host == "hephaestus", tls = host == "zeus" or host == "hephaestus",
}) })
local ntfy = Ntfy.new({ local ntfy = devices.Ntfy.new({
topic = secrets.ntfy_topic, topic = secrets.ntfy_topic,
}) })
device_manager:add(ntfy) device_manager:add(ntfy)
@@ -71,7 +72,7 @@ local on_presence = {
end, end,
} }
local presence_system = Presence.new({ local presence_system = devices.Presence.new({
topic = mqtt_automation("presence/+/#"), topic = mqtt_automation("presence/+/#"),
client = mqtt_client, client = mqtt_client,
callback = function(_, presence) callback = function(_, presence)
@@ -122,7 +123,7 @@ local on_light = {
self[#self + 1] = f self[#self + 1] = f
end, end,
} }
device_manager:add(LightSensor.new({ device_manager:add(devices.LightSensor.new({
identifier = "living_light_sensor", identifier = "living_light_sensor",
topic = mqtt_z2m("living/light"), topic = mqtt_z2m("living/light"),
client = mqtt_client, client = mqtt_client,
@@ -146,7 +147,7 @@ end)
local hue_ip = "10.0.0.102" local hue_ip = "10.0.0.102"
local hue_token = secrets.hue_token local hue_token = secrets.hue_token
local hue_bridge = HueBridge.new({ local hue_bridge = devices.HueBridge.new({
identifier = "hue_bridge", identifier = "hue_bridge",
ip = hue_ip, ip = hue_ip,
login = hue_token, login = hue_token,
@@ -163,7 +164,7 @@ on_presence:add(function(presence)
hue_bridge:set_flag("presence", presence) hue_bridge:set_flag("presence", presence)
end) end)
local kitchen_lights = HueGroup.new({ local kitchen_lights = devices.HueGroup.new({
identifier = "kitchen_lights", identifier = "kitchen_lights",
ip = hue_ip, ip = hue_ip,
login = hue_token, login = hue_token,
@@ -171,7 +172,7 @@ local kitchen_lights = HueGroup.new({
scene_id = "7MJLG27RzeRAEVJ", scene_id = "7MJLG27RzeRAEVJ",
}) })
device_manager:add(kitchen_lights) device_manager:add(kitchen_lights)
local living_lights = HueGroup.new({ local living_lights = devices.HueGroup.new({
identifier = "living_lights", identifier = "living_lights",
ip = hue_ip, ip = hue_ip,
login = hue_token, login = hue_token,
@@ -179,7 +180,7 @@ local living_lights = HueGroup.new({
scene_id = "SNZw7jUhQ3cXSjkj", scene_id = "SNZw7jUhQ3cXSjkj",
}) })
device_manager:add(living_lights) device_manager:add(living_lights)
local living_lights_relax = HueGroup.new({ local living_lights_relax = devices.HueGroup.new({
identifier = "living_lights", identifier = "living_lights",
ip = hue_ip, ip = hue_ip,
login = hue_token, login = hue_token,
@@ -188,7 +189,7 @@ local living_lights_relax = HueGroup.new({
}) })
device_manager:add(living_lights_relax) device_manager:add(living_lights_relax)
device_manager:add(HueSwitch.new({ device_manager:add(devices.HueSwitch.new({
name = "Switch", name = "Switch",
room = "Living", room = "Living",
client = mqtt_client, client = mqtt_client,
@@ -205,7 +206,7 @@ device_manager:add(HueSwitch.new({
battery_callback = check_battery, battery_callback = check_battery,
})) }))
device_manager:add(WakeOnLAN.new({ device_manager:add(devices.WakeOnLAN.new({
name = "Zeus", name = "Zeus",
room = "Living Room", room = "Living Room",
topic = mqtt_automation("appliance/living_room/zeus"), topic = mqtt_automation("appliance/living_room/zeus"),
@@ -214,7 +215,7 @@ device_manager:add(WakeOnLAN.new({
broadcast_ip = "10.0.3.255", broadcast_ip = "10.0.3.255",
})) }))
local living_mixer = OutletOnOff.new({ local living_mixer = devices.OutletOnOff.new({
name = "Mixer", name = "Mixer",
room = "Living Room", room = "Living Room",
topic = mqtt_z2m("living/mixer"), topic = mqtt_z2m("living/mixer"),
@@ -222,7 +223,7 @@ local living_mixer = OutletOnOff.new({
}) })
turn_off_when_away(living_mixer) turn_off_when_away(living_mixer)
device_manager:add(living_mixer) device_manager:add(living_mixer)
local living_speakers = OutletOnOff.new({ local living_speakers = devices.OutletOnOff.new({
name = "Speakers", name = "Speakers",
room = "Living Room", room = "Living Room",
topic = mqtt_z2m("living/speakers"), topic = mqtt_z2m("living/speakers"),
@@ -231,7 +232,7 @@ local living_speakers = OutletOnOff.new({
turn_off_when_away(living_speakers) turn_off_when_away(living_speakers)
device_manager:add(living_speakers) device_manager:add(living_speakers)
device_manager:add(IkeaRemote.new({ device_manager:add(devices.IkeaRemote.new({
name = "Remote", name = "Remote",
room = "Living Room", room = "Living Room",
client = mqtt_client, client = mqtt_client,
@@ -271,7 +272,7 @@ local function kettle_timeout()
end end
end end
local kettle = OutletPower.new({ local kettle = devices.OutletPower.new({
outlet_type = "Kettle", outlet_type = "Kettle",
name = "Kettle", name = "Kettle",
room = "Kitchen", room = "Kitchen",
@@ -286,7 +287,7 @@ local function set_kettle(_, on)
kettle:set_on(on) kettle:set_on(on)
end end
device_manager:add(IkeaRemote.new({ device_manager:add(devices.IkeaRemote.new({
name = "Remote", name = "Remote",
room = "Bedroom", room = "Bedroom",
client = mqtt_client, client = mqtt_client,
@@ -296,7 +297,7 @@ device_manager:add(IkeaRemote.new({
battery_callback = check_battery, battery_callback = check_battery,
})) }))
device_manager:add(IkeaRemote.new({ device_manager:add(devices.IkeaRemote.new({
name = "Remote", name = "Remote",
room = "Kitchen", room = "Kitchen",
client = mqtt_client, client = mqtt_client,
@@ -320,7 +321,7 @@ local function off_timeout(duration)
end end
end end
local bathroom_light = LightOnOff.new({ local bathroom_light = devices.LightOnOff.new({
name = "Light", name = "Light",
room = "Bathroom", room = "Bathroom",
topic = mqtt_z2m("bathroom/light"), topic = mqtt_z2m("bathroom/light"),
@@ -329,7 +330,7 @@ local bathroom_light = LightOnOff.new({
}) })
device_manager:add(bathroom_light) device_manager:add(bathroom_light)
device_manager:add(Washer.new({ device_manager:add(devices.Washer.new({
identifier = "bathroom_washer", identifier = "bathroom_washer",
topic = mqtt_z2m("bathroom/washer"), topic = mqtt_z2m("bathroom/washer"),
client = mqtt_client, client = mqtt_client,
@@ -344,7 +345,7 @@ device_manager:add(Washer.new({
end, end,
})) }))
device_manager:add(OutletOnOff.new({ device_manager:add(devices.OutletOnOff.new({
name = "Charger", name = "Charger",
room = "Workbench", room = "Workbench",
topic = mqtt_z2m("workbench/charger"), topic = mqtt_z2m("workbench/charger"),
@@ -352,7 +353,7 @@ device_manager:add(OutletOnOff.new({
callback = off_timeout(debug and 5 or 20 * 3600), callback = off_timeout(debug and 5 or 20 * 3600),
})) }))
local workbench_outlet = OutletOnOff.new({ local workbench_outlet = devices.OutletOnOff.new({
name = "Outlet", name = "Outlet",
room = "Workbench", room = "Workbench",
topic = mqtt_z2m("workbench/outlet"), topic = mqtt_z2m("workbench/outlet"),
@@ -361,7 +362,7 @@ local workbench_outlet = OutletOnOff.new({
turn_off_when_away(workbench_outlet) turn_off_when_away(workbench_outlet)
device_manager:add(workbench_outlet) device_manager:add(workbench_outlet)
local workbench_light = LightColorTemperature.new({ local workbench_light = devices.LightColorTemperature.new({
name = "Light", name = "Light",
room = "Workbench", room = "Workbench",
topic = mqtt_z2m("workbench/light"), topic = mqtt_z2m("workbench/light"),
@@ -371,7 +372,7 @@ turn_off_when_away(workbench_light)
device_manager:add(workbench_light) device_manager:add(workbench_light)
local delay_color_temp = Timeout.new() local delay_color_temp = Timeout.new()
device_manager:add(IkeaRemote.new({ device_manager:add(devices.IkeaRemote.new({
name = "Remote", name = "Remote",
room = "Workbench", room = "Workbench",
client = mqtt_client, client = mqtt_client,
@@ -394,14 +395,14 @@ device_manager:add(IkeaRemote.new({
battery_callback = check_battery, battery_callback = check_battery,
})) }))
local hallway_top_light = HueGroup.new({ local hallway_top_light = devices.HueGroup.new({
identifier = "hallway_top_light", identifier = "hallway_top_light",
ip = hue_ip, ip = hue_ip,
login = hue_token, login = hue_token,
group_id = 83, group_id = 83,
scene_id = "QeufkFDICEHWeKJ7", scene_id = "QeufkFDICEHWeKJ7",
}) })
device_manager:add(HueSwitch.new({ device_manager:add(devices.HueSwitch.new({
name = "SwitchBottom", name = "SwitchBottom",
room = "Hallway", room = "Hallway",
client = mqtt_client, client = mqtt_client,
@@ -411,7 +412,7 @@ device_manager:add(HueSwitch.new({
end, end,
battery_callback = check_battery, battery_callback = check_battery,
})) }))
device_manager:add(HueSwitch.new({ device_manager:add(devices.HueSwitch.new({
name = "SwitchTop", name = "SwitchTop",
room = "Hallway", room = "Hallway",
client = mqtt_client, client = mqtt_client,
@@ -480,7 +481,7 @@ local hallway_light_automation = {
end, end,
} }
local hallway_storage = LightBrightness.new({ local hallway_storage = devices.LightBrightness.new({
name = "Storage", name = "Storage",
room = "Hallway", room = "Hallway",
topic = mqtt_z2m("hallway/storage"), topic = mqtt_z2m("hallway/storage"),
@@ -490,7 +491,7 @@ local hallway_storage = LightBrightness.new({
turn_off_when_away(hallway_storage) turn_off_when_away(hallway_storage)
device_manager:add(hallway_storage) device_manager:add(hallway_storage)
local hallway_bottom_lights = HueGroup.new({ local hallway_bottom_lights = devices.HueGroup.new({
identifier = "hallway_bottom_lights", identifier = "hallway_bottom_lights",
ip = hue_ip, ip = hue_ip,
login = hue_token, login = hue_token,
@@ -531,7 +532,7 @@ local function presence(duration)
end end
end end
device_manager:add(IkeaRemote.new({ device_manager:add(devices.IkeaRemote.new({
name = "Remote", name = "Remote",
room = "Hallway", room = "Hallway",
client = mqtt_client, client = mqtt_client,
@@ -539,7 +540,7 @@ device_manager:add(IkeaRemote.new({
callback = hallway_light_automation:switch_callback(), callback = hallway_light_automation:switch_callback(),
battery_callback = check_battery, battery_callback = check_battery,
})) }))
local hallway_frontdoor = ContactSensor.new({ local hallway_frontdoor = devices.ContactSensor.new({
name = "Frontdoor", name = "Frontdoor",
room = "Hallway", room = "Hallway",
sensor_type = "Door", sensor_type = "Door",
@@ -554,7 +555,7 @@ local hallway_frontdoor = ContactSensor.new({
device_manager:add(hallway_frontdoor) device_manager:add(hallway_frontdoor)
hallway_light_automation.door = hallway_frontdoor hallway_light_automation.door = hallway_frontdoor
local hallway_trash = ContactSensor.new({ local hallway_trash = devices.ContactSensor.new({
name = "Trash", name = "Trash",
room = "Hallway", room = "Hallway",
sensor_type = "Drawer", sensor_type = "Drawer",
@@ -566,7 +567,7 @@ local hallway_trash = ContactSensor.new({
device_manager:add(hallway_trash) device_manager:add(hallway_trash)
hallway_light_automation.trash = hallway_trash hallway_light_automation.trash = hallway_trash
local guest_light = LightOnOff.new({ local guest_light = devices.LightOnOff.new({
name = "Light", name = "Light",
room = "Guest Room", room = "Guest Room",
topic = mqtt_z2m("guest/light"), topic = mqtt_z2m("guest/light"),
@@ -575,14 +576,14 @@ local guest_light = LightOnOff.new({
turn_off_when_away(guest_light) turn_off_when_away(guest_light)
device_manager:add(guest_light) device_manager:add(guest_light)
local bedroom_air_filter = AirFilter.new({ local bedroom_air_filter = devices.AirFilter.new({
name = "Air Filter", name = "Air Filter",
room = "Bedroom", room = "Bedroom",
url = "http://10.0.0.103", url = "http://10.0.0.103",
}) })
device_manager:add(bedroom_air_filter) device_manager:add(bedroom_air_filter)
local bedroom_lights = HueGroup.new({ local bedroom_lights = devices.HueGroup.new({
identifier = "bedroom_lights", identifier = "bedroom_lights",
ip = hue_ip, ip = hue_ip,
login = hue_token, login = hue_token,
@@ -590,7 +591,7 @@ local bedroom_lights = HueGroup.new({
scene_id = "PvRs-lGD4VRytL9", scene_id = "PvRs-lGD4VRytL9",
}) })
device_manager:add(bedroom_lights) device_manager:add(bedroom_lights)
local bedroom_lights_relax = HueGroup.new({ local bedroom_lights_relax = devices.HueGroup.new({
identifier = "bedroom_lights", identifier = "bedroom_lights",
ip = hue_ip, ip = hue_ip,
login = hue_token, login = hue_token,
@@ -599,7 +600,7 @@ local bedroom_lights_relax = HueGroup.new({
}) })
device_manager:add(bedroom_lights_relax) device_manager:add(bedroom_lights_relax)
device_manager:add(HueSwitch.new({ device_manager:add(devices.HueSwitch.new({
name = "Switch", name = "Switch",
room = "Bedroom", room = "Bedroom",
client = mqtt_client, client = mqtt_client,
@@ -613,7 +614,7 @@ device_manager:add(HueSwitch.new({
battery_callback = check_battery, battery_callback = check_battery,
})) }))
device_manager:add(ContactSensor.new({ device_manager:add(devices.ContactSensor.new({
name = "Balcony", name = "Balcony",
room = "Living Room", room = "Living Room",
sensor_type = "Door", sensor_type = "Door",
@@ -621,21 +622,21 @@ device_manager:add(ContactSensor.new({
client = mqtt_client, client = mqtt_client,
battery_callback = check_battery, battery_callback = check_battery,
})) }))
device_manager:add(ContactSensor.new({ device_manager:add(devices.ContactSensor.new({
name = "Window", name = "Window",
room = "Living Room", room = "Living Room",
topic = mqtt_z2m("living/window"), topic = mqtt_z2m("living/window"),
client = mqtt_client, client = mqtt_client,
battery_callback = check_battery, battery_callback = check_battery,
})) }))
device_manager:add(ContactSensor.new({ device_manager:add(devices.ContactSensor.new({
name = "Window", name = "Window",
room = "Bedroom", room = "Bedroom",
topic = mqtt_z2m("bedroom/window"), topic = mqtt_z2m("bedroom/window"),
client = mqtt_client, client = mqtt_client,
battery_callback = check_battery, battery_callback = check_battery,
})) }))
device_manager:add(ContactSensor.new({ device_manager:add(devices.ContactSensor.new({
name = "Window", name = "Window",
room = "Guest Room", room = "Guest Room",
topic = mqtt_z2m("guest/window"), topic = mqtt_z2m("guest/window"),
@@ -643,7 +644,7 @@ device_manager:add(ContactSensor.new({
battery_callback = check_battery, battery_callback = check_battery,
})) }))
local storage_light = LightBrightness.new({ local storage_light = devices.LightBrightness.new({
name = "Light", name = "Light",
room = "Storage", room = "Storage",
topic = mqtt_z2m("storage/light"), topic = mqtt_z2m("storage/light"),
@@ -652,7 +653,7 @@ local storage_light = LightBrightness.new({
turn_off_when_away(storage_light) turn_off_when_away(storage_light)
device_manager:add(storage_light) device_manager:add(storage_light)
device_manager:add(ContactSensor.new({ device_manager:add(devices.ContactSensor.new({
name = "Door", name = "Door",
room = "Storage", room = "Storage",
sensor_type = "Door", sensor_type = "Door",

View File

@@ -12,8 +12,8 @@ use std::time::{Duration, SystemTime, UNIX_EPOCH};
use ::config::{Environment, File}; use ::config::{Environment, File};
use automation_lib::config::{FulfillmentConfig, MqttConfig}; use automation_lib::config::{FulfillmentConfig, MqttConfig};
use automation_lib::device_manager::DeviceManager; use automation_lib::device_manager::DeviceManager;
use automation_lib::helpers;
use automation_lib::mqtt::{self, WrappedAsyncClient}; use automation_lib::mqtt::{self, WrappedAsyncClient};
use automation_lib::{Module, helpers};
use axum::extract::{FromRef, State}; use axum::extract::{FromRef, State};
use axum::http::StatusCode; use axum::http::StatusCode;
use axum::routing::post; use axum::routing::post;
@@ -30,6 +30,9 @@ use web::{ApiError, User};
use crate::secret::EnvironmentSecretFile; use crate::secret::EnvironmentSecretFile;
use crate::version::VERSION; use crate::version::VERSION;
// Force automation_devices to link so that it gets registered as a module
extern crate automation_devices;
#[derive(Clone)] #[derive(Clone)]
struct AppState { struct AppState {
pub openid_url: String, pub openid_url: String,
@@ -138,6 +141,13 @@ async fn app() -> anyhow::Result<()> {
})?; })?;
lua.globals().set("print", print)?; lua.globals().set("print", print)?;
debug!("Loading modules...");
for module in inventory::iter::<Module> {
debug!(name = module.get_name(), "Registering");
let table = module.register(&lua)?;
lua.register_module(module.get_name(), table)?;
}
let mqtt = lua.create_table()?; let mqtt = lua.create_table()?;
let event_channel = device_manager.event_channel(); let event_channel = device_manager.event_channel();
let mqtt_new = lua.create_function(move |lua, config: mlua::Value| { let mqtt_new = lua.create_function(move |lua, config: mlua::Value| {
@@ -179,7 +189,6 @@ async fn app() -> anyhow::Result<()> {
utils.set("sleep", sleep)?; utils.set("sleep", sleep)?;
lua.register_module("utils", utils)?; lua.register_module("utils", utils)?;
automation_devices::register_with_lua(&lua)?;
helpers::register_with_lua(&lua)?; helpers::register_with_lua(&lua)?;
let entrypoint = Path::new(&config.entrypoint); let entrypoint = Path::new(&config.entrypoint);