automation_rs/config.lua
Dreaded_X fbabc978b1
All checks were successful
Build and deploy / Build application (push) Successful in 4m15s
Build and deploy / Build container (push) Successful in 1m16s
Build and deploy / Deploy container (push) Successful in 19s
Reworked IkeaOutlet into more generic outlet that also (optionally) supports power measurement
This new power measurement feature is used to turn the kettle off
automatically once it is done boiling
2025-01-26 04:48:59 +01:00

440 lines
10 KiB
Lua

print("Hello from lua")
local host = automation.util.get_hostname()
print("Running @" .. host)
local debug, value = pcall(automation.util.get_env, "DEBUG")
if debug and value ~= "true" then
debug = false
end
local function mqtt_z2m(topic)
return "zigbee2mqtt/" .. topic
end
local function mqtt_automation(topic)
return "automation/" .. topic
end
automation.fulfillment = {
openid_url = "https://login.huizinga.dev/api/oidc",
}
local mqtt_client = automation.new_mqtt_client({
host = ((host == "zeus" or host == "hephaestus") and "olympus.lan.huizinga.dev") or "mosquitto",
port = 8883,
client_name = "automation-" .. host,
username = "mqtt",
password = automation.util.get_env("MQTT_PASSWORD"),
tls = host == "zeus" or host == "hephaestus",
})
automation.device_manager:add(Ntfy.new({
topic = automation.util.get_env("NTFY_TOPIC"),
event_channel = automation.device_manager:event_channel(),
}))
automation.device_manager:add(Presence.new({
topic = mqtt_automation("presence/+/#"),
client = mqtt_client,
event_channel = automation.device_manager:event_channel(),
}))
automation.device_manager:add(DebugBridge.new({
identifier = "debug_bridge",
topic = mqtt_automation("debug"),
client = mqtt_client,
}))
local hue_ip = "10.0.0.102"
local hue_token = automation.util.get_env("HUE_TOKEN")
automation.device_manager:add(HueBridge.new({
identifier = "hue_bridge",
ip = hue_ip,
login = hue_token,
flags = {
presence = 41,
darkness = 43,
},
}))
automation.device_manager:add(LightSensor.new({
identifier = "living_light_sensor",
topic = mqtt_z2m("living/light"),
client = mqtt_client,
min = 22000,
max = 23500,
event_channel = automation.device_manager:event_channel(),
}))
automation.device_manager:add(WakeOnLAN.new({
name = "Zeus",
room = "Living Room",
topic = mqtt_automation("appliance/living_room/zeus"),
client = mqtt_client,
mac_address = "30:9c:23:60:9c:13",
broadcast_ip = "10.0.3.255",
}))
-- TODO: Update this to 10.0.0.101 when DHCP want to finally work
local living_mixer = OutletOnOff.new({
name = "Mixer",
room = "Living Room",
topic = mqtt_z2m("living/mixer"),
client = mqtt_client,
})
automation.device_manager:add(living_mixer)
local living_speakers = OutletOnOff.new({
name = "Speakers",
room = "Living Room",
topic = mqtt_z2m("living/speakers"),
client = mqtt_client,
})
automation.device_manager:add(living_speakers)
automation.device_manager:add(IkeaRemote.new({
name = "Remote",
room = "Living Room",
client = mqtt_client,
topic = mqtt_z2m("living/remote"),
single_button = true,
callback = function(_, on)
if on then
if living_mixer:on() then
living_mixer:set_on(false)
living_speakers:set_on(false)
else
living_mixer:set_on(true)
living_speakers:set_on(true)
end
else
if not living_mixer:on() then
living_mixer:set_on(true)
else
living_speakers:set_on(not living_speakers:on())
end
end
end,
}))
local function kettle_timeout()
local timeout = Timeout.new()
return function(self, state)
if state.state and state.power < 100 then
timeout:start(3, function()
self:set_on(false)
end)
else
timeout:cancel()
end
end
end
local kettle = OutletPower.new({
outlet_type = "Kettle",
name = "Kettle",
room = "Kitchen",
topic = mqtt_z2m("kitchen/kettle"),
client = mqtt_client,
callback = kettle_timeout(),
})
automation.device_manager:add(kettle)
local function set_kettle(_, on)
kettle:set_on(on)
end
automation.device_manager:add(IkeaRemote.new({
name = "Remote",
room = "Bedroom",
client = mqtt_client,
topic = mqtt_z2m("bedroom/remote"),
single_button = true,
callback = set_kettle,
}))
automation.device_manager:add(IkeaRemote.new({
name = "Remote",
room = "Kitchen",
client = mqtt_client,
topic = mqtt_z2m("kitchen/remote"),
single_button = true,
callback = set_kettle,
}))
local function off_timeout(duration)
local timeout = Timeout.new()
return function(self, state)
if state.state then
timeout:start(duration, function()
self:set_on(false)
end)
else
timeout:cancel()
end
end
end
automation.device_manager:add(LightOnOff.new({
name = "Light",
room = "Bathroom",
topic = mqtt_z2m("bathroom/light"),
client = mqtt_client,
callback = off_timeout(debug and 60 or 45 * 60),
}))
automation.device_manager:add(Washer.new({
identifier = "bathroom_washer",
topic = mqtt_z2m("bathroom/washer"),
client = mqtt_client,
threshold = 1,
event_channel = automation.device_manager:event_channel(),
}))
automation.device_manager:add(OutletOnOff.new({
presence_auto_off = false,
name = "Charger",
room = "Workbench",
topic = mqtt_z2m("workbench/charger"),
client = mqtt_client,
callback = off_timeout(debug and 5 or 20 * 3600),
}))
automation.device_manager:add(OutletOnOff.new({
name = "Outlet",
room = "Workbench",
topic = mqtt_z2m("workbench/outlet"),
client = mqtt_client,
}))
local workbench_light = LightBrightness.new({
name = "Light",
room = "Workbench",
topic = mqtt_z2m("workbench/light"),
client = mqtt_client,
})
automation.device_manager:add(workbench_light)
automation.device_manager:add(IkeaRemote.new({
name = "Remote",
room = "Workbench",
client = mqtt_client,
topic = mqtt_z2m("workbench/remote"),
callback = function(_, on)
workbench_light:set_on(on)
end,
}))
local hallway_top_light = HueGroup.new({
identifier = "hallway_top_light",
ip = hue_ip,
login = hue_token,
group_id = 83,
scene_id = "QeufkFDICEHWeKJ7",
client = mqtt_client,
})
automation.device_manager:add(HueSwitch.new({
name = "SwitchBottom",
room = "Hallway",
client = mqtt_client,
topic = mqtt_z2m("hallway/switchbottom"),
left_callback = function()
hallway_top_light:set_on(not hallway_top_light:on())
end,
}))
automation.device_manager:add(HueSwitch.new({
name = "SwitchTop",
room = "Hallway",
client = mqtt_client,
topic = mqtt_z2m("hallway/switchtop"),
left_callback = function()
hallway_top_light:set_on(not hallway_top_light:on())
end,
}))
local hallway_light_automation = {
timeout = Timeout.new(),
forced = false,
switch_callback = function(self, on)
self.timeout:cancel()
self.group.set_on(on)
self.forced = on
end,
door_callback = function(self, open)
if open then
self.timeout:cancel()
self.group.set_on(true)
elseif not self.forced then
self.timeout:start(debug and 10 or 2 * 60, function()
if self.trash:open_percent() == 0 then
self.group.set_on(false)
end
end)
end
end,
trash_callback = function(self, open)
if open then
self.group.set_on(true)
else
if not self.timeout:is_waiting() and self.door:open_percent() == 0 and not self.forced then
self.group.set_on(false)
end
end
end,
light_callback = function(self, on)
if on and self.trash:open_percent() == 0 and self.door:open_percent() == 0 then
-- If the door and trash are not open, that means the light got turned on manually
self.timeout:cancel()
self.forced = true
elseif not on then
-- The light is never forced when it is off
self.forced = false
end
end,
}
local hallway_storage = LightBrightness.new({
name = "Storage",
room = "Hallway",
topic = mqtt_z2m("hallway/storage"),
client = mqtt_client,
callback = function(_, state)
hallway_light_automation:light_callback(state.state)
end,
})
automation.device_manager:add(hallway_storage)
local hallway_bottom_lights = HueGroup.new({
identifier = "hallway_bottom_lights",
ip = hue_ip,
login = hue_token,
group_id = 81,
scene_id = "3qWKxGVadXFFG4o",
client = mqtt_client,
})
automation.device_manager:add(hallway_bottom_lights)
hallway_light_automation.group = {
set_on = function(on)
if on then
hallway_storage:set_brightness(80)
else
hallway_storage:set_on(false)
end
hallway_bottom_lights:set_on(on)
end,
}
automation.device_manager:add(IkeaRemote.new({
name = "Remote",
room = "Hallway",
client = mqtt_client,
topic = mqtt_z2m("hallway/remote"),
callback = function(_, on)
hallway_light_automation:switch_callback(on)
end,
}))
local hallway_frontdoor = ContactSensor.new({
name = "Frontdoor",
room = "Hallway",
sensor_type = "Door",
topic = mqtt_z2m("hallway/frontdoor"),
client = mqtt_client,
presence = {
topic = mqtt_automation("presence/contact/frontdoor"),
timeout = debug and 10 or 15 * 60,
},
callback = function(_, open)
hallway_light_automation:door_callback(open)
end,
})
automation.device_manager:add(hallway_frontdoor)
hallway_light_automation.door = hallway_frontdoor
local hallway_trash = ContactSensor.new({
name = "Trash",
room = "Hallway",
sensor_type = "Drawer",
topic = mqtt_z2m("hallway/trash"),
client = mqtt_client,
callback = function(_, open)
hallway_light_automation:trash_callback(open)
end,
})
automation.device_manager:add(hallway_trash)
hallway_light_automation.trash = hallway_trash
automation.device_manager:add(LightOnOff.new({
name = "Light",
room = "Guest Room",
topic = mqtt_z2m("guest/light"),
client = mqtt_client,
}))
local bedroom_air_filter = AirFilter.new({
name = "Air Filter",
room = "Bedroom",
url = "http://10.0.1.245",
})
automation.device_manager:add(bedroom_air_filter)
automation.device_manager:add(ContactSensor.new({
name = "Balcony",
room = "Living Room",
sensor_type = "Door",
topic = mqtt_z2m("living/balcony"),
client = mqtt_client,
}))
automation.device_manager:add(ContactSensor.new({
name = "Window",
room = "Living Room",
topic = mqtt_z2m("living/window"),
client = mqtt_client,
}))
automation.device_manager:add(ContactSensor.new({
name = "Window",
room = "Bedroom",
topic = mqtt_z2m("bedroom/window"),
client = mqtt_client,
}))
automation.device_manager:add(ContactSensor.new({
name = "Window",
room = "Guest Room",
topic = mqtt_z2m("guest/window"),
client = mqtt_client,
}))
local storage_light = LightBrightness.new({
name = "Light",
room = "Storage",
topic = mqtt_z2m("storage/light"),
client = mqtt_client,
})
automation.device_manager:add(storage_light)
automation.device_manager:add(ContactSensor.new({
name = "Door",
room = "Storage",
sensor_type = "Door",
topic = mqtt_z2m("storage/door"),
client = mqtt_client,
callback = function(_, open)
if open then
storage_light:set_brightness(100)
else
storage_light:set_on(false)
end
end,
}))
automation.device_manager:schedule("0 0 19 * * *", function()
bedroom_air_filter:set_on(true)
end)
automation.device_manager:schedule("0 0 20 * * *", function()
bedroom_air_filter:set_on(false)
end)