Compare commits
35 Commits
f6fe2f9ab9
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| edc4cabde5 | |||
| bf5409d36e | |||
| 3491ac64db | |||
| c6301b9f76 | |||
| b8839bac3a | |||
| 2eba16f2e7 | |||
| 2c838a85a1 | |||
| 7dd83511a3 | |||
| 1bac8c5e4c | |||
| 106d6215b1 | |||
| e99c3aa967 | |||
| 90f895dbe5 | |||
| 2e6fcefca4 | |||
| 69c65c844f | |||
| a2343237c3 | |||
| 5dd43bbd89 | |||
| a797acf3ab | |||
| e72365df0a | |||
| 0bb4ced299 | |||
| 3ff5db1cbf | |||
| 5895c7c9dc | |||
| aee08c12cc | |||
| 2fdf78ac75 | |||
| d58ea02aeb | |||
| 1d0b0ff241 | |||
| 413eea13e0 | |||
| a170d7d0e2 | |||
| 336f8e2e74 | |||
| 59edb3265c | |||
| 1759929d9f | |||
| 6ccbe1839b | |||
| f719294bcf | |||
| 9e9dbf8e5f | |||
| 1f0cc41a58 | |||
| 146e4e6ab5 |
@@ -6,6 +6,11 @@ blueprint:
|
|||||||
min_version: "2024.6.0"
|
min_version: "2024.6.0"
|
||||||
description: >
|
description: >
|
||||||
Eine Automation zur automatischen Steuerung eines Bosch TRV Heizkörperthermostats.
|
Eine Automation zur automatischen Steuerung eines Bosch TRV Heizkörperthermostats.
|
||||||
|
|
||||||
|
**Temperatur-Prioritätslogik:**
|
||||||
|
1. Alarm armed_away → Abwesenheitstemperatur
|
||||||
|
2. Aktiver Zeitplan → Temperatur aus Schedule
|
||||||
|
3. Fallback → Abwesenheitstemperatur
|
||||||
domain: automation
|
domain: automation
|
||||||
author: Me
|
author: Me
|
||||||
input:
|
input:
|
||||||
@@ -25,6 +30,24 @@ blueprint:
|
|||||||
filter:
|
filter:
|
||||||
- domain: sensor
|
- domain: sensor
|
||||||
device_class: temperature
|
device_class: temperature
|
||||||
|
sensor_sync_threshold:
|
||||||
|
name: Sensor-Synchronisations-Schwellenwert
|
||||||
|
description: >
|
||||||
|
Minimale Temperaturdifferenz in °C, um eine Sensor-Synchronisation auszulösen (Default = 0.5°C).
|
||||||
|
|
||||||
|
**Synchronisation erfolgt bei:**
|
||||||
|
1. Differenz zwischen Sensor und TRV ≥ Schwellenwert
|
||||||
|
2. Sensor kreuzt Solltemperatur von unten (verhindert zu spätes Aufheizen)
|
||||||
|
3. Sensor kreuzt Solltemperatur von oben (verhindert Überhitzung)
|
||||||
|
4. Spätestens nach 25 Minuten ohne Änderung
|
||||||
|
default: 0.5
|
||||||
|
selector:
|
||||||
|
number:
|
||||||
|
mode: box
|
||||||
|
min: 0.1
|
||||||
|
max: 1.0
|
||||||
|
unit_of_measurement: "°C"
|
||||||
|
step: 0.1
|
||||||
heating_period_switch:
|
heating_period_switch:
|
||||||
name: Heizperiode Switch
|
name: Heizperiode Switch
|
||||||
description: Optional - Input Boolean der angibt ob Heizperiode aktiv ist. Wenn nicht gesetzt, ist die Heizperiode immer aktiv.
|
description: Optional - Input Boolean der angibt ob Heizperiode aktiv ist. Wenn nicht gesetzt, ist die Heizperiode immer aktiv.
|
||||||
@@ -35,7 +58,9 @@ blueprint:
|
|||||||
- domain: input_boolean
|
- domain: input_boolean
|
||||||
min_temperature:
|
min_temperature:
|
||||||
name: Minimale Temperatur
|
name: Minimale Temperatur
|
||||||
description: Minimale erlaubte Solltemperatur als Sicherheitsgrenze (Default = 15°C)
|
description: >
|
||||||
|
Minimale erlaubte Solltemperatur als Sicherheitsgrenze (Default = 15°C).
|
||||||
|
Alle berechneten Temperaturen werden auf diesen Minimalwert begrenzt (Clamping).
|
||||||
default: 15
|
default: 15
|
||||||
selector:
|
selector:
|
||||||
number:
|
number:
|
||||||
@@ -46,7 +71,9 @@ blueprint:
|
|||||||
step: 0.5
|
step: 0.5
|
||||||
max_temperature:
|
max_temperature:
|
||||||
name: Maximale Temperatur
|
name: Maximale Temperatur
|
||||||
description: Maximale erlaubte Solltemperatur als Sicherheitsgrenze (Default = 28°C)
|
description: >
|
||||||
|
Maximale erlaubte Solltemperatur als Sicherheitsgrenze (Default = 23°C).
|
||||||
|
Alle berechneten Temperaturen werden auf diesen Maximalwert begrenzt (Clamping).
|
||||||
default: 23
|
default: 23
|
||||||
selector:
|
selector:
|
||||||
number:
|
number:
|
||||||
@@ -58,7 +85,7 @@ blueprint:
|
|||||||
window_section:
|
window_section:
|
||||||
name: Fenster-/Türsensor Konfiguration
|
name: Fenster-/Türsensor Konfiguration
|
||||||
description: Konfiguration für den Fenster-/Türsensor.
|
description: Konfiguration für den Fenster-/Türsensor.
|
||||||
collapsed: false
|
collapsed: true
|
||||||
input:
|
input:
|
||||||
window_sensor:
|
window_sensor:
|
||||||
name: Fenster-/Türsensor (oder Gruppe)
|
name: Fenster-/Türsensor (oder Gruppe)
|
||||||
@@ -92,7 +119,7 @@ blueprint:
|
|||||||
schedule_section:
|
schedule_section:
|
||||||
name: Heizplan Konfiguration
|
name: Heizplan Konfiguration
|
||||||
description: Konfiguration der Heizpläne die für den Radiator berücksichtigt werden sollen
|
description: Konfiguration der Heizpläne die für den Radiator berücksichtigt werden sollen
|
||||||
collapsed: false
|
collapsed: true
|
||||||
input:
|
input:
|
||||||
radiator_schedules:
|
radiator_schedules:
|
||||||
name: Heizpläne
|
name: Heizpläne
|
||||||
@@ -123,7 +150,7 @@ blueprint:
|
|||||||
away_section:
|
away_section:
|
||||||
name: Konfiguration für Abwesenheitsmodus
|
name: Konfiguration für Abwesenheitsmodus
|
||||||
description: Konfiguration für das Absenken der Heizung im Abwesenheitsmodus eines Alarmsystems
|
description: Konfiguration für das Absenken der Heizung im Abwesenheitsmodus eines Alarmsystems
|
||||||
collapsed: false
|
collapsed: true
|
||||||
input:
|
input:
|
||||||
alarm_control_panel:
|
alarm_control_panel:
|
||||||
name: Alarm Control Panel
|
name: Alarm Control Panel
|
||||||
@@ -135,7 +162,12 @@ blueprint:
|
|||||||
- domain: alarm_control_panel
|
- domain: alarm_control_panel
|
||||||
away_temperature:
|
away_temperature:
|
||||||
name: Abwesenheitstemperatur
|
name: Abwesenheitstemperatur
|
||||||
description: Temperatur die eingestellt wird, wenn der Alarm im Abwesendmodus ist (Default = 18°C)
|
description: >
|
||||||
|
Temperatur die verwendet wird, wenn der Alarm im Abwesendmodus ist oder kein Zeitplan aktiv ist (Default = 18°C).
|
||||||
|
|
||||||
|
**Verwendung:**
|
||||||
|
- Primär: Alarm Control Panel im Modus 'armed_away' (höchste Priorität)
|
||||||
|
- Fallback: Wenn kein aktiver Zeitplan eine Temperatur liefert
|
||||||
default: 18
|
default: 18
|
||||||
selector:
|
selector:
|
||||||
number:
|
number:
|
||||||
@@ -144,10 +176,39 @@ blueprint:
|
|||||||
max: 25.0
|
max: 25.0
|
||||||
unit_of_measurement: "°C"
|
unit_of_measurement: "°C"
|
||||||
step: 0.5
|
step: 0.5
|
||||||
|
override_section:
|
||||||
|
name: Override Reset Konfiguration
|
||||||
|
description: Automatisches Zurücksetzen der Solltemperatur nach manueller Änderung am Thermostat
|
||||||
|
collapsed: true
|
||||||
|
input:
|
||||||
|
override_reset_duration:
|
||||||
|
name: Override Reset Zeitraum
|
||||||
|
description: >
|
||||||
|
Zeit nach der eine manuelle Temperaturänderung automatisch auf den Heizplan zurückgesetzt wird.
|
||||||
|
|
||||||
|
**Feature deaktiviert wenn auf 00:00:00 gesetzt** (Default = 00:00:00)
|
||||||
|
|
||||||
|
**Verhalten:**
|
||||||
|
- Nur manuelle Änderungen am Thermostat werden zurückgesetzt (nicht über Home Assistant)
|
||||||
|
- Timer startet neu bei jeder weiteren manuellen Änderung
|
||||||
|
- Reset erfolgt nur wenn Solltemperatur vom Heizplan abweicht
|
||||||
|
- Wenn kein Schedule aktiv ist, wird auf Abwesenheitstemperatur zurückgesetzt
|
||||||
|
- Alarm-Modus hat Priorität: Bei aktivem Alarm erfolgt kein Reset (Abwesenheitstemperatur gilt)
|
||||||
|
|
||||||
|
Beispiel: Nach 2 Stunden wird die Temperatur wieder auf den aktiven Heizplan-Wert gesetzt.
|
||||||
|
default:
|
||||||
|
hours: 0
|
||||||
|
minutes: 0
|
||||||
|
seconds: 0
|
||||||
|
selector:
|
||||||
|
duration:
|
||||||
|
enable_day: false
|
||||||
|
|
||||||
variables:
|
variables:
|
||||||
|
# Input-Variablen
|
||||||
trv: !input trv
|
trv: !input trv
|
||||||
temperature_sensor: !input temperature_sensor
|
temperature_sensor: !input temperature_sensor
|
||||||
|
sensor_sync_threshold: !input sensor_sync_threshold
|
||||||
heating_period_switch: !input heating_period_switch
|
heating_period_switch: !input heating_period_switch
|
||||||
radiator_schedules: !input radiator_schedules
|
radiator_schedules: !input radiator_schedules
|
||||||
active_scheduler_selector: !input active_scheduler_selector
|
active_scheduler_selector: !input active_scheduler_selector
|
||||||
@@ -155,101 +216,113 @@ variables:
|
|||||||
min_temperature: !input min_temperature
|
min_temperature: !input min_temperature
|
||||||
max_temperature: !input max_temperature
|
max_temperature: !input max_temperature
|
||||||
alarm_control_panel: !input alarm_control_panel
|
alarm_control_panel: !input alarm_control_panel
|
||||||
is_heating_period: >
|
override_reset_duration: !input override_reset_duration
|
||||||
{% if heating_period_switch is none or heating_period_switch == '' %}
|
|
||||||
true
|
# Konstanten
|
||||||
{% else %}
|
temperature_change_tolerance: 0.4 # °C - Minimale Differenz für Temperaturänderung
|
||||||
{{ is_state(heating_period_switch, 'on') }}
|
sensor_sync_max_age: 1499 # Sekunden (25 Minuten - 1 Sekunde) - Max Alter für Sensor-Sync
|
||||||
{% endif %}
|
random_delay_max_seconds: 30
|
||||||
|
|
||||||
|
# Zufalls-Delay für climate.set_temperature
|
||||||
|
random_delay_seconds: "{{ range(0, random_delay_max_seconds + 1) | random }}"
|
||||||
|
|
||||||
|
# Entity-Discovery
|
||||||
remote_temperature_entity: >
|
remote_temperature_entity: >
|
||||||
{% set entities = device_entities(device_id(trv)) %}
|
{{ device_entities(device_id(trv)) | select('search', 'remote_temperature') | list | first | default('') }}
|
||||||
{% set remote_temperature_entity_id = namespace(id='') %}
|
|
||||||
{% for entity in entities %}
|
|
||||||
{% if 'remote_temperature' in entity %}
|
|
||||||
{% set remote_temperature_entity_id.id = entity %}
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
{{ remote_temperature_entity_id.id }}
|
|
||||||
window_detection_entity: >
|
window_detection_entity: >
|
||||||
{% set entities = device_entities(device_id(trv)) %}
|
{{ device_entities(device_id(trv)) | select('search', 'window_detection') | list | first | default('') }}
|
||||||
{% set window_detection_entity_id = namespace(id='') %}
|
setpoint_change_source_entity: >
|
||||||
{% for entity in entities %}
|
{{ device_entities(device_id(trv)) | select('search', 'setpoint_change_source') | list | first | default('') }}
|
||||||
{% if 'window_detection' in entity %}
|
|
||||||
{% set window_detection_entity_id.id = entity %}
|
# Entity-Validierung
|
||||||
{% endif %}
|
remote_temperature_entity_valid: >
|
||||||
{% endfor %}
|
{{ remote_temperature_entity and states(remote_temperature_entity) not in ['unknown', 'unavailable', none] }}
|
||||||
{{ window_detection_entity_id.id }}
|
window_detection_entity_valid: >
|
||||||
|
{{ window_detection_entity and window_detection_entity | length > 0 }}
|
||||||
|
setpoint_change_source_entity_valid: >
|
||||||
|
{{ setpoint_change_source_entity and states(setpoint_change_source_entity) not in ['unknown', 'unavailable', none] }}
|
||||||
|
|
||||||
|
# Basis-Berechnungen
|
||||||
|
is_heating_period: >
|
||||||
|
{{ heating_period_switch in [none, ''] or is_state(heating_period_switch, 'on') }}
|
||||||
|
current_remote_temperature: >
|
||||||
|
{{ states(remote_temperature_entity) | float(0) if remote_temperature_entity_valid else 0 }}
|
||||||
|
remote_temperature_last_change: >
|
||||||
|
{{ states[remote_temperature_entity].last_changed if remote_temperature_entity_valid else none }}
|
||||||
scheduled_temperature: >
|
scheduled_temperature: >
|
||||||
{% set ns = namespace(current_temperature = none) %}
|
{% set selected = states(active_scheduler_selector) %}
|
||||||
{% set selected_friendly_name = states(active_scheduler_selector) %}
|
{% if selected not in [none, 'unknown', ''] %}
|
||||||
{% if selected_friendly_name is not none and selected_friendly_name != 'unknown' %}
|
{% for schedule in radiator_schedules if state_attr(schedule, 'friendly_name') == selected and is_state(schedule, 'on') %}
|
||||||
{% for schedule in radiator_schedules %}
|
{% set temp = state_attr(schedule, 'temp') %}
|
||||||
{% if state_attr(schedule, 'friendly_name') == selected_friendly_name and states(schedule) == 'on' %}
|
{% if temp is not none and temp | is_number %}
|
||||||
{% set temp = state_attr(schedule, 'temp') %}
|
{{ temp }}
|
||||||
{% if temp is not none and temp | is_number %}
|
{% break %}
|
||||||
{% set ns.current_temperature = temp %}
|
|
||||||
{% break %}
|
|
||||||
{% endif %}
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{{ ns.current_temperature }}
|
|
||||||
|
# Temperatur-Berechnungen
|
||||||
|
# Priorität: 1. Alarm armed_away → away_temperature, 2. Aktiver Zeitplan → scheduled_temperature, 3. Fallback → away_temperature
|
||||||
target_temperature: >
|
target_temperature: >
|
||||||
{% if alarm_control_panel and is_state(alarm_control_panel, 'armed_away') %}
|
{% if alarm_control_panel and is_state(alarm_control_panel, 'armed_away') %}
|
||||||
{{ away_temperature }}
|
{{ away_temperature }}
|
||||||
{% elif scheduled_temperature is not none %}
|
{% elif scheduled_temperature != none %}
|
||||||
{{ scheduled_temperature }}
|
{{ scheduled_temperature }}
|
||||||
{% else %}
|
{% else %}
|
||||||
{{ away_temperature }}
|
{{ away_temperature }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
# Begrenzt target_temperature auf den Bereich [min_temperature, max_temperature] (Clamping)
|
||||||
safe_temperature: >
|
safe_temperature: >
|
||||||
{% set temp = target_temperature | float(18) %}
|
{{ [min_temperature, [max_temperature, target_temperature | float(18)] | min] | max }}
|
||||||
{% if temp < min_temperature %}
|
|
||||||
{{ min_temperature }}
|
# Status-Prüfungen
|
||||||
{% elif temp > max_temperature %}
|
|
||||||
{{ max_temperature }}
|
|
||||||
{% else %}
|
|
||||||
{{ temp }}
|
|
||||||
{% endif %}
|
|
||||||
is_valid_temperature: >
|
is_valid_temperature: >
|
||||||
{{ safe_temperature is not none and safe_temperature | is_number }}
|
{{ safe_temperature is not none and safe_temperature | is_number }}
|
||||||
is_temperature_change_needed: >
|
is_temperature_change_needed: >
|
||||||
{% set current = state_attr(trv, 'temperature') | float(0) %}
|
{{ (safe_temperature | float(0) - state_attr(trv, 'temperature') | float(0)) | abs >= temperature_change_tolerance }}
|
||||||
{% set new = safe_temperature | float(0) %}
|
# Synchronisation nötig wenn: 1) Differenz > Schwelle, 2) Sensor kreuzt Soll-Temp von unten, 3) Sensor kreuzt Soll-Temp von oben
|
||||||
{% set diff = new - current %}
|
|
||||||
{% if new > current %}
|
|
||||||
true
|
|
||||||
{% elif diff | abs >= 0.5 %}
|
|
||||||
true
|
|
||||||
{% else %}
|
|
||||||
false
|
|
||||||
{% endif %}
|
|
||||||
is_sensor_sync_needed: >
|
is_sensor_sync_needed: >
|
||||||
{% set current_remote_temp = states(remote_temperature_entity) | float(0) %}
|
|
||||||
{% set new_sensor_temp = states(temperature_sensor) | float(0) %}
|
{% set new_sensor_temp = states(temperature_sensor) | float(0) %}
|
||||||
{% set target_temp = state_attr(trv, 'temperature') | float(0) %}
|
{% set target_temp = state_attr(trv, 'temperature') | float(0) %}
|
||||||
{% set diff = (new_sensor_temp - current_remote_temp) | abs %}
|
{% set diff = (new_sensor_temp - current_remote_temperature) | abs %}
|
||||||
{% if diff >= 0.5 %}
|
{{ diff >= sensor_sync_threshold or
|
||||||
true
|
(new_sensor_temp < target_temp and current_remote_temperature >= target_temp) or
|
||||||
{% elif new_sensor_temp < target_temp and current_remote_temp >= target_temp %}
|
(new_sensor_temp > target_temp and current_remote_temperature <= target_temp) }}
|
||||||
true
|
scheduler_mismatch: >
|
||||||
{% elif new_sensor_temp > target_temp and current_remote_temp <= target_temp %}
|
{% set selected = states(active_scheduler_selector) %}
|
||||||
true
|
{% if selected not in ['unknown', '', none] %}
|
||||||
|
{% set schedule_found = namespace(value=false) %}
|
||||||
|
{% for schedule in radiator_schedules %}
|
||||||
|
{% if state_attr(schedule, 'friendly_name') == selected %}
|
||||||
|
{% set schedule_found.value = true %}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
{{ not schedule_found.value }}
|
||||||
{% else %}
|
{% else %}
|
||||||
false
|
false
|
||||||
{% endif %}
|
{% endif %}
|
||||||
scheduler_mismatch: >
|
is_manual_override: >
|
||||||
{% set selected_friendly_name = states(active_scheduler_selector) %}
|
{{ (state_attr(trv, 'temperature') | float(0) - safe_temperature | float(0)) | abs >= temperature_change_tolerance }}
|
||||||
{% if selected_friendly_name not in ['unknown', '', none] %}
|
|
||||||
{% set found = namespace(value=false) %}
|
# Override Reset Berechnungen
|
||||||
{% for schedule in radiator_schedules %}
|
# Konvertiert duration-Dictionary {hours, minutes, seconds} in Gesamtsekunden
|
||||||
{% if state_attr(schedule, 'friendly_name') == selected_friendly_name %}
|
override_reset_duration_seconds: >
|
||||||
{% set found.value = true %}
|
{{ (override_reset_duration.hours | default(0) | int) * 3600 +
|
||||||
{% endif %}
|
(override_reset_duration.minutes | default(0) | int) * 60 +
|
||||||
{% endfor %}
|
(override_reset_duration.seconds | default(0) | int) if override_reset_duration is mapping else 0 }}
|
||||||
{{ not found.value }}
|
override_last_change: >
|
||||||
{% else %}
|
{{ states[setpoint_change_source_entity].last_updated if setpoint_change_source_entity_valid else none }}
|
||||||
|
is_setpoint_manual: >
|
||||||
|
{{ setpoint_change_source_entity_valid and states(setpoint_change_source_entity) == 'manual' }}
|
||||||
|
# Early exits: 1) Keine Änderung/Timeout=0 → false, 2) Nicht manuell → false, 3) Berechne Zeitdifferenz
|
||||||
|
override_duration_exceeded: >
|
||||||
|
{% if override_last_change == none or override_reset_duration_seconds == 0 %}
|
||||||
false
|
false
|
||||||
|
{% elif not is_setpoint_manual %}
|
||||||
|
false
|
||||||
|
{% else %}
|
||||||
|
{% set last_change = as_datetime(override_last_change) %}
|
||||||
|
{{ last_change != none and (now() - last_change).total_seconds() > override_reset_duration_seconds }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
triggers:
|
triggers:
|
||||||
@@ -259,21 +332,21 @@ triggers:
|
|||||||
from: "off"
|
from: "off"
|
||||||
to: "on"
|
to: "on"
|
||||||
for: !input window_delay_open
|
for: !input window_delay_open
|
||||||
id: FENSTER_OPEN
|
id: WINDOW_OPENED
|
||||||
- platform: state
|
- platform: state
|
||||||
entity_id:
|
entity_id:
|
||||||
- !input window_sensor
|
- !input window_sensor
|
||||||
from: "on"
|
from: "on"
|
||||||
to: "off"
|
to: "off"
|
||||||
for: !input window_delay_close
|
for: !input window_delay_close
|
||||||
id: FENSTER_CLOSED
|
id: WINDOW_CLOSED
|
||||||
- platform: time_pattern
|
- platform: time_pattern
|
||||||
# Synce Temperatur alle 5 Minuten (Teiler von 60)
|
# Periodische Überprüfung alle 5 Minuten (Temperatursynchronisation, Override-Check)
|
||||||
minutes: "/5"
|
minutes: "/5"
|
||||||
id: SYNC_TEMPERATURE
|
id: PERIODIC_CHECK
|
||||||
- platform: state
|
- platform: state
|
||||||
entity_id: !input temperature_sensor
|
entity_id: !input temperature_sensor
|
||||||
id: TEMP_CHANGED
|
id: SENSOR_TEMPERATURE_CHANGED
|
||||||
- platform: state
|
- platform: state
|
||||||
entity_id: !input alarm_control_panel
|
entity_id: !input alarm_control_panel
|
||||||
to: "armed_away"
|
to: "armed_away"
|
||||||
@@ -281,38 +354,43 @@ triggers:
|
|||||||
- platform: state
|
- platform: state
|
||||||
entity_id: !input alarm_control_panel
|
entity_id: !input alarm_control_panel
|
||||||
from: "armed_away"
|
from: "armed_away"
|
||||||
to: "disarmed"
|
id: ALARM_DISARMED
|
||||||
id: ALARM_DISARMED_AWAY
|
|
||||||
- platform: state
|
- platform: state
|
||||||
entity_id: !input heating_period_switch
|
entity_id: !input heating_period_switch
|
||||||
to: "on"
|
to: "on"
|
||||||
id: HEATING_PERIOD_ON
|
id: HEATING_PERIOD_STARTED
|
||||||
- platform: state
|
- platform: state
|
||||||
entity_id: !input heating_period_switch
|
entity_id: !input heating_period_switch
|
||||||
to: "off"
|
to: "off"
|
||||||
id: HEATING_PERIOD_OFF
|
id: HEATING_PERIOD_ENDED
|
||||||
- platform: state
|
- platform: state
|
||||||
entity_id: !input radiator_schedules
|
entity_id: !input radiator_schedules
|
||||||
attribute: temp
|
attribute: temp
|
||||||
id: SCHEDULE_TEMP_CHANGED
|
id: SCHEDULE_TEMPERATURE_CHANGED
|
||||||
- platform: state
|
- platform: state
|
||||||
entity_id: !input active_scheduler_selector
|
entity_id: !input active_scheduler_selector
|
||||||
id: SCHEDULER_CHANGED
|
id: SCHEDULE_SELECTOR_CHANGED
|
||||||
|
|
||||||
|
# Hinweis zur Wartbarkeit: climate.set_temperature wird an 4 Stellen verwendet:
|
||||||
|
# 1. Heizperiode aktiviert - Setzt Temperatur beim Einschalten der Heizung
|
||||||
|
# 2. Fenster geschlossen - Setzt Temperatur nach Fensterschließung
|
||||||
|
# 3. Override Reset - Setzt Temperatur zurück nach manuellem Override
|
||||||
|
# 4. Schedule/Alarm-Änderungen - Setzt Temperatur bei Zeitplan- oder Alarmänderungen
|
||||||
|
# Standardformat: service: climate.set_temperature | target: !input trv | data: safe_temperature
|
||||||
actions:
|
actions:
|
||||||
- choose:
|
- choose:
|
||||||
# Heizperiode Switch Aktionen
|
# Heizperiode Switch Aktionen
|
||||||
- conditions:
|
- conditions:
|
||||||
- condition: trigger
|
- condition: trigger
|
||||||
id:
|
id:
|
||||||
- HEATING_PERIOD_ON
|
- HEATING_PERIOD_STARTED
|
||||||
- HEATING_PERIOD_OFF
|
- HEATING_PERIOD_ENDED
|
||||||
sequence:
|
sequence:
|
||||||
- choose:
|
- choose:
|
||||||
- conditions:
|
- conditions:
|
||||||
- condition: trigger
|
- condition: trigger
|
||||||
id:
|
id:
|
||||||
- HEATING_PERIOD_ON
|
- HEATING_PERIOD_STARTED
|
||||||
sequence:
|
sequence:
|
||||||
- service: climate.set_hvac_mode
|
- service: climate.set_hvac_mode
|
||||||
target:
|
target:
|
||||||
@@ -330,8 +408,10 @@ actions:
|
|||||||
- if:
|
- if:
|
||||||
- condition: template
|
- condition: template
|
||||||
value_template: >
|
value_template: >
|
||||||
{{ is_valid_temperature and is_temperature_change_needed }}
|
{{ is_valid_temperature and is_temperature_change_needed and is_state(window_detection_entity, 'off') }}
|
||||||
then:
|
then:
|
||||||
|
- delay:
|
||||||
|
seconds: "{{ random_delay_seconds }}"
|
||||||
- service: climate.set_temperature
|
- service: climate.set_temperature
|
||||||
target:
|
target:
|
||||||
entity_id: !input trv
|
entity_id: !input trv
|
||||||
@@ -341,7 +421,7 @@ actions:
|
|||||||
- conditions:
|
- conditions:
|
||||||
- condition: trigger
|
- condition: trigger
|
||||||
id:
|
id:
|
||||||
- HEATING_PERIOD_OFF
|
- HEATING_PERIOD_ENDED
|
||||||
sequence:
|
sequence:
|
||||||
- service: switch.turn_off
|
- service: switch.turn_off
|
||||||
target:
|
target:
|
||||||
@@ -364,7 +444,7 @@ actions:
|
|||||||
- conditions:
|
- conditions:
|
||||||
- condition: trigger
|
- condition: trigger
|
||||||
id:
|
id:
|
||||||
- FENSTER_OPEN
|
- WINDOW_OPENED
|
||||||
- condition: template
|
- condition: template
|
||||||
value_template: >
|
value_template: >
|
||||||
{{ is_state(window_detection_entity, 'off') }}
|
{{ is_state(window_detection_entity, 'off') }}
|
||||||
@@ -376,7 +456,7 @@ actions:
|
|||||||
- conditions:
|
- conditions:
|
||||||
- condition: trigger
|
- condition: trigger
|
||||||
id:
|
id:
|
||||||
- FENSTER_CLOSED
|
- WINDOW_CLOSED
|
||||||
- condition: template
|
- condition: template
|
||||||
value_template: >
|
value_template: >
|
||||||
{{ is_state(window_detection_entity, 'on') }}
|
{{ is_state(window_detection_entity, 'on') }}
|
||||||
@@ -384,11 +464,15 @@ actions:
|
|||||||
- service: switch.turn_off
|
- service: switch.turn_off
|
||||||
target:
|
target:
|
||||||
entity_id: "{{ window_detection_entity }}"
|
entity_id: "{{ window_detection_entity }}"
|
||||||
|
- delay:
|
||||||
|
minutes: 1
|
||||||
- if:
|
- if:
|
||||||
- condition: template
|
- condition: template
|
||||||
value_template: >
|
value_template: >
|
||||||
{{ is_valid_temperature and is_temperature_change_needed }}
|
{{ is_valid_temperature and is_temperature_change_needed }}
|
||||||
then:
|
then:
|
||||||
|
- delay:
|
||||||
|
seconds: "{{ random_delay_seconds }}"
|
||||||
- service: climate.set_temperature
|
- service: climate.set_temperature
|
||||||
target:
|
target:
|
||||||
entity_id: !input trv
|
entity_id: !input trv
|
||||||
@@ -401,7 +485,7 @@ actions:
|
|||||||
- conditions:
|
- conditions:
|
||||||
- condition: trigger
|
- condition: trigger
|
||||||
id:
|
id:
|
||||||
- TEMP_CHANGED
|
- SENSOR_TEMPERATURE_CHANGED
|
||||||
- condition: template
|
- condition: template
|
||||||
value_template: >
|
value_template: >
|
||||||
{{ temperature_sensor is defined and states(temperature_sensor) | is_number }}
|
{{ temperature_sensor is defined and states(temperature_sensor) | is_number }}
|
||||||
@@ -417,13 +501,18 @@ actions:
|
|||||||
- conditions:
|
- conditions:
|
||||||
- condition: trigger
|
- condition: trigger
|
||||||
id:
|
id:
|
||||||
- SYNC_TEMPERATURE
|
- PERIODIC_CHECK
|
||||||
- condition: template
|
- condition: template
|
||||||
value_template: >
|
value_template: >
|
||||||
{{ temperature_sensor is defined and states(temperature_sensor) | is_number }}
|
{{ temperature_sensor is defined and states(temperature_sensor) | is_number }}
|
||||||
- condition: template
|
- condition: template
|
||||||
value_template: >
|
value_template: >
|
||||||
{{ (now() - states[remote_temperature_entity].last_changed).total_seconds() > 1499 }}
|
{% if remote_temperature_last_change != none %}
|
||||||
|
{% set last_change = as_datetime(remote_temperature_last_change) %}
|
||||||
|
{{ last_change != none and (now() - last_change).total_seconds() > sensor_sync_max_age }}
|
||||||
|
{% else %}
|
||||||
|
false
|
||||||
|
{% endif %}
|
||||||
sequence:
|
sequence:
|
||||||
- service: number.set_value
|
- service: number.set_value
|
||||||
data:
|
data:
|
||||||
@@ -432,18 +521,40 @@ actions:
|
|||||||
entity_id: "{{ remote_temperature_entity }}"
|
entity_id: "{{ remote_temperature_entity }}"
|
||||||
alias: Synchronisiere Temperatur am TRV (zeitbasiert, wenn länger als 25min unverändert)
|
alias: Synchronisiere Temperatur am TRV (zeitbasiert, wenn länger als 25min unverändert)
|
||||||
alias: Temperatursynchronisation
|
alias: Temperatursynchronisation
|
||||||
|
# override reset
|
||||||
|
- choose:
|
||||||
|
- conditions:
|
||||||
|
- condition: trigger
|
||||||
|
id:
|
||||||
|
- PERIODIC_CHECK
|
||||||
|
- condition: template
|
||||||
|
value_template: "{{ override_reset_duration_seconds > 0 }}"
|
||||||
|
- condition: template
|
||||||
|
value_template: "{{ is_manual_override }}"
|
||||||
|
- condition: template
|
||||||
|
value_template: "{{ override_duration_exceeded }}"
|
||||||
|
sequence:
|
||||||
|
- delay:
|
||||||
|
seconds: "{{ random_delay_seconds }}"
|
||||||
|
- service: climate.set_temperature
|
||||||
|
target:
|
||||||
|
entity_id: !input trv
|
||||||
|
data:
|
||||||
|
temperature: "{{ safe_temperature | float }}"
|
||||||
|
alias: Setze Solltemperatur zurück nach manuellem Override
|
||||||
|
alias: Override Reset
|
||||||
# setze Solltemperatur bei Schedule und Alarm-Status-Änderungen
|
# setze Solltemperatur bei Schedule und Alarm-Status-Änderungen
|
||||||
- choose:
|
- choose:
|
||||||
- conditions:
|
- conditions:
|
||||||
- condition: trigger
|
- condition: trigger
|
||||||
id:
|
id:
|
||||||
- ALARM_ARMED_AWAY
|
- ALARM_ARMED_AWAY
|
||||||
- ALARM_DISARMED_AWAY
|
- ALARM_DISARMED
|
||||||
- SCHEDULE_TEMP_CHANGED
|
- SCHEDULE_TEMPERATURE_CHANGED
|
||||||
- SCHEDULER_CHANGED
|
- SCHEDULE_SELECTOR_CHANGED
|
||||||
- condition: template
|
- condition: template
|
||||||
value_template: >
|
value_template: >
|
||||||
{% if trigger.id == 'SCHEDULE_TEMP_CHANGED' %}
|
{% if trigger.id == 'SCHEDULE_TEMPERATURE_CHANGED' %}
|
||||||
{% set selected_friendly_name = states(active_scheduler_selector) %}
|
{% set selected_friendly_name = states(active_scheduler_selector) %}
|
||||||
{{ state_attr(trigger.entity_id, 'friendly_name') == selected_friendly_name }}
|
{{ state_attr(trigger.entity_id, 'friendly_name') == selected_friendly_name }}
|
||||||
{% else %}
|
{% else %}
|
||||||
@@ -453,8 +564,10 @@ actions:
|
|||||||
- if:
|
- if:
|
||||||
- condition: template
|
- condition: template
|
||||||
value_template: >
|
value_template: >
|
||||||
{{ is_valid_temperature and is_temperature_change_needed }}
|
{{ is_valid_temperature and is_temperature_change_needed and is_state(window_detection_entity, 'off') }}
|
||||||
then:
|
then:
|
||||||
|
- delay:
|
||||||
|
seconds: "{{ random_delay_seconds }}"
|
||||||
- service: climate.set_temperature
|
- service: climate.set_temperature
|
||||||
target:
|
target:
|
||||||
entity_id: !input trv
|
entity_id: !input trv
|
||||||
|
|||||||
Reference in New Issue
Block a user