UK Based Heating Control - Multi Zoned, with Shelly TRV's

Hi All,

I’m a relative newcomer to Home Assistant … I’ve been running it on a Pi4 in parallel to my existing Home-Automation platform for about a year, but only to act as a bridge to integrate some wireless switches my existing platform can’t talk to. I’m running the latest version, and have ZHA installed - some smart plugs, have added my Shelly TRV’s … and have a couple of sample Aqara FP2 presence sensors, door sensors and Temp/Humidity Sensors connected … and a relay ready to install as the boiler demand.

I’m now considering swapping fully over to Home Assistant - but, (and especially being new and now yet “getting” YAML) - I’m struggling to picture how to achieve the same intelligent Heating Setup as I have in my existing system.

I currently have a single (system) Gas boiler - and each Radiator has a Shelly TRV, that is set to 0% open, or 100% (via Rest API) depending upon the heating controller (HVAC object) that sits within that room calling for heat or not. Each room has a notion of Occupancy, and each room has separate Temperature sensors so I’m not using the TRV temperature value in any way.

Here’s my requirements based on what my current system does that I want to replicate to migrate me over to HA;

  • I want a per-zone heating control (in most cases, per room, but I’ve got a Zone where I aggregate 2 different temperatures and treat both rooms as 1, controller by a single heating controller object)
  • For each heating zone, I want to be able to setup per day, per hour, temperature set points / profiles, for the heating to target. These would apply when the house, Zone or Room is occupied.
  • I want to be able to setup different set points to the above, that would apply if the house or Zone is unoccupied (clearly lower values)
  • I want the heating controller in any given room, to call for the boiler to fire up when there’s heating demand (turning an Aqara relay on), and also open the Shelly TRV associate with that room to 100% too.
  • I want a temporary “Boost” option, to increase the set point of any given (or all) heating zone.

There seems to be more “Thermostat” and “HVAC” threads in the forums than a little - but I just can’t seem to piece together answers to the above for the life of me.

I realise also that in the above, I’m probably asking multiple questions, and not going to get a single answer.

Thus far - I’ve experimented / researched to have setup the “Generic Thermostat”, where I can see that it’s simple to setup a “Basic” target temperature, and have this open/close a relay. (I’m turning on an off a smart-plug just to simulate in my experiment)

I can foresee that it’s possible to setup automations to alter the target temp of this Generic Thermostat at certain times of day, to mean a lower temp overnight for example; but this doesn’t achieve the complexity of my requirements above - and would quickly balloon for multiple zones and occupancy needs.

I’m also not seeing a neat way to both fire the boiler AND open the TRV in one control. Do I need to setup an Automation off the back of a Thermostat state to achieve this, or can the thermostat control itself also handle the TRV control?

If anyone has any guidance on either the “Here’s how you’d fire the boiler relay up, as well as opening the Shelly TRV” question, I’d appreciate it.

Likewise, if anyone has any guidance on the "Here’s how you’d create a per-zone, per Day, per hour, set-point curve - that allows for separate occupied and unoccupied states - I’d really appreciate this too.


1 Like

Just one aspect to think about. Having either 0% or 100% open for a TRV is not ideal. It will cause a radiator to change between hot and cold quickly which will cause some oscillation in the room temperature. There is also latency between the heat from the radiator and the temperature sensor caused principally by distance and air circulation.

I think you will find it a far more comfortable experience if you can set the the TRV to a target temperature so that it automatically reduces flow when approaching that. Or at least set it a bit higher than you need so that when getting hot it closes down with sufficient stored heat to raise the room temperature more gracefully without overshooting.

TRV’s work well when they can reduce the flow to a middle setting and they just oscillate around that keeping the radiator and therefore room temperature fairly stable.

I hear what you’re saying … I’ll consider this a bit more. In my current setup, it seems to work Okay with the 0%-100% approach, but you’re probably right that finesse could be improved.

The 0% and 100% approach is more born of the desire to avoid competition in the logic that you have an HVAC object calling for heat because the room isn’t at the set point, yet the TRV shuts down to such a degree that the temperature doesn’t rise to that set-point, either ever, or fast enough.

I’d rather live with an overshoot and have the boiler only run for the amount of time it takes to heat the room, than the boiler run for twice the amount of time, as the TRV tapers the input into the room - or the boiler stays on indefinitely because the Rad isn’t capable of outputting enough heat to quite reach the set point.

I’m sure there’s a middle ground I can play with though - so thanks for the thoughts :slight_smile:

In either case - whether I’m targeting a TRV open percentage, or a TRV Target Temp … I’m not clear on how a Home-Assistant Thermostat sets the state values in the Shelly TRV. (?)

