Skip to content

feat: SONOFF TRVZB add smart thermostat features (v1.4.4)#11466

Open
CubeZ2mDeveloper wants to merge 5 commits intoKoenkk:masterfrom
CubeZ2mDeveloper:sonoff-trvzb-1.4.4
Open

feat: SONOFF TRVZB add smart thermostat features (v1.4.4)#11466
CubeZ2mDeveloper wants to merge 5 commits intoKoenkk:masterfrom
CubeZ2mDeveloper:sonoff-trvzb-1.4.4

Conversation

@CubeZ2mDeveloper
Copy link
Contributor

Summary

  • Add support for Smart Temperature Control for SONOFF TRVZB.
  • The change is aligned with firmware trvzb_v1.4.4.

What’s included

  • New expose for smart temperature control.
  • OTA integration note: firmware trvzb_v1.4.4 has been submitted to zigbee-OTA.

Testing

  • Tested with Zigbee2MQTT on SONOFF ZBDongle-P.

  • Verified:

    • Pairing / interview
    • Read/write of thermostat setpoint and reporting
    • Smart Temperature Control related attributes
    • No regression on existing features

Related

zigbee-OTA PR: Koenkk/zigbee-OTA#1056

smartTemControl(): ModernExtend {
const expose = e
.enum("smart_temperature_control", ea.ALL, ["off", "precision", "smart"])
.withDescription("Manual mode: off or precision (same effect), Smart mode: automatic temperature control");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As already described in Koenkk/zigbee-OTA#1056 (comment), I would suggest adding a bit more detail for clarity.

A very good explanation of the new Smart Temperature Control ("Adaptive Mode") can be found here:
zigpy/zigpy-ota#23

"This release adds Adaptive Mode. It is a feature designed to minimize temperature fluctuations.
When enabled, the device dynamically adjusts the valve opening based on the temperature changes and the target temperature to maintain a more stable environment.

Note: Enabling Adaptive Mode will automatically disable Valve Opening Percentage and Temperature Accuracy."

If linking external references is acceptable, the official Sonoff blog announcement may also be helpful:
https://sonoff.tech/blogs/news/trvzb-upgrade-smart-temperature-control-for-more-stable-room-temperature

In particular, it would be great if the PR could explicitly include (or mention) the note that enabling Smart Temperature Control will disable the "Valve Opening Percentage" and "Temp. Accuracy" features, since this behavioural change is particularly important for users.

Thank you so much for your contribution!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the detailed feedback and the references!
We've updated the PR to add a clearer description of Smart Temperature Control (Adaptive Mode) and explicitly documented that enabling it will disable Valve Opening Percentage and Temperature Accuracy.

About the firmware: We are official maintainers of the Sonoff/eWeLink Zigbee firmware. The attached OTA image is provided by us and originates from the official Sonoff/eWeLink firmware release pipeline (i.e., an official build intended for end users).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, thanks!
Really appreciate the work you put into this. Happy to see more of your stuff down the road!

commandsResponse: {},
});
},
smartTemControl(): ModernExtend {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use m.enumLookup instead, example:

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the review. I considered using m.enumLookup but the mapping for this attribute is asymmetric between write and report:

toZigbee (write):

Mode Value
off 0x00
precision 0x00
smart 0x02

fromZigbee (report):

Value Mode
0x00 off
0x01 precision
0x02 smart

The device reports precision as 0x01, but to activate it you must write 0x00 (same as off). 0x01 is a report-only value — writing it to the device has no effect.

m.enumLookup uses a single lookup object for both directions (getFromLookup for toZigbee, getFromLookupByValue for fromZigbee), so it cannot represent this asymmetry. If we use {off: 0x00, precision: 0x01, smart: 0x02}, setting precision would incorrectly write 0x01 to the device.

Would you prefer I:

  1. Keep the custom extend as-is to preserve correct behavior, or
  2. Simplify to m.enumLookup with {off: 0x00, precision: 0x01, smart: 0x02} and accept that writing precision sends 0x01 (which the device will ignore)?

Happy to adjust either way.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've modified m.enumLookup to accept a custom converter: 3aac9b3

Example:

fzConvert: (model, msg, publish, options, meta) => {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @Koenkk! I've refactored smartTempControl to use m.enumLookup with a custom fzConvert to handle the asymmetric mapping (device reports 0x01 for manual mode, but write requires 0x00). Also renamed precision to manual for clarity.

Thanks for adding the fzConvert parameter to enumLookup — it made this much cleaner.

@KipK
Copy link
Contributor

KipK commented Feb 6, 2026

@CubeZ2mDeveloper I 've made an external converter of your PR to test.

It seems to works ok : https://gist.github.com/KipK/448992d0f5abda3c934bd098b29e4408

Something you should add to this PR, is to force the valve position to 100% when the mode is switched to Smart or the other internal logic.

If valve is previously set to 0 when in manual mode, then heating won't never start in Smart mode.
User have to manually put it to 100% and it's confusing.
Automating it from the converter would be better.

Fixing this on firmware side would be even better

@ActuallyRuben
Copy link
Contributor

I've tested the addition as an external converter as well. It appears to work correctly. I can hear the valve open and close partially when manipulating the temperature.

I am just wondering, what is the 'precision mode'? Why is setting it to precision mode mapped to writing a 0?
Looking at the ZHA script provided by SONOFF, it only lists 0 and 2 as valid values for the smart temperature control mode. Is the value 1 documented anywhere?

@fma965
Copy link

fma965 commented Feb 6, 2026

I've tested the addition as an external converter as well. It appears to work correctly. I can hear the valve open and close partially when manipulating the temperature.

Same here!, seems good.

@MeisterQ
Copy link

MeisterQ commented Feb 7, 2026

Wow finally. I made so many support tickets because of this feature. Then i finally sold my TRVs and bought aqaras w600. But they are so bad. They are very quiet, but the algoritm is really bad. How does it act on the sonoff? Someone got any graphs with current, target temp and valveposition?? Is there an expose for valve position now?

@KipK
Copy link
Contributor

KipK commented Feb 7, 2026

Wow finally. I made so many support tickets because of this feature. Then i finally sold my TRVs and bought aqaras w600. But they are so bad. They are very quiet, but the algoritm is really bad. How does it act on the sonoff? Someone got any graphs with current, target temp and valveposition?? Is there an expose for valve position now?

There's no valve position on sonoff trvzb unfortunately.

@MeisterQ
Copy link

MeisterQ commented Feb 7, 2026

Wow finally. I made so many support tickets because of this feature. Then i finally sold my TRVs and bought aqaras w600. But they are so bad. They are very quiet, but the algoritm is really bad. How does it act on the sonoff? Someone got any graphs with current, target temp and valveposition?? Is there an expose for valve position now?

There's no valve position on sonoff trvzb unfortunately.

To bad. Would be an easy made expose when they now use PID control.
I recently had a look on the hardware and found, they are using a 4-wire motor. Should be at least a simple stepper or a dc motor with rotary encoder.

@CubeZ2mDeveloper
Copy link
Contributor Author

I've tested the addition as an external converter as well. It appears to work correctly. I can hear the valve open and close partially when manipulating the temperature.

I am just wondering, what is the 'precision mode'? Why is setting it to precision mode mapped to writing a 0? Looking at the ZHA script provided by SONOFF, it only lists 0 and 2 as valid values for the smart temperature control mode. Is the value 1 documented anywhere?

Thanks for testing! @ActuallyRuben

Regarding your questions about precision mode:

What is precision mode?
When the device reports 0x01, it indicates "precision" (manual precision control) mode — meaning the TRV is operating with manual valve control rather than smart automatic adjustment. In the latest commit I've renamed it to manual for clarity.

Why does setting precision/manual write 0x00 instead of 0x01?
0x01 is a report-only value — the device uses it to indicate its current state, but for write commands, 0x00 (off) achieves the same effect. This is consistent with the SONOFF ZHA script which only lists 0 and 2 as valid write values. Writing 0x01 to the device has no documented effect.

Is 0x01 documented?
Not in the official SONOFF ZHA script. I discovered it through device attribute reports — when the TRV is in manual mode and actively controlling valve precision, it reports 0x01 instead of 0x00. So the mapping is:

Value Direction Meaning
0x00 Read/Write Off (smart control disabled)
0x01 Read only Manual mode (reported by device)
0x02 Read/Write Smart mode (automatic control)

This is why a custom fzConvert is needed in the m.enumLookup — the read and write mappings are asymmetric.

@CubeZ2mDeveloper
Copy link
Contributor Author

CubeZ2mDeveloper commented Feb 9, 2026

Changes in this update

  1. Refactored smartTempControl to use m. enumLookup with custom fzConvert (thanks to @Koenkk for adding the fzConvert parameter)

  2. Renamed precision to manual — clearer naming that pairs naturally with smart (off / manual / smart)

  3. Fixed typo in previous commits: smartTemControlsmartTempControl (missing p)

@GigiPompieru
Copy link

@CubeZ2mDeveloper thanks for support. Can you please then explain what is the difference between Off and Manual from an operation of device perspective?

@MeisterQ
Copy link

MeisterQ commented Feb 9, 2026

Value Direction Meaning
0x00 Read/Write Off (smart control disabled)
0x01 Read only Manual mode (reported by device)
0x02 Read/Write Smart mode (automatic control)
This is why a custom fzConvert is needed in the m.enumLookup — the read and write mappings are asymmetric.

Does this mean:

  1. With Off 0x00 its working like it was "0% or 100% opening"
  2. With Manual mode 0x01 you can set the valve position directly like "go to 50%"?
  3. With Smart mode 0x02 its working by itself with the pid controller?
  4. Is there a way to tweak the PID parameters?

@CubeZ2mDeveloper
Copy link
Contributor Author

CubeZ2mDeveloper commented Feb 9, 2026

@CubeZ2mDeveloper thanks for support. Can you please then explain what is the difference between Off and Manual from an operation of device perspective?

Hi, @GigiPompieru
0x01 is a report-only value — the device uses it to indicate its current state, but for write commands, 0x00 (off) achieves the same effect. This is consistent with the SONOFF ZHA script which only lists 0 and 2 as valid write values. Writing 0x01 to the device has no documented effect.

@GigiPompieru
Copy link

GigiPompieru commented Feb 9, 2026

So, the TRV is in off mode by default with valve values at 100% and 0%. If the user modifies these values in any way, as we can now, the TRV will switch to 0x01 meaning manual?

Will the TRV remain in manual until put into Smart or will it switch back to Off if the user returns the values to 100/0?

Sorry for all the questions, just trying to better understand the new feature.

@CubeZ2mDeveloper
Copy link
Contributor Author

So, the TRV is in off mode by default with valve values at 100% and 0%. If the user modifies these values in any way, as we can now, the TRV will switch to 0x01 meaning manual?

Will the TRV remain in manual until put into Smart or will it switch back to Off if the user returns the values to 100/0?

Sorry for all the questions, just trying to better understand the new feature.

No worries, great questions!

Does modifying valve values switch the TRV to manual (0x01)?
No. The valve opening percentage and temperature accuracy values take effect after you manually disable smart temperature control (i.e., set it to off or manual). Changing valve values alone does not switch the mode.

Will it switch back to off if you restore the values to 100/0?
This attribute is purely a toggle for smart temperature control — nothing more. off and manual are functionally identical; the only difference is that 0x00 is the write value and 0x01 is the report value for the same state. It has no relation to valve values or any other settings.

To put it simply:

  • off / manual → Smart temperature control disabled, TRV uses your configured valve opening percentage and temperature accuracy
  • smart → Smart temperature control enabled, TRV automatically adjusts valve parameters (your manual valve settings are ignored)

@pszemus
Copy link

pszemus commented Feb 9, 2026

So couldn't we just leave the "off" and "on" options for smart mode, for the sake of the UX?

@GigiPompieru
Copy link

So couldn't we just leave the "off" and "on" options for smart mode, for the sake of the UX?

I think that, even if they are not displayed in the UI, the manual value of 0x01 still needs to be coded.

Remember that when the external temp sensor was introduced we had just internal and external and people reported log errors because the TRV would have two other states, coded after as external_2 and external_3, which are basically the same as internal or external but have different values which Z2M didn't know about.

@CubeZ2mDeveloper
Copy link
Contributor Author

CubeZ2mDeveloper commented Feb 9, 2026

So couldn't we just leave the "off" and "on" options for smart mode, for the sake of the UX?

Good point from a UX perspective! However, there are two reasons to keep the three-value enum:

  1. Confirming the device actually responded. When you send off (0x00), the device reports back 0x01 (manual). If we only exposed off/on, the reported state would never match what the user sent — the UI would show off but the device reports a value that maps to something else. With three values, the user sends off, the device reports manual, and the state update is clear and unambiguous. It serves as confirmation that the device received and processed the command.

  2. Future extensibility. SONOFF may assign distinct behavior to other values in future firmware updates. Keeping them as separate values avoids a breaking change later if that happens.

@MeisterQ
Copy link

MeisterQ commented Feb 9, 2026

When will the smart mode be available? I updated to 1.4.4, but can it already use it?

@fma965
Copy link

fma965 commented Feb 9, 2026

When will the smart mode be available? I updated to 1.4.4, but can it already use it?

With this #11466 (comment) yes, without it when this PR is merged, then when next Z2M release is out.

Copy link
Contributor

@ActuallyRuben ActuallyRuben left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my opinion the distinction between the 0x0 and 0x1 states is confusing. I propose presenting both values as an off state. If 0x1 is never sent to the device, and 0x0 is never reported by the device, then what difference does it make if these are encoded as the same state?
If a later firmware update adds a different meaning to these values, then we should deal with that, whenever that update arrives.

m.enumLookup<"customSonoffTrvzb", SonoffTrvzb>({
name: "smart_temperature_control",
// manual sends 0x00 (same as off), 0x01 is report-only
lookup: {off: 0x00, manual: 0x00, smart: 0x02},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
lookup: {off: 0x00, manual: 0x00, smart: 0x02},
lookup: {off: 0x00, on: 0x02},

access: "ALL",
fzConvert: (model, msg, publish, options, meta) => {
if ("smartTempControl" in msg.data) {
const valueToMode: Record<number, string> = {0: "off", 1: "manual", 2: "smart"};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const valueToMode: Record<number, string> = {0: "off", 1: "manual", 2: "smart"};
const valueToMode: Record<number, string> = {0: "off", 1: "off", 2: "on"};

Comment on lines +2591 to +2592
"Manual mode: off or manual (same effect), Smart mode: automatic temperature control. " +
'After enabling the smart mode, "Valve Opening Percentage" and "Temperature Accuracy" will be automatically disabled.',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"Manual mode: off or manual (same effect), Smart mode: automatic temperature control. " +
'After enabling the smart mode, "Valve Opening Percentage" and "Temperature Accuracy" will be automatically disabled.',
'Off: fully opens or closes the radiator valve based on a threshold temperature, ' +
'On: adjust valve opening based on a PID algorithm. ' +
'After enabling the smart mode, "Valve Opening Percentage" and "Temperature Accuracy" will be automatically disabled.',

@GigiPompieru
Copy link

In my opinion the distinction between the 0x0 and 0x1 states is confusing. I propose presenting both values as an off state.

Although your statement is logical, as a 'basic' user I think the best way to implement it is as close as the vendor does it in its native app - be it flawed. This way there can be consistency of features and the terms used by users of all ecosystems.

Secondly, even if Z2M is not strictly HA, we know most of us are also using HA. But TRVZB can he integrated in HA with ZHA and with eWelink. Having Z2M expose just off while the other two will, probably, expose off and manual will create confusion between the users of the same hardware device.

@lifo9
Copy link

lifo9 commented Feb 10, 2026

For posterity, my TRVZB has been automatically upgraded to v1.4.4 and valve_opening_degree stopped working.
I use Versatile Thermostat to control the valve directly.

I had to send the following commands via MQTT:

  1. Disable smart temp control:

    {"custom":{"cluster":"customSonoffTrvzb","type":"set","payload":{"smartTempControl":0}}}
  2. Set TRV to pass-through mode:

    {"system_mode": "heat", "occupied_heating_setpoint": 35}

@KipK
Copy link
Contributor

KipK commented Feb 10, 2026

yes that's how it's made on the fw, if smartTempControl is activated then you can't control the valve position.

@lifo9
Copy link

lifo9 commented Feb 11, 2026

yes that's how it's made on the fw, if smartTempControl is activated then you can't control the valve position.

I understand, but:

  • Firmware 1.44 was pushed to me before this PR was merged.
  • It seems smartTempControl was automatically activated after the new firmware was installed, causing the Versatile Thermostat integration to suddenly stop working.

I had to use the MQTT console to resolve the issue.
I know this isn't directly related to this PR, but in the future, perhaps you could defer firmware updates until the Zigbee2Mqtt integration is ready.

Thanks

@KipK
Copy link
Contributor

KipK commented Feb 11, 2026

In fact it is related. The converter should default to Off instead of Smart.

I haven't checked but that would need to be fixed or there will have thousands of people complaining

@GigiPompieru
Copy link

  • Firmware 1.44 was pushed to me before this PR was merged.

  • It seems smartTempControl was automatically activated after the new firmware was installed, causing the Versatile Thermostat integration to suddenly stop working.

This is quite strange. I didn't even know that you can configure Z2M to auto-update.
I have updated 2 of my 6 TRVs for testing and, as @KipK said, it defaulted to off and the valve control works as on 1.4.1

@MeisterQ
Copy link

MeisterQ commented Feb 13, 2026

So, the TRV is in off mode by default with valve values at 100% and 0%. If the user modifies these values in any way, as we can now, the TRV will switch to 0x01 meaning manual?
Will the TRV remain in manual until put into Smart or will it switch back to Off if the user returns the values to 100/0?
Sorry for all the questions, just trying to better understand the new feature.

No worries, great questions!

Does modifying valve values switch the TRV to manual (0x01)? No. The valve opening percentage and temperature accuracy values take effect after you manually disable smart temperature control (i.e., set it to off or manual). Changing valve values alone does not switch the mode.

Will it switch back to off if you restore the values to 100/0? This attribute is purely a toggle for smart temperature control — nothing more. off and manual are functionally identical; the only difference is that 0x00 is the write value and 0x01 is the report value for the same state. It has no relation to valve values or any other settings.

To put it simply:

* `off` / `manual` → Smart temperature control **disabled**, TRV uses your configured valve opening percentage and temperature accuracy

* `smart` → Smart temperature control **enabled**, TRV automatically adjusts valve parameters (your manual valve settings are ignored)

Do you know if:

  1. we can modify PID parameters?
  2. Have a Valve position expose?#
  3. Do i have to set the valve opening and closing degeree to 100/0?
  4. how many steps / how fast will the valve act in smart mode?
  5. Do i have to do any other settings except of set the smart temperature control expose to "smart"?
  6. Whats the difference between off and precision?

@MeisterQ
Copy link

MeisterQ commented Feb 13, 2026

So, the TRV is in off mode by default with valve values at 100% and 0%. If the user modifies these values in any way, as we can now, the TRV will switch to 0x01 meaning manual?
Will the TRV remain in manual until put into Smart or will it switch back to Off if the user returns the values to 100/0?
Sorry for all the questions, just trying to better understand the new feature.

No worries, great questions!
Does modifying valve values switch the TRV to manual (0x01)? No. The valve opening percentage and temperature accuracy values take effect after you manually disable smart temperature control (i.e., set it to off or manual). Changing valve values alone does not switch the mode.
Will it switch back to off if you restore the values to 100/0? This attribute is purely a toggle for smart temperature control — nothing more. off and manual are functionally identical; the only difference is that 0x00 is the write value and 0x01 is the report value for the same state. It has no relation to valve values or any other settings.
To put it simply:

* `off` / `manual` → Smart temperature control **disabled**, TRV uses your configured valve opening percentage and temperature accuracy

* `smart` → Smart temperature control **enabled**, TRV automatically adjusts valve parameters (your manual valve settings are ignored)

Do you know if:

  1. we can modify PID parameters?
  2. Have a Valve position expose?#
  3. Do i have to set the valve opening and closing degeree to 100/0?
  4. how many steps / how fast will the valve act in smart mode?
  5. Do i have to do any other settings except of set the smart temperature control expose to "smart"?
  6. Whats the difference between off and precision?

Currently my TRVs are on "smart", im using the external sensor and it is already 0.4°C below setpoint and the valves are closed.
Feels like "nothing happens"

@ActuallyRuben
Copy link
Contributor

In my opinion the distinction between the 0x0 and 0x1 states is confusing. I propose presenting both values as an off state.

Although your statement is logical, as a 'basic' user I think the best way to implement it is as close as the vendor does it in its native app - be it flawed. This way there can be consistency of features and the terms used by users of all ecosystems.

Secondly, even if Z2M is not strictly HA, we know most of us are also using HA. But TRVZB can he integrated in HA with ZHA and with eWelink. Having Z2M expose just off while the other two will, probably, expose off and manual will create confusion between the users of the same hardware device.

I agree that consistency is good. I have no clue how it's presented in eWelink. However, on SONOFF's official blog, they provided a ZHA script. In this script they appear to implement the smart temperature control setting as a simple on/off:

    .switch(
        CustomSonoffCluster.AttributeDefs.smart_temperature_control.name,
        # ControlModeType,
        CustomSonoffCluster.cluster_id,
        on_value=2,
        off_value=0,
        translation_key="adaptive_mode",
        fallback_name="Adaptive mode",
    )

Supporting my suggestion to show it as an on/off setting in Z2M as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants