Perfect Heating Automation with Sonoff TRVZB

Well, if it’s true that trv doesn’t care if temperature sent to it is the same then simple option is automation which sends measured temperature +0.1, waits say 1 second and sends true value again in regular intervals.
But the question remains if trv “cares” about 0.1 degree changes? I know hysteresis for turn on / off can be changed as low as 0.2 degree…
Personally i don’t have these problems since my radiators run at on-off system, so my temperature always fluctuates, say 0.2 below and some 0.5 above.

I have my trv’s connected via ZHA, but i do have a spare one, so perhaps i’ll try to play with that one on my test HA installation to see if above claim is true.

I have the hysteresis set to 0.2 degrees. It’s not actually that simple as according to the hint at Z2M that’s not plus-minus 0.2 degrees. It’s only minus from the setpoint. i.e. if my setpoint is 20.5 C then it will start heating at 20.3 C and stop heating at 20.5 C. Terminology is not my best virtue :confused: Hysteresis or temperature accuracy?

And I think I came up a better solution than faking the temperature by 0.1 C and then setting the temperature again to the measured temperature. My solution with the added 0.01 C will result (currently with current bugs in TRVZB 1.4.1 and Z2M 2.7.2-1) that TRV will happily accept the given external sensor measurement and store it with 0.1 degree accuracy. Resetting the timer for external_2 fallback. Jumping 0.1 C and then reporting correct temperature after that would mean additional messages (may not mean anything honestly though :D) and theoretically more battery drain. (theoretically I know)
Jumpin 0.1C at any direction would mean that the TRV could initiate valve close or open unnessesary basis and then get back to either heating or not after the correct value is posted.

It would be really easy to implement the stale temperature or bad sensor detection by just checking the last_seen value of each temperature sensor and should it be too old something → stop reporting temperatures and let TRVZB act accordingly or even force it to internal if you wan’t to keep the control in your own hands.

But these are interesting times. Sonoff promised new firmware with partial valve opening support really soon
“the function will be supported around the end of Jan, 2026, please kindly wait for the new firmware version update.” Source: SONOFF Zigbee Thermostatic Radiator Valve | TRVZB

You were partially right here.
Some of my temperature sensors were glitching and although I’ve set them to 0.1C accuracy I was able to found half of them having way higher internal accuracy. I set the value from 10 (0.1 C) to 100 (1 C) and then back to 10 and now they all seem to be happily reporting 0.1 C changes without having to wait for the 1 hour default max report interva…

This does not change anything above though as I can still see hours of same temperature being reported.

But this lead me to investigate some other ways to smooth out or filter the inherint noise in the reporting as whenever temperature settles right around some specific value I’ll get multiple updated jumping 0.1C up and down. Luckily due to 0.2C hysteresis at TRV side this wont yield to a cycling valve at radiator.

Well, i did some testing: I connected my spare zb gateway and spare trv to my test HA via zb2mqtt.

  • i selected “external” on my sensor “select.trv_temperature_sensor_select”
  • i created an automation which sends fixed number “23.9” to “number.name_external_temperature_input” every full hour.

I created automation at 8:29, first send was at 9:00, then at 10:00, then last at 11:00 (so that’s 3 hours+ of not changing a value). If i’m looking at correct sensor (that’s select.trv_temperature_sensor_select) then this sensor is still at “external”. Am i looking at the wrong sensor? Which one should jump to internal_2 (or _3)?

Well, to tell my results of above test:

  • as long as i’ve had my automation enabled sensor remained at “external”. Note that i’ve sent fixed (exactly same) number every hour, so number definitely didn’t change.
  • then i disabled automation and after 2 hours sensor jumepd to “external_2”
  • after re-enabling automation sensor immediately jumped to “external_3”

So, after all i guess there’s no bug in trv. It must be your automation working …well, wrong ?.
And another “comment” to your above claim: you say sensor went from internal to external_3… that’s kinda not possible, so did you mean from external to external_3? If this happened then this only means that trv lost connection with HA and didn’t receive external temperature info in 2 hours, so it went to external_2, but then it came back, received it and that’s why it was on “external_3” → this means that connection was lost in the past and re-established (which is a very good function for debugging, btw).

1 Like