Better to let the boiler run longer at lower power, allowing it to avoid cycling and to use condensing mode. You will save a lot on your bills that way, by allowing the boiler to operate more efficiently.

1 Like

Hi Cliff,
I think I’ve achieved similar to what you’re aiming for (UK also but I’m using Danfoss TRV (Actually hive but directly paired with ZHA)).
I’ve gone with a couple of techniques:
First create some helpers, I use these to control what we’re trying to achieve:
heating_boost_temperature - when boost button pressed this is the target
heating_scheduletemperature - gets set by the ‘calendar’ integration which contains my overall day/hour control schedule (in the body of the event in calendar I put the temperature so my automation grabs that and updates this helper)
heating_targettemperature - This is the current target for the heating system. I have this different to the scheduletemperature above as people in the house can change the target but the system can always revert this back to the schedule if it needs (think during a boost, we change this value to our boost value for a 1hr period, then revert this helper to the value in scheduletemperature after that 1hr)

Then automations to control things:
Setup multiple automations that trigger based on your zones, for example this is my LOW-TEMPERATURE automation:

alias: HEATING-temperature-LOW
description: ""
  - platform: template
    value_template: >-
      {{ states('sensor.house_temperature_temperature')|float(0) <
      states('input_number.heating_targettemperature')|float(0) }}
      hours: 0
      minutes: 5
      seconds: 0
condition: []
  - service: switch.turn_on
    data: {}
      entity_id: switch.heating_relays_switch
mode: single

You’d add extra actions there to set the TRV’s to their target also.

The bit that talks to my calendar integration is this automation:

description: ""
  - platform: calendar
    event: start
    offset: "0:0:0"
    entity_id: calendar.heatingcalendar
  - condition: numeric_state
    entity_id: zone.home
    above: 0
  - service: climate.set_temperature
      temperature: "{{ trigger.calendar_event.description }}"
      entity_id: input_number.heating_targettemperature
  - service: climate.set_temperature
      temperature: "{{ trigger.calendar_event.description }}"
      entity_id: input_number.heating_scheduletemperature
  - service: automation.trigger
      skip_condition: false
      entity_id: automation.heating_main_temperature
    enabled: false
mode: single

So that sets the helpers to the correct values when a calendar event is triggered.
The boost is done using another helper, just an input_boolean to toggle on and off and a timer helper to set the boost time (1hr in my case), so my automation for boost-start is:

alias: HEATING-boost-START
description: ""
  - platform: state
      - input_button.heating_boostbutton
  - condition: state
    entity_id: input_boolean.automatic_heating_boost
    state: "off"
  - type: turn_on
    device_id: 54ccb6a41ba578a4b3ddfb0d5930d79d
    entity_id: b693d0448c9b8c2965081fa9ee85a126
    domain: switch
  - service: input_boolean.turn_on
    data: {}
      entity_id: input_boolean.automatic_heating_boost
  - service: timer.start
    data: {}
      entity_id: timer.heating_boost_timer
  - service: climate.set_temperature
      temperature: "{{ states('input_number.heating_boost_temperature') | float }}"
      entity_id: climate.living_room_radiator_thermostat
  - service: input_number.set_value
      value: "{{ states('input_number.heating_boost_temperature') | float }}"
      entity_id: input_number.heating_targettemperature
mode: single

Hopefully that gives you something to start from and build on, happy to give more info (or be corrected in my horrible implementation if others think so!)

1 Like

Thanks for this … this looks and sounds like a darn good start to what I was after, if not complete coverage.

I’ll give this a go when I’ve got a moment. The time I thought I had to tinker with this has been swallowed by a family bereavement: but I might find time, and the mental capacity to think in any way clearly over Xmas and come back to it.

Appreciate everyone’s advice greatly :slight_smile: :heart:

I think sometimes the most simple solution is the best, I could try for more elegant but the way I created mine was through a number of Automations

Please see the image above

I wrote some a custom markdown code that quickly and easily helps me see what’s on, and why ( Big wife approval!)

and below the markdown card is my controls, which we hardly touch because my automations take care of it

My automations consist of

Heating on when any radiator called for heat
Heating off when all radiators are idle
Set target heat based on the main thermostat from Heat pump/boiler

If any radiator is set to a higher temp, the automation doesnt touch, unless all radiators are at temp, which means they are al ldle then it resets all back to thier default base temp of the main thermostat again. This means we never have rogue radiators trying to pump more heat than needed, and it lets the heatpump/boiler turn off.

In some cases some rooms may want to be set to a different temp permanently , recently our son was born and the room temps in certain rooms he is in needs to be a few degrees higher, so I altered those rooms to operate higher and not reset to base heat level.

Its Janky I know, but I spent a lot of time trying to create this massive complex code that just would never work in every situation.

If you want some of my code logic, let me know :slight_smile: