Force Zigbee device update to solve TRV automation problem?

I’ve written an automation that is trying to overcome the terrible temperature recording you get from TRV’s because they are so close to the radiator.

The TRV has a ‘temperature offset’ which can be used to alleviate this problem to some extent, but its fixed value that you don’t usually change much. This means if I set it to a negative offset, whilst the radiator is on, its more or less ok. But when the radiator is off, the negative offset makes the room appear colder than it is.

I also have a separate temperature sensor in the same room, so i came up with the idea of writing an automation that fires every time the TRV reports a temperature change.

What the automation does, is checks what the temp sensor thinks the temperature is, and adjusts the TRV’s offset value dynamically so the TRV’s temperature now matches.

Its not perfect for a number of reasons:-

  1. The temp sensor reports within an accuracy of 0.1 degrees, but the TRV offset value is only in whole degrees, so it’s never going to be completely accurate.

  2. The biggest issue however, is that the automation fires after the TRV temperature has changed, so imagine this scenario:-

Room sensor says temperature is 18 degrees
TRV says its 14 degrees, and has a current offset value of -4 degrees

The automation will correctly deduce that the offset should be zero, so both the TRV and room sensor think its 18 degrees.

However, whilst I can change the offset immediately, the ‘last recorded’ temperature in Home Assistant stays at 14 until the next temp change is sent with the revised offset.

So the temperature is always displayed as one ‘behind’ the currently calculated offset.

I can solve this manually by waking up the TRV by touching the touch pad on the top and it immediately sends its current temperature (with the corrected offset) to HA, but is there a way of doing his in an automation.

There seems to be two possible options:-

  1. Somehow request the device to send its ‘current’ values (I’m using Zigbee/ZHA)
  2. Write a value to the devices cluster attribute with the corrected temperature. ← This I have tried through the UI inititally, but I get an error saying the value is of ‘nonetype’ is not iterable:-

Just create a generic thermostat that controls the TRV using the separate temperature sensor in the room.
That is the easiest way.
The generic thermostat wants a switch to toggle, but you can use an input boolean.

Create an automation to turn on/off the TRV with this boolean and set the temperature of the TRV with the value of the generic thermostat + 3-4 degrees.
This makes sure the TRV stays on until the generic thermostat turns it off.

I’ll take a look at the generic thermostat and see what can be done.
A few things in your reply aren’t clear tho.

You mentioned turning the TRV on/off based on the temperature from the generic thermostat. There is no way to ‘turn on/off’ the TRV as far as I can see, but I can change its valve position, I assume thats what you meant.

You also mentioned setting the temperature of the TRV with the value of the generic thermostat. Again, I can’t do this as mentioned in my original post, or I don’t know how to.

You don’t have this?

Thankyou, thats exactly what I needed, mine is like this:-

hvac_modes:
  - heat
min_temp: 5
max_temp: 25
preset_modes:
  - none
  - away
  - Schedule
  - eco
  - boost
  - Temporary manual
current_temperature: 19
temperature: 19
hvac_action: heating
preset_mode: none
system_mode: '[4]/heat'
occupancy: 1
occupied_heating_setpoint: 1900
icon: mdi:thermometer
friendly_name: TRV Downstairs Bathroom
supported_features: 17

So how do I go about changing the value of one of these attributes in an automation ?

