Opentherm Multi Room brainstorming / ideas

You got an extra % at the end there.
Also, always define a default value if for some reason the sensor wont work.

{% set masterbedroom_td = (states('sensor.target_temperature_br') - states('sensor.ble_temperature_clim_master_bedroom') | float(18)) %}

{{ (states('sensor.target_temperature_br') | float(18)) }}

Just a pointer which I’ve spent a while try to figure out!

I think the {% if index_td == 1 %} should start at 0 and then run through to 1 - the number of rooms you have.

I had issues where the list was picking out the second largest temperature difference!

Credit to Chat GPT AI who help me haha!

1 Like

You know, you are right. I never realized that it would count from zero.
My lack of programming skills shows :smiley: Seem thats always the case be it Jinja or Python.

Ow Frell me… I already took that into account. The living room (woonkamer is 0) so i just check for 1 and 2 and if its 0 then take the living room value.
I noticed when it stopped working correctly after changing it :frowning:

1 Like

Which sketch are you using? The DIYLESS Git Hub one or the modified version by Joparmen?

I think I have everything working other than, for some reason the set values don’t seem to trigger the boiler to start heating. I’ve checked in MQTT explorer and they are been sent over correctly, but the get topics never seem to update.

I am running the Joparmen version though.

Cheers, happy to help.

Maybe I’m impatient… It seems to have the values now…

still not working here. I receive state: unavailable

- platform: template
    sensors:
      virtual_temperature:
        friendly_name: "Virtual Temperature"
        unit_of_measurement: "°C"
        value_template: >
          {% set masterbedroom_td = (states('sensor.target_temperature_br') - states('sensor.ble_temperature_clim_master_bedroom') | float) %}
          {% set kidsbedroom_td = (states('sensor.target_temperature_kidsbr') - states('sensor.ble_temperature_clim_kids_bedroom') | float) %}
          {% set livingroom_td = (states('sensor.target_temperature_lr') - states('sensor.ble_temperature_clim_living') | float) %}
          {% set kitchen_td = (states('sensor.target_temperature_kit') - states('sensor.ble_temperature_clim_kitchen') | float) %}
          {% set bathroom_td = (states('sensor.target_temperature_bathr') - states('sensor.ble_temperature_clim_bathroom') | float) %}
          {% set max_td = ([masterbedroom_td,kidsbedroom_td,kitchen_td,bathroom_td,livingroom_td] | max) %}
          {% set list_room_td = [masterbedroom_td,kidsbedroom_td,kitchen_td,bathroom_td,livingroom_td] %}
          {% set index_td = list_room_td.index(max_td) %}
          {% if index_td == 1 %}
            {{ (states('sensor.ble_temperature_clim_master_bedroom') | float(18)) }}
          {% elif index_td == 2 %}
            {{ (states('sensor.ble_temperature_clim_kids_bedroom') | float(18)) }}
          {% elif index_td == 3 %}
            {{ (states('sensor.ble_temperature_clim_kitchen') | float(18)) }}
          {% elif index_td == 4 %}
            {{ (states('sensor.ble_temperature_clim_bathroom') | float(18)) }}
          {% else %}
            {{ (states('sensor.ble_temperature_clim_living') | float(18)) }}
          {% endif %}
      virtual_target:
        friendly_name: "Virtual Target"
        unit_of_measurement: "°C"
        value_template: >
          {% set masterbedroom_td = (states('sensor.target_temperature_br') - states('sensor.ble_temperature_clim_master_bedroom') | float) %}
          {% set kidsbedroom_td = (states('sensor.target_temperature_kidsbr') - states('sensor.ble_temperature_clim_kids_bedroom') | float) %}
          {% set livingroom_td = (states('sensor.target_temperature_lr') - states('sensor.ble_temperature_clim_living') | float) %}
          {% set kitchen_td = (states('sensor.target_temperature_kit') - states('sensor.ble_temperature_clim_kitchen') | float) %}
          {% set bathroom_td = (states('sensor.target_temperature_bathr') - states('sensor.ble_temperature_clim_bathroom') | float) %}
          {% set max_td = ([masterbedroom_td,kidsbedroom_td,kitchen_td,bathroom_td,livingroom_td] | max) %}
          {% set list_room_td = [masterbedroom_td,kidsbedroom_td,kitchen_td,bathroom_td,livingroom_td] %}
          {% set index_td = list_room_td.index(max_td) %}
          {% if index_td == 1 %}
            {{ (states('sensor.target_temperature_br') | float(18)) }}
          {% elif index_td == 2 %}
            {{ (states('sensor.target_temperature_kidsbr') | float(18)) }}
          {% elif index_td == 3 %}
            {{ (states('sensor.target_temperature_kit') | float(18)) }}
          {% elif index_td == 4 %}
            {{ (states('sensor.target_temperature_bathr') | float(18)) }}
          {% else %}
            {{ (states('sensor.target_temperature_lr') | float(18)) }}
          {% endif %}

