Perfect Heating Automation with Sonoff TRVZB

Perfect Heating Automation with Sonoff TRVZB

Hello everyone,
To keep this post concise, I’ll focus on practical solutions without diving into excessive details. Recently, I purchased a Sonoff TRVZB. This is not my first experience with TRVs; I’ve already been using seven Moes BRT-100 TRVs in my home. Let me tell you right away: Moes TRVs are the worst TRVs ever produced. After some time, they released newer versions to address their shortcomings.

I integrated the Sonoff TRVZB into Home Assistant via Zigbee2MQTT (Z2M) without any issues. After the installation, I examined the features provided by the Z2M panel. One feature that caught my attention was the “external temperature sensor integration”, introduced in a recent firmware update. Unfortunately, this feature wasn’t available in Z2M yet. This update is currently exclusive to Sonoff Zigbee Bridge Pro devices, and firmware updates can only be performed via this hub. Sonoff has announced that it will be available for other hubs by Q4 2024.


Problem 1: Inaccurate Temperature Sensor

The first problem I encountered was the inaccurate temperature readings from the built-in sensor on the TRV. Since the offset values kept changing, manual calibration wasn’t a viable option. My initial step was to disable temperature reporting from the TRV in Z2M and create an automation that pulls temperature data from an external sensor.

  • How to disable reporting:
    I disabled all reporting fields in Z2M to ensure the TRV doesn’t send inaccurate temperature data

image

  • External sensor selection:
    For the living room, I used a Sonoff SNZB-02D temperature sensor. However, even though these sensors were connected via Z2M, their reporting frequency wasn’t sufficient. For precise climate control, the sensor needs to update temperature data frequently. The Sonoff sensors, unfortunately, updated data every 5–10 minutes, which was inadequate.
  • Solution for faster updates:
    I adjusted the Z2M reporting settings to ensure quicker updates. Here are the settings I used:

After these adjustments, the sensors started updating more frequently, which resolved the issue. Now, I needed to transmit the updated sensor data to the Sonoff TRVs in real time. Since such a feature was not yet available via MQTT, I accomplished this through a Home Assistant automation. The automation is as follows

alias: TRV Calibration - BedroomTRV_Calibration
description: Bedroom TRV'nin sıcaklık kalibrasyonunu oda sıcaklık sensörüne göre ayarlar
triggers:
  - entity_id:
      - climate.bedroom_trv
    attribute: current_temperature
    trigger: state
  - entity_id:
      - sensor.xiaomi_bedroom_temperature
    trigger: state
conditions:
  - condition: template
    value_template: >
      {{ state_attr('climate.bedroom_trv', 'current_temperature') | float !=
      states('sensor.xiaomi_bedroom_temperature') | float }}
actions:
  - variables:
      trvtemp: "{{ state_attr('climate.bedroom_trv', 'current_temperature') | float }}"
      trvcalib: >-
        {{ states('number.0x847127fffe9ec06e_local_temperature_calibration') |
        float }}
      roomtemp: "{{ states('sensor.xiaomi_bedroom_temperature') | float }}"
      calibration: "{{ (trvcalib - (trvtemp - roomtemp)) | round(2) }}"
      vpayload: |
        {
          "local_temperature_calibration": {{ calibration }}
        }
  - data:
      topic: zigbee2mqtt/0x847127fffe9ec06e/set
      payload: "{{ vpayload }}"
    action: mqtt.publish
mode: single

In this automation, you will need the MQTT-configured Sonoff thermostat, the external sensor from which you will retrieve the temperature data, and the MQTT ID of the Sonoff TRV. You can find the MQTT ID on the Home Assistant Zigbee2MQTT main page.

image


Problem 2: Integrating Better Thermostat

With accurate temperature readings, the next step was to use Better Thermostat in Home Assistant. I created thermostat cards for each TRV in my home, assigning external temperature sensors, door/window sensors, and other inputs where applicable.

  • Key settings:
    • Target Base Temperature: Configured for optimal comfort.
    • Calibration: Disabled the app’s internal calibration to avoid errors, as I had already set accurate calibration through Z2M.

However, now a new issue emerged: Hysteresis values.


Problem 3: Hysteresis Handling

Sonoff TRVs use a hysteresis of about 1°C, meaning the valve opens when the room temperature drops 1°C below the set point. This was problematic in my case due to significant temperature variations in my home. For comparison:

  • Netatmo TRVs: Hysteresis = 0.3°C
  • Aqara TRVs: Hysteresis = 0.5°C

To bypass this limitation, I created a custom automation in Home Assistant:

  1. Compared Better Thermostat’s heating mode with the actual MQTT thermostat state.
  2. If Better Thermostat entered “heating mode,” the automation forced the MQTT thermostat to do the same.

