diff --git a/configs/pepe/home-assistant.nix b/configs/pepe/home-assistant.nix index 127dfb3..0c3c831 100644 --- a/configs/pepe/home-assistant.nix +++ b/configs/pepe/home-assistant.nix @@ -33,6 +33,8 @@ in { prometheus.namespace = "hass"; + input_boolean.bed_room_buttons.icon = "mdi:toggle-switch"; + automation = let # todo : at night only turn trigger essential groups presents = room_group: present_group: [ @@ -71,7 +73,7 @@ in { ]; group = let - create_room = { name, description }: { + create_room = { name, description, presentEntities ? [ ] }: { "${name}" = { name = description; view = false; @@ -81,6 +83,7 @@ in { control = "hidden"; name = "${description} Anwesend"; view = false; + entities = presentEntities; }; "${name}_essential" = { control = "hidden"; diff --git a/configs/pepe/home-assistant/zigbee2mqtt.nix b/configs/pepe/home-assistant/zigbee2mqtt.nix index 80a410d..2930921 100644 --- a/configs/pepe/home-assistant/zigbee2mqtt.nix +++ b/configs/pepe/home-assistant/zigbee2mqtt.nix @@ -11,15 +11,20 @@ let buttons = { "button_1" = { id = "0x00158d0002b04f65"; + # room = "living_room"; # is where it actually is placed (optional) (default "unknown") + # presents = "living_room_present" # presents group to append (optional) (default "unknown") + # states = { click = "input_boolean.living_room_button"; } # input state to hold (optional) (default "input_boolean.single_${name}") room = "living_room_present"; }; "button_2" = { id = "0x00158d0002b04f09"; room = "bed_room_present"; + states.single = "input_boolean.bed_room_buttons"; }; "button_3" = { id = "0x00158d0002b00e04"; room = "bed_room_present"; + states.single = "input_boolean.bed_room_buttons"; }; }; temperature = { @@ -65,9 +70,15 @@ let }; door = { "door_sensor_1" = { id = "0x00158d000312dc52"; }; - "door_sensor_2" = { id = "0x00158d000316d5bf"; }; + "door_sensor_2" = { + id = "0x00158d000316d5bf"; + room = "floor_room_present"; + }; "door_sensor_3" = { id = "0x00158d0002f9516f"; }; - "door_sensor_4" = { id = "0x00158d00031383b9"; }; + "door_sensor_4" = { + id = "0x00158d00031383b9"; + room = "floor_room_present"; + }; "door_sensor_5" = { id = "0x00158d0003120d3e"; }; }; }; @@ -122,21 +133,22 @@ in { # define input_boolean # -------------------- # which get toggled by the buttons - input_boolean = builtins.listToAttrs (lib.flatten (lib.mapAttrsToList (name: - { ... }: [ - { + input_boolean = let stripEmpty = lib.filter (a: a != { }); + in builtins.listToAttrs (stripEmpty (lib.flatten (lib.mapAttrsToList (name: + { states ? { }, ... }: [ + (lib.optionalAttrs (!lib.hasAttr "single" states) { name = "single_${name}"; - value = { icon = "mdi:radiobox-blank"; }; - } - { + value = { icon = "mdi:toggle-switch"; }; + }) + (lib.optionalAttrs (!lib.hasAttr "double" states) { name = "double_${name}"; - value = { icon = "mdi:radiobox-blank"; }; - } - { + value = { icon = "mdi:toggle-switch"; }; + }) + (lib.optionalAttrs (!lib.hasAttr "hold" states) { name = "hold_${name}"; - value = { icon = "mdi:radiobox-blank"; }; - } - ]) sensors.buttons)); + value = { icon = "mdi:toggle-switch"; }; + }) + ]) sensors.buttons))); # define sensors # -------------- @@ -254,16 +266,21 @@ in { information = name: [ "sensor.battery_${name}" "sensor.link_${name}" ]; sensorButtons = lib.mapAttrs' (name: - { ... }: { + { states ? { }, ... }: + let + entityIds = { single ? "input_boolean.single_${name}" + , double ? "input_boolean.double_${name}" + , hold ? "input_boolean.hold_${name}", ... }: [ + single + double + hold + ]; + in { name = name; value = { control = "hidden"; - entities = [ - "sensor.${name}" - "input_boolean.single_${name}" - "input_boolean.double_${name}" - "input_boolean.hold_${name}" - ] ++ (information name); + entities = [ "sensor.${name}" ] ++ (entityIds states) + ++ (information name); }; }) (sensors.buttons); @@ -308,33 +325,41 @@ in { }; }; - # 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'; + # sort sensors in room groups + # --------------------------- + allRoomsGroups = let + createGroupEntities = { sensors, entityNameing }: + let + flatSensors = + lib.mapAttrsToList (name: values: { name = name; } // values) + sensors; + allRooms' = + lib.groupBy ({ room ? "unknown", ... }: room) flatSensors; + allRooms = + lib.mapAttrs (_: devices: map entityNameing devices) allRooms'; + in allRooms; + groupEntries = { + motionGroups = createGroupEntities { + sensors = sensors.motion; + entityNameing = ({ name, ... }: "binary_sensor.${name}"); + }; + buttonGroups = createGroupEntities { + sensors = sensors.buttons; + entityNameing = ({ name + , states ? { single = "input_boolean.single_${name}"; }, ... }: + states.single); + }; + doorGroups = createGroupEntities { + sensors = sensors.door; + entityNameing = ({ name, ... }: "binary_sensor.${name}"); + }; + }; - # 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'; + # merge all group entries + in lib.mapAttrs (_: entities: { entities = lib.flatten entities; }) + (lib.zipAttrs (builtins.attrValues groupEntries)); - presentsAllRooms = - lib.mapAttrs (_: entities: { entities = lib.flatten entities; }) - (lib.zipAttrs [ buttonAllRooms motionAllRooms ]); - - in views // presentsAllRooms // sensorButtons // sensorMotions + in views // allRoomsGroups // sensorButtons // sensorMotions // sensorTemperature // sensorDoors // { all_sensors.entities = (lib.mapAttrsToList (name: { ... }: "sensor.${name}") @@ -348,55 +373,76 @@ in { automation = let # 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); + toggle_single_button_input = lib.mapAttrsToList (name: + { states ? { }, ... }: + let + entityId = if (lib.hasAttr "single" states) then + states.single + else + "input_boolean.single_${name}"; + in { + alias = "toggle single click ${name}"; + trigger = { + platform = "mqtt"; + topic = "zigbee2mqtt/${name}"; + }; + condition = { + condition = "template"; + value_template = ''{{ "single" == trigger.payload_json.click}}''; + }; + action = { + service = "input_boolean.toggle"; + data.entity_id = entityId; + }; + }) 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); + toggle_double_button_input = lib.mapAttrsToList (name: + { states ? { }, ... }: + let + entityId = if (lib.hasAttr "double" states) then + states.double + else + "input_boolean.double_${name}"; + in { + alias = "toggle double click ${name}"; + trigger = { + platform = "mqtt"; + topic = "zigbee2mqtt/${name}"; + }; + condition = { + condition = "template"; + value_template = ''{{ "double" == trigger.payload_json.click}}''; + }; + action = { + service = "input_boolean.toggle"; + data.entity_id = entityId; + }; + }) sensors.buttons; # hold - toggle_hold_button_input = map (button: { - alias = "toggle hold ${button}"; - trigger = { - platform = "mqtt"; - topic = "zigbee2mqtt/${button}"; - }; - condition = { - condition = "template"; - value_template = ''{{ "hold" == trigger.payload_json.action }}''; - }; - action = { - service = "input_boolean.toggle"; - data.entity_id = "input_boolean.hold_${button}"; - }; - }) (builtins.attrNames sensors.buttons); + toggle_hold_button_input = lib.mapAttrsToList (name: + { states ? { }, ... }: + let + entityId = if (lib.hasAttr "hold" states) then + states.hold + else + "input_boolean.hold_${name}"; + in { + alias = "toggle hold ${name}"; + trigger = { + platform = "mqtt"; + topic = "zigbee2mqtt/${name}"; + }; + condition = { + condition = "template"; + value_template = ''{{ "hold" == trigger.payload_json.action}}''; + }; + action = { + service = "input_boolean.toggle"; + data.entity_id = entityId; + }; + }) sensors.buttons; in lib.flatten (toggle_single_button_input ++ toggle_double_button_input ++ toggle_hold_button_input);