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
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;
homeAssistantDir = "/disk/persist/home-assistant";
in
@ -10,6 +42,7 @@ in
];
imports = [
(modules.mkModeSwitcher modes.flat { })
"${nixos-unstable}/nixos/modules/services/misc/home-assistant.nix"
./hexa-cards.nix
];
@ -39,16 +72,6 @@ in
};
};
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 = {
primary-color = "#858EFF";
};
@ -99,17 +122,19 @@ in
}
{
alias = "Thermostatsteuerung Schlafzimmer";
trigger = [
{ platform = "state"; entity_id = "input_number.target_temperature_schlafzimmer"; }
{ platform = "state"; entity_id = "sensor.schlafzimmer_temperature"; }
{ platform = "state"; entity_id = "binary_sensor.schlafzimmerfenster"; }
{ platform = "state"; entity_id = "climate.schlafzimmer"; }
trigger = with triggers; [
(stateTrigger "input_number.target_temperature_schlafzimmer")
(stateTrigger "sensor.schlafzimmer_temperature")
(stateTrigger "binary_sensor.schlafzimmerfenster")
(stateTrigger "climate.schlafzimmer")
(modeSwitchTrigger modes.flat)
];
action = [{
choose = [{
conditions = [
{ condition = "numeric_state"; entity_id = "sensor.schlafzimmer_temperature"; below = "input_number.target_temperature_schlafzimmer"; }
{ condition = "state"; entity_id = "binary_sensor.schlafzimmerfenster"; state = "off"; }
(conditions.modeIs modes.flat "active")
];
sequence = {
service = "climate.set_temperature";
@ -125,17 +150,19 @@ in
}
{
alias = "Thermostatsteuerung Küche";
trigger = [
trigger = with triggers; [
{ platform = "state"; entity_id = "input_number.target_temperature_kueche"; }
{ platform = "state"; entity_id = "sensor.kueche_temperature"; }
{ platform = "state"; entity_id = "binary_sensor.kuechenfenster"; }
{ platform = "state"; entity_id = "climate.kueche"; }
(modeSwitchTrigger modes.flat)
];
action = [{
choose = [{
conditions = [
{ condition = "numeric_state"; entity_id = "sensor.kueche_temperature"; below = "input_number.target_temperature_kueche"; }
{ condition = "state"; entity_id = "binary_sensor.kuechenfenster"; state = "off"; }
(conditions.modeIs modes.flat "active")
];
sequence = {
service = "climate.set_temperature";
@ -151,14 +178,16 @@ in
}
{
alias = "Thermostatsteuerung Wohnzimmer";
trigger = [
trigger = with triggers; [
{ platform = "state"; entity_id = "input_number.target_temperature_wohnzimmer"; }
{ platform = "state"; entity_id = "binary_sensor.wohnzimmerfenster"; }
{ platform = "state"; entity_id = "climate.wohnzimmer"; }
(modeSwitchTrigger modes.flat)
];
action = [{
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 = {
service = "climate.set_temperature";
target.area_id = "wohnzimmer";
@ -179,7 +208,7 @@ in
target.entity_id = "input_number.target_temperature_kueche";
data.value = ''
{% if is_state('input_select.scene_kueche', 'empty') %}
17
18
{% else %}
21
{% endif %}
@ -194,7 +223,7 @@ in
target.entity_id = "input_number.target_temperature_wohnzimmer";
data.value = ''
{% if is_state('input_select.scene_wohnzimmer', 'empty') %}
17
18
{% else %}
24
{% endif %}
@ -209,7 +238,7 @@ in
target.entity_id = "input_number.target_temperature_schlafzimmer";
data.value = ''
{% if is_state('input_select.scene_schlafzimmer', 'empty') %}
17
18
{% else %}
21
{% endif %}
@ -245,19 +274,19 @@ in
{
alias = "Schlafzimmer vorheizen";
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"; }];
}
{
alias = "Schlafzimmer nachts kühl";
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"; }];
}
{
alias = "Morgens Licht an";
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"; }];
}
# Warnung für offene Fenster oder Türen
@ -662,6 +691,7 @@ in
flurstack = {
type = "vertical-stack";
cards = [
(cards.modeSwitcher modes.flat)
{
type = "custom:mini-graph-card";
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; };
};
}