Add home-assistant functions
This commit is contained in:
parent
d19347344d
commit
82d5688ef7
|
@ -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 = [
|
||||||
|
|
12
nixos/roles/home-assistant-local/jinja.nix
Normal file
12
nixos/roles/home-assistant-local/jinja.nix
Normal 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}')";
|
||||||
|
}
|
68
nixos/roles/home-assistant-local/lib.nix
Normal file
68
nixos/roles/home-assistant-local/lib.nix
Normal 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; };
|
||||||
|
};
|
||||||
|
}
|
Loading…
Reference in a new issue