Lets take a step back and just insert this in the Developer ToolsTemplate

{% set masterbedroom_td = (states('sensor.target_temperature_br') - states('sensor.ble_temperature_clim_master_bedroom') | float) %}
{{ masterbedroom_td }}

And just this:

{{ states('sensor.target_temperature_br') }}
{{ states('sensor.ble_temperature_clim_master_bedroom') }}

Also you should always define a default value for if the sensor bugs out or any other startup problem when the sensor is unknow for some reason

So what do those 2 give?

The first one

TypeError: unsupported operand type(s) for -: ‘str’ and ‘float’

The second one
19.0
20.7

{% set masterbedroom_td = (states('sensor.target_temperature_br') | float(18) - states('sensor.ble_temperature_clim_master_bedroom') | float(18)) %}
{{ masterbedroom_td }}

I think you need to define both as floats (and give them a default value)
Right you you just specified the last one as a float and HA is seeing the first one as a string, and since you cannot subtract a float from a string, you get that error.

thank u this works. another problem, how can I exclude the rooms with a negative difference from the list? For example living room is 2 degrees to warm, the rest of the room is 0,5 degrees below set point. How do I ban the living room from determining the temperature?

You dont. 2 degrees to warm means its -2 difference. Thats smaller then 0,5 so it will pick the 0,5 difference

Hello,

I’m trying your code for the virtual temp and set temp.
I have more zones and tried to extend it.

It doesn’t seem to work, Can someone guide me what I’m doing wrong?

this is what I added in the “sensor.yaml”

Thanks in advance.

setpoint_cv_virtual:
  friendly_name: "CV Virtual Setpoint"
  unit_of_measurement: "°C"
  value_template: >
    {% set woonkamer_td = (state_attr('climate.woonkamer_bt','temperature') - states('sensor.living_room_temperature') | float) %}
    {% set berging_td = (state_attr('climate.berging_bt','temperature') - states('sensor.berging_mija_temp_temperature') | float) %}
    {% set slaapkamer_td = (state_attr('climate.slaapkamer','temperature') - states('sensor.mbr_temperature') | float) %}
    {% set badkamer_td = (state_attr('climate.badkamer_bt','temperature') - states('sensor.badkamer_mija_temp_temperature') | float) %}
    {% set inkomhall_td = (state_attr('climate.inkomhall','temperature') - states('sensor.inkomhal_radiator_local_temperature') | float) %}
    {% set fitness_td = (state_attr('climate.fitness','temperature') - states('sensor.fitness_temperature') | float) %}
    {% set max_td = ([woonkamer_td,berging_td,slaapkamer_td,badkamer_td,inkomhall_td,fitness_td] | max) %}
    {% set list_room_td = [woonkamer_td,berging_td,slaapkamer_td,badkamer_td,inkomhall_td,fitness_td] %}
    {% set index_td = list_room_td.index(max_td) %}
    {% if index_td == 1 %}
      {{ state_attr('climate.woonkamer_bt','temperature') }}
    {% elif index_td == 2 %}
      {{ state_attr('climate.berging_bt','temperature') }}
    {% elif index_td == 3 %}
      {{ state_attr('climate.slaapkamer','temperature') }} 
    {% elif index_td == 4 %}
      {{ state_attr('climate.badkamer_bt','temperature') }}  
    {% elif index_td == 5 %}
      {{ state_attr('climate.inkomhall','temperature') }}          
    {% else %}
      {{ state_attr('climate.fitness','temperature') }}          
    {% endif %}
