426 lines
10 KiB
Lua
426 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 = IkeaOutlet.new({
|
|
name = "Mixer",
|
|
room = "Living Room",
|
|
topic = mqtt_z2m("living/mixer"),
|
|
client = mqtt_client,
|
|
})
|
|
automation.device_manager:add(living_mixer)
|
|
local living_speakers = IkeaOutlet.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 off_timeout(duration)
|
|
local timeout = Timeout.new()
|
|
|
|
return function(self, on)
|
|
if on then
|
|
timeout:start(duration, function()
|
|
self:set_on(false)
|
|
end)
|
|
else
|
|
timeout:cancel()
|
|
end
|
|
end
|
|
end
|
|
|
|
local kettle = IkeaOutlet.new({
|
|
outlet_type = "Kettle",
|
|
name = "Kettle",
|
|
room = "Kitchen",
|
|
topic = mqtt_z2m("kitchen/kettle"),
|
|
client = mqtt_client,
|
|
callback = off_timeout(debug and 5 or 300),
|
|
})
|
|
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,
|
|
}))
|
|
|
|
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(IkeaOutlet.new({
|
|
outlet_type = "Charger",
|
|
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(IkeaOutlet.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://airfilter.lan.huizinga.dev",
|
|
})
|
|
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)
|