Nachdem ich mit Better Thermostat, Versatile Thermostat und diversen Blueprints nicht zufrieden war, was die Steuerung und vor allem die Nachvollziehbar mancher Aktionen betrifft, habe ich mich ein paar Stunden an Node-Red gesetzt und Flows zusammengebastelt, die ich Euch kurz vorstellen möchte.
Ich weiß, dass es Optimierungsmöglichkeiten gibt, weil ich bin kein Node-Red Spezi bin und es funktionellere Nodes gibt.
Mein Ziel war es, möglichst einfach und übersichtlich zu bleiben, damit Fehler schnell gefunden werden, wenn etwas Unbeabsichtigtes geschieht.
Für Vorschläge, die mich meinem Ziel noch näher bringen, bin ich sehr dankbar. Und bei Interesse stelle ich die Flows zur Verfügung.
Das Ganze habe ich 2 Blöcke gegliedert: Anwesenheitserkennung und Steuerung, wobei mehrere Helfer zum Einsatz kommen.
Die Regelung erfolgt je nach Anwesenheit, Zeitplan, Fenstersensor-Status oder manuellem Eingriff. Außerdem habe ich eine automatische Kalibrierung eingebaut.
Zur Anwesenheit:
Diese definiert sich anhand mehrerer Kriterien: Status zone.home, Status Presence Sensor, Status Stromverbrauch, Status TV. Ist nicht optimal, aber da ich zwei Katzen habe, verringert es die False Positives mit Aqara FP2 (im Wohnimmer) oder Sonoff SNZB-06P (im Büro) dennoch.
Zum Zeitplan:
Der ist recht simpel bei mir: ein Zeitplan Helfer, wenn der on ist, gelten 22°, wenn der off ist, 20°.
Zum manuellen Eingriff:
Wenn ich die Wunschtemperatur temporär ändern möchte, mache ich das mit einem input_number Helfer, der mir die Zieltemperatur in der climate-Entität setzt und einen Timer startet.
Zur Kalbirierung:
Hierfür habe ich einen Template-Helfer erstellt, der die Differenz vom internen Sensor des TRVs zu einem externen Raumsensor ausgibt.
Alle 10 Minuten wird der letzte Offset genullt und die Differenz neu berechnet, ist sie höher als 0,2 oder niedriger als -0,2, wird sie als Offset an das TRV übergeben.
Alle 5 bzw. 10 Minuten werden alle Stati geprüft und dementsprechend geregelt.
Hier eine Karte dafür fürs Dashbord (zeigt des Laufzeit des Timers, sofern aktiv):

type: custom:vertical-stack-in-card
cards:
- type: custom:bubble-card
card_type: button
button_type: state
entity: climate.th_buro
name: Büro
icon: mdi:radiator
show_state: false
show_attribute: true
attribute: current_temperature
sub_button:
- entity: binary_sensor.c_4_burofenster_contact
- entity: input_number.burotemperatur
icon: mdi:minus
show_background: false
tap_action:
action: call-service
service: input_number.decrement
target:
entity_id: input_number.burotemperatur
- show_icon: false
show_attribute: true
attribute: temperature
state_background: false
show_background: false
tap_action:
action: none
- entity: input_number.burotemperatur
icon: mdi:plus
state_background: false
show_background: false
tap_action:
action: call-service
service: input_number.increment
target:
entity_id: input_number.burotemperatur
tap_action:
action: none
double_tap_action:
action: none
hold_action:
action: none
button_action:
hold_action:
action: none
double_tap_action:
action: none
tap_action:
action: none
styles: >-
* {
font-size: 14px !important;
}
.bubble-icon {
color: ${hass.states[entity].attributes.hvac_action === 'idle' ? 'rgba(80,180,239,1)' : 'rgba(250,104,0,1)'} !important;
--mdc-icon-size: 28px !important;
}
.bubble-sub-button-icon {
--mdc-icon-size: 22px !important;
}
.bubble-button-card-container {
background-color: ${hass.states[entity].attributes.hvac_action === 'idle' ? 'rgba(80,180,239,0.3)' : 'rgba(250,104,0,0.5)'} !important; !important;
}
${icon.setAttribute("icon", hass.states[entity].attributes.hvac_action ===
'heating' ? 'mdi:radiator' : 'mdi:radiator-disabled')}
card_layout: large
- type: custom:layout-card
layout_type: custom:grid-layout
layout:
margin: "-22px 40px -20px 40px"
cards:
- type: custom:timer-bar-card
entity: timer.heizung_b_man
layout: full_row
text_width: 0px
bar_height: 4px
bar_background: orange
bar_foreground: lightgrey
bar_radius: 12px
sync_issues: ignore
visibility:
- condition: state
entity: timer.heizung_b_man
state: active
card_mod:
style: |
ha-card {
background-color: transparent;
}
