pepe: add home-assistant wip

This commit is contained in:
Ingolf Wagner 2020-04-08 16:43:09 +02:00
parent 8d9cdf514c
commit 5598ec5c5c
No known key found for this signature in database
GPG key ID: 76BF5F1928B9618B
15 changed files with 1258 additions and 46 deletions

View file

@ -2,37 +2,24 @@
imports = [
<system/desktop>
<system/server>
./hardware-configuration.nix
#./samba.nix
./syncthing.nix
#./syncthing.nix
./tinc.nix
#./wifi-access-point.nix
./wifi-access-point.nix
./home-assistant.nix
];
custom.samba-share = {
enable = false;
folders = { public = "/home/palo/movies"; };
system.custom.wifi = {
enable = true;
interfaces = [ "wlp3s0" ];
configurationFile = <secrets/wpa_supplicant>;
};
system.custom.wifi.interfaces = [ "wlp3s0" ];
networking.hostName = "pepe";
security.wrappers = {
pmount.source = "${pkgs.pmount}/bin/pmount";
pumount.source = "${pkgs.pmount}/bin/pumount";
};
# keybase
services.keybase.enable = false;
services.kbfs.enable = false;
programs.custom.steam.enable = false;
programs.custom.video.enable = false;
services.printing.enable = true;
# fonts
@ -51,10 +38,5 @@
};
};
configuration.desktop = {
width = 1366;
height = 768;
};
}

View file

@ -0,0 +1,213 @@
{ pkgs, config, lib, ... }:
let unstablePkgs = import <nixpkgs-unstable> { };
in {
imports = [
#./home-assistant/chaospott.nix
#./home-assistant/holiday.nix
#./home-assistant/mpd.nix
./home-assistant/sonoff.nix
./home-assistant/mqtt.nix
#./home-assistant/dayOfWeek.nix
#./home-assistant/timer.nix
#./home-assistant/kodi.nix
#./home-assistant/zigbee2mqtt.nix
];
services.homeAssistantConfig = {
# turn on to edit GUI
# lovelace = {};
homeassistant = {
latitude = 51.444847;
longitude = 6.967006;
elevation = 116;
auth_providers = [{
type = "trusted_networks";
trusted_networks =
[ config.module.cluster.services.tinc."private".networkSubnet ];
}];
};
prometheus.namespace = "hass";
automation = [
# 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";
# }
# ];
#}
#{
# alias = "Küchen Sensor An";
# trigger = {
# platform = "state";
# entity_id = [ "binary_sensor.motion_1" ];
# to = "on";
# };
# action = {
# service = "switch.turn_on";
# entity_id = "group.kitchen";
# };
#}
#{
# alias = "Küchen Sensor aus";
# trigger = {
# platform = "state";
# entity_id = [ "binary_sensor.motion_1" ];
# to = "off";
# for = "00:00:25";
# };
# action = {
# service = "switch.turn_off";
# entity_id = "group.kitchen";
# };
#}
];
group = {
bed_room = {
name = "Schlafzimmer";
view = false;
};
tv = {
name = "TV";
view = false;
};
living_room = {
name = "Wohnzimmer";
view = false;
};
kitchen = {
name = "Küche";
view = false;
};
today = {
control = "hidden";
name = "Today";
view = false;
entities = [ "sensor.weather_temperature" "sun.sun" ];
};
all_lights = {
name = "All Lights";
view = false;
};
unknown = {
control = "hidden";
name = "Not Used";
view = false;
};
view_rooms = {
name = "Räume";
view = true;
entities = [
"group.all_lights"
"group.bed_room"
"group.living_room"
"group.kitchen"
"group.tv"
];
};
view_overview = {
name = "Übersicht";
view = true;
entities = [ "group.today" ];
};
};
sun = { };
script.turn_all_off.sequence = [ ];
script.turn_all_on.sequence = [ ];
sensor = [
# Weather prediction
{
platform = "zamg";
name = "Weather";
}
];
# todo: add holidays package to home-assiatnt
binary_sensor = [
{
name = "before_workday";
platform = "workday";
country = "DE";
province = "NW";
workdays = [ "mon" "tue" "wed" "thu" "fri" ];
days_offset = 1;
}
{
name = "workday";
platform = "workday";
country = "DE";
province = "NW";
workdays = [ "mon" "tue" "wed" "thu" "fri" ];
}
];
};
services.home-assistant = {
enable = true;
package = unstablePkgs.home-assistant.override {
python3 = unstablePkgs.python37;
extraPackages = python: [
# todo : check which is still needed
python.netdisco
python.xmltodict
python.mpd2
# for mqtt
python.hbmqtt
python.paho-mqtt
# needed for platform workday
#(python.buildPythonPackage rec {
# pname = "holidays";
# version = "0.9.10";
# src = python.fetchPypi {
# inherit pname version;
# sha256 =
# "9f06d143eb708e8732230260636938f2f57114e94defd8fa2082408e0d422d6f";
# };
# doCheck = false;
# buildInputs = [ pkgs.dateutils ];
# propagatedBuildInputs = [ python."python-dateutil" python."six" ];
# meta = with pkgs.stdenv.lib; {
# homepage = "https://github.com/dr-prodigy/python-holidays";
# license = licenses.mit;
# description = "Generate and work with holidays in Python";
# maintainers = with maintainers; [ mrVanDalo ];
# };
#})
];
};
};
}