You might be interested in: Tuya radiator valve (TS0601) calibration from external sensor (via zigbee2mqtt) - Blueprints Exchange By implementing this you could wear out the memory of the TRV (Tuya radiator valve (TS0601) calibration from external sensor (via zigbee2mqtt) - #48 by robots01).

  • The Blueprint has a “flaw” that wears out the memory of the device; less frequent updates will prolong the life of the device,
  • The Blueprint has another flaw that makes the offset inaccurate, the TRV and sensor do not have to update it’s value at the same time; instead of updating with current data it’s probably better to update the averages over a period of time,
  • The statistics plaform and history stats integration aren’t suitable for averaging temperatures over a longer period; Average Sensor for Home Assistant is a better option.

I think I’m getting somewhere with this.
Seems you can set the values of ANY attributes via devtools, but they aren’t all available via automation (unless i can’t find the right service to call). For example, I can user Number:set to change the (target) temperature, but current_temperature doesn’t show in the list of items I can change (even tho I can do it via devtools)

This would seem to be a known issue, as their is a HACS integration that lets you do it:-

Creds to @MSandro who’s thread here might be my solution:-

Current temperature is the temperature the internal sensor in the TRV is reporting.
Temperature is the set temperature you want it to achieve.

I’ll post more later I’m a bit busy now.

Ok, I think this is the final solution. You can use the HACs set-state python script above, but its also possible to do the same thing using zha toolkit.

This seems to work just fine in my case:-

service: zha_toolkit.ha_set_state
data: 
  state_id: climate.moes_trv_downstairs_bathroom_becathermostat
  attr_val: 22.2
  # optional Parameters
  state_attr: current_temperature

However, I am concerned that changing the temperature offset on a regular basis might wear out the flash memory as per the thread linked above.

I highly advice against this. There is no reason to force values on sensor when you can just leverage Home Assistants native components.

What you need is and input boolean, this will be if heating is needed or not.

Set up a generic thermostat in configuration:

climate:
  - platform: generic_thermostat
    name: Vardagsrum
    heater: input_boolean.vardagsrum_heating
    target_sensor: sensor.temperatur_vardagsrum_temperature
    min_temp: 18
    max_temp: 24
    target_temp: 22
    cold_tolerance: 0.5
    hot_tolerance: 0
    initial_hvac_mode: heat
    min_cycle_duration:
      minutes: 5

Then create an automation that triggers on this boolean changing.

Something like:

description: ""
mode: single
trigger:
  - platform: state
    entity_id:
      - input_boolean.vardagsrum_heating
condition: []
action:
  - choose:
      - conditions:
          - condition: state
            entity_id: input_boolean.vardagsrum_heating
            state: "on"
        sequence:
          - service: climate.set_temperature
            data:
              temperature: "{{ state_attr('climate.vardagsrum', 'temperature') |float + 3.5 }}"
              hvac_mode: heat
            target:
              entity_id: climate.trv_vardagsrum_thermostat
  - choose:
      - conditions:
          - condition: state
            entity_id: input_boolean.vardagsrum_heating
            state: "off"
        sequence:
          - service: climate.set_temperature
            data:
              temperature: 0
              hvac_mode: away
            target:
              entity_id: climate.trv_vardagsrum_thermostat

This will trigger on the boolean and if the boolean goes on then it will set the temperature (set temperature) to what the generic thermostat is set to + 3.5.
This means the TRV will turn on and hopefully the internal temperature sensor will not reach " + 3.5" before the separate temperature sensor reaches the set temperature and shuts off the TRV.
With this method we effectively make the TRV dumb and just listens for commands and hopefully does not do any own decisions, this means HA and your automations is in control.

What could happen is that the internal sensor detects more than + 3.5 degrees and shuts off before the room sensor is OK with it. just increase the + 3.5 to 4 or 5 and it should be fine.

Thanks @Hellis81,

I’ll take a look at that later.

I did try using the zha toolkit method which did successfully change the entities current temperature value, but after about 20 seconds, something is setting is back again, and its not my automation.

Using your suggestion above, do I even need a generic thermostat ? Could I simply set the TRV to preset mode ‘temporary manual’ (forever - I assume this makes the TRV ‘dumb’), then just use an automation to trigger when the room sensor hits its threshold values for on and off, and send an hvac mode and/or change valve position command to the TRV ?

Actually, having re-read your reply and looked at the code, this does seem like a good way to go. Basically using the external thermostat to manipulate the target temperature of the device. I’ll try that later.

Again… Current temperature is the temperature sensor reading. You should not be changing that.
That is a sensor they are not supposed to be changed.
Whenever the sensor sends a new value HA will overwrite what you entered (as you have noticed).

The only attribute you should change is the temperature because that is the setting, the temperature the TRV wants the room to get to.
In order to get to that temperature ist has a temperature sensor, that is called current_temperature.

@Hellis81 - thankyou so much for the time and help. I’ll be using your code example as a basis for changing my automation.

1 Like

You can later add occupancy, so when everyone leaves the house the TRVs switch off.
Or window sensors to switch off if a window is open.

We have ours set up to switch off all TRVs as we leave home and if any window is open.

I’ve quickly knocked up a prototype before going to the full solution that @Hellis81 suggested, using a simple automation to manipulate the target temperature, based on the room sensors temps. Interesting this runs with no errors, but does not set the target temp:-

alias: Downstairs Bathroom TRV - Dynamic Adjust
description: ""
trigger:
  - platform: state
    entity_id:
      - sensor.lumi_lumi_weather_temperature_4
condition: []
action:
  - choose:
      - conditions:
          - condition: numeric_state
            entity_id: sensor.lumi_lumi_weather_temperature_4
            below: 20
        sequence:
          - service: climate.set_temperature
            data:
              temperature: 24
              hvac_mode: heat
            target:
              entity_id: climate.moes_trv_downstairs_bathroom_becathermostat
    default:
      - service: climate.set_temperature
        data:
          temperature: 0
          hvac_mode: "off"
        target:
          entity_id: climate.moes_trv_downstairs_bathroom_becathermostat
mode: single

Not sure if this is a bug, but re writing it to use zha_toolkit works fine:-

alias: Downstairs TRV with ZHA
description: ""
trigger:
  - platform: state
    entity_id:
      - sensor.lumi_lumi_weather_temperature_4
condition: []
action:
  - choose:
      - conditions:
          - condition: numeric_state
            entity_id: sensor.lumi_lumi_weather_temperature_4
            below: 20
        sequence:
          - service: zha_toolkit.ha_set_state
            data:
              state_id: climate.moes_trv_downstairs_bathroom_becathermostat
              attr_val: 25
              state_attr: temperature
    default:
      - service: zha_toolkit.ha_set_state
        data:
          state_id: climate.moes_trv_downstairs_bathroom_becathermostat
          attr_val: 0
          state_attr: temperature
mode: single

As for occupancy, I already have the main house wired up and working via tado, so thats covered, and these TRV’s don’t actuall call for heat, the’re mostly for just shutting off the heat in rooms that usually get hotter before the main house does.

update:— Using ZHA toolkit had the same problem as above, it sets the temperature value but then gets snapped back to an original value a few seconds later. The only way I seem to be able to set the target temperature at the moment, is via the love lace thermostat card.

update 2:- even the lovelace card has snapped back to the original target setting. I wonder if I’ve been chasing my tail and the device is not fully online. I’ve seen that happen before. I’ll have to check when i get home.

I found an error in the logs with the non ZHA toolkit version:-

Stopped because an error was encountered at 5 January 2023 at 14:25:52 (runtime: 0.03 seconds)

‘NoneType’ object is not iterable

I’m guessing this is something to do with how the quirk I have installed works with HA.

Do the TRV have a schedule it follows?
You said something about manual mode before, what happens if you enable this mode?

Turns out the error i spotted in the automation log:-

"Stopped because an error was encountered at 5 January 2023 at 14:25:52 (runtime: 0.03 seconds)

‘NoneType’ object is not iterable"

Was because you can’t set the HVAC mode on that device. If you just set the temperature only, the following code works fine:-

alias: Downstairs Bathroom TRV - Dynamic Adjust
description: ""
trigger:
  - platform: state
    entity_id:
      - sensor.lumi_lumi_weather_temperature_4
condition: []
action:
  - choose:
      - conditions:
          - condition: numeric_state
            entity_id: sensor.lumi_lumi_weather_temperature_4
            below: 20
        sequence:
          - service: climate.set_temperature
            data:
              temperature: 25
            target:
              entity_id: climate.moes_trv_downstairs_bathroom_becathermostat
    default:
      - service: climate.set_temperature
        data:
          temperature: 5
        target:
          entity_id: climate.moes_trv_downstairs_bathroom_becathermostat
mode: single

which essentially does what @Hellis81 suggested in his solution, just without a generic thermostat (which I still might do).

The only difference is that this automation triggers on every single change of the temperature sensor and sends a new command to the TRV again.
This means the TRV will never be in sleep mode and you will drain the battery quite fast

Indeed, which is why I did a final tweak to only send the TRV a temperature setting if the target temperature threshold is passed:-

alias: Downstairs Bathroom TRV - Dynamic Adjust
description: ""
trigger:
  - platform: state
    entity_id:
      - sensor.lumi_lumi_weather_temperature_4
condition: []
action:
  - choose:
      - conditions:
          - condition: numeric_state
            entity_id: climate.moes_trv_downstairs_bathroom_becathermostat
            below: 25
            attribute: temperature
          - condition: numeric_state
            entity_id: sensor.lumi_lumi_weather_temperature_4
            below: input_number.bathroom_s_trv_target_temperature
        sequence:
          - service: climate.set_temperature
            data:
              temperature: 25
            target:
              entity_id: climate.moes_trv_downstairs_bathroom_becathermostat
    default:
      - condition: numeric_state
        entity_id: climate.moes_trv_downstairs_bathroom_becathermostat
        above: 5
        attribute: temperature
      - service: climate.set_temperature
        data:
          temperature: 5
        target:
          entity_id: climate.moes_trv_downstairs_bathroom_becathermostat
mode: single

So the script basically turns the TRV target temperature to either 5 (if the room sensor temperature is on or above its required value, thus turning off the TRV), or 25 if the room sensor is under its required temperature.

And I only now send the command if the TRV’s current target temp isn’t already set to either 5 or 25, so I’m not sending streams of the same value every time the room sensor value changes.