Automating Tuya TRV via Z2MQTT

I’m pretty sure I’m making this more complicated than it needs to be - any suggestions / advice would be welcome.

I’ve just started playing with this TRV: TuYa TS0601_thermostat control via MQTT | Zigbee2MQTT and I’m just using it in force: open and force:close modes, controlled by a simple thermostat:

In switch.yaml, I define the TRV as a switch:

- platform: template
  switches:
    martin_office_trv:
      turn_on:
        service: mqtt.publish
        data:
          topic: zigbee2mqtt/TRV Martin Office/set
          payload: "{\"force\":\"open\"}"
      turn_off:
        service: mqtt.publish
        data:
          topic: zigbee2mqtt/TRV Martin Office/set
          payload: "{\"force\":\"close\"}"

And in my climate.yaml, I define a thermostat for the TRV with an external / room temperature sensor:

- platform: generic_thermostat
  name: Martin office TRV
  heater: switch.martin_office_trv
  target_sensor: sensor.martin_office_temperature_temperature
  target_temp: 20.5
  initial_hvac_mode: "heat"
  hot_tolerance: 0

So far, so good. This basically works fine. My lovelace card looks like this:

type: vertical-stack
cards:
  - type: custom:simple-thermostat
    entity: climate.martin_office_trv
    header:
      name: Martin office
      icon:
        heating: mdi:power
        'off': mdi:power-off
        idle: mdi:sleep
    control:
      hvac:
        heat:
          icon: mdi:power
        'off':
          icon: mdi:power-off
    hide:
      state: true
      temperature: true
    sensors:
      - attribute: current_temperature
        icon: mdi:thermometer
    layout:
      step: row
      mode:
        headings: false
        names: false
    decimals: 1
    step_size: 0.5
  - type: entities
    entities:
      - entity: switch.martin_office_trv
        name: TRV switch
        icon: mdi:pipe-valve
      - entity: sensor.trv_martin_office_position
      - entity: binary_sensor.martin_office_trv_error

I added the last binary error sensor into my sensor.yaml because I had a situation where the open / close MQTT command didn’t work and the switch status and valve position got out of sync:

- platform: template
  sensors:
    martin_office_trv_error:
      friendly_name: Martin Office TRV Error
      delay_on:
        seconds: 60
      value_template: >
        {% if is_state('sensor.trv_martin_office_position', '100') and is_state('switch.martin_office_trv', 'on') %} Off
        {% elif is_state('sensor.trv_martin_office_position', '0') and is_state('switch.martin_office_trv', 'off') %} Off       
        {% else %} On
        {% endif %}

This seems like a lot of moving parts to me for just one TRV. Is there a more simple method to control a TRV and get feedback about its position?

I played with MQTT Switch - Home Assistant for a while which seems to have state and availability built-in - but I couldn’t figure out the MQTT topics to make it work at all.

Is there a reason not to use it as a climate device?

There’s a lot of ‘stuff’ in there that I don’t want to use - schedules / temperatures etc. Ok for one TRV, but when I have a dozen or more, I want to be able to centralise the schedules and automation rather than deal with each TRV individually. Having said that, I haven’t really looked at climate devices too much

Well it is a climate device…

Yeah - you’d think it would be relatively straightforward, but the generic thermostat expects to engage a simple on/off device. You can have it talk to the TRV as a climate entity - but it doesn’t control it very well because the TRV reports states other than on/off. Hence converting the climate entity to a switch entity. I thought I’d maybe overcomplicated things by introducing this switched climate entity - but I can’t get the generic thermostat to work reliably without it

On the plus side, the fabulous scheduler component and scheduler card make it easy to add a schedule to the new switchified TRV climate device.

I imagined that there’d be a tidier way to combine the schedule functions with a climate entity that worked. My approach still seems like a lot of moving parts.

Hello
Bumped into the same problem, however managed to solve the problem with the reporting back. Problem: tuya TRV cannot use /get values so we need to extract the mode of the TRV reported back in the payload. Probably it is possible to get somehow by templating the valve position, as for value templates only mode, preset and temperature is supported in the zigbe2mqtt. However, if the device reports back state on/off of the valve, that is good enough. This works with the TRVs with the presets ON/OFF.
I will experiment with also ,“running_state”:“idle” (or heat) - which confirms that the valve opened fully. Now with the “position”:0 - which reports back valve percentage, it’s complicated, it can change 0 or 100 in eco mode but in comfort mode can be any value between 0-100. But this what I have with preset state is good enough I suppose. No more desynchronised status
I will add also a mqtt sensor, will post it here, so it can be used in automations , for instance if TRV becomes unavailable, automation (depending on heat demand request from other TRVs) would cut off heat demand on the boiler.
Here is what I came with:

mqtt:
  - switch:
      unique_id: bathroom_trv_switch
      name: "Bathroom TRV Switch"
      state_topic: "zigbee2mqtt/Bathroom TRV"
      value_template: "{{ value_json.preset }}"        
      command_topic: "zigbee2mqtt/Bathroom TRV/set/preset"
      availability:
        - topic: "zigbee2mqtt/Bathroom TRV/availability"
      payload_on: "ON"
      payload_off: "OFF"
      state_on: "on"
      state_off: "off"
      optimistic: false
      qos: 0
      retain: true

Yes. Method with binary switching the valve between ON and OFF allows to use external temperature sensor (or array of sensors) and allows us to create thermostat with much smarter capabilities - with PIDs etc.

Well in esphome a PID controller requires a continuous heating (or cooling) value, PID Climate — ESPHome

Please note the output must be controllable with continuous value (not only ON/OFF, but any state in between for example 50% heating power).

I guess you could set up anything you want though.

That is correct, however, other solutions (generic thermostat) just turn on/off the heater. I am using Smart Thermostat (PID) that sets the PWM to output calculating for how long the heater should stay in ON and OFF state. Defined the minimum ON period to protect the boiler and all working as it’s supposed to be.

Great stuff, thank you - I’ll have another look / play!