temperature_cv_virtual:
  friendly_name: "CV Virtual Temperature"
  unit_of_measurement: "°C"
  value_template: >
    {% set woonkamer_td = (state_attr('climate.woonkamer_bt','temperature') - states('sensor.living_room_temperature') | float) %}
    {% set berging_td = (state_attr('climate.berging_bt','temperature') - states('sensor.berging_mija_temp_temperature') | float)%}
    {% set slaapkamer_td = (state_attr('climate.slaapkamer','temperature') - states('sensor.mbr_temperature') | float) %}
    {% set badkamer_td = (state_attr('climate.badkamer_bt','temperature') - states('sensor.badkamer_mija_temp_temperature') | float) %}
    {% set inkomhall_td = (state_attr('climate.inkomhall','temperature') - states('sensor.inkomhal_radiator_local_temperature') | float) %}
    {% set fitness_td = (state_attr('climate.fitness','temperature') - states('sensor.fitness_temperature') | float) %}
    {% set max_td = ([woonkamer_td,berging_td,slaapkamer_td,badkamer_td,inkomhall_td,fitness_td] | max) %}
    {% set list_room_td = [woonkamer_td,berging_td,slaapkamer_td,badkamer_td,inkomhall_td,fitness_td] %}
    {% set index_td = list_room_td.index(max_td) %}
    {% if index_td == 1 %}
      {{ states('sensor.living_room_temperature') | float }}
    {% elif index_td == 2 %}
      {{ states('sensor.berging_mija_temp_temperature') | float }}
    {% elif index_td == 3 %}
      {{ states('sensor.mbr_temperature') | float }}  
    {% elif index_td == 4 %}
      {{ states('sensor.badkamer_mija_temp_temperature') | float }} 
    {% elif index_td == 5 %}
      {{ states('sensor.inkomhal_radiator_local_temperature') | float }} 
    {% else %}
      {{ states('sensor.fitness_temperature') | float }}          
    {% endif %}

If you are posting code, use the code tags and not quotes. That way you can pick out errors with indentations more easily. Like the first part:

setpoint_cv_virtual:
  friendly_name: "CV Virtual Setpoint"
  unit_of_measurement: "°C"
  value_template: >
    {% set woonkamer_td = (state_attr('climate.woonkamer_bt','temperature') - states('sensor.living_room_temperature') | float) %}
    {% set berging_td = (state_attr('climate.berging_bt','temperature') - states('sensor.berging_mija_temp_temperature') | float) %}
    {% set slaapkamer_td = (state_attr('climate.slaapkamer','temperature') - states('sensor.mbr_temperature') | float) %}
    {% set badkamer_td = (state_attr('climate.badkamer_bt','temperature') - states('sensor.badkamer_mija_temp_temperature') | float) %}
    {% set inkomhall_td = (state_attr('climate.inkomhall','temperature') - states('sensor.inkomhal_radiator_local_temperature') | float) %}
    {% set fitness_td = (state_attr('climate.fitness','temperature') - states('sensor.fitness_temperature') | float) %}
    {% set max_td = ([woonkamer_td,berging_td,slaapkamer_td,badkamer_td,inkomhall_td,fitness_td] | max) %}
    {% set list_room_td = [woonkamer_td,berging_td,slaapkamer_td,badkamer_td,inkomhall_td,fitness_td] %}
    {% set index_td = list_room_td.index(max_td) %}
    {% if index_td == 1 %}
      {{ state_attr('climate.woonkamer_bt','temperature') }}
    {% elif index_td == 2 %}
      {{ state_attr('climate.berging_bt','temperature') }}
    {% elif index_td == 3 %}
      {{ state_attr('climate.slaapkamer','temperature') }} 
    {% elif index_td == 4 %}
      {{ state_attr('climate.badkamer_bt','temperature') }}  
    {% elif index_td == 5 %}
      {{ state_attr('climate.inkomhall','temperature') }}          
    {% else %}
      {{ state_attr('climate.fitness','temperature') }}          
    {% endif %}

Having said that, you never seemed to define this is a template sensor.

Keep in mind that my code is old and had a few revisions. Important thing is to add default values so these get used when sensors are offline.