Since there’s no “force open valve” option in Home Assistant climate settings, I added a workaround by temporarily increasing the set temperature by 2°C and then reverting it.

alias: TRV - Salon TRV 3 Better - Periyodik HVAC Kontrol
description: >-
  Salon TRV 3 Better her 5 saniyede bir durum kontrolü yapar ve gerektiğinde
  işlem uygular.
triggers:
  - seconds: /59
    trigger: time_pattern
conditions: []
actions:
  - choose:
      - conditions:
          - condition: state
            entity_id: climate.salon_trv3_better
            attribute: hvac_action
            state: heating
          - condition: state
            entity_id: climate.salon_trv_3
            attribute: hvac_action
            state: heating
        sequence: []
      - conditions:
          - condition: state
            entity_id: climate.salon_trv3_better
            attribute: hvac_action
            state: heating
          - condition: state
            entity_id: climate.salon_trv_3
            attribute: hvac_action
            state: idle
        sequence:
          - variables:
              original_temperature: "{{ state_attr('climate.salon_trv_3', 'temperature') }}"
          - target:
              entity_id: climate.salon_trv_3
            data:
              temperature: "{{ original_temperature | float + 2 }}"
            action: climate.set_temperature
          - delay:
              seconds: 2
          - target:
              entity_id: climate.salon_trv_3
            data:
              temperature: "{{ original_temperature }}"
            action: climate.set_temperature
mode: single

This code will run in the background every 1 minute and compare the states of the Better Thermostat with the original MQTT thermostat. In the example, climate.salon_trv3_better is the entity ID created with Better Thermostat, while climate.salon_trv_3 refers to the original MQTT thermostat


Daily Automation

The final step was creating a daily automation to adjust temperatures based on my schedule:

  • 8 AM – 6 PM: Lower temperatures for efficiency.
  • 6 PM – 11:30 PM: Higher temperatures for comfort.
  • 11:30 PM onwards: Reduced all TRVs to 5°C as the central heating system shuts off.
alias: TRV Oto Mod - Zaman ve Duruma Göre
description: TRV'leri belirli saat aralıklarında ve koşullara göre ayarlar.
triggers:
  - trigger: time_pattern
    minutes: /10
conditions:
  - condition: state
    entity_id: input_boolean.live_tiles_trv_auto_aqara
    state: "on"
  - condition: state
    entity_id: person.berkan
    state: home
  - condition: state
    entity_id: alarm_control_panel.ha_alarm
    state: disarmed
actions:
  - choose:
      - conditions:
          - condition: time
            after: "08:00:00"
            before: "18:00:00"
        sequence:
          - target:
              entity_id: climate.bedroom_trv_better
            data:
              temperature: 20
            action: climate.set_temperature
          - target:
              entity_id: climate.ofis_trv_better
            data:
              temperature: 23
            action: climate.set_temperature
          - target:
              entity_id: climate.giysi_trv_better
            data:
              temperature: 22
            action: climate.set_temperature
          - target:
              entity_id:
                - climate.salon_trv_1_better
                - climate.salon_trv2_better
                - climate.salon_trv3_better
                - climate.salon_trv_4_better
            data:
              temperature: 22
            action: climate.set_temperature
      - conditions:
          - condition: time
            after: "18:00:00"
            before: "23:30:00"
        sequence:
          - target:
              entity_id: climate.bedroom_trv_better
            data:
              temperature: 22
            action: climate.set_temperature
          - target:
              entity_id: climate.ofis_trv_better
            data:
              temperature: 23
            action: climate.set_temperature
          - target:
              entity_id: climate.giysi_trv_better
            data:
              temperature: 23
            action: climate.set_temperature
          - target:
              entity_id:
                - climate.salon_trv_1_better
                - climate.salon_trv2_better
                - climate.salon_trv3_better
                - climate.salon_trv_4_better
            data:
              temperature: 23
            action: climate.set_temperature
      - conditions:
          - condition: time
            after: "23:30:00"
            before: "07:59:59"
        sequence:
          - target:
              entity_id:
                - climate.bedroom_trv_better
                - climate.ofis_trv_better
                - climate.giysi_trv_better
                - climate.salon_trv_1_better
                - climate.salon_trv2_better
                - climate.salon_trv3_better
                - climate.salon_trv_4_better
            data:
              temperature: 5
            action: climate.set_temperature
mode: single


Conclusion

By combining Zigbee2MQTT, Better Thermostat, and custom Home Assistant automations, I achieved a perfectly optimized heating system. It reacts to real-time changes, maintains accurate temperatures, and overcomes the limitations of Sonoff TRVs. Additionally, Sonoff TRVs allow you to configure the percentage at which the valves remain open or closed via MQTT. This feature enables you to create automations throughout the day based on temperature conditions. For example, even if the TRVs reach their set points after 6 PM, you can keep the valves 25% open to slow down the cooling of the room, ensuring a more comfortable environment.

