Tuya radiator valve (TS0601) calibration from external sensor (via zigbee2mqtt)

It would be better to use friendlyName instead of friendly_name in action.

What’s the difference?

friendly_name is used for the frontend and can be changed by the user after which the calibration will stop working. friendlyName is the name of the entity.

Thanks, I didn’t know that. I will look into that soon.

It does not work for me. I have changed the topic to

topic: "zigbee2mqtt/{{valve.split('.')[1]}}/set/local_temperature_calibration"

PS: I am using zigbee2mqtt

I found an issue with the second trigger. It never worked for me. I found that the variables are not visible in the trigger scope. So have added a workgorund.

trigger_variables:
  valve: !input valve
  temp_sensor: !input temp_sensor

I will share my version of the calibration of the thermal head Tuya TS0601.

There is a comparison of the temperature difference between the thermal head and the external sensor, if there is no difference, then nothing will happen, if there is a difference, then calibrates the temperature in the thermal head. I abandoned this integration Better Thermostat, because I don’t want to depend on the author of the integration and adapt to his changes, it was ai_thermostat, then better_thermostat was made, and then I’m not satisfied with the logic of his work.

Sensor

A sensor that shows whether calibration of the thermal head is needed or not. If calibration is required, it will show calibration. This will be executed as a trigger in automation

image

 - platform: template
   sensors:
     livingroom_termostat_local_temperature_calibration:
       friendly_name: "Living room: Thermal head. Temperature calibration"
       value_template: >
         {% set trv = state_attr('climate.gostinaia_termostat','current_temperature')|int(value) %}
         {% set tiv = states('sensor.gostinaia_tiv_temperature')|int(value) %}
         {% if trv != tiv %} Calibration
         {% else %} off
         {% endif %}
       icon_template: >
         {% set tltc = states('livingroom_termostat_local_temperature_calibration') %}
         {% if tltc in ('unknown', 'unavailable', 'off') %} mdi:lock-outline
         {% else %} mdi:scale-balance
         {% endif %}

In the automation action, we use the service number.set_value

service: number.set_value
target:
  entity_id: number.gostinaia_termostat_local_temperature_calibration
data:
  value: >
    {% set trv = state_attr('climate.gostinaia_termostat','current_temperature')|int(value) %}
    {% set tiv = states('sensor.gostinaia_tiv_temperature')|int(value) %}
    {% set tltc = states('number.gostinaia_termostat_local_temperature_calibration')|int(value) %}
    {% set sum = trv - tiv %}
    {% if trv != tiv %}
    {{ tltc - sum }}
    {% else %}
    {% endif %}

Explanation:
trv = thermal head, we use the current temperature in the thermal head
tiv = external temperature sensor
tltc = thermal head, local temperature calibration. I took it through the MQTT integration, opening the device itself and you can find number.name_termostat_local_temperature_calibration

Automation

alias: 'Living room: Thermal head. Temperature calibration'
description: >-
  The built-in temperature sensor in the thermal head records the temperature around
  thermal heads, which leads to inaccurate operation. For precise operation of the thermal head
  it is better to use an external temperature sensor. If calibration is enabled
  the thermal head, then there will be an automatic calibration of the thermal head according to the 
  external temperature sensor.
trigger:
  - platform: state
    entity_id: sensor.livingroom_termostat_local_temperature_calibration
    from: 'off'
    to: Calibration
    for:
      hours: 0
      minutes: 0
      seconds: 10
  - platform: state
    entity_id: switch.gostinaia_termogolovka_kalibrovka_temperatury
    from: 'off'
    to: 'on'
condition:
  - condition: not
    conditions:
      - condition: state
        entity_id: climate.gostinaia_termostat
        state: 'off'
  - condition: state
    entity_id: switch.gostinaia_termogolovka_kalibrovka_temperatury
    state: 'on'