View file

@ -0,0 +1,82 @@
{ config, pkgs, ... }:
let
name = "chaospott";
folderPath = config.services.home-assistant.configDir;
filePath = "${folderPath}/${name}.json";
in {
services.homeAssistantConfig = {
sensor = [
{
platform = "file";
name = "${name}_aerie";
file_path = filePath;
value_template = "{{ value_json.aerie }}";
}
{
platform = "file";
name = "${name}_cellar";
file_path = filePath;
value_template = "{{ value_json.cellar }}";
}
];
homeassistant = {
whitelist_external_dirs = [ folderPath ];
customize = {
"sensor.${name}_aerie" = {
icon = "mdi:store";
entity_picture = "https://chaospott.de/images/logo.png";
friendly_name = "ChaosPott Oben";
};
"sensor.${name}_cellar" = {
icon = "mdi:store";
entity_picture = "https://chaospott.de/images/logo.png";
friendly_name = "ChaosPott Unten";
};
};
};
group = {
"${name}" = {
name = "ChaosPott (Essen)";
control = "hidden";
entities = [ "sensor.${name}_aerie" "sensor.${name}_cellar" ];
};
view_overview.entities = [ "group.${name}" ];
};
};
systemd.services."${name}" = {
enable = true;
before = [ "home-assistant.service" ];
wantedBy = [ "home-assistant.service" ];
serviceConfig = {
User = "hass";
Type = "oneshot";
};
description = "set ${name} for homeassistant";
script = # sh
''
${pkgs.curl}/bin/curl -Ls https://status.chaospott.de/api \
| ${pkgs.jq}/bin/jq --compact-output \
'.sensors.door_locked |
[.[] | { "\(.location)" : (if .value then "closed" else "open" end) }] |
reduce .[] as $item ({}; . + $item) ' \
>> ${filePath}
'';
};
systemd.timers."${name}" = {
enable = true;
wantedBy = [ "multi-user.target" ];
timerConfig = {
OnCalendar = "hourly";
Persistent = "true";
};
};
}

View file

@ -0,0 +1,52 @@
{ config, ... }:
let
folderPath = config.services.home-assistant.configDir;
filePath = "${folderPath}/dayOfWeek.json";
in {
services.homeAssistantConfig = {
sensor = [{
platform = "file";
name = "day_of_week";
file_path = filePath;
value_template = "{{ value_json.dayOfWeek }}";
}];
homeassistant = {
whitelist_external_dirs = [ folderPath ];
customize."sensor.day_of_week" = {
icon = "mdi:calendar-today";
friendly_name = "Wochen Tag";
};
};
group = { overview.entities = [ "sensor.day_of_week" ]; };
};
systemd.services.dayOfWeek = {
enable = true;
before = [ "home-assistant.service" ];
wantedBy = [ "home-assistant.service" ];
serviceConfig = {
User = "hass";
Type = "oneshot";
};
description = "set day of wek for homeassistant";
script = # sh
''
date +'{"dayOfWeek":"%A"}' >> ${filePath}
'';
};
systemd.timers.dayOfWeek = {
enable = true;
wantedBy = [ "multi-user.target" ];
timerConfig = {
OnCalendar = "00:01:00";
Persistent = "true";
};
};
}