- platform: template
  sensors:
      setpoint_cv_virtual:
      friendly_name: "CV Virtual Setpoint"
      unit_of_measurement: "°C"
      value_template: >
        {% set alex_td = state_attr('climate.alex','temperature') | float(18) - states('sensor.alex_sensor_temperature') | float(18) %}
        {% set esther_td = state_attr('climate.esther','temperature') | float(18) - states('sensor.esther_sensor_temperature') | float(18) %}
        {% set woonkamer_td = state_attr('climate.woonkamer','temperature') | float(18) - states('sensor.woonkamer_sensor_temperature') | float(18) %}
        {% set max_td = ([woonkamer_td,alex_td,esther_td] | max) %}
        {% set list_room_td = [woonkamer_td,alex_td,esther_td] %}
        {% set index_td = list_room_td.index(max_td) %}
        {% if index_td == 1 %}
          {{ state_attr('climate.alex','temperature') | float(18)}}
        {% elif index_td == 2 %}
          {{ state_attr('climate.esther','temperature') | float(18)}}
        {% else %}
          {{ state_attr('climate.woonkamer','temperature') | float(18)}}
        {% endif %}
    temperature_cv_virtual:
      friendly_name: "CV Virtual Temperature"
      unit_of_measurement: "°C"
      value_template: >
        {% set alex_td = state_attr('climate.alex','temperature') - states('sensor.alex_sensor_temperature') | float(23) %}
        {% set esther_td = state_attr('climate.esther','temperature') - states('sensor.esther_sensor_temperature') | float(23) %}
        {% set woonkamer_td = state_attr('climate.woonkamer','temperature') - states('sensor.woonkamer_sensor_temperature') | float(23) %}
        {% set max_td = ([woonkamer_td,alex_td,esther_td] | max) %}
        {% set list_room_td = [woonkamer_td,alex_td,esther_td] %}
        {% set index_td = list_room_td.index(max_td) %}
        {% if index_td == 1 %}
          {{ states('sensor.alex_sensor_temperature') | float(23)}}
        {% elif index_td == 2 %}
          {{ states('sensor.esther_sensor_temperature') | float(23)}}
        {% else %}
          {{ states('sensor.woonkamer_sensor_temperature') | float(23)}}
        {% endif %}

Note that this is the old style as there was an issue getting the friendly_name to behave correctly in the new style. There is a long debate around this: Add (bring back) friendly_name to template sensors
But since the old style does not show signs of being decraped, i will use it like this :smiley:

Edit: i’ll mark this for future reference.

For now (31-7-2023) This is the code i use. Adjusted to use default values and some cleanup.

- platform: template
  sensors:
      setpoint_cv_virtual:
      friendly_name: "CV Virtual Setpoint"
      unit_of_measurement: "°C"
      value_template: >
        {% set alex_td = state_attr('climate.alex','temperature') | float(18) - states('sensor.alex_sensor_temperature') | float(18) %}
        {% set esther_td = state_attr('climate.esther','temperature') | float(18) - states('sensor.esther_sensor_temperature') | float(18) %}
        {% set woonkamer_td = state_attr('climate.woonkamer','temperature') | float(18) - states('sensor.woonkamer_sensor_temperature') | float(18) %}
        {% set max_td = ([woonkamer_td,alex_td,esther_td] | max) %}
        {% set list_room_td = [woonkamer_td,alex_td,esther_td] %}
        {% set index_td = list_room_td.index(max_td) %}
        {% if index_td == 1 %}
          {{ state_attr('climate.alex','temperature') | float(18)}}
        {% elif index_td == 2 %}
          {{ state_attr('climate.esther','temperature') | float(18)}}
        {% else %}
          {{ state_attr('climate.woonkamer','temperature') | float(18)}}
        {% endif %}
    temperature_cv_virtual:
      friendly_name: "CV Virtual Temperature"
      unit_of_measurement: "°C"
      value_template: >
        {% set alex_td = state_attr('climate.alex','temperature') - states('sensor.alex_sensor_temperature') | float(23) %}
        {% set esther_td = state_attr('climate.esther','temperature') - states('sensor.esther_sensor_temperature') | float(23) %}
        {% set woonkamer_td = state_attr('climate.woonkamer','temperature') - states('sensor.woonkamer_sensor_temperature') | float(23) %}
        {% set max_td = ([woonkamer_td,alex_td,esther_td] | max) %}
        {% set list_room_td = [woonkamer_td,alex_td,esther_td] %}
        {% set index_td = list_room_td.index(max_td) %}
        {% if index_td == 1 %}
          {{ states('sensor.alex_sensor_temperature') | float(23)}}
        {% elif index_td == 2 %}
          {{ states('sensor.esther_sensor_temperature') | float(23)}}
        {% else %}
          {{ states('sensor.woonkamer_sensor_temperature') | float(23)}}
        {% endif %}