action:
  - service: number.set_value
    target:
      entity_id: number.gostinaia_termostat_local_temperature_calibration
    data:
      value: >
        {% set trv = state_attr('climate.gostinaia_termostat','current_temperature')|int(value) %} 
        {% set tiv = states('sensor.gostinaia_tiv_temperature')|int(value) %}
        {% set tltc = states('number.gostinaia_termostat_local_temperature_calibration')|int(value) %} 
        {% set sum = trv - tiv %} 
        {% if trv != tiv %} 
        {{ tltc - sum }} 
        {% else %} 
        {% endif %}
mode: single

Card for the thermal head

image

type: entities
entities:
  - entity: sensor.thermostat_livingroom
    type: custom:multiple-entity-row
    icon: mdi:thermostat
    name: Thermostat
    secondary_info:
      attribute: Battery
      name: 'Battery:'
    show_state: false
    entities:
      - entity: group.livingroom_termostat_info_and_menu
        name: Menu
        state_color: true
        icon: mdi:information-outline
        styles:
          width: 50px
      - entity: sensor.gostinaia_tiv_temperature
        name: Temperature
        styles:
          width: 70px
      - entity: sensor.gostinaia_termostat_position
        name: Position
        styles:
          width: 50px
      - entity: sensor.livingroom_termostat_local_temperature_calibration
        name: Calibration
        styles:
          width: 90px
state_color: true

Текст на русском (Text in Russian)

Поделюсь своим вариантом калибровки термоголовки Tuya TS0601.

Идет сравнение разницы температур между термоголовкой и внешним датчиком, если разницы нет, то ничего не будет происходить, если разница есть, то откалибрует температуру в термоголовке. Я отказался от этой интеграции Better Thermostat, ибо не хочу зависеть от автора интеграции и подстраиваться под его изменения, то было ai_thermostat, потом сделали better_thermostat и потом, меня не устраивает логика его работы.

Сенсор

Сенсор, который показывает, нужна ли калибровка термоголовки или нет. Если требуется калибровка, то будет показывать калибровка. Это будет выполняться в качестве триггера в автоматизации

image

 - platform: template
   sensors:
     livingroom_termostat_local_temperature_calibration:
       friendly_name: "Гостиная: Термоголовка. Калибровка температуры"
       value_template: >
         {% set trv = state_attr('climate.gostinaia_termostat','current_temperature')|int(value) %}
         {% set tiv = states('sensor.gostinaia_tiv_temperature')|int(value) %}
         {% if trv != tiv %} Калибровка
         {% else %} off
         {% endif %}
       icon_template: >
         {% set tltc = states('livingroom_termostat_local_temperature_calibration') %}
         {% if tltc in ('unknown', 'unavailable', 'off') %} mdi:lock-outline
         {% else %} mdi:scale-balance
         {% endif %}

В действии автоматизации используем службу number.set_value

service: number.set_value
target:
  entity_id: number.gostinaia_termostat_local_temperature_calibration
data:
  value: >
    {% set trv = state_attr('climate.gostinaia_termostat','current_temperature')|int(value) %}
    {% set tiv = states('sensor.gostinaia_tiv_temperature')|int(value) %}
    {% set tltc = states('number.gostinaia_termostat_local_temperature_calibration')|int(value) %}
    {% set sum = trv - tiv %}
    {% if trv != tiv %}
    {{ tltc - sum }}
    {% else %}
    {% endif %}

Пояснение:
trv = термоголовка, используем текущую температуру в термоголовке
tiv = внешний датчик температуры
tltc = термоголовка, локальная калибровка температуры. Взял ее через интеграцию MQTT, открыв сам девайс и можно найти number.name_termostat_local_temperature_calibration

Автоматизация

alias: 'Гостиная: Термоголовка. Калибровка температуры'
description: >-
  Встроенный датчик температуры в термоголовке фиксирует температуру вокруг
  термоголовки, что приводит к неточной работе. Для точной работы термоголовки
  лучше использовать внешний датчик температуры. Если включена калибровка
  термоголовки, то будет автоматическая калибровка термоголовки по внешнему
  датчику температуры. 