View file

@ -0,0 +1,92 @@
{ config, pkgs, ... }:
let
state = "NW"; # NRW
# state = "BE"; # Berlin
name = "holiday";
folderPath = config.services.home-assistant.configDir;
filePath = "${folderPath}/${name}.json";
in {
services.homeAssistantConfig = {
# todo : use the python tool
sensor = [
{
platform = "file";
name = "${name}_date";
file_path = filePath;
value_template = "{{ value_json.date }}";
}
{
platform = "file";
name = "${name}_name";
file_path = filePath;
value_template = "{{ value_json.name }}";
}
];
homeassistant = {
whitelist_external_dirs = [ folderPath ];
customize = {
"sensor.${name}_date" = {
icon = "mdi:calendar";
friendly_name = "Nächster Feiertag";
};
"sensor.${name}_name" = {
icon = "mdi:calendar";
friendly_name = "Nächster Feiertag";
};
};
};
group = {
holidays = {
name = "Feiertage";
view = false;
control = "hidden";
entities = [ "sensor.${name}_date" "sensor.${name}_name" ];
};
view_overview.entities = [ "group.holidays" ];
};
};
systemd.services."${name}" = {
enable = true;
before = [ "home-assistant.service" ];
wantedBy = [ "home-assistant.service" ];
serviceConfig = {
User = "hass";
Type = "oneshot";
};
description = "set ${name} for homeassistant";
script = # sh
''
${pkgs.curl}/bin/curl \
-Ls "https://feiertage-api.de/api/?jahr=$( date +%Y )&nur_land=${state}" \
| ${pkgs.jq}/bin/jq --compact-output '
map_values( .datum ) |
to_entries |
map( { date: .value, name : .key } ) |
sort_by( .date ) |
map(select ( .date >= "'`date +%Y-%m-%d`'" )) |
.[0]' \
>> ${filePath}
'';
};
systemd.timers."${name}" = {
enable = true;
wantedBy = [ "multi-user.target" ];
timerConfig = {
OnCalendar = "daily";
Persistent = "true";
};
};
}

View file

@ -0,0 +1,81 @@
{ pkgs, config, lib, ... }: {
services.homeAssistantConfig = {
group.view_overview.entities = [ "media_player.kodi" ];
media_player = [{
platform = "kodi";
host = "127.0.0.1";
turn_on_action.service = "script.watch_tv";
turn_off_action.service = "script.stop_watch_tv";
}];
shell_command = {
start_display =
"sudo ${pkgs.systemd}/bin/systemctl start display-manager";
stop_display = "sudo ${pkgs.systemd}/bin/systemctl stop display-manager";
};
script = {
turn_all_off.sequence = [
# todo : use the shell_command here
{
alias = "turn off tv";
service = "switch.turn_off";
data.entity_id = "group.tv";
}
{
alias = "stop kodi";
service = "shell_command.stop_display";
}
];
test_display.sequence = [
{ service = "shell_command.start_display"; }
{ delay.seconds = 20; }
{ service = "shell_command.stop_display"; }
];
watch_tv = {
alias = "Watch TV";
sequence = [
{
alias = "turn on tv";
service = "switch.turn_on";
data.entity_id = "group.tv";
}
{ delay.minutes = 1; }
{
alias = "start kodi";
service = "shell_command.start_display";
}
];
};
stop_watch_tv = {
alias = "Stop TV";
sequence = [
{
alias = "turn off tv";
service = "switch.turn_off";
data.entity_id = "group.tv";
}
{
alias = "stop kodi";
service = "shell_command.stop_display";
}
];
};
};
group.tv.entities = [ "script.watch_tv" "script.stop_watch_tv" ];
};
security.sudo.extraConfig = ''
hass ALL= (root) NOPASSWD: ${pkgs.systemd}/bin/systemctl start display-manager
hass ALL= (root) NOPASSWD: ${pkgs.systemd}/bin/systemctl stop display-manager
'';
}

View file