Hello Dujith,

Thanks for your reply.

I forgot to mention that the code I added was only the part for these 2 sensors, I already defined the template sensor.

download the sensor.yaml here

When using this I get the following error while doing “Quick reload”

Failed to reload configuration

Cannot quick reload all YAML configurations because the configuration is not valid: Invalid config for [sensor.template]: invalid template (TemplateSyntaxError: unexpected ‘}’, expected ‘)’) for dictionary value @ data[‘sensors’][‘setpoint_cv_virtual’][‘value_template’]. Got "{% set woonkamer_td = (state_attr(‘climate.woonkamer_bt’,‘temperature’) | float(18) - states(‘sensor.living_room_temperature’) | float(18) %} {% set berging_td = (state_attr(‘climate.berging_bt’,‘temperature’) | float(18) - states(‘sensor.berging_mija_temp_temperature’) | float(18) %} {% set slaapkamer_td = (state_attr(‘climate.slaapkamer’,‘temperature’) | float(18) - states(‘sensor.mbr_temperature’) | float(18) %} {% set badkamer_td = (state_attr(‘climate.badkamer_bt’,‘temperature’) | float… (See ?, line ?).

Just need to add a ) or remove the one at the start: (state_attr
Check all the lines for the missing ) :smiley:

Thanks all for your help, that did it!

It has been interesting to read. I might end up pitching this to my moms association of owners.

The first alteration I would try is moving list_room_td up one line and try to use it for max_td to make things a bit more DRY.

HI I have read all your posts. My intended setup would be a little different. I have one main living room that shoul allways remain working. No matter the state of my HA instance. (i can be away for long times).
But: The bathroom, twoo studies, and maybe another room i want to control separate. I want to use Zigbee TRV’s in those rooms. If HA is not working everything should work the old fashioned way. Just based on the living room temeperature. So when the HA setup is working properly the boiler should turn on and supply heat to at least one room that is requesting heat. If the Living Room is not requesting heat, the floor heating system should be closed. In ALL other situations the floor heating valve must be open.
Is this setup possible?

Just wanted to chime in and say thanks and add a bit more for other people finding this in 2024 and beyond…

this set up so far looks super useful but could probably be updated a bit. So i took & adapted @dujith 's excellent posts above, and slightly updated it for the newer (referred to as “modern” style) template syntax

for example, what we have above in this thread uses parameters of “friendly_name” and “value_template”, which are now considered “legacy-format”, only found in that part of the docs-section, and is no longer recommended. Instead value_template is referred to just as “state” and “friendly_name” becomes (i believe) just the “name:” parameter (and what was the name can now be referred to as “unique_id”).

Here’s how i imagine it could be updated for the current template-format “style” - put the following in your templates.yaml:

 sensor:
    - name: "Central Heating Temperature"
      unique_id: ch_virtual_temperature
      unit_of_measurement: "°C"
      state: >
        {% if states('climate.trv_bedroom1') == "heat" %}
          {% set tempdiff_bedroom1 = state_attr('climate.trv_bedroom1','temperature') 
          - states('sensor.temperature_bedroom1_temperature') | float %}
        {% else %}
          {% set tempdiff_bedroom1 = '-99' | float %}
        {% endif %}
        
        {% if states('climate.trv_bedroom2') == "heat" %}
          {% set tempdiff_bedroom2 = state_attr('climate.trv_bedroom2','temperature') 
          - states('sensor.temperature_bedroom2_temperature') | float %}
        {% else %}
          {% set tempdiff_bedroom2 = '-99' | float %}
        {% endif %}
        
        {% if states('climate.trv_officegym') == "heat" %}
          {% set tempdiff_officegym = state_attr('climate.trv_officegym','temperature') 
          - states('sensor.temperature_officegym_temperature') | float %}
        {% else %}
          {% set tempdiff_officegym = '-99' | float %}
        {% endif %}
        
        {% if states('climate.trv_hallway') == "heat" %}
          {% set tempdiff_hallway = state_attr('climate.trv_hallway','temperature') 
          - states('sensor.temperature_hallway_lower_temperature') | float %}
        {% else %}
          {% set tempdiff_hallway = '-99' | float %}
        {% endif %}
        
        {% if states('climate.trv_bathroom_lower') == "heat" %}
          {% set tempdiff_bathroom_lower = state_attr('climate.trv_bathroom_lower','temperature') 
          - states('sensor.temperature_bathroom_lower_temperature') | float %}
        {% else %}
          {% set tempdiff_bathroom_lower = '-99' | float %}
        {% endif %}
        
        {% if states('climate.trv_kitchen') == "heat" %}
          {% set tempdiff_kitchen = state_attr('climate.trv_kitchen','temperature') 
          - states('sensor.temperature_livingroom_temperature') | float %}
        {% else %}
          {% set tempdiff_kitchen = '-99' | float %}
        {% endif %}
        
        {% if states('climate.trv_livingroom_center') == "heat" %}
          {% set tempdiff_livingroom_center = state_attr('climate.trv_livingroom_center','temperature') 
          - states('sensor.temperature_livingroom_temperature') | float %}
        {% else %}
          {% set tempdiff_livingroom_center = '-99' | float %}
        {% endif %}
        
        {% if states('climate.trv_livingroom_wall') == "heat" %}
          {% set tempdiff_livingroom_wall = state_attr('climate.trv_livingroom_wall','temperature') 
          - states('sensor.temperature_livingroom_temperature') | float %}
        {% else %}
          {% set tempdiff_livingroom_wall = '-99' | float %}
        {% endif %}
        
        {% set room_list_tempdiffs = [tempdiff_bedroom1,tempdiff_bedroom2,tempdiff_officegym,tempdiff_hallway,tempdiff_bathroom_lower,tempdiff_kitchen,tempdiff_livingroom_center,tempdiff_livingroom_wall] %}
        {% set max_tempdiff = (room_list_tempdiffs | max) %}
        {% set index_tempdiff = room_list_tempdiffs.index(max_tempdiff) %}
        
        {%   if index_tempdiff == 0 %}
          {{ (states('sensor.temperature_bedroom1_temperature') | float(18)) }}
        {% elif index_tempdiff == 1 %}
          {{ (states('sensor.temperature_bedroom2_temperature') | float(18)) }}
        {% elif index_tempdiff == 2 %}
          {{ (states('sensor.temperature_officegym_temperature') | float(18)) }}
        {% elif index_tempdiff == 3 %}
          {{ (states('sensor.temperature_hallway_lower_temperature') | float(18)) }}
        {% elif index_tempdiff == 4 %}
          {{ (states('sensor.temperature_bathroom_lower_temperature') | float(18)) }}
        {% else %}
          {{ (states('sensor.temperature_livingroom_temperature') | float(18)) }}
        {% endif %}

    - name: "Central Heating Setpoint"
      unique_id: ch_virtual_setpoint
      unit_of_measurement: "°C"
      state: >
        {% if states('climate.trv_bedroom1') == "heat" %}
          {% set tempdiff_bedroom1 = state_attr('climate.trv_bedroom1','temperature') 
          - states('sensor.temperature_bedroom1_temperature') | float %}
        {% else %}
          {% set tempdiff_bedroom1 = '-99' | float %}
        {% endif %}
        
        {% if states('climate.trv_bedroom2') == "heat" %}
          {% set tempdiff_bedroom2 = state_attr('climate.trv_bedroom2','temperature') 
          - states('sensor.temperature_bedroom2_temperature') | float %}
        {% else %}
          {% set tempdiff_bedroom2 = '-99' | float %}
        {% endif %}
        
        {% if states('climate.trv_officegym') == "heat" %}
          {% set tempdiff_officegym = state_attr('climate.trv_officegym','temperature') 
          - states('sensor.temperature_officegym_temperature') | float %}
        {% else %}
          {% set tempdiff_officegym = '-99' | float %}
        {% endif %}
        
        {% if states('climate.trv_hallway') == "heat" %}
          {% set tempdiff_hallway = state_attr('climate.trv_hallway','temperature') 
          - states('sensor.temperature_hallway_lower_temperature') | float %}
        {% else %}
          {% set tempdiff_hallway = '-99' | float %}
        {% endif %}
        
        {% if states('climate.trv_bathroom_lower') == "heat" %}
          {% set tempdiff_bathroom_lower = state_attr('climate.trv_bathroom_lower','temperature') 
          - states('sensor.temperature_bathroom_lower_temperature') | float %}
        {% else %}
          {% set tempdiff_bathroom_lower = '-99' | float %}
        {% endif %}
        
        {% if states('climate.trv_kitchen') == "heat" %}
          {% set tempdiff_kitchen = state_attr('climate.trv_kitchen','temperature') 
          - states('sensor.temperature_livingroom_temperature') | float %}
        {% else %}
          {% set tempdiff_kitchen = '-99' | float %}
        {% endif %}
        
        {% if states('climate.trv_livingroom_center') == "heat" %}
          {% set tempdiff_livingroom_center = state_attr('climate.trv_livingroom_center','temperature') 
          - states('sensor.temperature_livingroom_temperature') | float %}
        {% else %}
          {% set tempdiff_livingroom_center = '-99' | float %}
        {% endif %}
        
        {% if states('climate.trv_livingroom_wall') == "heat" %}
          {% set tempdiff_livingroom_wall = state_attr('climate.trv_livingroom_wall','temperature') 
          - states('sensor.temperature_livingroom_temperature') | float %}
        {% else %}
          {% set tempdiff_livingroom_wall = '-99' | float %}
        {% endif %}
        
        {% set room_list_tempdiffs = [tempdiff_bedroom1,tempdiff_bedroom2,tempdiff_officegym,tempdiff_hallway,tempdiff_bathroom_lower,tempdiff_kitchen,tempdiff_livingroom_center,tempdiff_livingroom_wall] %}
        {% set max_tempdiff = (room_list_tempdiffs | max) %}
        {% set index_tempdiff = room_list_tempdiffs.index(max_tempdiff) %}
        
        {%   if index_tempdiff == 0 %}
          {{ state_attr('climate.trv_bedroom1','temperature') | float(18) }}
        {% elif index_tempdiff == 1 %}
          {{ state_attr('climate.trv_bedroom2','temperature') | float(18) }}
        {% elif index_tempdiff == 2 %}
          {{ state_attr('climate.trv_officegym','temperature') | float(18) }}
        {% elif index_tempdiff == 3 %}
          {{ state_attr('climate.trv_hallway','temperature') | float(18) }}
        {% elif index_tempdiff == 4 %}
          {{ state_attr('climate.trv_bathroom_lower','temperature') | float(18) }}
        {% elif index_tempdiff == 5 %}
          {{ state_attr('climate.trv_kitchen','temperature')  | float(18) }}
        {% elif index_tempdiff == 6 %}
          {{ state_attr('climate.trv_livingroom_center','temperature')  | float(18) }}
        {% elif index_tempdiff == 7 %}
          {{ state_attr('climate.trv_livingroom_wall','temperature')  | float(18) }}
        {% endif %}