trigger:
  - platform: state
    entity_id: sensor.livingroom_termostat_local_temperature_calibration
    from: 'off'
    to: Калибровка
    for:
      hours: 0
      minutes: 0
      seconds: 10
  - platform: state
    entity_id: switch.gostinaia_termogolovka_kalibrovka_temperatury
    from: 'off'
    to: 'on'
condition:
  - condition: not
    conditions:
      - condition: state
        entity_id: climate.gostinaia_termostat
        state: 'off'
  - condition: state
    entity_id: switch.gostinaia_termogolovka_kalibrovka_temperatury
    state: 'on'
action:
  - service: number.set_value
    target:
      entity_id: number.gostinaia_termostat_local_temperature_calibration
    data:
      value: >
        {% set trv = state_attr('climate.gostinaia_termostat','current_temperature')|int(value) %} 
        {% set tiv = states('sensor.gostinaia_tiv_temperature')|int(value) %}
        {% set tltc = states('number.gostinaia_termostat_local_temperature_calibration')|int(value) %} 
        {% set sum = trv - tiv %} 
        {% if trv != tiv %} 
        {{ tltc - sum }} 
        {% else %} 
        {% endif %}
mode: single

Карточка для термоголовки

image

type: entities
entities:
  - entity: sensor.thermostat_livingroom
    type: custom:multiple-entity-row
    icon: mdi:thermostat
    name: Термостат
    secondary_info:
      attribute: Батарея
      name: 'Батарея:'
    show_state: false
    entities:
      - entity: group.livingroom_termostat_info_and_menu
        name: Меню
        state_color: true
        icon: mdi:information-outline
        styles:
          width: 50px
      - entity: sensor.gostinaia_tiv_temperature
        name: Температура
        styles:
          width: 70px
      - entity: sensor.gostinaia_termostat_position
        name: Позиция
        styles:
          width: 50px
      - entity: sensor.livingroom_termostat_local_temperature_calibration
        name: Калибровка
        styles:
          width: 90px
state_color: true

2 Likes

Hello, I’m new to Home Assistant. I would like to know if this also works with ZHA or is it only possible with zigbee2mqtt?

1 Like

Hey Klim,
How did you get an sensor for the local temperature on the TRV?

  - platform: mqtt
    name: "Tuya TRV Temperature"
    state_topic: "zigbee2mqtt/tuya_trv1/local_temperature"
    value_template: "{{ value }}"
    unit_of_measurement: "°C"

DivanX10 - thanks for sharing!

In the automation, you use the entity ‘switch.gostinaia_termogolovka_kalibrovka_temperatury’ both as trigger and condition.

I do not have a ‘switch’ entity for temperature calibration (which I assume the Russian entity name refers to), only for child_lock, eco_mode, window_detection and boost_heating. What is the relevance of the switch for the automation and is there an alternative?

Many thanks!

I use the Calibration trigger in automation in order to calibrate the temperature in the thermal head. I use mqtt switch as a switch, since it is important for me that all control is duplicated on the second HA, but you can use auxiliary elements, the same switch. If the trigger for temperature calibration has been triggered and if a switch or switch is turned on in the condition, then the calibration will work.

I have noticed that most blueprints won’t work when you have Home Assistant legacy entity attributes disabled in Zigbee2MQTT. This will remove the local_temperature_calibration as an attribute from the TS0601 entity itself.

The blueprint mentioned below will require an additional entity (the seperate number local_temperature_calibration enitity of the TS0601 valve)

I wrote a new TRV calibrator that I expect to work with other valves and it should be platform agnostic in certain degree (I expected to work with Z2M and ZHA). Can someone help me to test it?

It works great with my TV02-Zigbee

Hello,
I have a question regarding your blueprint.
I’ve imported it, but when I want to setup the automation, the blueprint asks me for “TRV Calibration State”, and in the entity field, I don’t have anything to chose, so the error that I have is : “Message malformed: Missing input trv_calibration_number”
I know I am a rookie in Home Assistant, please help me understand :slight_smile:

Thanks,

These TRVs store local calibration in flash memory - 100000 rw cycles max. That is 100000 changes of calibration.
If you change temperature every 10 minutes: 100000/ ( 24 * 6) = 694.44 days. In 2 years your TRV will be dead.

