From ab5ca9b1420c70485f45a2632d36425f458b3339 Mon Sep 17 00:00:00 2001 From: Ingolf Wagner Date: Tue, 14 Apr 2020 03:01:11 +0200 Subject: [PATCH] pepe: improved zigbee sensors and room logic --- configs/pepe/home-assistant.nix | 87 +++++-- configs/pepe/home-assistant/sonoff.nix | 4 +- configs/pepe/home-assistant/zigbee2mqtt.nix | 269 +++++++++++--------- modules/services/home-assistant.nix | 3 +- 4 files changed, 215 insertions(+), 148 deletions(-) diff --git a/configs/pepe/home-assistant.nix b/configs/pepe/home-assistant.nix index 1fcf891..c5ef633 100644 --- a/configs/pepe/home-assistant.nix +++ b/configs/pepe/home-assistant.nix @@ -33,54 +33,97 @@ in { prometheus.namespace = "hass"; - automation = [ + automation = let - # todo when ich weis ich bin zuhause - #{ - # alias = "Licht and wenn Dunkel"; - # trigger = { - # platform = "state"; - # entity_id = [ "binary_sensor.night" ]; - # from = "off"; - # to = "on"; - # }; - # action = [ - # { - # service = "switch.turn_on"; - # entity_id = "group.kitchen"; - # } - # { - # service = "switch.turn_on"; - # entity_id = "group.living_room"; - # } - # ]; - #} + presents = room_group: present_group: [ + { + alias = "presents -> turn on ${room_group} lights"; + trigger = { + platform = "state"; + entity_id = "group.${present_group}"; + from = "off"; + to = "on"; + }; + action = { + service = "switch.turn_on"; + entity_id = "group.${room_group}"; + }; + } + { + alias = "absents -> turn off ${room_group} lights"; + trigger = { + platform = "state"; + entity_id = "group.${present_group}"; + from = "on"; + to = "off"; + }; + action = { + service = "switch.turn_off"; + entity_id = "group.${room_group}"; + }; + } + + ]; + + in (presents "kitchen_room" "kitchen_room_present") + ++ (presents "living_room" "living_room_present") + ++ (presents "floor_room" "floor_room_present") + ++ (presents "bed_room" "bed_room_present") ++ [ ]; group = { # rooms # ----- + floor_room = { + name = "Flur"; + view = false; + }; + floor_room_present = { + control = "hidden"; + name = "Flur Anwesend"; + view = false; + }; bed_room = { name = "Schlafzimmer"; view = false; }; + bed_room_present = { + control = "hidden"; + name = "Schlafzimmer Anwesend"; + view = false; + }; living_room = { name = "Wohnzimmer"; view = false; }; + living_room_present = { + control = "hidden"; + name = "Wohnzimmer Anwesend"; + view = false; + }; kitchen_room = { name = "Küche"; view = false; }; + kitchen_room_present = { + control = "hidden"; + name = "Küche Anwesend"; + view = false; + }; view_rooms = { name = "Räume"; view = true; entities = [ "group.all_lights" + "group.floor_room" + "group.floor_room_present" "group.bed_room" + "group.bed_room_present" "group.living_room" + "group.living_room_present" "group.kitchen_room" + "group.kitchen_room_present" ]; }; @@ -108,7 +151,7 @@ in { view = false; }; all_lights = { - name = "All Lights"; + name = "Alle Lampen"; view = false; }; unknown = { diff --git a/configs/pepe/home-assistant/sonoff.nix b/configs/pepe/home-assistant/sonoff.nix index 2712a67..bc9fe04 100644 --- a/configs/pepe/home-assistant/sonoff.nix +++ b/configs/pepe/home-assistant/sonoff.nix @@ -9,9 +9,9 @@ let type = "light"; }; "pal02" = { - label = "Schlafzimmer Lampe Bett"; + label = "Flur Lampe"; icon = "mdi:lightbulb-on"; - room = "bed_room"; + room = "floor_room"; type = "light"; }; "pal03" = { diff --git a/configs/pepe/home-assistant/zigbee2mqtt.nix b/configs/pepe/home-assistant/zigbee2mqtt.nix index 7b9875e..68abe0f 100644 --- a/configs/pepe/home-assistant/zigbee2mqtt.nix +++ b/configs/pepe/home-assistant/zigbee2mqtt.nix @@ -9,30 +9,63 @@ let sensors = { buttons = { - "button_1".id = "0x00158d0002b04f65"; - "button_2".id = "0x00158d0002b04f09"; - "button_3".id = "0x00158d0002b00e04"; + "button_1" = { + id = "0x00158d0002b04f65"; + room = "living_room_present"; + }; + "button_2" = { + id = "0x00158d0002b04f09"; + room = "bed_room_present"; + }; + "button_3" = { + id = "0x00158d0002b00e04"; + room = "bed_room_present"; + }; }; temperature = { - "temperature_sensor_1".id = "0x00158d0002d79220"; - "temperature_sensor_2".id = "0x00158d0002d7913d"; + "temperature_sensor_1" = { + id = "0x00158d0002d79220"; + room = "living_room_present"; + }; + "temperature_sensor_2" = { + id = "0x00158d0002d7913d"; + room = "living_room_present"; + }; }; motion = { - "motion_sensor_1".id = "0x00158d0002fbd451"; - "motion_sensor_2".id = "0x00158d0002f9a6b8"; - "motion_sensor_3".id = "0x00158d0002f04522"; - "motion_sensor_4".id = "0x00158d0002f9a558"; - "motion_sensor_5".id = "0x00158d0002f9a56f"; - "motion_sensor_6".id = "0x00158d0002f9a5cb"; - "motion_sensor_7".id = "0x00158d0002f9a6aa"; - "motion_sensor_8".id = "0x00158d0002f04637"; + "motion_sensor_1" = { + id = "0x00158d0002fbd451"; + room = "kitchen_room_present"; + }; + "motion_sensor_2" = { + id = "0x00158d0002f9a6b8"; + room = "kitchen_room_present"; + }; + "motion_sensor_3" = { + id = "0x00158d0002f04522"; + room = "living_room_present"; + }; + "motion_sensor_4" = { + id = "0x00158d0002f9a558"; + room = "living_room_present"; + }; + "motion_sensor_5" = { + id = "0x00158d0002f9a56f"; + room = "floor_room_present"; + }; + "motion_sensor_6" = { + id = "0x00158d0002f9a5cb"; + room = "floor_room_present"; + }; + "motion_sensor_7" = { id = "0x00158d0002f9a6aa"; }; + "motion_sensor_8" = { id = "0x00158d0002f04637"; }; }; door = { - "door_sensor_1".id = "0x00158d000312dc52"; - "door_sensor_2".id = "0x00158d000316d5bf"; - "door_sensor_3".id = "0x00158d0002f9516f"; - "door_sensor_4".id = "0x00158d00031383b9"; - "door_sensor_5".id = "0x00158d0003120d3e"; + "door_sensor_1" = { id = "0x00158d000312dc52"; }; + "door_sensor_2" = { id = "0x00158d000316d5bf"; }; + "door_sensor_3" = { id = "0x00158d0002f9516f"; }; + "door_sensor_4" = { id = "0x00158d00031383b9"; }; + "door_sensor_5" = { id = "0x00158d0003120d3e"; }; }; }; @@ -83,6 +116,25 @@ in { services.homeAssistantConfig = { + # define input_boolean + # -------------------- + # which get toggled by the buttons + input_boolean = builtins.listToAttrs (lib.flatten (lib.mapAttrsToList (name: + { ... }: [ + { + name = "single_${name}"; + value = { icon = "mdi:radiobox-blank"; }; + } + { + name = "double_${name}"; + value = { icon = "mdi:radiobox-blank"; }; + } + { + name = "hold_${name}"; + value = { icon = "mdi:radiobox-blank"; }; + } + ]) sensors.buttons)); + # define sensors # -------------- sensor = let @@ -203,7 +255,12 @@ in { name = name; value = { control = "hidden"; - entities = [ "sensor.${name}" ] ++ (information name); + entities = [ + "sensor.${name}" + "input_boolean.single_${name}" + "input_boolean.double_${name}" + "input_boolean.hold_${name}" + ] ++ (information name); }; }) (sensors.buttons); @@ -248,8 +305,34 @@ in { }; }; - in views // sensorButtons // sensorMotions // sensorTemperature - // sensorDoors // { + # todo : make this more generic + # append to *_room_present group + flatMotionSensors = + lib.mapAttrsToList (name: values: { name = name; } // values) + sensors.motion; + motionAllRooms' = + lib.groupBy ({ room ? "unknown", ... }: room) flatMotionSensors; + motionAllRooms = lib.mapAttrs + (_: devices: map ({ name, ... }: "binary_sensor.${name}") devices) + motionAllRooms'; + + # todo : make this more generic + # append to *_room_present group + flatButtonSensors = + lib.mapAttrsToList (name: values: { name = name; } // values) + sensors.buttons; + buttonAllRooms' = + lib.groupBy ({ room ? "unknown", ... }: room) flatButtonSensors; + buttonAllRooms = lib.mapAttrs (_: devices: + map ({ name, ... }: "input_boolean.single_${name}") devices) + buttonAllRooms'; + + presentsAllRooms = + lib.mapAttrs (_: entities: { entities = lib.flatten entities; }) + (lib.zipAttrs [ buttonAllRooms motionAllRooms ]); + + in views // presentsAllRooms // sensorButtons // sensorMotions + // sensorTemperature // sensorDoors // { all_sensors.entities = (lib.mapAttrsToList (name: { ... }: "sensor.${name}") (sensors.buttons // sensors.temperature)) @@ -259,12 +342,45 @@ in { # create automation # ----------------- - # todo : this belongs in the home-assistant.nix automation = let - # hold, turn off the lights everywhere - all_lights_off = map (button: { - alias = "turn all lights off on holding a button"; + # single click + toggle_single_button_input = map (button: { + alias = "toggle hold ${button}"; + trigger = { + platform = "mqtt"; + topic = "zigbee2mqtt/${button}"; + }; + condition = { + condition = "template"; + value_template = ''{{ "single" == trigger.payload_json.click}}''; + }; + action = { + service = "input_boolean.toggle"; + data.entity_id = "input_boolean.single_${button}"; + }; + }) (builtins.attrNames sensors.buttons); + + # double click + toggle_double_button_input = map (button: { + alias = "toggle hold ${button}"; + trigger = { + platform = "mqtt"; + topic = "zigbee2mqtt/${button}"; + }; + condition = { + condition = "template"; + value_template = ''{{ "double" == trigger.payload_json.click}}''; + }; + action = { + service = "input_boolean.toggle"; + data.entity_id = "input_boolean.double_${button}"; + }; + }) (builtins.attrNames sensors.buttons); + + # hold + toggle_hold_button_input = map (button: { + alias = "toggle hold ${button}"; trigger = { platform = "mqtt"; topic = "zigbee2mqtt/${button}"; @@ -273,107 +389,14 @@ in { condition = "template"; value_template = ''{{ "hold" == trigger.payload_json.action }}''; }; - action = { service = "script.turn_all_off"; }; - }) [ "button_1" "button_2" "button_3" ]; - - # one click, turn on the light in the room - room_lights_on = map ({ button, room }: { - alias = "turn on lights in ${room}, on ${button} click"; - trigger = { - platform = "mqtt"; - topic = "zigbee2mqtt/${button}"; - }; - condition = { - condition = "template"; - value_template = ''{{ "single" == trigger.payload_json.click }}''; - }; action = { - service = "switch.turn_on"; - entity_id = "group.${room}"; + service = "input_boolean.toggle"; + data.entity_id = "input_boolean.hold_${button}"; }; - }) [ - { - button = "button_1"; - room = "living_room"; - } - { - button = "button_2"; - room = "bed_room"; - } - { - button = "button_3"; - room = "bed_room"; - } - ]; + }) (builtins.attrNames sensors.buttons); - # double click, turn off the light in the room - room_lights_off = map ({ button, room }: { - alias = "turn on lights in ${room}, on ${button} click"; - trigger = { - platform = "mqtt"; - topic = "zigbee2mqtt/${button}"; - }; - condition = { - condition = "template"; - value_template = ''{{ "double" == trigger.payload_json.click }}''; - }; - action = { - service = "switch.turn_off"; - entity_id = "group.${room}"; - }; - }) [ - { - button = "button_1"; - room = "living_room"; - } - { - button = "button_2"; - room = "bed_room"; - } - { - button = "button_3"; - room = "bed_room"; - } - ]; - - # kitchen light automation - # ------------------------ - # https://www.home-assistant.io/integrations/binary_sensor.template/ - kitchen_lights = map (motion: [ - { - alias = "turn on kitchen lights, on motion detected"; - trigger = { - platform = "state"; - entity_id = "binary_sensor.${motion}"; - from = "off"; - to = "on"; - }; - action = { - service = "switch.turn_on"; - entity_id = "group.kitchen_room"; - }; - } - { - alias = "turn off kitchen lights, on motion clear"; - trigger = { - platform = "state"; - entity_id = "binary_sensor.${motion}"; - from = "on"; - to = "off"; - }; - action = { - service = "switch.turn_off"; - entity_id = "group.kitchen_room"; - }; - } - ]) [ "motion_sensor_1" ]; - - in lib.flatten - (kitchen_lights ++ all_lights_off ++ room_lights_on ++ room_lights_off); - - # click = double => music an aus - - # click = hold => film an aus + in lib.flatten (toggle_single_button_input ++ toggle_double_button_input + ++ toggle_hold_button_input); }; diff --git a/modules/services/home-assistant.nix b/modules/services/home-assistant.nix index 991bad4..10b94d0 100644 --- a/modules/services/home-assistant.nix +++ b/modules/services/home-assistant.nix @@ -53,13 +53,14 @@ in { ''; }; entities = mkOption { + default = [ ]; type = with types; listOf str; description = '' (list)(Required)Array or comma delimited string, list of entities to group. ''; }; all = mkOption { - default = true; + default = false; type = with types; bool; description = '' (boolean)(Optional)Set this to true if the group state should only turn on if all grouped entities are on.