Compare commits
14 Commits
34c7cc90b9
...
f6fe2f9ab9
| Author | SHA1 | Date | |
|---|---|---|---|
| f6fe2f9ab9 | |||
| 55dff75ce5 | |||
| 5fdc338194 | |||
| 4de21e35ec | |||
| ddc8408a73 | |||
| 7042453358 | |||
| d3beca60b6 | |||
| d68a173de6 | |||
| ab94183c65 | |||
| 576b6fa98a | |||
| e200814de6 | |||
| 9cb8b30fca | |||
| 640681ce43 | |||
| e40e2b3e90 |
@@ -1,4 +1,5 @@
|
|||||||
mode: single
|
mode: queued
|
||||||
|
max: 10
|
||||||
blueprint:
|
blueprint:
|
||||||
name: Bosch BTH-RA Radiator Control
|
name: Bosch BTH-RA Radiator Control
|
||||||
homeassistant:
|
homeassistant:
|
||||||
@@ -32,6 +33,28 @@ blueprint:
|
|||||||
multiple: false
|
multiple: false
|
||||||
filter:
|
filter:
|
||||||
- domain: input_boolean
|
- domain: input_boolean
|
||||||
|
min_temperature:
|
||||||
|
name: Minimale Temperatur
|
||||||
|
description: Minimale erlaubte Solltemperatur als Sicherheitsgrenze (Default = 15°C)
|
||||||
|
default: 15
|
||||||
|
selector:
|
||||||
|
number:
|
||||||
|
mode: box
|
||||||
|
min: 10.0
|
||||||
|
max: 20.0
|
||||||
|
unit_of_measurement: "°C"
|
||||||
|
step: 0.5
|
||||||
|
max_temperature:
|
||||||
|
name: Maximale Temperatur
|
||||||
|
description: Maximale erlaubte Solltemperatur als Sicherheitsgrenze (Default = 28°C)
|
||||||
|
default: 23
|
||||||
|
selector:
|
||||||
|
number:
|
||||||
|
mode: box
|
||||||
|
min: 20.0
|
||||||
|
max: 25.0
|
||||||
|
unit_of_measurement: "°C"
|
||||||
|
step: 0.5
|
||||||
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.
|
||||||
@@ -73,13 +96,30 @@ blueprint:
|
|||||||
input:
|
input:
|
||||||
radiator_schedules:
|
radiator_schedules:
|
||||||
name: Heizpläne
|
name: Heizpläne
|
||||||
description: Alle Heizpläne die für den Radiator berücksichtigt werden sollen. Sind mehrere Schedules aktiv, wird der erste mit einem gültigen Slot verwendet.
|
description: Alle Heizpläne die für den Radiator berücksichtigt werden sollen. Sind mehrere Schedules aktiv, wird der erste mit einer gültigen Temperatur verwendet.
|
||||||
default: []
|
default: []
|
||||||
selector:
|
selector:
|
||||||
entity:
|
entity:
|
||||||
multiple: true
|
multiple: true
|
||||||
filter:
|
filter:
|
||||||
- domain: switch
|
- domain: schedule
|
||||||
|
|
||||||
|
active_scheduler_selector:
|
||||||
|
name: Aktiver Scheduler Selector
|
||||||
|
description: >
|
||||||
|
Input Select der den aktuell aktiven Scheduler enthält (per Friendly Name).
|
||||||
|
Wird verwendet um zu bestimmen welcher Schedule für die Temperatur verwendet werden soll.
|
||||||
|
|
||||||
|
**WICHTIG**: Die Options müssen die Friendly Names der Scheduler aus der Scheduler-Liste enthalten.
|
||||||
|
|
||||||
|
**HINWEIS**: Wenn der angezeigte Scheduler inaktiv ist (off), wird automatisch
|
||||||
|
auf die Abwesenheitstemperatur zurückgegriffen.
|
||||||
|
|
||||||
|
Beispiel: Wird typischerweise vom "Heizplan Selector" Blueprint gesteuert.
|
||||||
|
selector:
|
||||||
|
entity:
|
||||||
|
filter:
|
||||||
|
- domain: input_select
|
||||||
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
|
||||||
@@ -110,7 +150,10 @@ variables:
|
|||||||
temperature_sensor: !input temperature_sensor
|
temperature_sensor: !input temperature_sensor
|
||||||
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
|
||||||
away_temperature: !input away_temperature
|
away_temperature: !input away_temperature
|
||||||
|
min_temperature: !input min_temperature
|
||||||
|
max_temperature: !input max_temperature
|
||||||
alarm_control_panel: !input alarm_control_panel
|
alarm_control_panel: !input alarm_control_panel
|
||||||
is_heating_period: >
|
is_heating_period: >
|
||||||
{% if heating_period_switch is none or heating_period_switch == '' %}
|
{% if heating_period_switch is none or heating_period_switch == '' %}
|
||||||
@@ -138,19 +181,18 @@ variables:
|
|||||||
{{ window_detection_entity_id.id }}
|
{{ window_detection_entity_id.id }}
|
||||||
scheduled_temperature: >
|
scheduled_temperature: >
|
||||||
{% set ns = namespace(current_temperature = none) %}
|
{% set ns = namespace(current_temperature = none) %}
|
||||||
{% for schedule in radiator_schedules %}
|
{% set selected_friendly_name = states(active_scheduler_selector) %}
|
||||||
{% if states(schedule) == 'on' and state_attr(schedule, 'current_slot') is not none %}
|
{% if selected_friendly_name is not none and selected_friendly_name != 'unknown' %}
|
||||||
{% set current_slot = state_attr(schedule, 'current_slot') %}
|
{% for schedule in radiator_schedules %}
|
||||||
{% set actions = state_attr(schedule, 'actions') %}
|
{% if state_attr(schedule, 'friendly_name') == selected_friendly_name and states(schedule) == 'on' %}
|
||||||
{% if actions is not none and actions | length > current_slot %}
|
{% set temp = state_attr(schedule, 'temp') %}
|
||||||
{% set action = actions[current_slot] %}
|
{% if temp is not none and temp | is_number %}
|
||||||
{% if action.data.temperature is defined and action.data.temperature | is_number %}
|
{% set ns.current_temperature = temp %}
|
||||||
{% set ns.current_temperature = action.data.temperature %}
|
|
||||||
{% break %}
|
{% break %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endfor %}
|
||||||
{% endfor %}
|
{% endif %}
|
||||||
{{ ns.current_temperature }}
|
{{ ns.current_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') %}
|
||||||
@@ -160,6 +202,55 @@ variables:
|
|||||||
{% else %}
|
{% else %}
|
||||||
{{ away_temperature }}
|
{{ away_temperature }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
safe_temperature: >
|
||||||
|
{% set temp = target_temperature | float(18) %}
|
||||||
|
{% if temp < min_temperature %}
|
||||||
|
{{ min_temperature }}
|
||||||
|
{% elif temp > max_temperature %}
|
||||||
|
{{ max_temperature }}
|
||||||
|
{% else %}
|
||||||
|
{{ temp }}
|
||||||
|
{% endif %}
|
||||||
|
is_valid_temperature: >
|
||||||
|
{{ safe_temperature is not none and safe_temperature | is_number }}
|
||||||
|
is_temperature_change_needed: >
|
||||||
|
{% set current = state_attr(trv, 'temperature') | float(0) %}
|
||||||
|
{% set new = safe_temperature | float(0) %}
|
||||||
|
{% set diff = new - current %}
|
||||||
|
{% if new > current %}
|
||||||
|
true
|
||||||
|
{% elif diff | abs >= 0.5 %}
|
||||||
|
true
|
||||||
|
{% else %}
|
||||||
|
false
|
||||||
|
{% endif %}
|
||||||
|
is_sensor_sync_needed: >
|
||||||
|
{% set current_remote_temp = states(remote_temperature_entity) | float(0) %}
|
||||||
|
{% set new_sensor_temp = states(temperature_sensor) | float(0) %}
|
||||||
|
{% set target_temp = state_attr(trv, 'temperature') | float(0) %}
|
||||||
|
{% set diff = (new_sensor_temp - current_remote_temp) | abs %}
|
||||||
|
{% if diff >= 0.5 %}
|
||||||
|
true
|
||||||
|
{% elif new_sensor_temp < target_temp and current_remote_temp >= target_temp %}
|
||||||
|
true
|
||||||
|
{% elif new_sensor_temp > target_temp and current_remote_temp <= target_temp %}
|
||||||
|
true
|
||||||
|
{% else %}
|
||||||
|
false
|
||||||
|
{% endif %}
|
||||||
|
scheduler_mismatch: >
|
||||||
|
{% set selected_friendly_name = states(active_scheduler_selector) %}
|
||||||
|
{% if selected_friendly_name not in ['unknown', '', none] %}
|
||||||
|
{% set found = namespace(value=false) %}
|
||||||
|
{% for schedule in radiator_schedules %}
|
||||||
|
{% if state_attr(schedule, 'friendly_name') == selected_friendly_name %}
|
||||||
|
{% set found.value = true %}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
{{ not found.value }}
|
||||||
|
{% else %}
|
||||||
|
false
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
triggers:
|
triggers:
|
||||||
- platform: state
|
- platform: state
|
||||||
@@ -200,6 +291,13 @@ triggers:
|
|||||||
entity_id: !input heating_period_switch
|
entity_id: !input heating_period_switch
|
||||||
to: "off"
|
to: "off"
|
||||||
id: HEATING_PERIOD_OFF
|
id: HEATING_PERIOD_OFF
|
||||||
|
- platform: state
|
||||||
|
entity_id: !input radiator_schedules
|
||||||
|
attribute: temp
|
||||||
|
id: SCHEDULE_TEMP_CHANGED
|
||||||
|
- platform: state
|
||||||
|
entity_id: !input active_scheduler_selector
|
||||||
|
id: SCHEDULER_CHANGED
|
||||||
|
|
||||||
actions:
|
actions:
|
||||||
- choose:
|
- choose:
|
||||||
@@ -232,13 +330,13 @@ actions:
|
|||||||
- if:
|
- if:
|
||||||
- condition: template
|
- condition: template
|
||||||
value_template: >
|
value_template: >
|
||||||
{{ target_temperature is not none and target_temperature | is_number }}
|
{{ is_valid_temperature and is_temperature_change_needed }}
|
||||||
then:
|
then:
|
||||||
- service: climate.set_temperature
|
- service: climate.set_temperature
|
||||||
target:
|
target:
|
||||||
entity_id: !input trv
|
entity_id: !input trv
|
||||||
data:
|
data:
|
||||||
temperature: "{{ target_temperature | float }}"
|
temperature: "{{ safe_temperature | float }}"
|
||||||
alias: Heizperiode aktiviert - Setze Modus auf heat, synchronisiere Fensterstatus und Solltemperatur
|
alias: Heizperiode aktiviert - Setze Modus auf heat, synchronisiere Fensterstatus und Solltemperatur
|
||||||
- conditions:
|
- conditions:
|
||||||
- condition: trigger
|
- condition: trigger
|
||||||
@@ -289,13 +387,13 @@ actions:
|
|||||||
- if:
|
- if:
|
||||||
- condition: template
|
- condition: template
|
||||||
value_template: >
|
value_template: >
|
||||||
{{ target_temperature is not none and target_temperature | is_number }}
|
{{ is_valid_temperature and is_temperature_change_needed }}
|
||||||
then:
|
then:
|
||||||
- service: climate.set_temperature
|
- service: climate.set_temperature
|
||||||
target:
|
target:
|
||||||
entity_id: !input trv
|
entity_id: !input trv
|
||||||
data:
|
data:
|
||||||
temperature: "{{ target_temperature | float }}"
|
temperature: "{{ safe_temperature | float }}"
|
||||||
alias: Setze Fenster auf geschlossen und setze Solltemperatur auf Wert aus Zeitplan (wenn vorhanden)
|
alias: Setze Fenster auf geschlossen und setze Solltemperatur auf Wert aus Zeitplan (wenn vorhanden)
|
||||||
alias: Fensterstatus Änderung
|
alias: Fensterstatus Änderung
|
||||||
# temperature sensor sync
|
# temperature sensor sync
|
||||||
@@ -307,6 +405,8 @@ actions:
|
|||||||
- 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
|
||||||
|
value_template: "{{ is_sensor_sync_needed }}"
|
||||||
sequence:
|
sequence:
|
||||||
- service: number.set_value
|
- service: number.set_value
|
||||||
data:
|
data:
|
||||||
@@ -323,34 +423,61 @@ actions:
|
|||||||
{{ 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[temperature_sensor].last_changed).total_seconds() > 1199 }}
|
{{ (now() - states[remote_temperature_entity].last_changed).total_seconds() > 1499 }}
|
||||||
sequence:
|
sequence:
|
||||||
- service: number.set_value
|
- service: number.set_value
|
||||||
data:
|
data:
|
||||||
value: "{{ states(temperature_sensor) | float }}"
|
value: "{{ states(temperature_sensor) | float }}"
|
||||||
target:
|
target:
|
||||||
entity_id: "{{ remote_temperature_entity }}"
|
entity_id: "{{ remote_temperature_entity }}"
|
||||||
alias: Synchronisiere Temperatur am TRV (zeitbasiert, wenn länger als 20min unverändert)
|
alias: Synchronisiere Temperatur am TRV (zeitbasiert, wenn länger als 25min unverändert)
|
||||||
alias: Temperatursynchronisation
|
alias: Temperatursynchronisation
|
||||||
# setze Solltemperatur basierend auf Alarm-Status
|
# 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_AWAY
|
||||||
|
- SCHEDULE_TEMP_CHANGED
|
||||||
|
- SCHEDULER_CHANGED
|
||||||
|
- condition: template
|
||||||
|
value_template: >
|
||||||
|
{% if trigger.id == 'SCHEDULE_TEMP_CHANGED' %}
|
||||||
|
{% set selected_friendly_name = states(active_scheduler_selector) %}
|
||||||
|
{{ state_attr(trigger.entity_id, 'friendly_name') == selected_friendly_name }}
|
||||||
|
{% else %}
|
||||||
|
true
|
||||||
|
{% endif %}
|
||||||
sequence:
|
sequence:
|
||||||
- if:
|
- if:
|
||||||
- condition: template
|
- condition: template
|
||||||
value_template: >
|
value_template: >
|
||||||
{{ target_temperature is not none and target_temperature | is_number }}
|
{{ is_valid_temperature and is_temperature_change_needed }}
|
||||||
then:
|
then:
|
||||||
- service: climate.set_temperature
|
- service: climate.set_temperature
|
||||||
target:
|
target:
|
||||||
entity_id: !input trv
|
entity_id: !input trv
|
||||||
data:
|
data:
|
||||||
temperature: "{{ target_temperature | float }}"
|
temperature: "{{ safe_temperature | float }}"
|
||||||
alias: Setze Solltemperatur basierend auf Alarm-Status
|
# Notification bei Scheduler-Mismatch
|
||||||
alias: Solltemperatur setzen
|
- if:
|
||||||
|
- condition: template
|
||||||
|
value_template: "{{ scheduler_mismatch and trigger.id == 'SCHEDULER_CHANGED' }}"
|
||||||
|
then:
|
||||||
|
- service: persistent_notification.create
|
||||||
|
data:
|
||||||
|
title: "⚠️ Radiator Control - Scheduler nicht gefunden"
|
||||||
|
message: >
|
||||||
|
Der ausgewählte Scheduler '{{ states(active_scheduler_selector) }}' wurde nicht in der
|
||||||
|
Scheduler-Liste gefunden.
|
||||||
|
|
||||||
|
TRV '{{ state_attr(trv, 'friendly_name') }}' nutzt Fallback-Temperatur: {{ safe_temperature }}°C
|
||||||
|
(Original: {{ target_temperature }}°C, Limits: {{ min_temperature }}-{{ max_temperature }}°C)
|
||||||
|
|
||||||
|
Bitte Konfiguration überprüfen.
|
||||||
|
notification_id: "radiator_control_scheduler_mismatch_{{ trv }}"
|
||||||
|
alias: Setze Solltemperatur
|
||||||
|
alias: Solltemperatur bei Änderungen
|
||||||
alias: Aktionen während Heizperiode
|
alias: Aktionen während Heizperiode
|
||||||
alias: Hauptsteuerung
|
alias: Hauptsteuerung
|
||||||
268
Climate/schedule_selector.yaml
Normal file
268
Climate/schedule_selector.yaml
Normal file
@@ -0,0 +1,268 @@
|
|||||||
|
blueprint:
|
||||||
|
name: Heizplan Selector basierend auf Kalenderereignissen
|
||||||
|
description: >
|
||||||
|
Wählt automatisch einen Heizplan basierend auf Kalenderereignissen aus.
|
||||||
|
|
||||||
|
Der Blueprint überwacht einen Kalender und wechselt zwischen verschiedenen
|
||||||
|
Schedule-Helfern basierend auf Keywords im Event-Titel oder der Beschreibung.
|
||||||
|
|
||||||
|
**WICHTIG**: Die Anzahl der Scheduler und Keywordlisten muss übereinstimmen!
|
||||||
|
Jede Zeile in den Keywordlisten entspricht einem Scheduler an der gleichen Position.
|
||||||
|
|
||||||
|
Bei Event-Ende wird zum Standard-Scheduler zurückgekehrt, außer ein anderes
|
||||||
|
Event ist bereits aktiv.
|
||||||
|
|
||||||
|
Required = *
|
||||||
|
domain: automation
|
||||||
|
homeassistant:
|
||||||
|
min_version: "2024.6.0"
|
||||||
|
author: Me
|
||||||
|
input:
|
||||||
|
calendar_section:
|
||||||
|
name: Kalender-Einstellungen
|
||||||
|
description: Kalender und zeitlicher Offset für Events
|
||||||
|
collapsed: false
|
||||||
|
input:
|
||||||
|
calendar_entity:
|
||||||
|
name: Kalender *
|
||||||
|
description: Der Kalender, der für Event-Erkennung überwacht wird
|
||||||
|
selector:
|
||||||
|
entity:
|
||||||
|
filter:
|
||||||
|
- domain: calendar
|
||||||
|
|
||||||
|
event_offset:
|
||||||
|
name: Zeitlicher Offset
|
||||||
|
description: >
|
||||||
|
Optional: Zeitlicher Versatz für Event-Start und -Ende.
|
||||||
|
Beispiel: "-00:15:00" startet 15 Minuten vor dem Event.
|
||||||
|
default: "00:00:00"
|
||||||
|
selector:
|
||||||
|
duration:
|
||||||
|
enable_day: false
|
||||||
|
|
||||||
|
scheduler_section:
|
||||||
|
name: Scheduler-Konfiguration
|
||||||
|
description: Schedule-Helfer und zugeordnete Keywords
|
||||||
|
collapsed: false
|
||||||
|
input:
|
||||||
|
scheduler_list:
|
||||||
|
name: Scheduler-Liste *
|
||||||
|
description: >
|
||||||
|
Liste der Schedule-Helfer (schedule entities).
|
||||||
|
Die Reihenfolge muss mit den Keywordlisten übereinstimmen!
|
||||||
|
selector:
|
||||||
|
entity:
|
||||||
|
multiple: true
|
||||||
|
filter:
|
||||||
|
- domain: schedule
|
||||||
|
|
||||||
|
keyword_lists:
|
||||||
|
name: Keywordlisten *
|
||||||
|
description: >
|
||||||
|
Eine Keywordliste pro Zeile (komma-separiert).
|
||||||
|
Beispiel:
|
||||||
|
urlaub,vacation,holiday
|
||||||
|
homeoffice,wfh,remote
|
||||||
|
normal,standard
|
||||||
|
|
||||||
|
**Position in der Liste = Position im Scheduler!**
|
||||||
|
Zeile 1 → Scheduler 1, Zeile 2 → Scheduler 2, etc.
|
||||||
|
selector:
|
||||||
|
text:
|
||||||
|
multiline: true
|
||||||
|
type: text
|
||||||
|
|
||||||
|
default_scheduler:
|
||||||
|
name: Standard-Scheduler *
|
||||||
|
description: >
|
||||||
|
Dieser Scheduler wird aktiviert, wenn kein Keyword matched
|
||||||
|
oder ein Event endet (und kein anderes aktiv ist).
|
||||||
|
selector:
|
||||||
|
entity:
|
||||||
|
filter:
|
||||||
|
- domain: schedule
|
||||||
|
|
||||||
|
helper_section:
|
||||||
|
name: Helper-Entity
|
||||||
|
description: Entity zum Speichern des aktiven Schedulers
|
||||||
|
collapsed: false
|
||||||
|
input:
|
||||||
|
helper_entity:
|
||||||
|
name: Input Select Helper *
|
||||||
|
description: >
|
||||||
|
Die input_select Helper-Entity, in die der aktive Scheduler geschrieben wird.
|
||||||
|
|
||||||
|
**WICHTIG**: Die Options der input_select müssen vorbereitet werden!
|
||||||
|
Sie müssen die Friendly Names folgender Entities enthalten:
|
||||||
|
- Alle Scheduler aus der Scheduler-Liste
|
||||||
|
- Den Standard-Scheduler
|
||||||
|
|
||||||
|
Beispiel Options:
|
||||||
|
["Urlaub Heizplan", "Home Office Heizplan", "Normal Heizplan", "Standard Heizplan"]
|
||||||
|
|
||||||
|
Die Blueprint schreibt den Friendly Name (nicht die Entity-ID) in die Helper-Entity.
|
||||||
|
selector:
|
||||||
|
entity:
|
||||||
|
filter:
|
||||||
|
- domain: input_select
|
||||||
|
|
||||||
|
mode: single
|
||||||
|
max_exceeded: silent
|
||||||
|
|
||||||
|
triggers:
|
||||||
|
- platform: calendar
|
||||||
|
event: start
|
||||||
|
entity_id: !input calendar_entity
|
||||||
|
offset: !input event_offset
|
||||||
|
id: CALENDAR_START
|
||||||
|
|
||||||
|
- platform: calendar
|
||||||
|
event: end
|
||||||
|
entity_id: !input calendar_entity
|
||||||
|
offset: !input event_offset
|
||||||
|
id: CALENDAR_END
|
||||||
|
|
||||||
|
variables:
|
||||||
|
schedulers: !input scheduler_list
|
||||||
|
keywords_raw: !input keyword_lists
|
||||||
|
default_scheduler: !input default_scheduler
|
||||||
|
helper: !input helper_entity
|
||||||
|
calendar: !input calendar_entity
|
||||||
|
|
||||||
|
# Keywords in Liste umwandeln (eine pro Zeile)
|
||||||
|
keyword_lists: >
|
||||||
|
{{ keywords_raw.split('\n') | select() | list }}
|
||||||
|
|
||||||
|
# Bei Event-Start: Keywords matchen
|
||||||
|
matched_scheduler: >
|
||||||
|
{% set ns = namespace(scheduler = none) %}
|
||||||
|
{% if trigger.id == 'CALENDAR_START' %}
|
||||||
|
{% set event_text = (trigger.calendar_event.summary | lower) ~ ' ' ~ (trigger.calendar_event.description | default('') | lower) %}
|
||||||
|
{% for i in range(keyword_lists | length) %}
|
||||||
|
{% set keywords = keyword_lists[i].split(',') | map('trim') | map('lower') | list %}
|
||||||
|
{% set matched = namespace(found = false) %}
|
||||||
|
{% for keyword in keywords %}
|
||||||
|
{% if keyword in event_text %}
|
||||||
|
{% set matched.found = true %}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
{% if matched.found and i < (schedulers | length) %}
|
||||||
|
{% set ns.scheduler = schedulers[i] %}
|
||||||
|
{% break %}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
{{ ns.scheduler }}
|
||||||
|
|
||||||
|
# Bei Event-Ende: Prüfen ob ein anderes Event aktiv ist
|
||||||
|
other_event_active: >
|
||||||
|
{% if trigger.id == 'CALENDAR_END' %}
|
||||||
|
{% set start = state_attr(calendar, 'start_time') %}
|
||||||
|
{% set end = state_attr(calendar, 'end_time') %}
|
||||||
|
{% if start and end %}
|
||||||
|
{% set now_ts = now().timestamp() %}
|
||||||
|
{% set start_ts = as_timestamp(start) %}
|
||||||
|
{% set end_ts = as_timestamp(end) %}
|
||||||
|
{{ start_ts <= now_ts and now_ts <= end_ts }}
|
||||||
|
{% else %}
|
||||||
|
false
|
||||||
|
{% endif %}
|
||||||
|
{% else %}
|
||||||
|
false
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
conditions: []
|
||||||
|
|
||||||
|
actions:
|
||||||
|
- choose:
|
||||||
|
# Event-Start: Scheduler aktivieren wenn Keyword matched
|
||||||
|
- conditions:
|
||||||
|
- condition: trigger
|
||||||
|
id: CALENDAR_START
|
||||||
|
- condition: template
|
||||||
|
value_template: "{{ matched_scheduler is not none and matched_scheduler != '' }}"
|
||||||
|
sequence:
|
||||||
|
- if:
|
||||||
|
- condition: template
|
||||||
|
value_template: >
|
||||||
|
{{ state_attr(matched_scheduler, 'friendly_name') in state_attr(helper, 'options') }}
|
||||||
|
then:
|
||||||
|
# Matched Scheduler ist in Options vorhanden
|
||||||
|
- service: input_select.select_option
|
||||||
|
target:
|
||||||
|
entity_id: !input helper_entity
|
||||||
|
data:
|
||||||
|
option: "{{ state_attr(matched_scheduler, 'friendly_name') }}"
|
||||||
|
else:
|
||||||
|
# Matched Scheduler nicht vorhanden - Fallback auf Default
|
||||||
|
- if:
|
||||||
|
- condition: template
|
||||||
|
value_template: >
|
||||||
|
{{ state_attr(default_scheduler, 'friendly_name') in state_attr(helper, 'options') }}
|
||||||
|
then:
|
||||||
|
- service: input_select.select_option
|
||||||
|
target:
|
||||||
|
entity_id: !input helper_entity
|
||||||
|
data:
|
||||||
|
option: "{{ state_attr(default_scheduler, 'friendly_name') }}"
|
||||||
|
- service: persistent_notification.create
|
||||||
|
data:
|
||||||
|
title: "⚠️ Heizplan Selector - Konfigurationsfehler"
|
||||||
|
message: >
|
||||||
|
Der gematchte Scheduler '{{ state_attr(matched_scheduler, 'friendly_name') }}' ({{ matched_scheduler }}) ist nicht in den Options der input_select '{{ helper }}' vorhanden.
|
||||||
|
|
||||||
|
Fallback auf Standard-Scheduler '{{ state_attr(default_scheduler, 'friendly_name') }}' ({{ default_scheduler }}).
|
||||||
|
|
||||||
|
Event: {{ trigger.calendar_event.summary }}
|
||||||
|
notification_id: "schedule_selector_config_error"
|
||||||
|
else:
|
||||||
|
# Auch Default-Scheduler nicht vorhanden
|
||||||
|
- service: persistent_notification.create
|
||||||
|
data:
|
||||||
|
title: "❌ Heizplan Selector - Kritischer Konfigurationsfehler"
|
||||||
|
message: >
|
||||||
|
Weder der gematchte Scheduler '{{ state_attr(matched_scheduler, 'friendly_name') }}' ({{ matched_scheduler }}) noch der Standard-Scheduler '{{ state_attr(default_scheduler, 'friendly_name') }}' ({{ default_scheduler }}) sind in den Options der input_select '{{ helper }}' vorhanden.
|
||||||
|
|
||||||
|
Kein Scheduler wurde aktiviert!
|
||||||
|
|
||||||
|
Bitte input_select Options korrigieren.
|
||||||
|
|
||||||
|
Event: {{ trigger.calendar_event.summary }}
|
||||||
|
notification_id: "schedule_selector_critical_error"
|
||||||
|
alias: Event-Start - Scheduler aktivieren
|
||||||
|
|
||||||
|
# Event-Ende: Zu Standard zurückkehren (nur wenn kein anderes Event aktiv)
|
||||||
|
- conditions:
|
||||||
|
- condition: trigger
|
||||||
|
id: CALENDAR_END
|
||||||
|
- condition: template
|
||||||
|
value_template: "{{ not other_event_active }}"
|
||||||
|
sequence:
|
||||||
|
- if:
|
||||||
|
- condition: template
|
||||||
|
value_template: >
|
||||||
|
{{ state_attr(default_scheduler, 'friendly_name') in state_attr(helper, 'options') }}
|
||||||
|
then:
|
||||||
|
- service: input_select.select_option
|
||||||
|
target:
|
||||||
|
entity_id: !input helper_entity
|
||||||
|
data:
|
||||||
|
option: "{{ state_attr(default_scheduler, 'friendly_name') }}"
|
||||||
|
else:
|
||||||
|
- service: persistent_notification.create
|
||||||
|
data:
|
||||||
|
title: "❌ Heizplan Selector - Konfigurationsfehler"
|
||||||
|
message: >
|
||||||
|
Der Standard-Scheduler '{{ state_attr(default_scheduler, 'friendly_name') }}' ({{ default_scheduler }}) ist nicht in den Options der input_select '{{ helper }}' vorhanden.
|
||||||
|
|
||||||
|
Kein Scheduler wurde aktiviert!
|
||||||
|
|
||||||
|
Bitte input_select Options korrigieren.
|
||||||
|
|
||||||
|
Event: {{ trigger.calendar_event.summary }}
|
||||||
|
notification_id: "schedule_selector_default_error"
|
||||||
|
alias: Event-Ende - Standard-Scheduler aktivieren
|
||||||
|
|
||||||
|
default: []
|
||||||
|
|
||||||
Reference in New Issue
Block a user