Подскажите пожалуйста, как определить:

switch.gostinaia_termogolovka_kalibrovka_temperatury

и на что он должен ссылаться?

и что за группа?

group.livingroom_termostat_info_and_menu

у Вас несколько радиаторов? Можно тоже пример?

Это все индивидуальные настройки и моя собственная стилизация.

switch.gostinaia_termogolovka_kalibrovka_temperatury нужен в качестве нужно ли нам включать автокалибровку или нет. Я могу для себя решить, должна ли работать калибровка или нет. Если нет, то просто выключаю, а если да, то включаю. Это аналогично тому, что мы просто выключаем автоматизацию, только выключать автоматизации глупо, так как можно использовать вспомогательные элементы выключатель или просто выключатель MQTT в качестве условии

group.livingroom_termostat_info_and_menu это нужно для стилизации. Я просто создаю группу и добавляю туда все управление от головки и смотрится в гуи компактно, а как кликаешь на меню, то разворачивается панель, где выводится вся инфа и все управление термоголовкой и так я делаю для каждой комнаты

image

Код для гуи, как видно скриншоте

entity: sensor.thermostat_livingroom
type: custom:multiple-entity-row
icon: mdi:thermostat
name: Термостат
secondary_info:
  attribute: Батарея
  name: 'Батарея:'
show_state: false
entities:
  - entity: group.livingroom_termostat_info_and_menu
    name: Меню
    state_color: true
    icon: mdi:information-outline
    styles:
      width: 50px
  - entity: sensor.gostinaia_tiv_temperature
    name: Температура
    styles:
      width: 70px
  - entity: sensor.gostinaia_termostat_position
    name: Позиция
    styles:
      width: 50px
  - entity: sensor.livingroom_termostat_local_temperature_calibration
    name: Калибровка
    state_color: true
    icon: false
    styles:
      width: 90px

а в файлик groups.yaml (группы) я добавил следующее и это меню и отображается в гуи

#Гостиная: Термостат
#Объект: group.livingroom_termostat_info_and_menu
livingroom_termostat_info_and_menu:
  name: "Гостиная: Термостат. Инфо и меню"
  icon: mdi:thermostat
  all: false
  entities:
    - switch.livingroom_termostat_local_temperature_calibration #Включить\выключить автокалибровку термоголовки
    - sensor.gostinaia_termostat_position #Position
    - sensor.gostinaia_termostat_comfort_temperature #Comfort temperature
    - number.gostinaia_termostat_comfort_temperature #Comfort temperature
    - number.gostinaia_termostat_eco_temperature #Eco temperature
    - sensor.gostinaia_termostat_min_temperature #Min temperature
    - sensor.gostinaia_termostat_max_temperature #Max temperature
    - number.gostinaia_termostat_min_temperature #Min temperature
    - number.gostinaia_termostat_max_temperature #Max temperature
    - number.gostinaia_termostat_local_temperature_calibration #Local temperature calibration
    - sensor.gostinaia_termostat_force #Force
    - switch.gostinaia_termostat_auto_lock #Auto lock
    - switch.gostinaia_termostat_valve_detection #Valve detection
    - switch.gostinaia_termostat_window_detection #Window detection
    - switch.gostinaia_termostat_away_mode #Away mode
    - number.gostinaia_termostat_away_preset_days #Away preset days
    - number.gostinaia_termostat_away_preset_temperature #Away preset temperature
    - lock.gostinaia_termostat_child_lock #Child lock
    - select.gostinaia_termostat_force #Force
    - number.gostinaia_termostat_boost_time #Boost time
    - binary_sensor.gostinaia_termostat_battery_low #Battery low
    - binary_sensor.gostinaia_termostat_update_available #Update available
    - sensor.gostinaia_termostat_update_state #Update state

Nobody cares if your are not writing in English.

5 Likes

Спасибо за ответ.
Просто если из GUI создавать выключатель то он input_boolean, поэтому и смутило почему switch, если его создавать через template, надо задать что делать в режимах on и off,