Smart heating in the morning

I like to share this project which aims to simulate the smart heating present in some thermostats, in my case a Tado v3+. The aim is to obtain a certain temperature at a certain time, starting the heating well in advance. As a first step, I estimated the heating capacity of my system, in °C / h. This estimate is empirical, and can be done by observing the delta temperature and time during heating, or by creating a derivative sensor with the thermostat’s temperature sensor. In my case the observed values vary from about 0.5 to 1.5 °C / h, depending on the external temperature. First, I created a sensor to correct this heating ratio as a function of the external temperature (value from a sonoff zigbee sensor placed outdoor ‘sensor.sonoff_a480003084_temperature’). I consequently assumed that this variation occurs between a minimum (I chose 0 °C) and a maximum external temperature of 12 °C, which is the temperature below which my heating system is programmed to start (morning heating starts if the minimum temperature expected for the next day is below 12 °C). I then created two numeric helpers whose values are respectively the minimum and maximum °C / h (called ‘input_number.tado_offset_slope’ and ‘input_number.tado_max_slope’ with starting values of 0.5 and 1.5 as mentioned above) allowing future adjustments.

So, I calculated the correct ratio in °C / h as follows:

adjust_slope_outside_temp_living_room: 
     friendly_name: adjust_slope_outside_temp_living_room
     value_template: >
        {%- set delta_slope = ((states('input_number.tado_max_slope')|float(default=16))-(states('input_number.tado_offset_slope')|float(default=16)))/12 -%}
        {{(states('input_number.tado_offset_slope')|float(default=16)+((states('sensor.sonoff_a480003084_temperature')|float(default=16))*delta_slope))|round(2)}}

below is a sensor that calculates the delta temperature to be filled in order to reach the preset temperature, as the difference between the target temperature and the current temperature in the room:

delta_t_tado_thermostat:
        friendly_name: 'delta_t_tado_thermostat'
        value_template: >   
{{((states('input_number.tado_thermostat_temp1')|float(default=16)-(states('sensor.state_current_temp_thermostat_living_room')|float(default=16))))|round(2)}}  

the value can, of course, be positive or negative. The next sensor calculates the necessary time in minutes, dividing the temperature delta by the ratio in ° C / h and then multiplying by 60:

time_heating_tado_thermostat: 
        friendly_name: 'time_heating_tado_thermostat'
        value_template: >   
{{((states('input_number.tado_thermostat_temp1')|float(default=16)-(states('sensor.state_current_temp_thermostat_living_room')|float(default=16)))|round(2)/((states('sensor.adjust_slope_outside_temp_living_room')|float(default=1)))*60)|round(2)}}      

the next step was to establish the start time of the heating. A good way for me was to use the next alarm sensor provided in the companion app. Since there are three of us in the house, I wrote a template that returns the value with the alarm set before, and then subtracts the time (converted in seconds) calculated above:

    set_preheating_thermostat_tado_living_room:
        friendly_name: set_preheating_thermostat_tado_living_room  
        value_template: >   
          {%- set alarm_list = [(as_timestamp(states('sensor.emma_next_alarm'))),   (as_timestamp(states('sensor.pixel_2_xl_next_alarm'))), (as_timestamp(states('sensor.mi_a2_next_alarm'))) ] -%}
          {% if (states('sensor.pixel_2_xl_next_alarm'))== "unavailable" and (states('sensor.emma_next_alarm'))== "unavailable" and (states('sensor.mi_a2_next_alarm'))== "unavailable" -%}
                        "08:00"
          {%- else %}
          {{(min(alarm_list)|float(default=1)-(states('sensor.time_heating_tado_thermostat')|float(default=1)*60)) | timestamp_custom('%I:%M') }}
          {%- endif %}

The sensor output is like “6:01”. If any alarm is available may be sunday…The value was then used in an automation that set the start time in the morning:

alias: Set tado thermostat by alarm living room
description: ''
trigger:
  - platform: state
    entity_id: sensor.time_heating_tado_thermostat
    for:
      hours: 0
      minutes: 0
      seconds: 0
      milliseconds: 0
condition:
  - condition: template
    value_template: '{{(states(''sensor.time_heating_tado_thermostat''))|float(default=1)>0}}'
  - condition: time
    weekday:
      - mon
      - tue
      - wed
      - thu
      - fri
      - sat
    after: '00:00'
    before: '11:00'
action:
  - service: input_datetime.set_datetime
    data:
      time: '{{ states(''sensor.set_preheating_thermostat_tado_living_room'') }}'
    target:
      entity_id:
        - input_datetime.tado_thermostat_start1
mode: single

Condition is that heating time is>0. Automation that contain input_datetime.tado_thermostat_start1 is (This automation also sets up a tado smart radiator other than the thermostat):

alias: Tado schedule thermostat ON1
description: ''
trigger:
  - platform: state
    entity_id: input_datetime.tado_thermostat_start1
  - platform: template
    value_template: >-
      {{ states('sensor.time') >=
      (states('input_datetime.tado_thermostat_start1')) }}
  - platform: state
    entity_id: input_datetime.tado_thermostat_start1
  - platform: state
    entity_id: input_datetime.tado_thermostat_end1
condition:
  - condition: template
    value_template: '{{states(''sensor.valuta_giorno_schedule_thermostat_tado'')}}'
  - condition: template
    value_template: >-
      {{ states('sensor.time') >=
      (states('input_datetime.tado_thermostat_start1')) }}
  - condition: template
    value_template: >-
      {{ states('sensor.time') <=
      (states('input_datetime.tado_thermostat_end1')) }}
  - condition: template
    value_template: >-
      {{ (states('input_datetime.tado_thermostat_end1'))!="00:00" and
      (states('input_datetime.tado_thermostat_start1'))!="00:00"  }}
  - condition: time
    after: '00:00'
    weekday:
      - mon
      - tue
      - wed
      - thu
      - fri
      - sat
action:
  - delay:
      hours: 0
      minutes: 0
      seconds: 30
      milliseconds: 0
  - service: climate.turn_on
    target:
      entity_id:
        - climate.tado_smart_thermostat_ruxxxxxxxxxx
        - climate.tado_smart_radiator_thermostat_vayyyyyyyyyy
  - service: climate.set_temperature
    target:
      entity_id:
        - climate.tado_smart_radiator_thermostat_vayyyyyyyyy
    data:
      temperature: >
        {{
        states('input_number.tado_thermostat_temp1')|float-(states('input_number.tado_offset_smart_radiator')|float)}}
  - service: climate.set_temperature
    target:
      entity_id: climate.tado_smart_thermostat_ruxxxxxxxxxx
    data:
      temperature: |
        {{states('input_number.tado_thermostat_temp1')|float}}
mode: single
max: 10

This last automation is not well explained, but the goal here is to set up morning start time. I am a beginner aware that the code could have been written more efficiently and smarter. I’ve been using it for many days and seems to be working fine: heating time is well estimated, of course not perfectly. I’m going to adjust the empirical data. That’s all I have. :wink:

6 Likes

This is great - thanks! I’ve been thinking about doing something similar, but haven’t gotten any further than “that would be great”. You’ve inspired me to actually put this on my list of things to do rather than just thinking it would be a good idea.

1 Like

Hello, what you have done is very valuable. I applied the system for myself. But what kind of settings do I need to make for the delta sensor and the system to work. I would be very happy if you can explainDurumlar – Home Assistant