I hope this helps anyone facing similar issues. Feel free to ask questions or share your thoughts!

3 Likes

Hi I’m also trying to use external sensors for my Sonoff TRVZB. I think it might be easier to just use external temperature sensors to adjust the TRV’s offset value. This way there’s no need to adjust the polling rate as it just need to verify the offset value every 5-10 min

Hello. Actually, I initially tried a similar solution. However, I noticed some issues when I didn’t disable the internal sensor on the Sonoff TRV itself. For example, the temperature readings were highly unstable. Let’s say the room was 23°C, the sensor would show 23.4°C at one moment, then drop to 22.8°C, and later record something like 23.3°C. In short, the readings weren’t consistent. How can you manually assign a stable value to an external sensor when the readings fluctuate like this? For instance, the offset value can go from -2.3 to +2 in a short period of time. In my opinion, at least for me, the most reliable method is to disable this reporting and use automation instead.

2 Likes

Mükemmel çalışma. Yaklaşık 20 gündür bu sorunları halletmek için okumadığım konu kalmamıştı. Dışarıdan sensör atamak için bir blueprint bulmuştum onunla idare etmeye çalışıyordum. Fakat bu otomasyon gerçek zamanlı çalışmıyordu, çok geç güncelleme yapıyordu. En kısa sürede ZHA’dan Z2M’ye geçiş yapıp bunları uygulayacağım. Elleriniz dert görmesin. Bu mecrada bir vatandaşımı görmek, Tükçe yazılmış YAML içerikleri görmek çok farklı bir duygu. Teşekkürler…

1 Like

Bu şekilde otomasyonları yaptım fakat çalışmadı. 5 saniyede bir otomasyon çalışıyor fakat TRV’nin local temperature değeri external sensöre göre güncellenmiyor. TRV kendi lokal ısısını esas alarak motoru on off yapıyor. Hatam nerde, bakarsanız sevinirim.

  • id: ‘1723312973429’
    alias: TRV - trv_z2m - Periyodik HVAC Kontrol
    description: >-
    trv_z2m Better her 5 saniyede bir durum kontrolü yapar ve gerektiğinde
    işlem uygular.
    triggers:

    • seconds: /5
      trigger: time_pattern
      conditions:
      actions:
    • choose:
      • conditions:
        • condition: state
          entity_id: climate.trv_z2m_better
          attribute: hvac_action
          state: heating
        • condition: state
          entity_id: climate.trv_z2m
          attribute: hvac_action
          state: heating
          sequence:
      • conditions:
        • condition: state
          entity_id: climate.trv_z2m_better
          attribute: hvac_action
          state: heating
        • condition: state
          entity_id: climate.trv_z2m
          attribute: hvac_action
          state: idle
          sequence:
        • variables:
          original_temperature: “{{ state_attr(‘climate.trv_z2m’, ‘temperature’) }}”
        • target:
          entity_id: climate.trv_z2m
          data:
          temperature: “{{ original_temperature | float + 2 }}”
          action: climate.set_temperature
        • delay:
          seconds: 2
        • target:
          entity_id: climate.trv_z2m
          data:
          temperature: “{{ original_temperature }}”
          action: climate.set_temperature
          mode: single
  • id: ‘1723312973428’
    alias: TRV Calibration - trv_z2m_Calibration
    description: trv_z2m’nin sıcaklık kalibrasyonunu oda sıcaklık sensörüne göre ayarlar
    triggers:

    • entity_id:
      • climate.trv_z2m
        attribute: current_temperature
        trigger: state
    • entity_id:
      • sensor.elifoda_temperature
        trigger: state
        conditions:
    • condition: template
      value_template: >
      {{ state_attr(‘climate.trv_z2m’, ‘current_temperature’) | float !=
      states(‘sensor.elifoda_temperature’) | float }}
      actions:
    • variables:
      trvtemp: “{{ state_attr(‘climate.trv_z2m’, ‘current_temperature’) | float }}”
      trvcalib: >-
      {{ states(‘number.0x0cae5ffffeb122fb_local_temperature_calibration’) |
      float }}
      roomtemp: “{{ states(‘sensor.elifoda_temperature’) | float }}”
      calibration: “{{ (trvcalib - (trvtemp - roomtemp)) | round(2) }}”
      vpayload: |
      {
      “local_temperature_calibration”: {{ calibration }}
      }
    • data:
      topic: zigbee2mqtt/0x0cae5ffffeb122fb/set
      payload: “{{ vpayload }}”
      action: mqtt.publish
      mode: single