497 lines
13 KiB
Nix
497 lines
13 KiB
Nix
{ pkgs, config, lib, ... }:
|
|
let unstablePkgs = import <nixpkgs-unstable> { };
|
|
in {
|
|
|
|
imports = [
|
|
#./home-assistant/mpd.nix
|
|
#./home-assistant/timer.nix
|
|
./home-assistant/light-control.nix
|
|
./home-assistant/chaospott.nix
|
|
./home-assistant/kodi.nix
|
|
./home-assistant/mqtt.nix
|
|
./home-assistant/sonoff.nix
|
|
./home-assistant/stocks.nix
|
|
./home-assistant/weather.nix
|
|
./home-assistant/workday.nix
|
|
./home-assistant/zigbee2mqtt.nix
|
|
];
|
|
|
|
services.homeAssistantConfig = {
|
|
|
|
# turn on to edit GUI
|
|
lovelace = { };
|
|
|
|
homeassistant = {
|
|
|
|
name = "Home";
|
|
latitude = 51.444847;
|
|
longitude = 6.967006;
|
|
elevation = 116;
|
|
unit_system = "metric";
|
|
|
|
time_zone = config.time.timeZone;
|
|
auth_providers = [{
|
|
type = "trusted_networks";
|
|
trusted_networks = [
|
|
config.module.cluster.services.tinc."private".networkSubnet
|
|
# lan network
|
|
"10.1.0.0/24"
|
|
];
|
|
}];
|
|
|
|
};
|
|
|
|
# needed, don't know why
|
|
default_config = { };
|
|
config = { };
|
|
|
|
# to grab metrics via prometheus
|
|
prometheus.namespace = "hass";
|
|
|
|
# manual state
|
|
# ------------
|
|
# all scenes
|
|
input_select.scene = {
|
|
icon = "mdi:brightness-auto";
|
|
options = [ "default" "night" "outside" "cooking" ];
|
|
};
|
|
# scenes controlled by buttons
|
|
input_select.scene_button = {
|
|
icon = "mdi:brightness-auto";
|
|
options = [ "default" "night" ];
|
|
};
|
|
input_boolean.situation_toggle.icon = "mdi:toggle-switch";
|
|
input_boolean.printer_toggle.icon = "mdi:toggle-switch";
|
|
|
|
input_boolean.windows_up.icon = "mdi:toggle-switch";
|
|
|
|
# heater scenes
|
|
input_select.heater_state = {
|
|
#icon = "mdi:brightness-auto";
|
|
options = [ "off" "on1" "on2" ];
|
|
};
|
|
|
|
automation = [
|
|
|
|
{
|
|
alias = "Hold Button -> Toggle Printer";
|
|
trigger = {
|
|
platform = "state";
|
|
entity_id = "input_boolean.printer_toggle";
|
|
};
|
|
action = {
|
|
service = "switch.toggle";
|
|
data.entity_id = "switch.pal02";
|
|
};
|
|
}
|
|
|
|
{
|
|
alias = "set light-control scene";
|
|
trigger = {
|
|
platform = "state";
|
|
entity_id = "input_select.scene";
|
|
};
|
|
action = {
|
|
service = "mqtt.publish";
|
|
data_template = {
|
|
topic = "control/lights/set";
|
|
payload_template =
|
|
''{"scene":"{{ states('input_select.scene')}}"}'';
|
|
};
|
|
};
|
|
}
|
|
|
|
# control situation with buttons
|
|
{
|
|
alias = "Button -> Change Scene";
|
|
trigger = {
|
|
platform = "state";
|
|
entity_id = "input_boolean.situation_toggle";
|
|
};
|
|
action = {
|
|
service = "input_select.select_next";
|
|
data.entity_id = "input_select.scene_button";
|
|
};
|
|
}
|
|
{
|
|
alias = "Button Scene -> Scene";
|
|
trigger = {
|
|
platform = "state";
|
|
entity_id = "input_select.scene_button";
|
|
};
|
|
action = {
|
|
service = "input_select.select_option";
|
|
data_template = {
|
|
entity_id = "input_select.scene";
|
|
option = "{{ states('input_select.scene_button') }}";
|
|
};
|
|
};
|
|
}
|
|
|
|
# outside and home
|
|
{
|
|
alias = "Set Scene To Outside when opening door";
|
|
trigger = [
|
|
{
|
|
platform = "state";
|
|
# todo : groups are not working right now
|
|
entity_id = "binary_sensor.door_sensor_4";
|
|
from = "off";
|
|
to = "on";
|
|
}
|
|
{
|
|
platform = "state";
|
|
# todo : groups are not working right now
|
|
entity_id = "binary_sensor.door_sensor_4";
|
|
from = "on";
|
|
to = "off";
|
|
}
|
|
];
|
|
action = {
|
|
service = "input_select.select_option";
|
|
data = {
|
|
entity_id = "input_select.scene";
|
|
option = "outside";
|
|
};
|
|
};
|
|
}
|
|
|
|
{
|
|
alias = "Set default for motion inside";
|
|
trigger = map (entity_id: {
|
|
platform = "state";
|
|
entity_id = entity_id;
|
|
from = "off";
|
|
to = "on";
|
|
}) [
|
|
"binary_sensor.motion_sensor_1"
|
|
"binary_sensor.motion_sensor_2"
|
|
"binary_sensor.motion_sensor_3"
|
|
"binary_sensor.motion_sensor_4"
|
|
"binary_sensor.motion_sensor_5"
|
|
"binary_sensor.motion_sensor_6"
|
|
"binary_sensor.motion_sensor_7"
|
|
"binary_sensor.motion_sensor_8"
|
|
];
|
|
condition = {
|
|
condition = "template";
|
|
value_template =
|
|
''{{ states.input_select.scene.state == "outside" }}'';
|
|
};
|
|
action = {
|
|
service = "input_select.select_option";
|
|
data = {
|
|
entity_id = "input_select.scene";
|
|
option = "default";
|
|
};
|
|
};
|
|
}
|
|
|
|
# window roles
|
|
{
|
|
alias = "windows state = down in the evening";
|
|
trigger = [{
|
|
platform = "sun";
|
|
event = "sunset";
|
|
offset = "+00:01:00"; # 10 min after sunset
|
|
}];
|
|
action = [{
|
|
service = "input_boolean.turn_off";
|
|
data.entity_id = "input_boolean.windows_up";
|
|
}];
|
|
}
|
|
{
|
|
alias = "windows state = up in the morning";
|
|
trigger = [{
|
|
platform = "time";
|
|
at = "09:00:00";
|
|
}];
|
|
action = [{
|
|
service = "input_boolean.turn_on";
|
|
data.entity_id = "input_boolean.windows_up";
|
|
}];
|
|
}
|
|
{
|
|
alias = "enforce window_up state";
|
|
trigger = [
|
|
{
|
|
platform = "time_pattern";
|
|
minutes = "/5"; # every 5 minutes
|
|
}
|
|
{
|
|
platform = "state";
|
|
entity_id = "input_boolean.windows_up";
|
|
}
|
|
];
|
|
action = [{
|
|
service = "script.turn_on";
|
|
data_template.entity_id = ''
|
|
{% if is_state('input_boolean.windows_up','on') -%}
|
|
script.fyrtur_up
|
|
{%- else -%}
|
|
script.fyrtur_down
|
|
{%- endif %}
|
|
'';
|
|
}];
|
|
}
|
|
|
|
# heater
|
|
{
|
|
alias = "heater state = on1 in the morning";
|
|
trigger = [{
|
|
platform = "time";
|
|
at = "09:00:00";
|
|
}];
|
|
action = [{
|
|
service = "input_select.select_option";
|
|
data = {
|
|
entity_id = "input_select.heater_state";
|
|
option = "on1";
|
|
};
|
|
}];
|
|
}
|
|
{
|
|
alias = "heater state = on2 in the early evening";
|
|
trigger = [{
|
|
platform = "time";
|
|
at = "22:30:00";
|
|
}];
|
|
action = [{
|
|
service = "input_select.select_option";
|
|
data = {
|
|
entity_id = "input_select.heater_state";
|
|
option = "on2";
|
|
};
|
|
}];
|
|
}
|
|
{
|
|
alias = "heater state = off in the evening";
|
|
trigger = [{
|
|
platform = "time";
|
|
at = "23:30:00";
|
|
}];
|
|
action = [{
|
|
service = "input_select.select_option";
|
|
data = {
|
|
entity_id = "input_select.heater_state";
|
|
option = "off";
|
|
};
|
|
}];
|
|
}
|
|
{
|
|
alias = "enforce heater state";
|
|
trigger = [
|
|
{
|
|
platform = "time_pattern";
|
|
minutes = "/5"; # every 5 minutes
|
|
}
|
|
{
|
|
platform = "state";
|
|
entity_id = "input_select.heater_state";
|
|
}
|
|
];
|
|
action = [{
|
|
service = "script.turn_on";
|
|
data_template.entity_id =
|
|
"script.heater_{{ states('input_select.heater_state') }}";
|
|
}];
|
|
}
|
|
];
|
|
|
|
group = let
|
|
create_room = { name, description }: {
|
|
"${name}" = {
|
|
name = "${description}";
|
|
entities = [ ];
|
|
};
|
|
};
|
|
create_rooms = rooms:
|
|
lib.foldr (a: b: a // b) { } (map create_room rooms);
|
|
# rooms
|
|
# -----
|
|
in (create_rooms [
|
|
{
|
|
name = "floor_room";
|
|
description = "Flur";
|
|
}
|
|
{
|
|
name = "bed_room";
|
|
description = "Schlafzimmer";
|
|
}
|
|
{
|
|
name = "living_room";
|
|
description = "Wohnzimmer";
|
|
}
|
|
{
|
|
name = "kitchen_room";
|
|
description = "Küche";
|
|
}
|
|
{
|
|
name = "bath_room";
|
|
description = "Klo";
|
|
}
|
|
]) // {
|
|
|
|
# overview
|
|
# --------
|
|
all_sensors = { name = "Alle Sensoren"; };
|
|
today = {
|
|
name = "Today";
|
|
entities = [ "input_select.scene" ];
|
|
};
|
|
# other stuff
|
|
# -----------
|
|
tv = { name = "TV"; };
|
|
all_lights = { name = "Alle Lampen"; };
|
|
unknown = {
|
|
name = "Not Used";
|
|
entities = [ ];
|
|
};
|
|
|
|
};
|
|
|
|
script = let
|
|
# delay in seconds
|
|
delay = 2;
|
|
|
|
heater_on = heater: temperatur: {
|
|
service = "mqtt.publish";
|
|
data_template = {
|
|
topic = "zigbee2mqtt/${heater}/set"; # office
|
|
payload_template = ''
|
|
{"system_mode":"auto","current_heating_setpoint":${
|
|
toString temperatur
|
|
}}'';
|
|
};
|
|
};
|
|
heater_off = heater: {
|
|
service = "mqtt.publish";
|
|
data_template = {
|
|
topic = "zigbee2mqtt/${heater}/set"; # office
|
|
payload_template = ''{"system_mode":"off"}'';
|
|
};
|
|
};
|
|
|
|
hot = 27;
|
|
cold = 19;
|
|
|
|
fyrtur_command = device: position: {
|
|
service = "mqtt.publish";
|
|
data_template = {
|
|
topic = "zigbee2mqtt/${device}/set";
|
|
payload_template = ''{"position":"${toString position}"}'';
|
|
};
|
|
};
|
|
|
|
in {
|
|
heater_off = {
|
|
sequence = [
|
|
(heater_on "heater1" 5) # office
|
|
{ delay = delay; }
|
|
(heater_on "heater2" 5) # office
|
|
{ delay = delay; }
|
|
(heater_on "heater3" 5) # bed room
|
|
{ delay = delay; }
|
|
(heater_on "heater4" 5) # storage room
|
|
];
|
|
};
|
|
heater_on1 = {
|
|
sequence = [
|
|
(heater_on "heater1" hot) # office
|
|
{ delay = delay; }
|
|
(heater_on "heater2" hot) # office
|
|
{ delay = delay; }
|
|
(heater_on "heater3" cold) # bed room
|
|
{ delay = delay; }
|
|
(heater_on "heater4" cold) # storage room
|
|
];
|
|
};
|
|
heater_on2 = {
|
|
sequence = [
|
|
(heater_on "heater1" hot) # office
|
|
{ delay = delay; }
|
|
(heater_on "heater2" hot) # office
|
|
{ delay = delay; }
|
|
(heater_on "heater3" hot) # bed room
|
|
{ delay = delay; }
|
|
(heater_on "heater4" cold) # storage room
|
|
];
|
|
};
|
|
|
|
fyrtur_up = {
|
|
sequence = [
|
|
(fyrtur_command "fyrtur1" 100)
|
|
{ delay = delay; }
|
|
(fyrtur_command "fyrtur2" 100)
|
|
{ delay = delay; }
|
|
(fyrtur_command "fyrtur3" 100)
|
|
{ delay = delay; }
|
|
(fyrtur_command "fyrtur4" 100)
|
|
];
|
|
};
|
|
|
|
fyrtur_down = {
|
|
sequence = [
|
|
(fyrtur_command "fyrtur1" 16)
|
|
{ delay = delay; }
|
|
(fyrtur_command "fyrtur2" 16)
|
|
{ delay = delay; }
|
|
(fyrtur_command "fyrtur3" 22)
|
|
{ delay = delay; }
|
|
(fyrtur_command "fyrtur4" 22)
|
|
];
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
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 ];
|
|
# # };
|
|
# #})
|
|
# ];
|
|
#};
|
|
|
|
};
|
|
|
|
# host nginx setup
|
|
services.nginx = {
|
|
enable = true;
|
|
recommendedProxySettings = true;
|
|
virtualHosts = {
|
|
"iot.pepe.private" = {
|
|
serverAliases = [ "hass.pepe.private" "home.pepe.private" ];
|
|
locations."/" = { proxyPass = "http://pepe.private:8123"; };
|
|
};
|
|
};
|
|
};
|
|
|
|
}
|