I’ve also incorporated the idea from @Snelf in the above post, so that when a TRV is not set to heat, it will default to “skipping” it (setting its suggested temp-differential to -99, to effectively prevent it from the choosing (unless we’re in an ice-age perhaps)).

Additionally, things to be aware of about my setup:

  • i have only one temperature-sensor (all mine are aqara ones) for the area in the house that includes both the kitchen/living room (as they’re connected, w/o a significant partition between them, so thermally i treat them the-same), but there are in-fact three radiators (and thus TRVs) there - so i check each of them for the temp-diff in both template-sensors, but for the temperature, it’s picked as a “fall-back” in the if-block, and for the setpoint if-block, i actually use the setpoint of the specific TRV).

At the moment, these two values look like this for the temperature:

And like this for the setpoint:

If anyone has any ideas/feedback on my approach, or ideas for improvement, i’im open to them. One thing i’m not sure about which was touched upon in the above thread was whether the boiler will function efficiently if its idea of what the current temperature and the setpoint changes regularly. It seems it wouldn’t be able to “calibrate” its internal PID parameters since each room is slightly different and it won’t be able to converge on the correct parameters if the values/behaviour of the heating keeps shifting between different rooms.

Finally, things that are missing still:

  • i need to actually wire-up the thermostat to my boiler still :slight_smile:
  • come up with automations that take-into-account whether no one is home (i am using the advhanced-heating-control blueprint for that on the individual-TRV basis, but need to incorporate it also telling the boiler to not generate heat if all TRV’s are not needing heat - which at the moment i’m not sure if that can ever happen?).