Compare commits
5 Commits
master
...
95d7bfc43e
| Author | SHA1 | Date | |
|---|---|---|---|
|
95d7bfc43e
|
|||
|
4e2da2ecca
|
|||
|
65c7ed6349
|
|||
|
a0ed373971
|
|||
|
5e13dff2b5
|
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -94,11 +94,13 @@ dependencies = [
|
|||||||
"async-trait",
|
"async-trait",
|
||||||
"automation_devices",
|
"automation_devices",
|
||||||
"automation_lib",
|
"automation_lib",
|
||||||
|
"automation_macro",
|
||||||
"axum",
|
"axum",
|
||||||
"config",
|
"config",
|
||||||
"git-version",
|
"git-version",
|
||||||
"google_home",
|
"google_home",
|
||||||
"inventory",
|
"inventory",
|
||||||
|
"lua_typed",
|
||||||
"mlua",
|
"mlua",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"rumqttc",
|
"rumqttc",
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ anyhow = { workspace = true }
|
|||||||
async-trait = { workspace = true }
|
async-trait = { workspace = true }
|
||||||
automation_devices = { workspace = true }
|
automation_devices = { workspace = true }
|
||||||
automation_lib = { workspace = true }
|
automation_lib = { workspace = true }
|
||||||
|
automation_macro = { path = "./automation_macro" }
|
||||||
axum = { workspace = true }
|
axum = { workspace = true }
|
||||||
config = { version = "0.15.15", default-features = false, features = [
|
config = { version = "0.15.15", default-features = false, features = [
|
||||||
"async",
|
"async",
|
||||||
@@ -77,6 +78,7 @@ config = { version = "0.15.15", default-features = false, features = [
|
|||||||
] }
|
] }
|
||||||
git-version = "0.3.9"
|
git-version = "0.3.9"
|
||||||
google_home = { workspace = true }
|
google_home = { workspace = true }
|
||||||
|
lua_typed = { workspace = true }
|
||||||
inventory = { workspace = true }
|
inventory = { workspace = true }
|
||||||
mlua = { workspace = true }
|
mlua = { workspace = true }
|
||||||
reqwest = { workspace = true }
|
reqwest = { workspace = true }
|
||||||
|
|||||||
@@ -70,13 +70,35 @@ pub fn create_module(lua: &mlua::Lua) -> mlua::Result<mlua::Table> {
|
|||||||
Ok(devices)
|
Ok(devices)
|
||||||
}
|
}
|
||||||
|
|
||||||
type RegisterTypeFn = fn() -> Option<String>;
|
type TypeNameFn = fn() -> String;
|
||||||
|
type TypeDefinitionFn = fn() -> Option<String>;
|
||||||
|
|
||||||
pub struct RegisteredType(RegisterTypeFn);
|
pub struct RegisteredType {
|
||||||
|
name_fn: TypeNameFn,
|
||||||
|
definition_fn: TypeDefinitionFn,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RegisteredType {
|
||||||
|
pub const fn new(name_fn: TypeNameFn, definition_fn: TypeDefinitionFn) -> Self {
|
||||||
|
Self {
|
||||||
|
name_fn,
|
||||||
|
definition_fn,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_name(&self) -> String {
|
||||||
|
(self.name_fn)()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn register(&self) -> Option<String> {
|
||||||
|
(self.definition_fn)()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! register_type {
|
macro_rules! register_type {
|
||||||
($ty:ty) => {
|
($ty:ty) => {
|
||||||
::inventory::submit!(crate::RegisteredType(
|
::inventory::submit!(crate::RegisteredType::new(
|
||||||
|
<$ty as ::lua_typed::Typed>::type_name,
|
||||||
<$ty as ::lua_typed::Typed>::generate_full
|
<$ty as ::lua_typed::Typed>::generate_full
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
@@ -88,9 +110,12 @@ inventory::collect!(RegisteredType);
|
|||||||
fn generate_definitions() -> String {
|
fn generate_definitions() -> String {
|
||||||
let mut output = String::new();
|
let mut output = String::new();
|
||||||
|
|
||||||
|
let mut types: Vec<_> = inventory::iter::<RegisteredType>.into_iter().collect();
|
||||||
|
types.sort_by_key(|ty| ty.get_name());
|
||||||
|
|
||||||
output += "---@meta\n\nlocal devices\n\n";
|
output += "---@meta\n\nlocal devices\n\n";
|
||||||
for ty in inventory::iter::<RegisteredType> {
|
for ty in types {
|
||||||
if let Some(def) = ty.0() {
|
if let Some(def) = (ty.definition_fn)() {
|
||||||
output += &(def + "\n");
|
output += &(def + "\n");
|
||||||
} else {
|
} else {
|
||||||
// NOTE: Due to how this works the typed is erased, so we don't know the cause
|
// NOTE: Due to how this works the typed is erased, so we don't know the cause
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ use std::fmt::Debug;
|
|||||||
|
|
||||||
use automation_cast::Cast;
|
use automation_cast::Cast;
|
||||||
use dyn_clone::DynClone;
|
use dyn_clone::DynClone;
|
||||||
|
use lua_typed::Typed;
|
||||||
use mlua::ObjectLike;
|
use mlua::ObjectLike;
|
||||||
|
|
||||||
use crate::event::OnMqtt;
|
use crate::event::OnMqtt;
|
||||||
@@ -41,4 +42,10 @@ impl mlua::FromLua for Box<dyn Device> {
|
|||||||
}
|
}
|
||||||
impl mlua::UserData for Box<dyn Device> {}
|
impl mlua::UserData for Box<dyn Device> {}
|
||||||
|
|
||||||
|
impl Typed for Box<dyn Device> {
|
||||||
|
fn type_name() -> String {
|
||||||
|
"DeviceInterface".into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dyn_clone::clone_trait_object!(Device);
|
dyn_clone::clone_trait_object!(Device);
|
||||||
|
|||||||
85
config.lua
85
config.lua
@@ -30,6 +30,11 @@ local mqtt_client = require("automation:mqtt").new(device_manager, {
|
|||||||
tls = host == "zeus" or host == "hephaestus",
|
tls = host == "zeus" or host == "hephaestus",
|
||||||
})
|
})
|
||||||
|
|
||||||
|
local devs = {}
|
||||||
|
function devs:add(device)
|
||||||
|
table.insert(self, device)
|
||||||
|
end
|
||||||
|
|
||||||
local ntfy_topic = secrets.ntfy_topic
|
local ntfy_topic = secrets.ntfy_topic
|
||||||
if ntfy_topic == nil then
|
if ntfy_topic == nil then
|
||||||
error("Ntfy topic is not specified")
|
error("Ntfy topic is not specified")
|
||||||
@@ -37,7 +42,7 @@ end
|
|||||||
local ntfy = devices.Ntfy.new({
|
local ntfy = devices.Ntfy.new({
|
||||||
topic = ntfy_topic,
|
topic = ntfy_topic,
|
||||||
})
|
})
|
||||||
device_manager:add(ntfy)
|
devs:add(ntfy)
|
||||||
|
|
||||||
--- @type {[string]: number}
|
--- @type {[string]: number}
|
||||||
local low_battery = {}
|
local low_battery = {}
|
||||||
@@ -92,7 +97,7 @@ local presence_system = devices.Presence.new({
|
|||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
device_manager:add(presence_system)
|
devs:add(presence_system)
|
||||||
on_presence:add(function(presence)
|
on_presence:add(function(presence)
|
||||||
ntfy:send_notification({
|
ntfy:send_notification({
|
||||||
title = "Presence",
|
title = "Presence",
|
||||||
@@ -166,7 +171,7 @@ local on_light = {}
|
|||||||
function on_light:add(f)
|
function on_light:add(f)
|
||||||
self[#self + 1] = f
|
self[#self + 1] = f
|
||||||
end
|
end
|
||||||
device_manager:add(devices.LightSensor.new({
|
devs: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,
|
||||||
@@ -202,7 +207,7 @@ local hue_bridge = devices.HueBridge.new({
|
|||||||
darkness = 43,
|
darkness = 43,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
device_manager:add(hue_bridge)
|
devs:add(hue_bridge)
|
||||||
on_light:add(function(light)
|
on_light:add(function(light)
|
||||||
hue_bridge:set_flag("darkness", not light)
|
hue_bridge:set_flag("darkness", not light)
|
||||||
end)
|
end)
|
||||||
@@ -217,7 +222,7 @@ local kitchen_lights = devices.HueGroup.new({
|
|||||||
group_id = 7,
|
group_id = 7,
|
||||||
scene_id = "7MJLG27RzeRAEVJ",
|
scene_id = "7MJLG27RzeRAEVJ",
|
||||||
})
|
})
|
||||||
device_manager:add(kitchen_lights)
|
devs:add(kitchen_lights)
|
||||||
local living_lights = devices.HueGroup.new({
|
local living_lights = devices.HueGroup.new({
|
||||||
identifier = "living_lights",
|
identifier = "living_lights",
|
||||||
ip = hue_ip,
|
ip = hue_ip,
|
||||||
@@ -225,7 +230,7 @@ local living_lights = devices.HueGroup.new({
|
|||||||
group_id = 1,
|
group_id = 1,
|
||||||
scene_id = "SNZw7jUhQ3cXSjkj",
|
scene_id = "SNZw7jUhQ3cXSjkj",
|
||||||
})
|
})
|
||||||
device_manager:add(living_lights)
|
devs:add(living_lights)
|
||||||
local living_lights_relax = devices.HueGroup.new({
|
local living_lights_relax = devices.HueGroup.new({
|
||||||
identifier = "living_lights",
|
identifier = "living_lights",
|
||||||
ip = hue_ip,
|
ip = hue_ip,
|
||||||
@@ -233,9 +238,9 @@ local living_lights_relax = devices.HueGroup.new({
|
|||||||
group_id = 1,
|
group_id = 1,
|
||||||
scene_id = "eRJ3fvGHCcb6yNw",
|
scene_id = "eRJ3fvGHCcb6yNw",
|
||||||
})
|
})
|
||||||
device_manager:add(living_lights_relax)
|
devs:add(living_lights_relax)
|
||||||
|
|
||||||
device_manager:add(devices.HueSwitch.new({
|
devs:add(devices.HueSwitch.new({
|
||||||
name = "Switch",
|
name = "Switch",
|
||||||
room = "Living",
|
room = "Living",
|
||||||
client = mqtt_client,
|
client = mqtt_client,
|
||||||
@@ -252,7 +257,7 @@ device_manager:add(devices.HueSwitch.new({
|
|||||||
battery_callback = check_battery,
|
battery_callback = check_battery,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
device_manager:add(devices.WakeOnLAN.new({
|
devs: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"),
|
||||||
@@ -268,7 +273,7 @@ local living_mixer = devices.OutletOnOff.new({
|
|||||||
client = mqtt_client,
|
client = mqtt_client,
|
||||||
})
|
})
|
||||||
turn_off_when_away(living_mixer)
|
turn_off_when_away(living_mixer)
|
||||||
device_manager:add(living_mixer)
|
devs:add(living_mixer)
|
||||||
local living_speakers = devices.OutletOnOff.new({
|
local living_speakers = devices.OutletOnOff.new({
|
||||||
name = "Speakers",
|
name = "Speakers",
|
||||||
room = "Living Room",
|
room = "Living Room",
|
||||||
@@ -276,9 +281,9 @@ local living_speakers = devices.OutletOnOff.new({
|
|||||||
client = mqtt_client,
|
client = mqtt_client,
|
||||||
})
|
})
|
||||||
turn_off_when_away(living_speakers)
|
turn_off_when_away(living_speakers)
|
||||||
device_manager:add(living_speakers)
|
devs:add(living_speakers)
|
||||||
|
|
||||||
device_manager:add(devices.IkeaRemote.new({
|
devs:add(devices.IkeaRemote.new({
|
||||||
name = "Remote",
|
name = "Remote",
|
||||||
room = "Living Room",
|
room = "Living Room",
|
||||||
client = mqtt_client,
|
client = mqtt_client,
|
||||||
@@ -329,14 +334,14 @@ local kettle = devices.OutletPower.new({
|
|||||||
callback = kettle_timeout(),
|
callback = kettle_timeout(),
|
||||||
})
|
})
|
||||||
turn_off_when_away(kettle)
|
turn_off_when_away(kettle)
|
||||||
device_manager:add(kettle)
|
devs:add(kettle)
|
||||||
|
|
||||||
--- @param on boolean
|
--- @param on boolean
|
||||||
local function set_kettle(_, on)
|
local function set_kettle(_, on)
|
||||||
kettle:set_on(on)
|
kettle:set_on(on)
|
||||||
end
|
end
|
||||||
|
|
||||||
device_manager:add(devices.IkeaRemote.new({
|
devs:add(devices.IkeaRemote.new({
|
||||||
name = "Remote",
|
name = "Remote",
|
||||||
room = "Bedroom",
|
room = "Bedroom",
|
||||||
client = mqtt_client,
|
client = mqtt_client,
|
||||||
@@ -346,7 +351,7 @@ device_manager:add(devices.IkeaRemote.new({
|
|||||||
battery_callback = check_battery,
|
battery_callback = check_battery,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
device_manager:add(devices.IkeaRemote.new({
|
devs:add(devices.IkeaRemote.new({
|
||||||
name = "Remote",
|
name = "Remote",
|
||||||
room = "Kitchen",
|
room = "Kitchen",
|
||||||
client = mqtt_client,
|
client = mqtt_client,
|
||||||
@@ -379,9 +384,9 @@ local bathroom_light = devices.LightOnOff.new({
|
|||||||
client = mqtt_client,
|
client = mqtt_client,
|
||||||
callback = off_timeout(debug and 60 or 45 * 60),
|
callback = off_timeout(debug and 60 or 45 * 60),
|
||||||
})
|
})
|
||||||
device_manager:add(bathroom_light)
|
devs:add(bathroom_light)
|
||||||
|
|
||||||
device_manager:add(devices.Washer.new({
|
devs: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,
|
||||||
@@ -396,7 +401,7 @@ device_manager:add(devices.Washer.new({
|
|||||||
end,
|
end,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
device_manager:add(devices.OutletOnOff.new({
|
devs:add(devices.OutletOnOff.new({
|
||||||
name = "Charger",
|
name = "Charger",
|
||||||
room = "Workbench",
|
room = "Workbench",
|
||||||
topic = mqtt_z2m("workbench/charger"),
|
topic = mqtt_z2m("workbench/charger"),
|
||||||
@@ -411,7 +416,7 @@ local workbench_outlet = devices.OutletOnOff.new({
|
|||||||
client = mqtt_client,
|
client = mqtt_client,
|
||||||
})
|
})
|
||||||
turn_off_when_away(workbench_outlet)
|
turn_off_when_away(workbench_outlet)
|
||||||
device_manager:add(workbench_outlet)
|
devs:add(workbench_outlet)
|
||||||
|
|
||||||
local workbench_light = devices.LightColorTemperature.new({
|
local workbench_light = devices.LightColorTemperature.new({
|
||||||
name = "Light",
|
name = "Light",
|
||||||
@@ -420,10 +425,10 @@ local workbench_light = devices.LightColorTemperature.new({
|
|||||||
client = mqtt_client,
|
client = mqtt_client,
|
||||||
})
|
})
|
||||||
turn_off_when_away(workbench_light)
|
turn_off_when_away(workbench_light)
|
||||||
device_manager:add(workbench_light)
|
devs:add(workbench_light)
|
||||||
|
|
||||||
local delay_color_temp = utils.Timeout.new()
|
local delay_color_temp = utils.Timeout.new()
|
||||||
device_manager:add(devices.IkeaRemote.new({
|
devs:add(devices.IkeaRemote.new({
|
||||||
name = "Remote",
|
name = "Remote",
|
||||||
room = "Workbench",
|
room = "Workbench",
|
||||||
client = mqtt_client,
|
client = mqtt_client,
|
||||||
@@ -453,7 +458,7 @@ local hallway_top_light = devices.HueGroup.new({
|
|||||||
group_id = 83,
|
group_id = 83,
|
||||||
scene_id = "QeufkFDICEHWeKJ7",
|
scene_id = "QeufkFDICEHWeKJ7",
|
||||||
})
|
})
|
||||||
device_manager:add(devices.HueSwitch.new({
|
devs:add(devices.HueSwitch.new({
|
||||||
name = "SwitchBottom",
|
name = "SwitchBottom",
|
||||||
room = "Hallway",
|
room = "Hallway",
|
||||||
client = mqtt_client,
|
client = mqtt_client,
|
||||||
@@ -463,7 +468,7 @@ device_manager:add(devices.HueSwitch.new({
|
|||||||
end,
|
end,
|
||||||
battery_callback = check_battery,
|
battery_callback = check_battery,
|
||||||
}))
|
}))
|
||||||
device_manager:add(devices.HueSwitch.new({
|
devs:add(devices.HueSwitch.new({
|
||||||
name = "SwitchTop",
|
name = "SwitchTop",
|
||||||
room = "Hallway",
|
room = "Hallway",
|
||||||
client = mqtt_client,
|
client = mqtt_client,
|
||||||
@@ -546,7 +551,7 @@ local hallway_storage = devices.LightBrightness.new({
|
|||||||
callback = hallway_light_automation:light_callback(),
|
callback = hallway_light_automation:light_callback(),
|
||||||
})
|
})
|
||||||
turn_off_when_away(hallway_storage)
|
turn_off_when_away(hallway_storage)
|
||||||
device_manager:add(hallway_storage)
|
devs:add(hallway_storage)
|
||||||
|
|
||||||
local hallway_bottom_lights = devices.HueGroup.new({
|
local hallway_bottom_lights = devices.HueGroup.new({
|
||||||
identifier = "hallway_bottom_lights",
|
identifier = "hallway_bottom_lights",
|
||||||
@@ -555,7 +560,7 @@ local hallway_bottom_lights = devices.HueGroup.new({
|
|||||||
group_id = 81,
|
group_id = 81,
|
||||||
scene_id = "3qWKxGVadXFFG4o",
|
scene_id = "3qWKxGVadXFFG4o",
|
||||||
})
|
})
|
||||||
device_manager:add(hallway_bottom_lights)
|
devs:add(hallway_bottom_lights)
|
||||||
|
|
||||||
hallway_light_automation.group = {
|
hallway_light_automation.group = {
|
||||||
set_on = function(on)
|
set_on = function(on)
|
||||||
@@ -591,7 +596,7 @@ local function presence(duration)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
device_manager:add(devices.IkeaRemote.new({
|
devs:add(devices.IkeaRemote.new({
|
||||||
name = "Remote",
|
name = "Remote",
|
||||||
room = "Hallway",
|
room = "Hallway",
|
||||||
client = mqtt_client,
|
client = mqtt_client,
|
||||||
@@ -611,7 +616,7 @@ local hallway_frontdoor = devices.ContactSensor.new({
|
|||||||
},
|
},
|
||||||
battery_callback = check_battery,
|
battery_callback = check_battery,
|
||||||
})
|
})
|
||||||
device_manager:add(hallway_frontdoor)
|
devs:add(hallway_frontdoor)
|
||||||
window_sensors:add(hallway_frontdoor)
|
window_sensors:add(hallway_frontdoor)
|
||||||
hallway_light_automation.door = hallway_frontdoor
|
hallway_light_automation.door = hallway_frontdoor
|
||||||
|
|
||||||
@@ -624,7 +629,7 @@ local hallway_trash = devices.ContactSensor.new({
|
|||||||
callback = hallway_light_automation:trash_callback(),
|
callback = hallway_light_automation:trash_callback(),
|
||||||
battery_callback = check_battery,
|
battery_callback = check_battery,
|
||||||
})
|
})
|
||||||
device_manager:add(hallway_trash)
|
devs:add(hallway_trash)
|
||||||
hallway_light_automation.trash = hallway_trash
|
hallway_light_automation.trash = hallway_trash
|
||||||
|
|
||||||
local guest_light = devices.LightOnOff.new({
|
local guest_light = devices.LightOnOff.new({
|
||||||
@@ -634,14 +639,14 @@ local guest_light = devices.LightOnOff.new({
|
|||||||
client = mqtt_client,
|
client = mqtt_client,
|
||||||
})
|
})
|
||||||
turn_off_when_away(guest_light)
|
turn_off_when_away(guest_light)
|
||||||
device_manager:add(guest_light)
|
devs:add(guest_light)
|
||||||
|
|
||||||
local bedroom_air_filter = devices.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)
|
devs:add(bedroom_air_filter)
|
||||||
|
|
||||||
local bedroom_lights = devices.HueGroup.new({
|
local bedroom_lights = devices.HueGroup.new({
|
||||||
identifier = "bedroom_lights",
|
identifier = "bedroom_lights",
|
||||||
@@ -650,7 +655,7 @@ local bedroom_lights = devices.HueGroup.new({
|
|||||||
group_id = 3,
|
group_id = 3,
|
||||||
scene_id = "PvRs-lGD4VRytL9",
|
scene_id = "PvRs-lGD4VRytL9",
|
||||||
})
|
})
|
||||||
device_manager:add(bedroom_lights)
|
devs:add(bedroom_lights)
|
||||||
local bedroom_lights_relax = devices.HueGroup.new({
|
local bedroom_lights_relax = devices.HueGroup.new({
|
||||||
identifier = "bedroom_lights",
|
identifier = "bedroom_lights",
|
||||||
ip = hue_ip,
|
ip = hue_ip,
|
||||||
@@ -658,9 +663,9 @@ local bedroom_lights_relax = devices.HueGroup.new({
|
|||||||
group_id = 3,
|
group_id = 3,
|
||||||
scene_id = "60tfTyR168v2csz",
|
scene_id = "60tfTyR168v2csz",
|
||||||
})
|
})
|
||||||
device_manager:add(bedroom_lights_relax)
|
devs:add(bedroom_lights_relax)
|
||||||
|
|
||||||
device_manager:add(devices.HueSwitch.new({
|
devs:add(devices.HueSwitch.new({
|
||||||
name = "Switch",
|
name = "Switch",
|
||||||
room = "Bedroom",
|
room = "Bedroom",
|
||||||
client = mqtt_client,
|
client = mqtt_client,
|
||||||
@@ -682,7 +687,7 @@ local balcony = devices.ContactSensor.new({
|
|||||||
client = mqtt_client,
|
client = mqtt_client,
|
||||||
battery_callback = check_battery,
|
battery_callback = check_battery,
|
||||||
})
|
})
|
||||||
device_manager:add(balcony)
|
devs:add(balcony)
|
||||||
window_sensors:add(balcony)
|
window_sensors:add(balcony)
|
||||||
local living_window = devices.ContactSensor.new({
|
local living_window = devices.ContactSensor.new({
|
||||||
name = "Window",
|
name = "Window",
|
||||||
@@ -691,7 +696,7 @@ local living_window = devices.ContactSensor.new({
|
|||||||
client = mqtt_client,
|
client = mqtt_client,
|
||||||
battery_callback = check_battery,
|
battery_callback = check_battery,
|
||||||
})
|
})
|
||||||
device_manager:add(living_window)
|
devs:add(living_window)
|
||||||
window_sensors:add(living_window)
|
window_sensors:add(living_window)
|
||||||
local bedroom_window = devices.ContactSensor.new({
|
local bedroom_window = devices.ContactSensor.new({
|
||||||
name = "Window",
|
name = "Window",
|
||||||
@@ -700,7 +705,7 @@ local bedroom_window = devices.ContactSensor.new({
|
|||||||
client = mqtt_client,
|
client = mqtt_client,
|
||||||
battery_callback = check_battery,
|
battery_callback = check_battery,
|
||||||
})
|
})
|
||||||
device_manager:add(bedroom_window)
|
devs:add(bedroom_window)
|
||||||
window_sensors:add(bedroom_window)
|
window_sensors:add(bedroom_window)
|
||||||
local guest_window = devices.ContactSensor.new({
|
local guest_window = devices.ContactSensor.new({
|
||||||
name = "Window",
|
name = "Window",
|
||||||
@@ -709,7 +714,7 @@ local guest_window = devices.ContactSensor.new({
|
|||||||
client = mqtt_client,
|
client = mqtt_client,
|
||||||
battery_callback = check_battery,
|
battery_callback = check_battery,
|
||||||
})
|
})
|
||||||
device_manager:add(guest_window)
|
devs:add(guest_window)
|
||||||
window_sensors:add(guest_window)
|
window_sensors:add(guest_window)
|
||||||
|
|
||||||
local storage_light = devices.LightBrightness.new({
|
local storage_light = devices.LightBrightness.new({
|
||||||
@@ -719,9 +724,9 @@ local storage_light = devices.LightBrightness.new({
|
|||||||
client = mqtt_client,
|
client = mqtt_client,
|
||||||
})
|
})
|
||||||
turn_off_when_away(storage_light)
|
turn_off_when_away(storage_light)
|
||||||
device_manager:add(storage_light)
|
devs:add(storage_light)
|
||||||
|
|
||||||
device_manager:add(devices.ContactSensor.new({
|
devs:add(devices.ContactSensor.new({
|
||||||
name = "Door",
|
name = "Door",
|
||||||
room = "Storage",
|
room = "Storage",
|
||||||
sensor_type = "Door",
|
sensor_type = "Door",
|
||||||
@@ -744,8 +749,10 @@ device_manager:schedule("0 0 20 * * *", function()
|
|||||||
bedroom_air_filter:set_on(false)
|
bedroom_air_filter:set_on(false)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
---@type Config
|
||||||
return {
|
return {
|
||||||
fulfillment = {
|
fulfillment = {
|
||||||
openid_url = "https://login.huizinga.dev/api/oidc",
|
openid_url = "https://login.huizinga.dev/api/oidc",
|
||||||
},
|
},
|
||||||
|
devices = devs,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,17 +3,13 @@
|
|||||||
|
|
||||||
local devices
|
local devices
|
||||||
|
|
||||||
---@class KasaOutletConfig
|
---@class Action
|
||||||
---@field identifier string
|
---@field action
|
||||||
---@field ip string
|
---| "broadcast"
|
||||||
local KasaOutletConfig
|
---@field extras table<string, string>?
|
||||||
|
---@field label string
|
||||||
---@class KasaOutlet: DeviceInterface, OnOffInterface
|
---@field clear boolean?
|
||||||
local KasaOutlet
|
local Action
|
||||||
devices.KasaOutlet = {}
|
|
||||||
---@param config KasaOutletConfig
|
|
||||||
---@return KasaOutlet
|
|
||||||
function devices.KasaOutlet.new(config) end
|
|
||||||
|
|
||||||
---@class AirFilter: DeviceInterface, OnOffInterface
|
---@class AirFilter: DeviceInterface, OnOffInterface
|
||||||
local AirFilter
|
local AirFilter
|
||||||
@@ -28,21 +24,73 @@ function devices.AirFilter.new(config) end
|
|||||||
---@field url string
|
---@field url string
|
||||||
local AirFilterConfig
|
local AirFilterConfig
|
||||||
|
|
||||||
---@class Presence: DeviceInterface
|
---@class ConfigLightLightStateBrightness
|
||||||
local Presence
|
---@field name string
|
||||||
devices.Presence = {}
|
---@field room string?
|
||||||
---@param config PresenceConfig
|
|
||||||
---@return Presence
|
|
||||||
function devices.Presence.new(config) end
|
|
||||||
---@async
|
|
||||||
---@return boolean
|
|
||||||
function Presence:overall_presence() end
|
|
||||||
|
|
||||||
---@class PresenceConfig
|
|
||||||
---@field topic string
|
---@field topic string
|
||||||
---@field callback fun(_: Presence, _: boolean) | fun(_: Presence, _: boolean)[]?
|
---@field callback fun(_: LightBrightness, _: LightStateBrightness) | fun(_: LightBrightness, _: LightStateBrightness)[]?
|
||||||
|
---@field client AsyncClient?
|
||||||
|
local ConfigLightLightStateBrightness
|
||||||
|
|
||||||
|
---@class ConfigLightLightStateColorTemperature
|
||||||
|
---@field name string
|
||||||
|
---@field room string?
|
||||||
|
---@field topic string
|
||||||
|
---@field callback fun(_: LightColorTemperature, _: LightStateColorTemperature) | fun(_: LightColorTemperature, _: LightStateColorTemperature)[]?
|
||||||
|
---@field client AsyncClient?
|
||||||
|
local ConfigLightLightStateColorTemperature
|
||||||
|
|
||||||
|
---@class ConfigLightLightStateOnOff
|
||||||
|
---@field name string
|
||||||
|
---@field room string?
|
||||||
|
---@field topic string
|
||||||
|
---@field callback fun(_: LightOnOff, _: LightStateOnOff) | fun(_: LightOnOff, _: LightStateOnOff)[]?
|
||||||
|
---@field client AsyncClient?
|
||||||
|
local ConfigLightLightStateOnOff
|
||||||
|
|
||||||
|
---@class ConfigOutletOutletStateOnOff
|
||||||
|
---@field name string
|
||||||
|
---@field room string?
|
||||||
|
---@field topic string
|
||||||
|
---@field outlet_type OutletType?
|
||||||
|
---@field callback fun(_: OutletOnOff, _: OutletStateOnOff) | fun(_: OutletOnOff, _: OutletStateOnOff)[]?
|
||||||
---@field client AsyncClient
|
---@field client AsyncClient
|
||||||
local PresenceConfig
|
local ConfigOutletOutletStateOnOff
|
||||||
|
|
||||||
|
---@class ConfigOutletOutletStatePower
|
||||||
|
---@field name string
|
||||||
|
---@field room string?
|
||||||
|
---@field topic string
|
||||||
|
---@field outlet_type OutletType?
|
||||||
|
---@field callback fun(_: OutletPower, _: OutletStatePower) | fun(_: OutletPower, _: OutletStatePower)[]?
|
||||||
|
---@field client AsyncClient
|
||||||
|
local ConfigOutletOutletStatePower
|
||||||
|
|
||||||
|
---@class ContactSensor: DeviceInterface, OpenCloseInterface
|
||||||
|
local ContactSensor
|
||||||
|
devices.ContactSensor = {}
|
||||||
|
---@param config ContactSensorConfig
|
||||||
|
---@return ContactSensor
|
||||||
|
function devices.ContactSensor.new(config) end
|
||||||
|
|
||||||
|
---@class ContactSensorConfig
|
||||||
|
---@field name string
|
||||||
|
---@field room string?
|
||||||
|
---@field topic string
|
||||||
|
---@field sensor_type SensorType?
|
||||||
|
---@field callback fun(_: ContactSensor, _: boolean) | fun(_: ContactSensor, _: boolean)[]?
|
||||||
|
---@field battery_callback fun(_: ContactSensor, _: number) | fun(_: ContactSensor, _: number)[]?
|
||||||
|
---@field client AsyncClient?
|
||||||
|
local ContactSensorConfig
|
||||||
|
|
||||||
|
---@alias Flag
|
||||||
|
---| "presence"
|
||||||
|
---| "darkness"
|
||||||
|
|
||||||
|
---@class FlagIDs
|
||||||
|
---@field presence integer
|
||||||
|
---@field darkness integer
|
||||||
|
local FlagIDs
|
||||||
|
|
||||||
---@class HueBridge: DeviceInterface
|
---@class HueBridge: DeviceInterface
|
||||||
local HueBridge
|
local HueBridge
|
||||||
@@ -55,11 +103,6 @@ function devices.HueBridge.new(config) end
|
|||||||
---@param value boolean
|
---@param value boolean
|
||||||
function HueBridge:set_flag(flag, value) end
|
function HueBridge:set_flag(flag, value) end
|
||||||
|
|
||||||
---@class FlagIDs
|
|
||||||
---@field presence integer
|
|
||||||
---@field darkness integer
|
|
||||||
local FlagIDs
|
|
||||||
|
|
||||||
---@class HueBridgeConfig
|
---@class HueBridgeConfig
|
||||||
---@field identifier string
|
---@field identifier string
|
||||||
---@field ip string
|
---@field ip string
|
||||||
@@ -67,49 +110,6 @@ local FlagIDs
|
|||||||
---@field flags FlagIDs
|
---@field flags FlagIDs
|
||||||
local HueBridgeConfig
|
local HueBridgeConfig
|
||||||
|
|
||||||
---@alias Flag
|
|
||||||
---| "presence"
|
|
||||||
---| "darkness"
|
|
||||||
|
|
||||||
---@class WasherConfig
|
|
||||||
---@field identifier string
|
|
||||||
---@field topic string
|
|
||||||
---@field threshold number
|
|
||||||
---@field done_callback fun(_: Washer) | fun(_: Washer)[]?
|
|
||||||
---@field client AsyncClient
|
|
||||||
local WasherConfig
|
|
||||||
|
|
||||||
---@class Washer: DeviceInterface
|
|
||||||
local Washer
|
|
||||||
devices.Washer = {}
|
|
||||||
---@param config WasherConfig
|
|
||||||
---@return Washer
|
|
||||||
function devices.Washer.new(config) end
|
|
||||||
|
|
||||||
---@class LightSensor: DeviceInterface
|
|
||||||
local LightSensor
|
|
||||||
devices.LightSensor = {}
|
|
||||||
---@param config LightSensorConfig
|
|
||||||
---@return LightSensor
|
|
||||||
function devices.LightSensor.new(config) end
|
|
||||||
|
|
||||||
---@class LightSensorConfig
|
|
||||||
---@field identifier string
|
|
||||||
---@field topic string
|
|
||||||
---@field min integer
|
|
||||||
---@field max integer
|
|
||||||
---@field callback fun(_: LightSensor, _: boolean) | fun(_: LightSensor, _: boolean)[]?
|
|
||||||
---@field client AsyncClient
|
|
||||||
local LightSensorConfig
|
|
||||||
|
|
||||||
---@class HueGroupConfig
|
|
||||||
---@field identifier string
|
|
||||||
---@field ip string
|
|
||||||
---@field login string
|
|
||||||
---@field group_id integer
|
|
||||||
---@field scene_id string
|
|
||||||
local HueGroupConfig
|
|
||||||
|
|
||||||
---@class HueGroup: DeviceInterface, OnOffInterface
|
---@class HueGroup: DeviceInterface, OnOffInterface
|
||||||
local HueGroup
|
local HueGroup
|
||||||
devices.HueGroup = {}
|
devices.HueGroup = {}
|
||||||
@@ -117,203 +117,13 @@ devices.HueGroup = {}
|
|||||||
---@return HueGroup
|
---@return HueGroup
|
||||||
function devices.HueGroup.new(config) end
|
function devices.HueGroup.new(config) end
|
||||||
|
|
||||||
---@class IkeaRemote: DeviceInterface
|
---@class HueGroupConfig
|
||||||
local IkeaRemote
|
---@field identifier string
|
||||||
devices.IkeaRemote = {}
|
---@field ip string
|
||||||
---@param config IkeaRemoteConfig
|
---@field login string
|
||||||
---@return IkeaRemote
|
---@field group_id integer
|
||||||
function devices.IkeaRemote.new(config) end
|
---@field scene_id string
|
||||||
|
local HueGroupConfig
|
||||||
---@class IkeaRemoteConfig
|
|
||||||
---@field name string
|
|
||||||
---@field room string?
|
|
||||||
---@field single_button boolean?
|
|
||||||
---@field topic string
|
|
||||||
---@field client AsyncClient
|
|
||||||
---@field callback fun(_: IkeaRemote, _: boolean) | fun(_: IkeaRemote, _: boolean)[]?
|
|
||||||
---@field battery_callback fun(_: IkeaRemote, _: number) | fun(_: IkeaRemote, _: number)[]?
|
|
||||||
local IkeaRemoteConfig
|
|
||||||
|
|
||||||
---@class WolConfig
|
|
||||||
---@field name string
|
|
||||||
---@field room string?
|
|
||||||
---@field topic string
|
|
||||||
---@field mac_address string
|
|
||||||
---@field broadcast_ip string?
|
|
||||||
---@field client AsyncClient
|
|
||||||
local WolConfig
|
|
||||||
|
|
||||||
---@class WakeOnLAN: DeviceInterface
|
|
||||||
local WakeOnLAN
|
|
||||||
devices.WakeOnLAN = {}
|
|
||||||
---@param config WolConfig
|
|
||||||
---@return WakeOnLAN
|
|
||||||
function devices.WakeOnLAN.new(config) end
|
|
||||||
|
|
||||||
---@class ConfigOutletOutletStateOnOff
|
|
||||||
---@field name string
|
|
||||||
---@field room string?
|
|
||||||
---@field topic string
|
|
||||||
---@field outlet_type OutletType?
|
|
||||||
---@field callback fun(_: OutletOnOff, _: OutletStateOnOff) | fun(_: OutletOnOff, _: OutletStateOnOff)[]?
|
|
||||||
---@field client AsyncClient
|
|
||||||
local ConfigOutletOutletStateOnOff
|
|
||||||
|
|
||||||
---@class OutletStatePower
|
|
||||||
---@field state boolean
|
|
||||||
---@field power number
|
|
||||||
local OutletStatePower
|
|
||||||
|
|
||||||
---@class ConfigOutletOutletStatePower
|
|
||||||
---@field name string
|
|
||||||
---@field room string?
|
|
||||||
---@field topic string
|
|
||||||
---@field outlet_type OutletType?
|
|
||||||
---@field callback fun(_: OutletPower, _: OutletStatePower) | fun(_: OutletPower, _: OutletStatePower)[]?
|
|
||||||
---@field client AsyncClient
|
|
||||||
local ConfigOutletOutletStatePower
|
|
||||||
|
|
||||||
---@alias OutletType
|
|
||||||
---| "Outlet"
|
|
||||||
---| "Kettle"
|
|
||||||
|
|
||||||
---@class OutletStateOnOff
|
|
||||||
---@field state boolean
|
|
||||||
local OutletStateOnOff
|
|
||||||
|
|
||||||
---@class OutletOnOff: DeviceInterface, OnOffInterface
|
|
||||||
local OutletOnOff
|
|
||||||
devices.OutletOnOff = {}
|
|
||||||
---@param config ConfigOutletOutletStateOnOff
|
|
||||||
---@return OutletOnOff
|
|
||||||
function devices.OutletOnOff.new(config) end
|
|
||||||
|
|
||||||
---@class OutletPower: DeviceInterface, OnOffInterface
|
|
||||||
local OutletPower
|
|
||||||
devices.OutletPower = {}
|
|
||||||
---@param config ConfigOutletOutletStatePower
|
|
||||||
---@return OutletPower
|
|
||||||
function devices.OutletPower.new(config) end
|
|
||||||
|
|
||||||
---@class ContactSensorConfig
|
|
||||||
---@field name string
|
|
||||||
---@field room string?
|
|
||||||
---@field topic string
|
|
||||||
---@field sensor_type SensorType?
|
|
||||||
---@field callback fun(_: ContactSensor, _: boolean) | fun(_: ContactSensor, _: boolean)[]?
|
|
||||||
---@field battery_callback fun(_: ContactSensor, _: number) | fun(_: ContactSensor, _: number)[]?
|
|
||||||
---@field client AsyncClient?
|
|
||||||
local ContactSensorConfig
|
|
||||||
|
|
||||||
---@alias SensorType
|
|
||||||
---| "Door"
|
|
||||||
---| "Drawer"
|
|
||||||
---| "Window"
|
|
||||||
|
|
||||||
---@class ContactSensor: DeviceInterface, OpenCloseInterface
|
|
||||||
local ContactSensor
|
|
||||||
devices.ContactSensor = {}
|
|
||||||
---@param config ContactSensorConfig
|
|
||||||
---@return ContactSensor
|
|
||||||
function devices.ContactSensor.new(config) end
|
|
||||||
|
|
||||||
---@class LightStateOnOff
|
|
||||||
---@field state boolean
|
|
||||||
local LightStateOnOff
|
|
||||||
|
|
||||||
---@class ConfigLightLightStateColorTemperature
|
|
||||||
---@field name string
|
|
||||||
---@field room string?
|
|
||||||
---@field topic string
|
|
||||||
---@field callback fun(_: LightColorTemperature, _: LightStateColorTemperature) | fun(_: LightColorTemperature, _: LightStateColorTemperature)[]?
|
|
||||||
---@field client AsyncClient?
|
|
||||||
local ConfigLightLightStateColorTemperature
|
|
||||||
|
|
||||||
---@class LightStateBrightness
|
|
||||||
---@field state boolean
|
|
||||||
---@field brightness number
|
|
||||||
local LightStateBrightness
|
|
||||||
|
|
||||||
---@class LightStateColorTemperature
|
|
||||||
---@field state boolean
|
|
||||||
---@field brightness number
|
|
||||||
---@field color_temp integer
|
|
||||||
local LightStateColorTemperature
|
|
||||||
|
|
||||||
---@class LightBrightness: DeviceInterface, OnOffInterface, BrightnessInterface
|
|
||||||
local LightBrightness
|
|
||||||
devices.LightBrightness = {}
|
|
||||||
---@param config ConfigLightLightStateBrightness
|
|
||||||
---@return LightBrightness
|
|
||||||
function devices.LightBrightness.new(config) end
|
|
||||||
|
|
||||||
---@class LightColorTemperature: DeviceInterface, OnOffInterface, BrightnessInterface, ColorSettingInterface
|
|
||||||
local LightColorTemperature
|
|
||||||
devices.LightColorTemperature = {}
|
|
||||||
---@param config ConfigLightLightStateColorTemperature
|
|
||||||
---@return LightColorTemperature
|
|
||||||
function devices.LightColorTemperature.new(config) end
|
|
||||||
|
|
||||||
---@class ConfigLightLightStateOnOff
|
|
||||||
---@field name string
|
|
||||||
---@field room string?
|
|
||||||
---@field topic string
|
|
||||||
---@field callback fun(_: LightOnOff, _: LightStateOnOff) | fun(_: LightOnOff, _: LightStateOnOff)[]?
|
|
||||||
---@field client AsyncClient?
|
|
||||||
local ConfigLightLightStateOnOff
|
|
||||||
|
|
||||||
---@class ConfigLightLightStateBrightness
|
|
||||||
---@field name string
|
|
||||||
---@field room string?
|
|
||||||
---@field topic string
|
|
||||||
---@field callback fun(_: LightBrightness, _: LightStateBrightness) | fun(_: LightBrightness, _: LightStateBrightness)[]?
|
|
||||||
---@field client AsyncClient?
|
|
||||||
local ConfigLightLightStateBrightness
|
|
||||||
|
|
||||||
---@class LightOnOff: DeviceInterface, OnOffInterface
|
|
||||||
local LightOnOff
|
|
||||||
devices.LightOnOff = {}
|
|
||||||
---@param config ConfigLightLightStateOnOff
|
|
||||||
---@return LightOnOff
|
|
||||||
function devices.LightOnOff.new(config) end
|
|
||||||
|
|
||||||
---@class Action
|
|
||||||
---@field action
|
|
||||||
---| "broadcast"
|
|
||||||
---@field extras table<string, string>?
|
|
||||||
---@field label string
|
|
||||||
---@field clear boolean?
|
|
||||||
local Action
|
|
||||||
|
|
||||||
---@class NtfyConfig
|
|
||||||
---@field url string?
|
|
||||||
---@field topic string
|
|
||||||
local NtfyConfig
|
|
||||||
|
|
||||||
---@class Notification
|
|
||||||
---@field title string
|
|
||||||
---@field message string?
|
|
||||||
---@field tags string[]?
|
|
||||||
---@field priority Priority?
|
|
||||||
---@field actions Action[]?
|
|
||||||
local Notification
|
|
||||||
|
|
||||||
---@alias Priority
|
|
||||||
---| "min"
|
|
||||||
---| "low"
|
|
||||||
---| "default"
|
|
||||||
---| "high"
|
|
||||||
---| "max"
|
|
||||||
|
|
||||||
---@class Ntfy: DeviceInterface
|
|
||||||
local Ntfy
|
|
||||||
devices.Ntfy = {}
|
|
||||||
---@param config NtfyConfig
|
|
||||||
---@return Ntfy
|
|
||||||
function devices.Ntfy.new(config) end
|
|
||||||
---@async
|
|
||||||
---@param notification Notification
|
|
||||||
function Ntfy:send_notification(notification) end
|
|
||||||
|
|
||||||
---@class HueSwitch: DeviceInterface
|
---@class HueSwitch: DeviceInterface
|
||||||
local HueSwitch
|
local HueSwitch
|
||||||
@@ -334,4 +144,194 @@ function devices.HueSwitch.new(config) end
|
|||||||
---@field battery_callback fun(_: HueSwitch, _: number) | fun(_: HueSwitch, _: number)[]?
|
---@field battery_callback fun(_: HueSwitch, _: number) | fun(_: HueSwitch, _: number)[]?
|
||||||
local HueSwitchConfig
|
local HueSwitchConfig
|
||||||
|
|
||||||
|
---@class IkeaRemote: DeviceInterface
|
||||||
|
local IkeaRemote
|
||||||
|
devices.IkeaRemote = {}
|
||||||
|
---@param config IkeaRemoteConfig
|
||||||
|
---@return IkeaRemote
|
||||||
|
function devices.IkeaRemote.new(config) end
|
||||||
|
|
||||||
|
---@class IkeaRemoteConfig
|
||||||
|
---@field name string
|
||||||
|
---@field room string?
|
||||||
|
---@field single_button boolean?
|
||||||
|
---@field topic string
|
||||||
|
---@field client AsyncClient
|
||||||
|
---@field callback fun(_: IkeaRemote, _: boolean) | fun(_: IkeaRemote, _: boolean)[]?
|
||||||
|
---@field battery_callback fun(_: IkeaRemote, _: number) | fun(_: IkeaRemote, _: number)[]?
|
||||||
|
local IkeaRemoteConfig
|
||||||
|
|
||||||
|
---@class KasaOutlet: DeviceInterface, OnOffInterface
|
||||||
|
local KasaOutlet
|
||||||
|
devices.KasaOutlet = {}
|
||||||
|
---@param config KasaOutletConfig
|
||||||
|
---@return KasaOutlet
|
||||||
|
function devices.KasaOutlet.new(config) end
|
||||||
|
|
||||||
|
---@class KasaOutletConfig
|
||||||
|
---@field identifier string
|
||||||
|
---@field ip string
|
||||||
|
local KasaOutletConfig
|
||||||
|
|
||||||
|
---@class LightBrightness: DeviceInterface, OnOffInterface, BrightnessInterface
|
||||||
|
local LightBrightness
|
||||||
|
devices.LightBrightness = {}
|
||||||
|
---@param config ConfigLightLightStateBrightness
|
||||||
|
---@return LightBrightness
|
||||||
|
function devices.LightBrightness.new(config) end
|
||||||
|
|
||||||
|
---@class LightColorTemperature: DeviceInterface, OnOffInterface, BrightnessInterface, ColorSettingInterface
|
||||||
|
local LightColorTemperature
|
||||||
|
devices.LightColorTemperature = {}
|
||||||
|
---@param config ConfigLightLightStateColorTemperature
|
||||||
|
---@return LightColorTemperature
|
||||||
|
function devices.LightColorTemperature.new(config) end
|
||||||
|
|
||||||
|
---@class LightOnOff: DeviceInterface, OnOffInterface
|
||||||
|
local LightOnOff
|
||||||
|
devices.LightOnOff = {}
|
||||||
|
---@param config ConfigLightLightStateOnOff
|
||||||
|
---@return LightOnOff
|
||||||
|
function devices.LightOnOff.new(config) end
|
||||||
|
|
||||||
|
---@class LightSensor: DeviceInterface
|
||||||
|
local LightSensor
|
||||||
|
devices.LightSensor = {}
|
||||||
|
---@param config LightSensorConfig
|
||||||
|
---@return LightSensor
|
||||||
|
function devices.LightSensor.new(config) end
|
||||||
|
|
||||||
|
---@class LightSensorConfig
|
||||||
|
---@field identifier string
|
||||||
|
---@field topic string
|
||||||
|
---@field min integer
|
||||||
|
---@field max integer
|
||||||
|
---@field callback fun(_: LightSensor, _: boolean) | fun(_: LightSensor, _: boolean)[]?
|
||||||
|
---@field client AsyncClient
|
||||||
|
local LightSensorConfig
|
||||||
|
|
||||||
|
---@class LightStateBrightness
|
||||||
|
---@field state boolean
|
||||||
|
---@field brightness number
|
||||||
|
local LightStateBrightness
|
||||||
|
|
||||||
|
---@class LightStateColorTemperature
|
||||||
|
---@field state boolean
|
||||||
|
---@field brightness number
|
||||||
|
---@field color_temp integer
|
||||||
|
local LightStateColorTemperature
|
||||||
|
|
||||||
|
---@class LightStateOnOff
|
||||||
|
---@field state boolean
|
||||||
|
local LightStateOnOff
|
||||||
|
|
||||||
|
---@class Notification
|
||||||
|
---@field title string
|
||||||
|
---@field message string?
|
||||||
|
---@field tags string[]?
|
||||||
|
---@field priority Priority?
|
||||||
|
---@field actions Action[]?
|
||||||
|
local Notification
|
||||||
|
|
||||||
|
---@class Ntfy: DeviceInterface
|
||||||
|
local Ntfy
|
||||||
|
devices.Ntfy = {}
|
||||||
|
---@param config NtfyConfig
|
||||||
|
---@return Ntfy
|
||||||
|
function devices.Ntfy.new(config) end
|
||||||
|
---@async
|
||||||
|
---@param notification Notification
|
||||||
|
function Ntfy:send_notification(notification) end
|
||||||
|
|
||||||
|
---@class NtfyConfig
|
||||||
|
---@field url string?
|
||||||
|
---@field topic string
|
||||||
|
local NtfyConfig
|
||||||
|
|
||||||
|
---@class OutletOnOff: DeviceInterface, OnOffInterface
|
||||||
|
local OutletOnOff
|
||||||
|
devices.OutletOnOff = {}
|
||||||
|
---@param config ConfigOutletOutletStateOnOff
|
||||||
|
---@return OutletOnOff
|
||||||
|
function devices.OutletOnOff.new(config) end
|
||||||
|
|
||||||
|
---@class OutletPower: DeviceInterface, OnOffInterface
|
||||||
|
local OutletPower
|
||||||
|
devices.OutletPower = {}
|
||||||
|
---@param config ConfigOutletOutletStatePower
|
||||||
|
---@return OutletPower
|
||||||
|
function devices.OutletPower.new(config) end
|
||||||
|
|
||||||
|
---@class OutletStateOnOff
|
||||||
|
---@field state boolean
|
||||||
|
local OutletStateOnOff
|
||||||
|
|
||||||
|
---@class OutletStatePower
|
||||||
|
---@field state boolean
|
||||||
|
---@field power number
|
||||||
|
local OutletStatePower
|
||||||
|
|
||||||
|
---@alias OutletType
|
||||||
|
---| "Outlet"
|
||||||
|
---| "Kettle"
|
||||||
|
|
||||||
|
---@class Presence: DeviceInterface
|
||||||
|
local Presence
|
||||||
|
devices.Presence = {}
|
||||||
|
---@param config PresenceConfig
|
||||||
|
---@return Presence
|
||||||
|
function devices.Presence.new(config) end
|
||||||
|
---@async
|
||||||
|
---@return boolean
|
||||||
|
function Presence:overall_presence() end
|
||||||
|
|
||||||
|
---@class PresenceConfig
|
||||||
|
---@field topic string
|
||||||
|
---@field callback fun(_: Presence, _: boolean) | fun(_: Presence, _: boolean)[]?
|
||||||
|
---@field client AsyncClient
|
||||||
|
local PresenceConfig
|
||||||
|
|
||||||
|
---@alias Priority
|
||||||
|
---| "min"
|
||||||
|
---| "low"
|
||||||
|
---| "default"
|
||||||
|
---| "high"
|
||||||
|
---| "max"
|
||||||
|
|
||||||
|
---@alias SensorType
|
||||||
|
---| "Door"
|
||||||
|
---| "Drawer"
|
||||||
|
---| "Window"
|
||||||
|
|
||||||
|
---@class WakeOnLAN: DeviceInterface
|
||||||
|
local WakeOnLAN
|
||||||
|
devices.WakeOnLAN = {}
|
||||||
|
---@param config WolConfig
|
||||||
|
---@return WakeOnLAN
|
||||||
|
function devices.WakeOnLAN.new(config) end
|
||||||
|
|
||||||
|
---@class Washer: DeviceInterface
|
||||||
|
local Washer
|
||||||
|
devices.Washer = {}
|
||||||
|
---@param config WasherConfig
|
||||||
|
---@return Washer
|
||||||
|
function devices.Washer.new(config) end
|
||||||
|
|
||||||
|
---@class WasherConfig
|
||||||
|
---@field identifier string
|
||||||
|
---@field topic string
|
||||||
|
---@field threshold number
|
||||||
|
---@field done_callback fun(_: Washer) | fun(_: Washer)[]?
|
||||||
|
---@field client AsyncClient
|
||||||
|
local WasherConfig
|
||||||
|
|
||||||
|
---@class WolConfig
|
||||||
|
---@field name string
|
||||||
|
---@field room string?
|
||||||
|
---@field topic string
|
||||||
|
---@field mac_address string
|
||||||
|
---@field broadcast_ip string?
|
||||||
|
---@field client AsyncClient
|
||||||
|
local WolConfig
|
||||||
|
|
||||||
return devices
|
return devices
|
||||||
|
|||||||
13
definitions/config.lua
Normal file
13
definitions/config.lua
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
-- DO NOT MODIFY, FILE IS AUTOMATICALLY GENERATED
|
||||||
|
---@meta
|
||||||
|
|
||||||
|
---@class FulfillmentConfig
|
||||||
|
---@field openid_url string
|
||||||
|
---@field ip string?
|
||||||
|
---@field port integer?
|
||||||
|
local FulfillmentConfig
|
||||||
|
|
||||||
|
---@class Config
|
||||||
|
---@field fulfillment FulfillmentConfig
|
||||||
|
---@field devices DeviceInterface[]
|
||||||
|
local Config
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
#![feature(iter_intersperse)]
|
#![feature(iter_intersperse)]
|
||||||
mod config;
|
|
||||||
mod secret;
|
|
||||||
mod version;
|
|
||||||
mod web;
|
|
||||||
|
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::process;
|
use std::process;
|
||||||
|
|
||||||
use ::config::{Environment, File};
|
use ::config::{Environment, File};
|
||||||
|
use automation::config::{Config, Setup};
|
||||||
|
use automation::secret::EnvironmentSecretFile;
|
||||||
|
use automation::version::VERSION;
|
||||||
|
use automation::web::{ApiError, User};
|
||||||
use automation_lib::device_manager::DeviceManager;
|
use automation_lib::device_manager::DeviceManager;
|
||||||
use axum::extract::{FromRef, State};
|
use axum::extract::{FromRef, State};
|
||||||
use axum::http::StatusCode;
|
use axum::http::StatusCode;
|
||||||
@@ -18,11 +18,6 @@ use google_home::{GoogleHome, Request, Response};
|
|||||||
use mlua::LuaSerdeExt;
|
use mlua::LuaSerdeExt;
|
||||||
use tokio::net::TcpListener;
|
use tokio::net::TcpListener;
|
||||||
use tracing::{debug, error, info, warn};
|
use tracing::{debug, error, info, warn};
|
||||||
use web::{ApiError, User};
|
|
||||||
|
|
||||||
use crate::config::{Config, Setup};
|
|
||||||
use crate::secret::EnvironmentSecretFile;
|
|
||||||
use crate::version::VERSION;
|
|
||||||
|
|
||||||
// Force automation_devices to link so that it gets registered as a module
|
// Force automation_devices to link so that it gets registered as a module
|
||||||
extern crate automation_devices;
|
extern crate automation_devices;
|
||||||
@@ -141,8 +136,11 @@ async fn app() -> anyhow::Result<()> {
|
|||||||
lua.register_module("automation:secrets", lua.to_value(&setup.secrets)?)?;
|
lua.register_module("automation:secrets", lua.to_value(&setup.secrets)?)?;
|
||||||
|
|
||||||
let entrypoint = Path::new(&setup.entrypoint);
|
let entrypoint = Path::new(&setup.entrypoint);
|
||||||
let config: mlua::Value = lua.load(entrypoint).eval_async().await?;
|
let config: Config = lua.load(entrypoint).eval_async().await?;
|
||||||
let config: Config = lua.from_value(config)?;
|
|
||||||
|
for device in config.devices {
|
||||||
|
device_manager.add(device).await;
|
||||||
|
}
|
||||||
|
|
||||||
// Create google home fulfillment route
|
// Create google home fulfillment route
|
||||||
let fulfillment = Router::new().route("/google_home", post(fulfillment));
|
let fulfillment = Router::new().route("/google_home", post(fulfillment));
|
||||||
@@ -1,32 +1,57 @@
|
|||||||
use std::fs::{self, File};
|
use std::fs::{self, File};
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
|
||||||
|
use automation::config::{Config, FulfillmentConfig};
|
||||||
use automation_lib::Module;
|
use automation_lib::Module;
|
||||||
|
use lua_typed::Typed;
|
||||||
use tracing::{info, warn};
|
use tracing::{info, warn};
|
||||||
|
|
||||||
extern crate automation_devices;
|
extern crate automation_devices;
|
||||||
|
|
||||||
fn main() -> std::io::Result<()> {
|
fn write_definitions(filename: &str, definitions: &str) -> std::io::Result<()> {
|
||||||
tracing_subscriber::fmt::init();
|
|
||||||
|
|
||||||
let definitions_directory =
|
let definitions_directory =
|
||||||
std::path::Path::new(std::env!("CARGO_MANIFEST_DIR")).join("definitions");
|
std::path::Path::new(std::env!("CARGO_MANIFEST_DIR")).join("definitions");
|
||||||
fs::create_dir_all(&definitions_directory)?;
|
fs::create_dir_all(&definitions_directory)?;
|
||||||
|
|
||||||
|
let mut file = File::create(definitions_directory.join(filename))?;
|
||||||
|
|
||||||
|
file.write_all(b"-- DO NOT MODIFY, FILE IS AUTOMATICALLY GENERATED\n")?;
|
||||||
|
file.write_all(definitions.as_bytes())?;
|
||||||
|
|
||||||
|
// Make sure we have a trailing new line
|
||||||
|
if !definitions.ends_with("\n") {
|
||||||
|
file.write_all(b"\n")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn config_definitions() -> String {
|
||||||
|
let mut output = "---@meta\n\n".to_string();
|
||||||
|
|
||||||
|
output +=
|
||||||
|
&FulfillmentConfig::generate_full().expect("FulfillmentConfig should have a definition");
|
||||||
|
output += "\n";
|
||||||
|
output += &Config::generate_full().expect("FulfillmentConfig should have a definition");
|
||||||
|
|
||||||
|
output
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> std::io::Result<()> {
|
||||||
|
tracing_subscriber::fmt::init();
|
||||||
|
|
||||||
for module in inventory::iter::<Module> {
|
for module in inventory::iter::<Module> {
|
||||||
if let Some(definitions) = module.definitions() {
|
if let Some(definitions) = module.definitions() {
|
||||||
info!(name = module.get_name(), "Generating definitions");
|
info!(name = module.get_name(), "Generating definitions");
|
||||||
|
|
||||||
let filename = format!("{}.lua", module.get_name());
|
let filename = format!("{}.lua", module.get_name());
|
||||||
let mut file = File::create(definitions_directory.join(filename))?;
|
write_definitions(&filename, &definitions)?;
|
||||||
|
|
||||||
file.write_all(b"-- DO NOT MODIFY, FILE IS AUTOMATICALLY GENERATED\n")?;
|
|
||||||
file.write_all(definitions.as_bytes())?;
|
|
||||||
file.write_all(b"\n")?;
|
|
||||||
} else {
|
} else {
|
||||||
warn!(name = module.get_name(), "No definitions");
|
warn!(name = module.get_name(), "No definitions");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
write_definitions("config.lua", &config_definitions())?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::net::{Ipv4Addr, SocketAddr};
|
use std::net::{Ipv4Addr, SocketAddr};
|
||||||
|
|
||||||
|
use automation_lib::device::Device;
|
||||||
|
use automation_macro::LuaDeviceConfig;
|
||||||
|
use lua_typed::Typed;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
@@ -17,18 +20,22 @@ fn default_entrypoint() -> String {
|
|||||||
"./config.lua".into()
|
"./config.lua".into()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize, Typed)]
|
||||||
pub struct FulfillmentConfig {
|
pub struct FulfillmentConfig {
|
||||||
pub openid_url: String,
|
pub openid_url: String,
|
||||||
#[serde(default = "default_fulfillment_ip")]
|
#[serde(default = "default_fulfillment_ip")]
|
||||||
|
#[typed(default)]
|
||||||
pub ip: Ipv4Addr,
|
pub ip: Ipv4Addr,
|
||||||
#[serde(default = "default_fulfillment_port")]
|
#[serde(default = "default_fulfillment_port")]
|
||||||
|
#[typed(default)]
|
||||||
pub port: u16,
|
pub port: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, LuaDeviceConfig, Typed)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
pub fulfillment: FulfillmentConfig,
|
pub fulfillment: FulfillmentConfig,
|
||||||
|
#[device_config(from_lua, default)]
|
||||||
|
pub devices: Vec<Box<dyn Device>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<FulfillmentConfig> for SocketAddr {
|
impl From<FulfillmentConfig> for SocketAddr {
|
||||||
|
|||||||
4
src/lib.rs
Normal file
4
src/lib.rs
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
pub mod config;
|
||||||
|
pub mod secret;
|
||||||
|
pub mod version;
|
||||||
|
pub mod web;
|
||||||
Reference in New Issue
Block a user