@ -0,0 +1,37 @@
{ lib, ... }:
{
services.homeAssistantConfig = {
group.view_overview.entities = [ "media_player.mpd" ];
media_player = [{
platform = "mpd";
host = "localhost";
}];
script.turn_all_off.sequence = [{
alias = "turn mpd off";
service = "media_player.turn_off";
data.entity_id = "media_player.mpd";
}];
script.turn_all_on.sequence = [
{
alias = "turn mpd on";
service = "media_player.turn_on";
data.entity_id = "media_player.mpd";
}
{
alias = "Adjust volume";
service = "media_player.volume_set";
data = {
entity_id = "media_player.mpd";
volume_level = "0.90";
};
}
];
};
}

View file

@ -0,0 +1,28 @@
{ lib, ... }:
{
services.homeAssistantConfig.mqtt = {
# discovery = false;
# for mosquitto
broker = "127.0.0.1";
username = lib.fileContents <secrets/home-assistant/mqtt-user>;
password = lib.fileContents <secrets/home-assistant/mqtt-password>;
};
services.mosquitto = {
enable = true;
host = "0.0.0.0";
users = {
homeassistant = {
password = lib.fileContents <secrets/mosquitto/password>;
acl = [ "topic readwrite #" ];
};
zigbee = {
password = lib.fileContents <secrets/zigbee/password>;
acl = [ "topic readwrite #" ];
};
};
};
}

View file

@ -0,0 +1,119 @@
{ pkgs, config, lib, ... }:
let unstablePkgs = import <nixpkgs-unstable> { };
in {
services.homeAssistantConfig = let
sonoffSwitches = {
"pal01" = {
label = "Schlafzimmer";
icon = "mdi:lightbulb-on";
};
"pal02" = {
label = "Schlafzimmer";
icon = "mdi:lightbulb-on";
};
"pal03" = {
label = "Wohnzimmer";
icon = "mdi:lightbulb-on";
};
"pal04" = {
label = "Wohnzimmer";
icon = "mdi:lightbulb-on";
};
"pal05" = {
label = "TV";
icon = "mdi:television";
};
"pal06" = {
label = "Küche";
icon = "mdi:lightbulb-on";
};
"pal07" = {
label = "Nummer 7";
icon = "mdi:power-plug-off";
};
"pal08" = {
label = "Nummer 8";
icon = "mdi:power-plug-off";
};
};
toSwitch = name: "switch.${name}";
in {
homeassistant = {
customize = lib.mapAttrs' (entity: value: {
name = toSwitch entity;
value = {
friendly_name = value.label;
icon = value.icon;
};
}) sonoffSwitches;
};
script.turn_all_off.sequence = [
{
alias = "turn off sonoff";
service = "switch.turn_off";
data.entity_id = "group.all_lights";
}
{
alias = "turn off sonoff";
service = "switch.turn_off";
data.entity_id = "group.tv";
}
];
script.turn_all_on.sequence = [{
alias = "turn on all lights";
service = "switch.turn_on";
data.entity_id = "group.all_lights";
}];
group = {
bed_room = { entities = builtins.map toSwitch [ "pal01" "pal02"]; };
living_room = { entities = builtins.map toSwitch [ "pal03" "pal04" ]; };
tv = { entities = builtins.map toSwitch [ "pal05" ]; };
kitchen = { entities = builtins.map toSwitch [ "pal06" ]; };
unknown = {
entities = builtins.map toSwitch [ "pal07" "pal08" ];
};
all_lights = {
entities = builtins.map toSwitch [ "pal01" "pal02" "pal03" "pal04" "pal05" "pal06" ];
};
};
switch = let
sonoffConfigurations = builtins.map (name: {
name = name;
platform = "mqtt";
command_topic = "cmnd/${lib.toUpper name}/POWER";
state_topic = "stat/${lib.toUpper name}/POWER";
payload_on = "ON";
payload_off = "OFF";
state_on = "ON";
state_off = "OFF";
}) (builtins.attrNames sonoffSwitches);
in sonoffConfigurations;
# discover state on init
automation = [{
alias = "Sonoff initial Power state";
trigger = {
platform = "homeassistant";
event = "start";
};
action = builtins.map (name: {
service = "mqtt.publish";
data = {
topic = "cmnd/${lib.toUpper name}/power";
payload = "";
};
}) (builtins.attrNames sonoffSwitches);
}];
};
}

