summaryrefslogtreecommitdiffstats
path: root/lass/2configs/hass
diff options
context:
space:
mode:
Diffstat (limited to 'lass/2configs/hass')
-rw-r--r--lass/2configs/hass/default.nix106
-rw-r--r--lass/2configs/hass/lib.nix263
-rw-r--r--lass/2configs/hass/rooms/bett.nix8
-rw-r--r--lass/2configs/hass/rooms/essen.nix9
-rw-r--r--lass/2configs/hass/rooms/nass.nix10
-rw-r--r--lass/2configs/hass/zigbee.nix151
6 files changed, 547 insertions, 0 deletions
diff --git a/lass/2configs/hass/default.nix b/lass/2configs/hass/default.nix
new file mode 100644
index 000000000..639ba3d3f
--- /dev/null
+++ b/lass/2configs/hass/default.nix
@@ -0,0 +1,106 @@
+{ config, lib, pkgs, ... }:
+with import ./lib.nix { inherit lib; };
+
+{
+ imports = [
+ ./zigbee.nix
+ ./rooms/bett.nix
+ ./rooms/essen.nix
+ ./rooms/nass.nix
+ ];
+
+ krebs.iptables.tables.filter.INPUT.rules = [
+ { predicate = "-i int0 -p tcp --dport 1883"; target = "ACCEPT"; } # mosquitto
+ { predicate = "-i docker0 -p tcp --dport 1883"; target = "ACCEPT"; } # mosquitto
+ { predicate = "-i int0 -p tcp --dport 8123"; target = "ACCEPT"; } # hass
+ { predicate = "-i retiolum -p tcp --dport 8123"; target = "ACCEPT"; } # hass
+ ];
+
+ services.home-assistant = {
+ enable = true;
+ package = pkgs.home-assistant.override {
+ # extraComponents = [ "hue" ];
+ };
+ configWritable = true;
+ };
+
+ lass.hass.config = let
+ tasmota_s20 = name: topic: {
+ platform = "mqtt";
+ inherit name;
+ state_topic = "stat/${topic}/POWER";
+ command_topic = "cmnd/${topic}/POWER";
+ payload_on = "ON";
+ payload_off = "OFF";
+ };
+ in {
+ homeassistant = {
+ name = "Home";
+ time_zone = "Europe/Berlin";
+ latitude = "52.46187";
+ longitude = "13.41489";
+ elevation = 90;
+ unit_system = "metric";
+ customize = friendly_names;
+ };
+ config = {};
+ sun.elevation = 66;
+ discovery = {};
+ frontend = {};
+ mqtt = {
+ broker = "localhost";
+ port = 1883;
+ client_id = "home-assistant";
+ username = "gg23";
+ password = "gg23-mqtt";
+ keepalive = 60;
+ protocol = 3.1;
+
+ discovery = true;
+ birth_message = {
+ topic = "/hass/status";
+ payload = "online";
+ };
+ will_message = {
+ topic = "/hass/status";
+ payload = "offline";
+ };
+ };
+ sensor = [
+ {
+ platform = "dwd_weather_warnings";
+ region_name = "Berlin";
+ }
+ ];
+ switch = [
+ (tasmota_s20 "TV" "tv")
+ (tasmota_s20 "Drucker Strom" "drucker")
+ (tasmota_s20 "Waschmaschine" "wasch")
+ (tasmota_s20 "Stereo Anlage" "stereo")
+ ];
+ mobile_app = {};
+ hue = {};
+ weather = [
+ {
+ platform = "openweathermap";
+ api_key = "xxx"; # TODO put into secrets
+ }
+ ];
+ system_health = {};
+ history = {};
+ shopping_list = {};
+ };
+
+ services.mosquitto = {
+ enable = true;
+ host = "0.0.0.0";
+ allowAnonymous = false;
+ checkPasswords = true;
+ users.gg23 = {
+ password = "gg23-mqtt";
+ acl = [ "topic readwrite #" ];
+ };
+ };
+
+ environment.systemPackages = [ pkgs.mosquitto ];
+}
diff --git a/lass/2configs/hass/lib.nix b/lass/2configs/hass/lib.nix
new file mode 100644
index 000000000..555cfae28
--- /dev/null
+++ b/lass/2configs/hass/lib.nix
@@ -0,0 +1,263 @@
+{ lib, ... }:
+rec {
+ lights = {
+ bett = "0x0017880106ed3bd8";
+ essen = "0x0017880108327622";
+ arbeit = "0x0017880106ee2865";
+ nass = "0x00178801082e9f2f";
+ };
+
+ switches = {
+ dimmer = {
+ bett = "0x00178801086ac38c";
+ essen = "0x00178801086ad1fb";
+ nass = "0x00178801086ac373";
+ };
+ };
+
+ sensors = {
+ movement = {
+ essen = "0x0017880106f772f2";
+ nass = "0x0017880106f77f30";
+ };
+ };
+
+ friendly_names =
+ lib.mapAttrs' (n: v: lib.nameValuePair "light.${v}_light" { friendly_name = "l.${n}"; }) lights //
+ lib.mapAttrs' (n: v: lib.nameValuePair "binary_sensor.${v}_update_available" { friendly_name = "s.${n}_up"; }) switches.dimmer //
+ lib.mapAttrs' (n: v: lib.nameValuePair "binary_sensor.${v}_update_available" { friendly_name = "i.${n}_up"; }) sensors.movement //
+ lib.mapAttrs' (n: v: lib.nameValuePair "binary_sensor.${v}_update_available" { friendly_name = "l.${n}_up"; }) lights //
+ lib.mapAttrs' (n: v: lib.nameValuePair "sensor.${v}_linkquality" { friendly_name = "s.${n}_link"; }) switches.dimmer //
+ lib.mapAttrs' (n: v: lib.nameValuePair "sensor.${v}_linkquality" { friendly_name = "i.${n}_link"; }) sensors.movement //
+ lib.mapAttrs' (n: v: lib.nameValuePair "sensor.${v}_linkquality" { friendly_name = "l.${n}_link"; }) lights //
+ lib.mapAttrs' (n: v: lib.nameValuePair "sensor.${v}_battery" { friendly_name = "s.${n}_bat"; }) switches.dimmer //
+ lib.mapAttrs' (n: v: lib.nameValuePair "sensor.${v}_battery" { friendly_name = "i.${n}_bat"; }) sensors.movement //
+ lib.mapAttrs' (n: v: lib.nameValuePair "sensor.${v}_action" { friendly_name = "s.${n}_act"; }) switches.dimmer //
+ lib.mapAttrs' (n: v: lib.nameValuePair "binary_sensor.${v}_occupancy" { friendly_name = "i.${n}_move"; }) sensors.movement //
+ lib.mapAttrs' (n: v: lib.nameValuePair "binary_sensor.${v}_occupancy" { friendly_name = "i.${n}_move"; }) sensors.movement //
+ lib.mapAttrs' (n: v: lib.nameValuePair "sensor.${v}_temperature" { friendly_name = "i.${n}_heat"; }) sensors.movement //
+ lib.mapAttrs' (n: v: lib.nameValuePair "sensor.${v}_temperature" { friendly_name = "i.${n}_heat"; }) sensors.movement //
+ lib.mapAttrs' (n: v: lib.nameValuePair "sensor.${v}_illuminance" { friendly_name = "i.${n}_lux"; }) sensors.movement //
+ lib.mapAttrs' (n: v: lib.nameValuePair "sensor.${v}_illuminance" { friendly_name = "i.${n}_lux"; }) sensors.movement //
+ {};
+
+ detect_movement = sensor: light: delay:
+ let
+ id = "${sensor}_${light}";
+ sensor_ = "binary_sensor.${sensor}_occupancy";
+ light_ = "light.${light}_light";
+ in {
+ input_boolean."${id}" = {
+ };
+ timer."${id}" = {
+ duration = delay;
+ };
+ automation = [
+ # {
+ # alias = "debug detect_movement";
+ # trigger = {
+ # platform = "state";
+ # entity_id = sensor_;
+ # };
+ # action = [
+ # {
+ # service = "system_log.write";
+ # data_template = {
+ # message = "XXXXXXXXXXXXXXXXXXXXXX {{ states('input_boolean.${sensor}_${light}_triggered') == 'on' }}";
+ # #message = "XXXXXXXXXXXXXXXXXXXXXX {{ state_attr('trigger.to_state.state', 'illuminance') }}";
+ # };
+ # }
+ # ];
+ # }
+ {
+ alias = "movement reset timer ${id}";
+ hide_entity = true;
+ trigger = {
+ platform = "state";
+ entity_id = sensor_;
+ from = "off";
+ to = "on";
+ };
+ action = [
+ {
+ service = "timer.cancel";
+ data_template.entity_id = "timer.${id}";
+ }
+ ];
+ }
+ {
+ alias = "movement on ${id}";
+ # hide_entity = true;
+ trigger = {
+ platform = "state";
+ entity_id = "binary_sensor.${sensor}_occupancy";
+ from = "off";
+ to = "on";
+ };
+ condition = {
+ condition = "and";
+ conditions = [
+ {
+ condition = "template";
+ value_template = "{{ trigger.to_state.attributes.illuminance < 13000 }}";
+ }
+ {
+ condition = "template";
+ value_template = "{{ states('${light_}') == 'off' }}";
+ }
+ ];
+ };
+ action = [
+ {
+ service = "light.turn_on";
+ data_template = {
+ entity_id = light_;
+ brightness = "100";
+ };
+ }
+ { delay = "0:00:02"; }
+ {
+ service = "input_boolean.turn_on";
+ data_template.entity_id = "input_boolean.${id}";
+ }
+ ];
+ }
+ {
+ alias = "movement off ${id}";
+ hide_entity = true;
+ trigger = {
+ platform = "state";
+ entity_id = sensor_;
+ from = "on";
+ to = "off";
+ };
+ condition = {
+ condition = "template";
+ value_template = "{{ states('input_boolean.${id}') == 'on' }}";
+ };
+ action = [
+ {
+ service = "timer.start";
+ entity_id = "timer.${id}";
+ }
+ ];
+ }
+ {
+ alias = "movement override ${id}";
+ hide_entity = true;
+ trigger = {
+ platform = "state";
+ entity_id = light_;
+ };
+ action = [
+ {
+ service = "input_boolean.turn_off";
+ data_template.entity_id = "input_boolean.${id}";
+ }
+ {
+ service = "system_log.write";
+ data_template = {
+ message = "XXXXXXXXXXXXXXXXXXXXXX {{ trigger }}";
+ };
+ }
+ ];
+ }
+ {
+ alias = "movement expired ${id}";
+ hide_entity = true;
+ trigger = {
+ platform = "event";
+ event_type = "timer.finished";
+ event_data.entity_id = "timer.${id}";
+ };
+ action = [
+ {
+ service = "light.turn_off";
+ data_template = {
+ entity_id = light_;
+ };
+ }
+ {
+ service = "input_boolean.turn_off";
+ data_template.entity_id = "input_boolean.${id}";
+ }
+ ];
+ }
+ ];
+ };
+
+ lightswitch = switch: light: {
+ automation = [
+ {
+ alias = "lightswitch ${switch} turn on light ${light}";
+ hide_entity = "true";
+ trigger = {
+ platform = "mqtt";
+ topic = "zigbee/${switch}";
+ };
+ condition = {
+ condition = "or";
+ conditions = [
+ {
+ condition = "template";
+ value_template = "{{ trigger.payload_json.action == 'on-press' }}";
+ }
+ {
+ condition = "template";
+ value_template = "{{ trigger.payload_json.action == 'up-press' }}";
+ }
+ {
+ condition = "and";
+ conditions = [
+ {
+ condition = "template";
+ value_template = "{{ trigger.payload_json.action == 'down-press' }}";
+ }
+ {
+ condition = "template";
+ value_template = "{{ trigger.payload_json.brightness > 30 }}";
+ }
+ ];
+ }
+ ];
+ };
+ action = [
+ {
+ service = "light.turn_on";
+ data_template = {
+ entity_id = "light.${light}_light";
+ brightness = "{{ trigger.payload_json.brightness }}";
+ };
+ }
+ ];
+ }
+ {
+ alias = "lightswitch ${switch} turn off light ${light}";
+ hide_entity = "true";
+ trigger = {
+ platform = "mqtt";
+ topic = "zigbee/${switch}";
+ };
+ condition = {
+ condition = "or";
+ conditions = [
+ {
+ condition = "template";
+ value_template = "{{ trigger.payload_json.action == 'off-press' }}";
+ }
+ {
+ condition = "template";
+ value_template = "{{ trigger.payload_json.brightness < 30 }}";
+ }
+ ];
+ };
+ action = {
+ service = "light.turn_off";
+ data_template = {
+ entity_id = "light.${light}_light";
+ };
+ };
+ }
+ ];
+ };
+}
diff --git a/lass/2configs/hass/rooms/bett.nix b/lass/2configs/hass/rooms/bett.nix
new file mode 100644
index 000000000..b5da9221c
--- /dev/null
+++ b/lass/2configs/hass/rooms/bett.nix
@@ -0,0 +1,8 @@
+{ lib, ... }:
+with import ../lib.nix { inherit lib; };
+
+{
+ lass.hass.config = lib.mkMerge [
+ (lightswitch switches.dimmer.bett lights.bett)
+ ];
+}
diff --git a/lass/2configs/hass/rooms/essen.nix b/lass/2configs/hass/rooms/essen.nix
new file mode 100644
index 000000000..f74996154
--- /dev/null
+++ b/lass/2configs/hass/rooms/essen.nix
@@ -0,0 +1,9 @@
+{ lib, ... }:
+with import ../lib.nix { inherit lib; };
+
+{
+ lass.hass.config = lib.mkMerge [
+ (detect_movement sensors.movement.essen lights.essen 10)
+ (lightswitch switches.dimmer.essen lights.essen)
+ ];
+}
diff --git a/lass/2configs/hass/rooms/nass.nix b/lass/2configs/hass/rooms/nass.nix
new file mode 100644
index 000000000..163f4fc48
--- /dev/null
+++ b/lass/2configs/hass/rooms/nass.nix
@@ -0,0 +1,10 @@
+{ lib, ... }:
+with import ../lib.nix { inherit lib; };
+
+{
+ lass.hass.config = lib.mkMerge [
+ (detect_movement sensors.movement.nass lights.nass 100)
+ (lightswitch switches.dimmer.nass lights.nass)
+ ];
+}
+
diff --git a/lass/2configs/hass/zigbee.nix b/lass/2configs/hass/zigbee.nix
new file mode 100644
index 000000000..6d091066e
--- /dev/null
+++ b/lass/2configs/hass/zigbee.nix
@@ -0,0 +1,151 @@
+{config, pkgs, lib, ...}: let
+
+ zigbee2mqtt_cfg = pkgs.writeText "zigbee2mqtt.json" (builtins.toJSON {
+ homeassistant = true;
+ permit_join = false;
+ mqtt = {
+ discovery = true;
+ base_topic = "zigbee";
+ server = "mqtt://10.42.0.1";
+ user = "gg23";
+ password = "gg23-mqtt";
+ };
+ serial.port = "/dev/cc2531";
+ });
+
+in {
+ # symlink the zigbee controller
+ services.udev.extraRules = ''
+ SUBSYSTEM=="tty", ATTRS{idVendor}=="0451", ATTRS{idProduct}=="16a8", SYMLINK+="cc2531", MODE="0660", GROUP="dailout"
+ '';
+
+ system.activationScripts.installZigbee = ''
+ install -d /var/lib/zigbee2mqtt
+ install ${zigbee2mqtt_cfg} /var/lib/zigbee2mqtt/configuration.yaml
+ '';
+
+ # hack to restart docker container on config change
+ systemd.services.docker-zigbee2mqtt.environment.cfg = zigbee2mqtt_cfg;
+
+ docker-containers.zigbee2mqtt = {
+ image = "koenkk/zigbee2mqtt";
+ extraDockerOptions = [
+ "--device=/dev/cc2531:/dev/cc2531"
+ ];
+ volumes = ["/var/lib/zigbee2mqtt:/app/data"];
+ };
+
+ lass.hass.config = {
+ sensor = [
+ # Sensor for monitoring the bridge state
+ {
+ platform = "mqtt";
+ name = "Zigbee2mqtt Bridge state";
+ state_topic = "/zigbee2mqtt/bridge/state";
+ icon = "mdi:router-wireless";
+ }
+ # Sensor for Showing the Zigbee2mqtt Version
+ {
+ platform = "mqtt";
+ name = "Zigbee2mqtt Version";
+ state_topic = "/zigbee2mqtt/bridge/config";
+ value_template = "{{ value_json.version }}";
+ icon = "mdi:zigbee";
+ }
+ # Sensor for Showing the Coordinator Version
+ {
+ platform = "mqtt";
+ name = "Coordinator Version";
+ state_topic = "/zigbee2mqtt/bridge/config";
+ value_template = "{{ value_json.coordinator }}";
+ icon = "mdi:chip";
+ }
+ ];
+ switch = [
+ {
+ platform = "mqtt";
+ name = "zigbee2mqtt_join";
+ state_topic = "/zigbee2mqtt/bridge/config/permit_join";
+ command_topic = "/zigbee2mqtt/bridge/config/permit_join";
+ payload_on = "true";
+ payload_off = "false";
+ }
+ ];
+ automation = [
+ #{
+ # alias = "Zigbee2mqtt Log Level";
+ # initial_state = "on";
+ # trigger = {
+ # platform = "state";
+ # entity_id = "input_select.zigbee2mqtt_log_level";
+ # };
+ # action = [
+ # {
+ # service = "mqtt.publish";
+ # data = {
+ # payload_template = "{{ states('input_select.zigbee2mqtt_log_level') }}";
+ # topic = "/zigbee2mqtt/bridge/config/log_level";
+ # };
+ # }
+ # ];
+ #}
+ # Automation to start timer when enable join is turned on
+ {
+ id = "zigbee_join_enabled";
+ alias = "";
+ hide_entity = "true";
+ trigger = {
+ platform = "state";
+ entity_id = "switch.zigbee2mqtt_join";
+ to = "on";
+ };
+ action = {
+ service = "timer.start";
+ entity_id = "timer.zigbee_permit_join";
+ };
+ }
+ # Automation to stop timer when switch turned off and turn off switch when timer finished
+ {
+ id = "zigbee_join_disabled";
+ hide_entity = "true";
+ trigger = [
+ {
+ platform = "event";
+ event_type = "timer.finished";
+ event_data.entity_id = "timer.zigbee_permit_join";
+ }
+ {
+ platform = "state";
+ entity_id = "switch.zigbee2mqtt_join";
+ to = "off";
+ }
+ ];
+ action = [
+ { service = "timer.cancel";
+ data.entity_id = "timer.zigbee_permit_join";
+ }
+ { service = "switch.turn_off";
+ entity_id = "switch.zigbee2mqtt_join";
+ }
+ ];
+ }
+ ];
+ #input_select.zigbee2mqtt_log_level = {
+ # name = "Zigbee2mqtt Log Level";
+ # options = [
+ # "debug"
+ # "info"
+ # "warn"
+ # "error"
+ # ];
+ # initial = "info";
+ # icon = "mdi:format-list-bulleted";
+ #};
+
+ timer.zigbee_permit_join = {
+ name = "Zigbee Time remaining";
+ duration = 120;
+ };
+ };
+}
+