Here is part two of my journey to smart heating control.
First of all, I created some helpers:
- HZ_Night_temperature is a helper for night setback.
- HZ_Tagtemperatur is a helper for the night setback.
- HZ_Solltemperatur Wohnzimmer is a helper for the setpoint temperature for the radiators in the living room.
- HZ_Solltemperatur Bad is a helper for the setpoint temperature for the radiators in the bathroom.
- HZ_Steuerung_An_Aus cancels the automation.
- HeatingScenes are my different requirements for the heating control:
- Tue % Thu in Cologne, my standard days in the office
- Night setback -> night setback e.g. due to vacation
- At home -> everything at daytime temperature
- in Cologne, exceptional day in the office
The selection of the scene then controls the heating control sequence.
E.g. Tue & Thu in Cologne, then everything goes to day temperature at 6:00am, but Tue & Thu the heating switches to night temperature during office hours (7:00am-5:00pm).
An automation reacts to the selection in the scene drop-down menu and then each scene has an automation that is switched on or off depending on the selection. In some cases, the automation is also started in order to set the desired temperature values.
Yaml Code HeatingControl
alias: Heizungssteuerung
description: “”
trigger:
- platform: state entity_id:
- input_select.dropd
condition: []
action:
- input_select.dropd
- choose:
- conditions:
- condition: state
entity_id: input_select.dropd
state: Nachtabsenkung
sequence: - service: automation.turn_on
data: {}
target:
entity_id: automation.heizung_17_grad - service: automation.turn_off
data:
stop_actions: true
target:
entity_id:
– automation.heizung_zuhause
– automation.heizung_koeln
– automation.di_do_neu
– automation.heizung_di_do_koeln - service: automation.trigger
data:
skip_condition: true
target:
entity_id: automation.heizung_17_grad
- condition: state
- conditions:
- condition: state
entity_id: input_select.dropd
state: Zuhause
sequence: - service: automation.turn_on
data: {}
target:
entity_id: automation.heizung_zuhause - service: automation.turn_off
data:
stop_actions: true
target:
entity_id:
– automation.heizung_17_grad
– automation.heizung_koeln
– automation.heizung_di_do_koeln - service: automation.trigger
data:
skip_condition: true
target:
entity_id: automation.heizung_zuhause
- condition: state
- conditions:
- condition: state
entity_id: input_select.dropd
state: in Köln
sequence: - service: automation.turn_on
data: {}
target:
entity_id: automation.heizung_koeln - service: automation.turn_off
data:
stop_actions: true
target:
entity_id:
– automation.heizung_17_grad
– automation.heizung_zuhause
– automation.heizung_di_do_koeln
- condition: state
- conditions:
- condition: state
entity_id: input_select.dropd
state: Di % Do in Köln
sequence: - service: automation.turn_on
data: {}
target:
entity_id: automation.heizung_di_do_koeln - service: automation.turn_off
data:
stop_actions: true
target:
entity_id:
– automation.heizung_17_grad
– automation.heizung_koeln
– automation.heizung_zuhause
default: []
- condition: state
- conditions:
- service: input_boolean.turn_on
data: {}
target:
entity_id: input_boolean.hz_steuerung_an_aus
mode: single
As mentioned above, there is then one automation per scene, here the “Tue & Thu in Cologne”.
Each of the automation for a scene starts with triggers that cover my standard times.
I’m in the office on Tuesdays and Thursdays, so I “only” have to go to the bathroom and then come back in the afternoon. On those days, I run the bathroom in the morning and turn all the heaters back on at the end of the day. In the meantime, everything is set to night setback.
On the other days, I’m in the home office, so the living room also needs to be heated. We get up later at the weekend, so the heating doesn’t start until 8:00 am. We go to bed normally around 11:00 pm, so the heating goes down at 10:00 pm.
These triggers are the same in all automations for the heating scenes, the actions are different.
Triggers can have IDs, which are then evaluated again by the actions, so the action can be triggered depending on the time and can also be differentiated by day(s) of the week via a condition.
This is the basic structure, now “only” the temperature setpoint values for all thermostats have to be set depending on the condition.
So that I can switch off the controller and control everything “manually”, there is the helper HZ_Steuerung_An_Aus, which the automation checks. If HZ_Steuerung is ON, the automations and thus the time controls are executed; if HZ_Steuerung is OFF, the control can be carried out manually via the helpers HZ_SollTempertur & HZ_Nachttemperatur.
Yaml Code Tue & Thu in Cologne
alias: Heizung_di_do_koeln
description: “”
trigger:
- platform: time
at: “06:00:00”
id: “6” - platform: time
at: “07:00:00”
id: “7” - platform: time
at: “08:00:00”
id: “8” - platform: time
at: “17:00:00”
id: “17” - platform: time
at: “22:00:00”
id: “22”
condition: []
action: - choose:
- conditions:
- condition: trigger id:
- “6”
- condition: time weekday:
- tue
- thu
sequence:
- service: climate.set_temperature
data:
temperature: “{{ states(‘input_number.hz_tagtemperatur’) }}”
target:
entity_id:
– climate.bad_1_og
– climate.bad_1_og_fenster - service: climate.set_temperature
data:
temperature: 24
target:
device_id: 65bf2234146f1a77c1c0cf629f8fa3c8 - service: input_number.set_value
data:
value: “{{states(‘input_number.hz_tagtemperatur’)}}”
target:
entity_id:
– input_number.hz_solltemperatur_bad1og
- condition: trigger id:
- conditions:
- condition: trigger id:
- “7”
- condition: time weekday:
- tue
- thu
sequence:
- service: climate.set_temperature
data:
temperature: “{{ states(‘input_number.hz_nachttemperatur’) }}”
target:
entity_id:
– climate.bad_1_og
– climate.bad_1_og_fenster
– climate.esszimmer
– climate.kuche
– climate.wohnzimmer_fenster - service: climate.set_temperature
data:
temperature: “{{ states(‘input_number.hz_nachttemperatur’) }}”
target:
device_id: 65bf2234146f1a77c1c0cf629f8fa3c8 - service: input_number.set_value
data:
value: “{{states(‘input_number.hz_nachttemperatur’)}}”
target:
entity_id:
– input_number.hz_solltemperatur_wohnesszimmer
– input_number.hz_solltemperatur_bad1og
- condition: trigger id:
- conditions:
- condition: trigger id:
- “7”
- condition: time weekday:
- mon
- wed
- fri
sequence:
- service: climate.set_temperature
data:
temperature: “{{ states(‘input_number.hz_tagtemperatur’) }}”
target:
entity_id:
– climate.bad_1_og
– climate.bad_1_og_fenster
– climate.esszimmer
– climate.kuche
– climate.wohnzimmer_fenster - service: climate.set_temperature
data:
temperature: 24
target:
device_id: 65bf2234146f1a77c1c0cf629f8fa3c8 - service: input_number.set_value
data:
value: “{{states(‘input_number.hz_tagtemperatur’)}}”
target:
entity_id:
– input_number.hz_solltemperatur_wohnesszimmer
– input_number.hz_solltemperatur_bad1og
- condition: trigger id:
- conditions:
- condition: trigger id:
- “8”
- condition: time weekday:
- sun
- mon
- wed
- fri
- sat
sequence:
- service: climate.set_temperature
data:
temperature: “{{ states(‘input_number.hz_tagtemperatur’) }}”
target:
entity_id:
– climate.bad_1_og
– climate.bad_1_og_fenster
– climate.esszimmer
– climate.kuche
– climate.wohnzimmer_fenster - service: climate.set_temperature
data:
temperature: 24
target:
device_id: 65bf2234146f1a77c1c0cf629f8fa3c8 - service: input_number.set_value
data:
value: “{{states(‘input_number.hz_tagtemperatur’)}}”
target:
entity_id:
– input_number.hz_solltemperatur_wohnesszimmer
– input_number.hz_solltemperatur_bad1og
- condition: trigger id:
- conditions:
- condition: trigger id:
- “17”
- condition: time weekday:
- tue
- thu
sequence:
- service: climate.set_temperature
data:
temperature: “{{ states(‘input_number.hz_tagtemperatur’) }}”
target:
entity_id:
– climate.bad_1_og
– climate.bad_1_og_fenster
– climate.esszimmer
– climate.kuche
– climate.wohnzimmer_fenster - service: climate.set_temperature
data:
temperature: 24
target:
device_id: 65bf2234146f1a77c1c0cf629f8fa3c8 - service: input_number.set_value
data:
value: “{{states(‘input_number.hz_tagtemperatur’)}}”
target:
entity_id:
– input_number.hz_solltemperatur_wohnesszimmer
– input_number.hz_solltemperatur_bad1og
- condition: trigger id:
- conditions:
- condition: trigger id:
- “22”
sequence:
- “22”
- service: climate.set_temperature
data:
temperature: “{{ states(‘input_number.hz_nachttemperatur’) }}”
target:
entity_id:
– climate.bad_1_og
– climate.bad_1_og_fenster
– climate.esszimmer
– climate.kuche
– climate.wohnzimmer_fenster - service: climate.set_temperature
data:
temperature: “{{ states(‘input_number.hz_nachttemperatur’) }}”
target:
device_id: 65bf2234146f1a77c1c0cf629f8fa3c8 - service: input_number.set_value
data:
value: “{{states(‘input_number.hz_nachttemperatur’)}}”
target:
entity_id:
– input_number.hz_solltemperatur_wohnesszimmer
– input_number.hz_solltemperatur_bad1og
default: []
mode: single
- condition: trigger id:
- conditions:
Now the offset comes into play again, if the setpoint temperature for the room is not the same as the measured temperature in the room, all thermostats on the radiators must be set higher.
I calculate the offset per room using a template sensor that is defined in configuration.yaml.
YAML Code OffSet Sensor
template:
- sensor:
- name: “Bad1OGZimmerOffset”
state: >
{{ (states.input_number.HZ_Solltemperatur_Bad1OG.state | float) – (states.sensor.bad_1og.state | float ) }} - name: “WohnZimmerOffset”
state: >
{{ (states.input_number.hz_solltemperatur_wohnesszimmer.state | float) – (states.sensor.wohnzimmer.state | float ) }}
- name: “Bad1OGZimmerOffset”
The thermostat, which controls the heating itself, is located in the living room. The target temperature of this thermostat must be >= the setpoint temperature of the living room for the heating to come on at all. I therefore check in the IF loop whether one of the OffSet values is > 0.1, i.e. heat is requested. I then set the setpoint temperature for the heating thermostat to the living room setpoint +2. If no heat is requested (all offset values < 0.1), I set the heating thermostat to the living room setpoint temperature. This ensures that the gas heating only comes on when heat is requested.
YAML Code Offset automation
alias: Heizung_Offset_5min
description: “”
trigger:
- platform: time_pattern
minutes: /5
condition: []
action: - service: climate.set_temperature
data:
temperature: >-
{{ states(‘input_number.hz_solltemperatur_bad1og’) | float(0) +
states(‘sensor.Bad1OGZimmerOffset’) | float(0) }}
target:
entity_id:
– climate.bad_1_og
– climate.bad_1_og_fenster - service: climate.set_temperature
data:
temperature: >-
{{ states(‘input_number.hz_solltemperatur_wohnesszimmer’) | float(0) +
states(‘sensor.wohnzimmeroffset’) | float(0) }}
target:
entity_id:
– climate.esszimmer
– climate.wohnzimmer_fenster
– climate.kuche
enabled: true - if:
- condition: numeric_state
entity_id: sensor.wohnzimmeroffset
above: 0.1 - condition: or conditions:
- condition: numeric_state
entity_id: sensor.bad1ogzimmeroffset
above: 0.1
then:
- condition: numeric_state
- service: climate.set_temperature
data:
temperature: >-
{{ states(‘input_number.hz_solltemperatur_wohnesszimmer’) | float(0)
+ 2 }}
target:
entity_id: climate.hmip_bwth_000c9f298af21b
else: - service: climate.set_temperature
data:
temperature: “{{ states(‘input_number.hz_solltemperatur_wohnesszimmer’) }}”
target:
entity_id: climate.hmip_bwth_000c9f298af21b
mode: single
- condition: numeric_state