View file

@ -0,0 +1,244 @@
{ config, ... }: {
imports = [ ./mpd.nix ];
services.homeAssistantConfig = {
sensor = [{
platform = "time_date";
display_options = [ "time" "date" ];
}];
input_datetime = {
wakeup = {
name = "Arbeitswecker";
has_time = true;
has_date = false;
icon = "mdi:alarm";
};
leave = {
name = "Turn off Time";
has_time = true;
has_date = false;
icon = "mdi:alarm";
};
return = {
name = "Return home";
has_time = true;
has_date = false;
icon = "mdi:alarm";
};
sleep = {
name = "Turn off Time";
has_time = true;
has_date = false;
icon = "mdi:alarm";
};
};
input_boolean = {
wakeup = {
name = "enable";
icon = "mdi:toggle-switch";
};
leave = {
name = "enable";
icon = "mdi:toggle-switch";
};
return = {
name = "enable";
icon = "mdi:toggle-switch";
};
sleep = {
name = "enable";
icon = "mdi:toggle-switch";
};
};
input_select = {
wakeup = {
name = "Playlist";
icon = "mdi:library-music";
options = [ "wakeup" "wakeup1" "wakeup2" ];
};
};
binary_sensor = [
{
platform = "tod";
name = "night";
after = "sunset";
before = "sunrise";
}
{
platform = "tod";
name = "daytime";
after = "sunrise";
before = "sunset";
}
];
group = {
timer_wakeup = {
view = false;
name = "Arbeits Aufwachen";
control = "hidden";
entities = [
"input_boolean.wakeup"
"input_datetime.wakeup"
"input_select.wakeup"
];
};
timer_leave = {
view = false;
name = "Leave Time";
control = "hidden";
entities = [ "input_boolean.leave" "input_datetime.leave" ];
};
timer_return = {
view = false;
name = "Nach Hause kommen";
control = "hidden";
entities = [ "input_boolean.return" "input_datetime.return" ];
};
timer_sleep = {
view = false;
name = "Einschlafen";
control = "hidden";
entities = [ "input_boolean.sleep" "input_datetime.sleep" ];
};
timers.entities = [
"group.timer_wakeup"
"group.timer_leave"
"group.timer_return"
"group.timer_sleep"
"binary_sensor.night"
"binary_sensor.daytime"
];
today.entities = [ "sensor.date" "sensor.time" ];
view_overview.entities = [
"group.timer_wakeup"
"group.timer_leave"
"group.timer_return"
"group.timer_sleep"
];
};
automation = [
{
alias = "Wecker Arbeiten";
trigger = {
platform = "template";
value_template =
"{{ states('sensor.time') == (states.input_datetime.wakeup.attributes.timestamp | int | timestamp_custom('%H:%M', False)) }}";
};
condition = {
condition = "and";
conditions = [
{
condition = "state";
entity_id = "input_boolean.wakeup";
state = "on";
}
{
condition = "state";
entity_id = "binary_sensor.workday";
state = "on";
}
];
};
action = [
{
alias = "Play wakeup list";
service = "media_player.play_media";
data_template = {
entity_id = "media_player.mpd";
media_content_type = "playlist";
media_content_id = "{{ states('input_select.wakeup') }}";
};
}
{
alias = "turn all on";
service = "script.turn_on";
entity_id = "script.turn_all_on";
}
];
}
{
alias = "Leave Turn all off Timer";
trigger = {
platform = "template";
value_template =
"{{ states('sensor.time') == (states.input_datetime.leave.attributes.timestamp | int | timestamp_custom('%H:%M', False)) }}";
};
condition = {
condition = "and";
conditions = [{
condition = "state";
entity_id = "input_boolean.leave";
state = "on";
}];
};
action = [{
alias = "turn all off";
service = "script.turn_on";
entity_id = "script.turn_all_off";
}];
}
{
alias = "Return to Home";
trigger = {
platform = "template";
value_template =
"{{ states('sensor.time') == (states.input_datetime.return.attributes.timestamp | int | timestamp_custom('%H:%M', False)) }}";
};
condition = {
condition = "and";
conditions = [{
condition = "state";
entity_id = "input_boolean.return";
state = "on";
}];
};
action = [{
alias = "turn all on";
service = "script.turn_on";
entity_id = "script.turn_all_on";
}];
}
{
alias = "Sleep Turn all off Timer";
trigger = {
platform = "template";
value_template =
"{{ states('sensor.time') == (states.input_datetime.sleep.attributes.timestamp | int | timestamp_custom('%H:%M', False)) }}";
};
condition = {
condition = "and";
conditions = [{
condition = "state";
entity_id = "input_boolean.sleep";
state = "on";
}];
};
action = [{
alias = "turn all off";
service = "script.turn_on";
entity_id = "script.turn_all_off";
}];
}
];
};
}

