{ pkgs, lib, config, ... }: let # allow new devices to join enablePairing = true; device = "/dev/ttyACM0"; dataFolder = "/srv/zigbee/data"; sensors = { buttons = { "button_1".id = "0x00158d0002b04f65"; "button_2".id = "0x00158d0002b04f09"; "button_3".id = "0x00158d0002b00e04"; }; temperature = { "temperature_sensor_1".id = "0x00158d0002d79220"; "temperature_sensor_2".id = "0x00158d0002d7913d"; }; 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"; }; }; # todo : rename with allSensors allSensors = with sensors; buttons // temperature // motion; zigBee2MqttConfig = { # Home Assistant integration (MQTT discovery) homeassistant = false; # homeassistant = true; # allow new devices to join permit_join = enablePairing; # MQTT settings mqtt = { # MQTT base topic for zigbee2mqtt MQTT messages base_topic = "zigbee2mqtt"; # MQTT server URL server = "mqtt://127.0.0.1:1883"; # MQTT server authentication, uncomment if required: user = "zigbee"; password = lib.fileContents ; }; # Serial settings serial = { port = "/dev/ttyACM0"; # Optional: disable LED of CC2531 USB sniffer disable_led = true; }; devices = lib.mapAttrs' (name: { id, ... }: { name = id; value = { retain = false; friendly_name = name; }; }) allSensors; }; configurationYaml = pkgs.writeText "configuration.yml" (builtins.toJSON zigBee2MqttConfig); in { imports = [ ./mqtt.nix ]; services.homeAssistantConfig = { # group.unknown.entities = [ "sensor.button_1" ]; sensor = let buttons = with 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 }}"; }]) sensors.buttons; temperature = with lib; mapAttrsToList (name: { ... }: [ { platform = "mqtt"; name = name; state_topic = "zigbee2mqtt/${name}"; availability_topic = "zigbee2mqtt/bridge/state"; unit_of_measurement = "°C"; device_class = "temperature"; value_template = "{{ value_json.temperature }}"; } { platform = "mqtt"; name = "humidity_${name}"; state_topic = "zigbee2mqtt/${name}"; availability_topic = "zigbee2mqtt/bridge/state"; unit_of_measurement = "%"; device_class = "humidity"; value_template = "{{ value_json.humidity }}"; } { platform = "mqtt"; name = "pressure_${name}"; state_topic = "zigbee2mqtt/${name}"; availability_topic = "zigbee2mqtt/bridge/state"; unit_of_measurement = "hPa"; device_class = "pressure"; value_template = "{{ value_json.pressure }}"; } ]) sensors.temperature; informations = lib.mapAttrsToList (name: { ... }: [ { 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 }}"; } ]) allSensors; in lib.flatten (buttons ++ temperature ++ informations); binary_sensor = let motion = 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 }}"; }) sensors.motion; in lib.flatten (motion); group = let information = name: [ "sensor.battery_${name}" "sensor.link_${name}" ]; sensor = lib.mapAttrs' (name: { ... }: { name = name; value = { control = "hidden"; entities = [ "sensor.${name}" ] ++ (information name); }; }) (sensors.buttons); sensorTemperature = lib.mapAttrs' (name: { ... }: { name = name; value = { control = "hidden"; entities = [ "sensor.${name}" "sensor.humidity_${name}" "sensor.pressure_${name}" ] ++ (information name); }; }) (sensors.temperature); binarySensor = lib.mapAttrs' (name: { ... }: { name = name; value = { control = "hidden"; entities = [ "binary_sensor.${name}" ] ++ (information name); }; }) (sensors.motion); views = { view_sensors = { name = "Sensoren"; control = "hidden"; view = true; entities = lib.mapAttrsToList (name: { ... }: "group.${name}") allSensors; }; }; in views // sensor // binarySensor // sensorTemperature; automation = let lights = map (button: { alias = "Toggle all lights, on click"; trigger = { platform = "mqtt"; topic = "zigbee2mqtt/${button}"; }; condition = { condition = "template"; value_template = ''{{ "single" == trigger.payload_json.click }}''; }; action = { service = "switch.toggle"; entity_id = "group.all_lights"; }; }) [ "button_1" "button_2" "button_3" ]; #mpd = map (button: { # alias = "Toggle mpd, on double click"; # trigger = { # platform = "mqtt"; # topic = "zigbee2mqtt/${button}"; # }; # condition = { # condition = "template"; # value_template = ''{{ "double" == trigger.payload_json.click }}''; # }; # action = { # service = "media_player.toggle"; # # todo use a group here # entity_id = "media_player.mpd"; # }; #}) [ "button_1" "button_2" "button_3" ]; # https://www.home-assistant.io/integrations/binary_sensor.template/ kitchen_lights = map (motion: [ { alias = "turn on lights, on motion"; trigger = { platform = "state"; entity_id = "binary_sensor.${motion}"; from = "off"; to = "on"; }; action = { service = "switch.turn_on"; entity_id = "group.kitchen"; }; } { alias = "turn off lights, on no motion"; trigger = { platform = "state"; entity_id = "binary_sensor.${motion}"; from = "on"; to = "off"; }; action = { service = "switch.turn_off"; entity_id = "group.kitchen"; }; } ]) [ "motion_sensor_1" ]; in lib.flatten (lights ++ kitchen_lights); # click = double => music an aus # click = hold => film an aus }; virtualisation.docker.enable = true; # todo : einen eigenen container bauen mit dockerTool : https://nixos.wiki/wiki/Docker systemd.services."zigbee2mqtt" = { enable = true; description = "Allows you to use your Zigbee devices without the vendors bridge/gateway."; after = [ "docker.service" ]; requires = [ "docker.service" ]; # todo : udev rule erstellen, die diesen service erst startet, dieses wanted by ist labil wantedBy = [ "home-assistant.service" ]; preStart = '' if [ -f ${dataFolder}/configuration.yaml ] then rm ${dataFolder}/configuration.yaml fi mkdir -p ${dataFolder} cat ${configurationYaml} | ${pkgs.yq}/bin/yq --yaml-output '.' > ${dataFolder}/configuration.yaml ''; restartTriggers = [ configurationYaml ]; script = '' # delete old instance to ensure update ${pkgs.docker}/bin/docker stop zigbee2mqtt || true && ${pkgs.docker}/bin/docker rm -f zigbee2mqtt || true # start instance ${pkgs.docker}/bin/docker run \ --network="host" \ --name zigbee2mqtt \ -v ${dataFolder}:/app/data \ --device=${device} \ koenkk/zigbee2mqtt ''; }; }