{ pkgs, lib, ... }: let # we create 3 input_boolean which get toggled by the 3 types of buttons pressed. # input_boolean.single_${name} : single click # input_boolean.double_${name} : double click # input_boolean.hold_${name} : hold # if you override these input (via states) you have to create the input yourself # https://www.zigbee2mqtt.io/devices/WXKG12LM.html allDevices = { "button_a1" = { id = "0x00158d0002b04f65"; #groups = [ "living_room" ]; states.single = "input_boolean.situation_toggle"; states.hold = "input_boolean.printer_toggle"; states.double = "input_boolean.windows_up"; }; "button_a2" = { id = "0x00158d0002b04f09"; #groups = [ "bed_room" ]; states.single = "input_boolean.situation_toggle"; states.hold = "input_boolean.printer_toggle"; states.double = "input_boolean.windows_up"; }; "button_a3" = { id = "0x00158d0002b00e04"; #groups = [ "bed_room" ]; states.single = "input_boolean.situation_toggle"; states.hold = "input_boolean.printer_toggle"; states.double = "input_boolean.windows_up"; }; }; in { services.zigbee2mqttConfiguration = lib.mapAttrs' (name: { id, ... }: { name = id; value = { retain = false; friendly_name = name; }; }) allDevices; services.homeAssistantConfig = { # define input_boolean # -------------------- # which get toggled by the buttons 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:toggle-switch"; }; }) (lib.optionalAttrs (!lib.hasAttr "double" states) { name = "double_${name}"; value = { icon = "mdi:toggle-switch"; }; }) (lib.optionalAttrs (!lib.hasAttr "hold" states) { name = "hold_${name}"; value = { icon = "mdi:toggle-switch"; }; }) ]) allDevices))); # define meta information sensors sensor = lib.flatten (lib.mapAttrsToList (name: { ... }: [ { platform = "mqtt"; name = name; icon = "mdi:toggle-switch"; state_topic = "zigbee2mqtt/${name}"; availability_topic = "zigbee2mqtt/bridge/state"; value_template = "{{ value_json.click }}"; } { name = "battery_${name}"; platform = "mqtt"; state_topic = "zigbee2mqtt/${name}"; availability_topic = "zigbee2mqtt/bridge/state"; unit_of_measurement = "%"; icon = "mdi:battery-10"; value_template = "{{ value_json.battery }}"; } { name = "link_${name}"; platform = "mqtt"; state_topic = "zigbee2mqtt/${name}"; availability_topic = "zigbee2mqtt/bridge/state"; icon = "mdi:signal"; unit_of_measurement = "lqi"; value_template = "{{ value_json.linkquality }}"; } ]) allDevices); binary_sensor = lib.mapAttrsToList (name: { ... }: { name = name; platform = "mqtt"; device_class = "motion"; state_topic = "zigbee2mqtt/${name}"; availability_topic = "zigbee2mqtt/bridge/state"; payload_on = true; payload_off = false; value_template = "{{ value_json.occupancy }}"; }) allDevices; # create groups # ------------- #group = let # # to have nice panels for every device # sensorGroups = 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 { # entities = [ "sensor.${name}" ] ++ (entityIds states) # ++ [ "sensor.battery_${name}" "sensor.link_${name}" ]; # }) allDevices; # # sort lights into given groups. # sortedInGroups = let # groupEntries = lib.zipAttrs (lib.flatten (lib.mapAttrsToList (name: # { groups ? [ ], states ? { }, ... }: # map (groupName: { # "${groupName}" = if (lib.hasAttr "single" states) then # states.single # else # "input_boolean.single_${name}"; # }) groups) allDevices)); # in lib.mapAttrs (name: entities: { inherit entities; }) groupEntries; #in sortedInGroups // sensorGroups // { # all_sensors.entities = # lib.mapAttrsToList (name: { ... }: "binary_sensor.${name}") allDevices; #}; # create automation # ----------------- automation = let # single click 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; }; }) allDevices; # double click 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; }; }) allDevices; # hold 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; }; }) allDevices; in lib.flatten (toggle_single_button_input ++ toggle_double_button_input ++ toggle_hold_button_input); }; }