View file

@ -0,0 +1,279 @@
{ 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"; };
};
# 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 <secrets/zigbee/password>;
};
# 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:
{ ... }: [
{
platform = "mqtt";
name = "battery_${name}";
state_topic = "zigbee2mqtt/${name}";
availability_topic = "zigbee2mqtt/bridge/state";
unit_of_measurement = "%";
device_class = "battery";
value_template = "{{ value_json.battery }}";
}
{
name = "link_${name}";
platform = "mqtt";
state_topic = "zigbee2mqtt/${name}";
availability_topic = "zigbee2mqtt/bridge/state";
unit_of_measurement = "-";
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";
#icon = "mdi:motion-sensor";
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" ];
in lights ++ mpd;
# 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
'';
};
}

View file

@ -1,14 +1,15 @@
{ lib, pkgs, ... }:
let
wifi = "wlp0s29u1u2";
ipAddress = "10.123.145.1";
wifi = "wlp0s26u1u2";
ipAddress = "10.23.45.1";
prefixLength = 24;
servedAddressRange = "10.123.145.2,10.123.145.150,12h";
ssid = "bumbumbum";
wifiPassword = lib.fileContents <secrets/wifi-access-point>;
servedAddressRange = "10.23.45.2,10.23.45.150,12h";
ssid = "palosiot";
wifiPassword = lib.fileContents <secrets/iot_wifi>;
in {
# todo only open needed ports
networking.firewall.trustedInterfaces = [ wifi ];
@ -20,19 +21,10 @@ in {
prefixLength = prefixLength;
}];
# forward traffic coming in trough the access point => provide internet and vpn network access
# todo : forward to own servers
boot.kernel.sysctl = {
"net.ipv4.conf.${wifi}.forwarding" = true;
"net.ipv6.conf.${wifi}.forwarding" = true;
};
systemd.services.hostapd = {
description = "hostapd wireless AP";
path = [ pkgs.hostapd ];
# start manual
# wantedBy = [ "network.target" ];
wantedBy = [ "network.target" ];
after = [
"${wifi}-cfg.service"

View file

@ -1,5 +1,6 @@
{ pkgs, lib, ... }:
let
remote-access = import ../lib/remote-access.nix {
# cat ~/.ssh/id_rsa.pub
@ -8,15 +9,24 @@ let
# remote-install-get-hiddenReceiver
hiddenReceiver = "";
};
in {
imports = [ remote-access ];
# network configuration
networking.networkmanager.enable = true;
networking.wireless.enable = lib.mkForce false;
# ---------------------
# no wifi
#networking.networkmanager.enable = true;
# wifi
networking.wireless.enable = true;
networking.wireless.networks."ssid".psk = "password";
# configuration
environment.extraInit = ''
# use vi shortcuts
# ----------------

View file

@ -231,11 +231,11 @@ in {
};
input_boolean = mkOption {
default = null;
type = with types; (attrsOf attrs);
type = with types; nullOr (attrsOf attrs);
};
input_datetime = mkOption {
default = null;
type = with types; (attrsOf attrs);
type = with types; nullOr (attrsOf attrs);
};
calendar = mkOption {
default = [ ];

View file

@ -1,7 +1,8 @@
let
# host used to install stuff. (can be an onion id if you use torify)
installHost = "localhost";
#installHost = "localhost";
installHost = "adsf.onion";
#ops = import ../plops ;
ops = import ((import <nixpkgs> { }).fetchgit {