1
0
Fork 0

Add home-assistant functions

This commit is contained in:
Malte Brandy 2021-12-23 18:02:52 +01:00
parent d19347344d
commit 82d5688ef7
3 changed files with 135 additions and 25 deletions

View file

@ -1,5 +1,37 @@
{ pkgs, ... }: { pkgs, lib, ... }:
let let
haLib = import ./lib.nix lib;
inherit (haLib) modules util cards conditions triggers;
modes =
let
empty = {
icon = util.mkIcon "account-off";
title = "Leer";
};
heat = {
icon = util.mkIcon "radiator";
title = "Heizen";
};
active = {
icon = util.mkIcon "account";
title = "Aktiv";
};
force-active = {
icon = util.mkIcon "lightbulb-on";
title = "Alles An";
};
vacation = {
icon = util.mkIcon "airplane";
title = "Urlaub";
};
in
{
flat = {
title = "Wohnung";
name = "flat";
options = { inherit active vacation; };
};
};
inherit (import ../../../nix/sources.nix) nixos-unstable; inherit (import ../../../nix/sources.nix) nixos-unstable;
homeAssistantDir = "/disk/persist/home-assistant"; homeAssistantDir = "/disk/persist/home-assistant";
in in
@ -10,6 +42,7 @@ in
]; ];
imports = [ imports = [
(modules.mkModeSwitcher modes.flat { })
"${nixos-unstable}/nixos/modules/services/misc/home-assistant.nix" "${nixos-unstable}/nixos/modules/services/misc/home-assistant.nix"
./hexa-cards.nix ./hexa-cards.nix
]; ];
@ -39,16 +72,6 @@ in
}; };
}; };
homeassistant = pkgs.privateValue { } "homeassistant-home"; homeassistant = pkgs.privateValue { } "homeassistant-home";
logger = {
default = "info";
logs = {
"homeassistant.core" = "debug";
"homeassistant.components.zha" = "debug";
zigpy = "debug";
zigpy_znp = "debug";
zhaquirks = "debug";
};
};
frontend.themes.ourdefault = { frontend.themes.ourdefault = {
primary-color = "#858EFF"; primary-color = "#858EFF";
}; };
@ -99,17 +122,19 @@ in
} }
{ {
alias = "Thermostatsteuerung Schlafzimmer"; alias = "Thermostatsteuerung Schlafzimmer";
trigger = [ trigger = with triggers; [
{ platform = "state"; entity_id = "input_number.target_temperature_schlafzimmer"; } (stateTrigger "input_number.target_temperature_schlafzimmer")
{ platform = "state"; entity_id = "sensor.schlafzimmer_temperature"; } (stateTrigger "sensor.schlafzimmer_temperature")
{ platform = "state"; entity_id = "binary_sensor.schlafzimmerfenster"; } (stateTrigger "binary_sensor.schlafzimmerfenster")
{ platform = "state"; entity_id = "climate.schlafzimmer"; } (stateTrigger "climate.schlafzimmer")
(modeSwitchTrigger modes.flat)
]; ];
action = [{ action = [{
choose = [{ choose = [{
conditions = [ conditions = [
{ condition = "numeric_state"; entity_id = "sensor.schlafzimmer_temperature"; below = "input_number.target_temperature_schlafzimmer"; } { condition = "numeric_state"; entity_id = "sensor.schlafzimmer_temperature"; below = "input_number.target_temperature_schlafzimmer"; }
{ condition = "state"; entity_id = "binary_sensor.schlafzimmerfenster"; state = "off"; } { condition = "state"; entity_id = "binary_sensor.schlafzimmerfenster"; state = "off"; }
(conditions.modeIs modes.flat "active")
]; ];
sequence = { sequence = {
service = "climate.set_temperature"; service = "climate.set_temperature";
@ -125,17 +150,19 @@ in
} }
{ {
alias = "Thermostatsteuerung Küche"; alias = "Thermostatsteuerung Küche";
trigger = [ trigger = with triggers; [
{ platform = "state"; entity_id = "input_number.target_temperature_kueche"; } { platform = "state"; entity_id = "input_number.target_temperature_kueche"; }
{ platform = "state"; entity_id = "sensor.kueche_temperature"; } { platform = "state"; entity_id = "sensor.kueche_temperature"; }
{ platform = "state"; entity_id = "binary_sensor.kuechenfenster"; } { platform = "state"; entity_id = "binary_sensor.kuechenfenster"; }
{ platform = "state"; entity_id = "climate.kueche"; } { platform = "state"; entity_id = "climate.kueche"; }
(modeSwitchTrigger modes.flat)
]; ];
action = [{ action = [{
choose = [{ choose = [{
conditions = [ conditions = [
{ condition = "numeric_state"; entity_id = "sensor.kueche_temperature"; below = "input_number.target_temperature_kueche"; } { condition = "numeric_state"; entity_id = "sensor.kueche_temperature"; below = "input_number.target_temperature_kueche"; }
{ condition = "state"; entity_id = "binary_sensor.kuechenfenster"; state = "off"; } { condition = "state"; entity_id = "binary_sensor.kuechenfenster"; state = "off"; }
(conditions.modeIs modes.flat "active")
]; ];
sequence = { sequence = {
service = "climate.set_temperature"; service = "climate.set_temperature";
@ -151,14 +178,16 @@ in
} }
{ {
alias = "Thermostatsteuerung Wohnzimmer"; alias = "Thermostatsteuerung Wohnzimmer";
trigger = [ trigger = with triggers; [
{ platform = "state"; entity_id = "input_number.target_temperature_wohnzimmer"; } { platform = "state"; entity_id = "input_number.target_temperature_wohnzimmer"; }
{ platform = "state"; entity_id = "binary_sensor.wohnzimmerfenster"; } { platform = "state"; entity_id = "binary_sensor.wohnzimmerfenster"; }
{ platform = "state"; entity_id = "climate.wohnzimmer"; } { platform = "state"; entity_id = "climate.wohnzimmer"; }
(modeSwitchTrigger modes.flat)
]; ];
action = [{ action = [{
choose = [{ choose = [{
conditions = [{ condition = "state"; entity_id = "binary_sensor.wohnzimmerfenster"; state = "off"; }]; conditions = [{ condition = "state"; entity_id = "binary_sensor.wohnzimmerfenster"; state = "off"; }
(conditions.modeIs modes.flat "active")];
sequence = { sequence = {
service = "climate.set_temperature"; service = "climate.set_temperature";
target.area_id = "wohnzimmer"; target.area_id = "wohnzimmer";
@ -179,7 +208,7 @@ in
target.entity_id = "input_number.target_temperature_kueche"; target.entity_id = "input_number.target_temperature_kueche";
data.value = '' data.value = ''
{% if is_state('input_select.scene_kueche', 'empty') %} {% if is_state('input_select.scene_kueche', 'empty') %}
17 18
{% else %} {% else %}
21 21
{% endif %} {% endif %}
@ -194,7 +223,7 @@ in
target.entity_id = "input_number.target_temperature_wohnzimmer"; target.entity_id = "input_number.target_temperature_wohnzimmer";
data.value = '' data.value = ''
{% if is_state('input_select.scene_wohnzimmer', 'empty') %} {% if is_state('input_select.scene_wohnzimmer', 'empty') %}
17 18
{% else %} {% else %}
24 24
{% endif %} {% endif %}
@ -209,7 +238,7 @@ in
target.entity_id = "input_number.target_temperature_schlafzimmer"; target.entity_id = "input_number.target_temperature_schlafzimmer";
data.value = '' data.value = ''
{% if is_state('input_select.scene_schlafzimmer', 'empty') %} {% if is_state('input_select.scene_schlafzimmer', 'empty') %}
17 18
{% else %} {% else %}
21 21
{% endif %} {% endif %}
@ -245,19 +274,19 @@ in
{ {
alias = "Schlafzimmer vorheizen"; alias = "Schlafzimmer vorheizen";
trigger = [{ platform = "time"; at = "19:00:00"; } { platform = "time"; at = "04:00:00"; }]; trigger = [{ platform = "time"; at = "19:00:00"; } { platform = "time"; at = "04:00:00"; }];
condition = [{ condition = "state"; entity_id = "input_select.scene_schlafzimmer"; state = "empty"; }]; condition = [{ condition = "state"; entity_id = "input_select.scene_schlafzimmer"; state = "empty"; } (conditions.modeIs modes.flat "active")];
action = [{ service = "input_select.select_option"; data.option = "heat"; entity_id = "input_select.scene_schlafzimmer"; }]; action = [{ service = "input_select.select_option"; data.option = "heat"; entity_id = "input_select.scene_schlafzimmer"; }];
} }
{ {
alias = "Schlafzimmer nachts kühl"; alias = "Schlafzimmer nachts kühl";
trigger = [{ platform = "time"; at = "01:00:00"; }]; trigger = [{ platform = "time"; at = "01:00:00"; }];
condition = [{ condition = "state"; entity_id = "input_select.scene_schlafzimmer"; state = "heat"; }]; condition = [{ condition = "state"; entity_id = "input_select.scene_schlafzimmer"; state = "heat"; } (conditions.modeIs modes.flat "active")];
action = [{ service = "input_select.select_option"; data.option = "empty"; entity_id = "input_select.scene_schlafzimmer"; }]; action = [{ service = "input_select.select_option"; data.option = "empty"; entity_id = "input_select.scene_schlafzimmer"; }];
} }
{ {
alias = "Morgens Licht an"; alias = "Morgens Licht an";
trigger = [{ platform = "time"; at = "08:00:00"; }]; trigger = [{ platform = "time"; at = "08:00:00"; }];
condition = [{ condition = "state"; entity_id = "input_select.scene_schlafzimmer"; state = "heat"; }]; condition = [{ condition = "state"; entity_id = "input_select.scene_schlafzimmer"; state = "heat"; } (conditions.modeIs modes.flat "active")];
action = [{ service = "input_select.select_option"; data.option = "active"; entity_id = "input_select.scene_schlafzimmer"; }]; action = [{ service = "input_select.select_option"; data.option = "active"; entity_id = "input_select.scene_schlafzimmer"; }];
} }
# Warnung für offene Fenster oder Türen # Warnung für offene Fenster oder Türen
@ -662,6 +691,7 @@ in
flurstack = { flurstack = {
type = "vertical-stack"; type = "vertical-stack";
cards = [ cards = [
(cards.modeSwitcher modes.flat)
{ {
type = "custom:mini-graph-card"; type = "custom:mini-graph-card";
entities = [ entities = [

View file

@ -0,0 +1,12 @@
lib: rec {
case = default: attrs: ''
{% if ${lib.concatStringsSep "\n{% elseif " (lib.mapAttrsToList (condition: result: "${condition} %}\n ${result}") attrs)}
{% else %}
${default}
{% endif %}
'';
if' = condition: ifTrue: ifFalse: case ifFalse { ${condition} = ifTrue; };
or = lhs: rhs: "(${lhs} or ${rhs})";
and = lhs: rhs: "(${lhs} and ${rhs})";
isState = entity: state: "is_state('${entity}','${state}')";
}

View file

@ -0,0 +1,68 @@
lib:
let
# name refers to an internal name
# title refers to a human readable name
# mode = { name, title, options = { <option_name> : { title , icon } } }
in
rec {
jinja = import ./jinja.nix lib;
tap_actions = {
setMode = mode: option: {
action = "call-service";
service = "input_select.select_option";
service_data = { entity_id = util.modeSelectEntity mode; inherit option; };
};
};
util = rec {
mkIcon = name: "mdi:${name}";
mkMode = name: options: { inherit name options; };
modeSelectEntity = mode: "input_select.${modeSelectName mode}";
modeSelectName = mode: "mode_${mode.name}";
modeBinarySensorName = mode: option: "${modeSelectName mode}_is_${option}";
modeBinarySensorEntity = mode: option: "binary_sensor.${modeBinarySensorName mode option}";
};
triggers = rec {
stateTrigger = entity: { platform = "state"; entity_id = entity; };
modeSwitchTrigger = mode: stateTrigger (util.modeSelectEntity mode);
};
conditions = {
modeIs = mode: option: { condition = "state"; entity_id = util.modeSelectEntity mode; state = option; };
};
modules = rec {
mkHAConfig = attrs: {
services.home-assistant.config = attrs;
};
mkModeSwitcher = mode: attrs: { ... }:
let
options = builtins.attrNames mode.options;
in
mkHAConfig {
input_select.${util.modeSelectName mode} = { inherit options; } // attrs;
template = builtins.map (templates.binarySensorForMode mode) options;
};
};
cards = {
modeSwitcher = mode:
let
mkEntity = optionName: option:
{
entity = util.modeBinarySensorEntity mode optionName;
name = option.title;
inherit (option) icon;
tap_action = tap_actions.setMode mode optionName;
};
in
{
type = "glance";
inherit (mode) title;
columns = builtins.length (builtins.attrNames mode.options);
show_state = false;
entities = lib.mapAttrsToList mkEntity mode.options;
};
};
templates = rec {
binarySensor = state: attrs: { binary_sensor = [ ({ inherit state; } // attrs) ]; };
binarySensorFromCondition = condition: binarySensor (jinja.if' condition "1" "0");
binarySensorForMode = mode: option: binarySensorFromCondition (jinja.isState (util.modeSelectEntity mode) option) { name = util.modeBinarySensorName mode option; };
};
}