Good catch / carefully read.
Yes, it was set to external and went to external_2 and then external_3.
Bugger… I cant’ edit that wrong word any more. I hope it wong cause additional confusion.

Do you have your TRVZB’s at Firmware 1.4.1?
I can very easily reproduce the behaviour in my setup and going trough the traces for automation I can verify that they indeed fired properly.
I can even reproduce the behaviour manually.

Activity at the MQTT device
This is me setting the jittered number

  • Temperature changed to 20.38 triggered by action Number: Set

Followed immediately by line

  • Temperature changed to 20.3 triggered by action Number: Set

and this can go forever, it will always change the temperature.

Now this is me setting the temperature to 20.4 manually

  • Temperature changed to 20.4 triggered by action Number: Set

And every consecutive run with the same 20.4 C temperature

  • (…) no new lines in activity.

Z2M version 2.7.2-1
TRVZB version 1.4.1
HA OS
Core 2026.1.2
Supervisor 2026.01.1

Yep.

Messages can fire up in automation, but i guess it can happen that trv doesn’t receive it. It did happen to me when i played with it: i turned it off (or on) but nothing happened until i sent command again (but as said, i played with it so it must be that i sent multiple commands too fast). Sometimes i’ve got a kind of warning at the bottom of HA screen…

One of the main reasons i’m seriously thinking of going from ZHA to Z2MQTT is this sensor - i like to have things under control and monitoring ha ↔ trv connection is one of them. I can make an automation which will warn me if any trv goes to “external_3”, so i’ll check and possibly add more zb routers. Or, for that matter, i can make a warning for going to “external_2” to check out on temperature sensor (batteries…)

I think that in your case adding time trigger to automation would solve all problems. Just set it at rather more frequent than 1 hour, say 30 minutes, to be on a safe side.

I have 1 hour interval refresh trigger, but as I’ve explained above it does not work in my setup. I might not bother to investigate any further as implementing the jitter solved the issue and now regardless if the sensors update or not I’m pushing jittered temps to TRV’s either at temperature change or hourly intervals.

Congratulations, Hount.
I’ve been struggling with the same issue for the last few days as well. Especially in the living room, where I have four TRVs, I occasionally experience connection drops. In addition to that, I’ve also seen cases where some of them fall back to external_2.

Based on the information you shared, I updated my automation accordingly. Below you can see an example of my current automation setup. I’d genuinely appreciate your thoughts or feedback on this approach.

Separately from this, I’m also considering moving my Sonoff TRVs back to their original Sonoff hub. Because of this, I’ve purchased a Hub Ultra and I’m planning to migrate the TRVs and temperature sensors there and continue from that setup. This way, I won’t need additional Home Assistant automations just to bind external temperature sensors, since I can handle those assignments directly in the eWeLink app. With the Sonoff LAN integration, I can still control the TRVs from Home Assistant.

This also means I won’t need to deal with things like:

  • forcing hysteresis to 0.2,
  • tweaking external sensor reporting intervals,
    since all of these are already configurable inside eWeLink.

The only real downside I can think of is the lack of percentage-based valve opening control. That feature isn’t exposed via the Sonoff LAN integration, so I can’t use it in HA automations, for example, I won’t be able to say “keep the valve 25% open when heating is off.”
That said, for my use case, this isn’t a major issue.

alias: TRV Calibration - SalonTRV4 External Temp 
description: 
triggers:
  - entity_id: sensor.xiaomi_salon_temperature
    for: "00:00:01"
    trigger: state
  - minutes: /30
    trigger: time_pattern
conditions:
  - condition: template
    value_template: "{{ is_number(states('sensor.xiaomi_salon_temperature')) }}"
actions:
  - variables:
      t: "{{ states('sensor.xiaomi_salon_temperature') | float }}"
      send_t: "{{ (t + 0.01) | round(2) }}"
  - target:
      entity_id: number.salon_trv_4_external_temperature_input
    data:
      value: "{{ send_t }}"
    action: number.set_value
mode: single

Have you tried using ZHA recently, instead of Z2M ?

I haven’t had any issues using ZHA, once I became aware of the External sensor dropping back to Internal, if it doesn’t get updates at least every two hours.
Using TRVZ 1.4.1 exposes open/close %, if you need it…

Might be easier than introducing more Sonoff hardware?

Also does it whenever you change the batteries. I now have an automation that checks for this and switches it back on!

