This new power measurement feature is used to turn the kettle off automatically once it is done boiling
440 lines
10 KiB
Lua
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)
|