Any idea if you can read the internal temperature value, if the TRVZB ‘External Sensor’ has been selected (in ZHA) ?

My efforts always result in the External value being provided.

I don’t believe this is possible.

I am not trying to derail this thread - but it seems like it is the main thread for SONOFF TRVZB.

Did anyboby play around with the valve control on these things.
I have 6 of these and I noticed that when ever they are heating they always open up 100% making my radiators very warm (we’ll get to the valve open degree).
I live in a country where we have district heating and here you want to / are required to use the energy in the water that is circulated. If we focus on a radiator, then this means that I should make sure that I extract as much energy from the water flowing through the radiator.
If the inlet temperature is 65 C and the valve is fully open - then the outlet temperature will be approx 60-62 C. That is not very good.
So I started experimenting by actually measuring the inlet and outlet on the radiator, and regulating the valve open degree parameter (VOD) - adjust it so that the difference between inlet and outlet is as big as possible.
You can adjust it between 0-100% and my finding was that around 15-17% i get the biggest gap. Quite surprisingly, I also found that there is a very small gap where you can actually use the VOD - What I saw was that if the optimal was 17%, then it would be fully closed at 15% and fully open at 20%.
If I compare this to a normal manual (eg. Danfoss) thermostat then you can actually adjust the valve in the full range - you can do very fine grained control with it.
I don’t understand why this is not the case with the TRVZB as it is working in the same way - with a stepper motor (I assume)
Does anybody have any insights to this? why does it regulate so poorly? is it the hardware?
Any comments would be welcomed

Interesting.
Have you heard that there is now firmware 1.4.4 (already released to eWelink hub users, hopefully soon to Z2M) which should add adaptive mode.

But it’s bad news if the TRV steps are too big for practical use.
My initial thought was that maybe the 0-100% is the relative range between idle steps and closing steps (value exposed by Z2M, automatically fetched by the TRV when calibrating)
For my 4 TRV’s the values range: Idle steps: 30-36, and Closing steps 199-234. Identical radiators. Good sanity check that calibration was somewhat successfull in all TRV’s

Unfortunately there is no way to adjust the automatically detected valve range manually, but you could check what’s your range and if it’s excessive or varies greatly between radiators you may consider re-calibrating the TRV’s so that with a good luck the opening and closing degrees may come closer to eachother and 0-100 resolution between the extremeties have more steps.

I briefly considered implementing PID control with various “ready” options there are. So that the TRV would adjust the opening and closing degrees to have fine grained control. But I quickly ditched that idea as the promised adaptive control should be released soon. And even with fully opening-closing the valve I’m able to reach very stable temperatures in rooms where there are no other heat sources. I have district heating here too. I believe that there is some control too to the circulating water temperature based on outside temperature as I don’t see change in TRV duty cycles even as the outside temperature have fluctuated lately.

Did anyone “received” firmware update in zha mode yet? I have one test valve in z2m, that one updated, but 3 valves in zha mode didn’t receive fw update information yet, it still says “updated”…

Thanks for your reply!
I was not aware that a new firmware is making it’s way - do you have a link to this. would love to see what adaptive control can offer.

I will check my idle and closing steps - my understanding of what that is, is actually not good enough

Regarding the PID control - i dropped that thought. I think it would be overkill. As such I have no problem regulating to the desired temperature. The only thing I don’t like is how the radiator goes to fully open everytime it turns - it is actually not nice being in a room which momentarily heats up like that

Bonus question… I have read a lot about how the radiator should or should not recalibrate every monday at noon. I don’t believe it does… Is there a way to make a thermostat recalibrate?

Not even confirmed :rofl:

2 Likes

I received the update on Z2M, but Z2M support is coming later.
Funny (or not) that page listed initially ZHA support coming earlier than Z2M, but it’s been updated to the current “To be confirmed”
What I’ve read about the 1.4.4 from eWeLink forums it’s not silver bullet solution.
I’ve had Better Thermostat Beta version’s PID for some time now and it manages to maintain the same hysteresis as plain 0-100 valve actuation did. Which is no surprise in my case as the temperature sensor’s accuracy is now the limit. But it’s nice to hear the valve move only slightly. Although now it moves slighly more often so I don’t know if this has any effect on battery life :slight_smile: