Перейти к содержимому

Как настроить Tuya TS0201 Neo в Home Assistant ZHA: чтобы датчики температуры и влажности наконец заработали

Машинный перевод

Почему датчик _TZ3000_qaaysllp теряет показания и как это исправить с помощью кастомного quirk

Я приобрел датчик температуры, влажности и освещенности Neo Tuya TS0201 (идентификатор производителя _TZ3000_qaaysllp, также известный как NAS-TH02B2), рассчитывая на простую настройку в ZHA. Синхронизировался он нормально — батарея и освещенность появились сразу. Но температуры и влажности не было вовсе. Никаких сущностей, никаких данных, ничего.

Существующий quirk в zha-device-handlers должен был обслуживать это устройство, но не помог. После нескольких часов копания в перехваченных Zigbee-пакетах и отладочных логах ZHA я выяснил, что проблема имеет три отдельных уровня — а апстримный quirk закрывает лишь один из них. В этой статье я разбираю всё, что нашёл, и предлагаю рабочий фикс.

Симптомы: что вы увидите

После сопряжения ZHA обычно показывает:

  • Процент заряда батареи — работает нормально
  • Освещенность — работает нормально
  • Температура — показатель отсутствует или отображается unknown / 0
  • Влажность — сущность отсутствует или показывает unknown / 0

В логах Home Assistant (с включенной отладкой ZHA) можно увидеть сообщения типа:

Ignoring message on unknown endpoint 2

Или во время настройки устройства:

UNSUPPORTED_ATTRIBUTE on cluster 0x0402 (TemperatureMeasurement)UNSUPPORTED_ATTRIBUTE on cluster 0x0405 (RelativeHumidity)

Почему так происходит: первопричина

Эта проблема имеет три уровня, и чтобы датчик заработал, нужно устранить неисправности на всех трёх. Вот что происходит под капотом.

Уровень 1: устройство предоставляет неверную информацию о своих возможностях

Каждое Zigbee-устройство транслирует «простой дескриптор» (simple descriptor), который сообщает координатору, какие кластеры (функции) оно поддерживает и на каких эндпоинтах. TS0201 Neo анонсирует следующее:

Конечная точка 1: Basic, PowerConfiguration, IlluminanceMeasurement, Tuya Alarm (0xE002)

Обратите внимание, чего не хватает: TemperatureMeasurement (0x0402) и RelativeHumidity (0x0405) не указаны вообще. Устройство просто не сообщает, что умеет измерять температуру или влажность.

Уровень 2: данные поступают на неанонсированный эндпоинт

После определенной последовательности активации (о ней ниже) устройство все же начинает отправлять данные о температуре и влажности — но на конечную точку 2, о которой оно координатору никогда не сообщало. zigpy, библиотека Zigbee, которую использует ZHA, вполне справедливо отбрасывает эти сообщения:

Ignoring message on unknown endpoint 2

Существующий апстрим-quirk в zha-device-handlers (zhaquirks/tuya/ts0201.py) всё-таки добавляет виртуальный endpoint 2 в модель устройства, что частично решает эту проблему. Но он не исправляет остальные два уровня.

Уровень 3: отсутствует последовательность активации

Даже с указанным endpoint 2 устройство не начнет передавать данные о температуре и влажности, пока не получит так называемый «Tuya magic packet» — считывание определенных атрибутов кластера Basic, в первую очередь — специфичного для производителя атрибута 0xFFFE. Это тот же механизм, который zigbee2mqtt реализует как tuya.configureMagicPacket.

апстримовый quirk для ZHA этот magic packet не отправляет. Без него endpoint 2 существует в модели устройства, но устройство никогда не отправляет на него никаких данных.

Бонусный уровень: UNSUPPORTED_ATTRIBUTE уничтожает сущности

Когда ZHA инициализирует устройство, она считывает атрибуты, чтобы определить, какие сущности Home Assistant следует создать. Это устройство соответствует UNSUPPORTED_ATTRIBUTE (код ошибки 0x86) при прямом чтении кластеров температуры и влажности. Quirk «Апстрим» использует голые ID кластеров на endpoint 2, поэтому эти запросы доходят до устройства и завершаются сбоем. ZHA обнаруживает ошибку и вообще пропускает создание сущностей.

Фикс: пользовательский quirk для ZHA

Я опубликовал рабочий quirk, который закрывает все три уровня: ts0201.py — GitHub Gist

Чем отличается этот quirk

По сравнению с версией из апстрима, этот quirk добавляет:

  1. Mixin TuyaCachedReadCluster — перехватывает вызовы read_attributes() и возвращает кэшированные значения (из предыдущих отчетов) или нулевое значение по умолчанию. Также он вызывает _update_attribute(), чтобы уведомить цепочку слушателей ZHA, обеспечивая создание сущностей даже тогда, когда устройство возвращает UNSUPPORTED_ATTRIBUTE.
  2. Magic packet в bind() — когда ZHA настраивает подписки на отчеты в кластере alarm, quirk сначала считывает атрибуты кластера Basic, в частности специфический для Tuya 0xFFFE. Это активирует стандартную отчетность кластеров устройства на endpoint 2.
  3. Исправление бага: ID атрибута alarm_humidity_max — в апстрим-quirk он указан как 0xD00C, но на самом деле устройство отправляет отчет 0xD00D. Проверено на реальных данных устройства.
  4. NodeDescriptor — добавлено в словарь замены (replacement dict), скопировано из реального ответа устройства.
  5. Пользовательские классы кластеров на EP2 — вместо «голых» ID кластеров (которые просто маршрутизируют сообщения, но не переопределяют поведение) quirk использует классы TuyaTemperatureMeasurement и TuyaRelativeHumidity, которые наследуют поведение кэшированного чтения.

Установка: пошаговая инструкция

Шаг 1: создайте каталог для пользовательских quirks

Если вы ещё этого не сделали, создайте каталог для пользовательских quirks. С помощью файлового редактора Home Assistant, SSH или Samba:

/homeassistant/custom_zha_quirks/

Шаг 2: загрузите quirk

Загрузите ts0201.py с GitHub Gist и поместите его в:

/homeassistant/custom_zha_quirks/ts0201.py

Шаг 3: настройте ZHA на использование пользовательских режимов

Добавьте это в свой configuration.yaml:

zha:  custom_quirks_path: /config/custom_zha_quirks

Шаг 4: перезапустите Home Assistant

Требуется полный перезапуск — не просто перезагрузка конфигурации.

Шаг 5: удалите устройство и выполните сопряжение заново

Этот шаг очень важен. Многие особенности вступают в силу только во время сопряжения устройства (процесса сопряжения). После перезапуска:

  1. Перейдите в «Настройки» > «Устройства и службы» > «ZHA»
  2. Найдите устройство TS0201 и удалите его
  3. Переведите датчик в режим сопряжения (обычно длительным нажатием кнопки)
  4. Снова сопрягите устройство через ZHA

После сопряжения устройства потребуется минута-две, чтобы полностью настроиться (у устройств Tuya ограничение на параллелизм составляет примерно 2 одновременных запроса, поэтому настройка происходит последовательно). Когда всё завершится, вы должны увидеть:

  • Температура — обновляется с реальными значениями
  • Влажность — обновляется с реальными значениями
  • Освещенность — работает как и раньше
  • Батарея — работает как и раньше

Как это работает: техническое погружение

Для тех, кто хочет понять механику, вот поток данных после применения quirk:

Device pairs    → ZHA applies quirk (signature matches _TZ3000_qaaysllp / TS0201)    → Replacement creates virtual EP2 with custom cluster classes
ZHA configures EP1 alarm cluster    → bind() override triggers magic packet    → Reads Basic attributes [0x0000, 0x0001, 0x0004, 0x0005, 0x0007, 0xFFFE]    → 0xFFFE activates the device's reporting mechanism
Device starts sending unsolicited reports on EP2    → TemperatureMeasurement (0x0402): measured_value in hundredths of °C    → RelativeHumidity (0x0405): measured_value in hundredths of %
ZHA reads attributes during init    → TuyaCachedReadCluster intercepts the read    → Returns cached value (or 0 if no report yet)    → Calls _update_attribute() → ZHA creates the HA entity
Ongoing operation    → Device sends reports every ~1 minute (or on significant change)    → zigpy routes to EP2 → custom cluster → _update_attribute() → HA entity updates

Почему _update_attribute() важен

В zigpy _update_attribute() — это центральный механизм уведомлений. При вызове он:

  1. Обновляет внутренний _attr_cache кластера
  2. Запускает колбек zdo.ATTR_UPDATED
  3. ClusterHandler в ZHA, получает его и обновляет сущность Home Assistant

Без вызова _update_attribute() в переопределении кэшированного чтения ZHA никогда бы не узнала о значении и не создавала бы сущностей.

Почему работает magic packet

Атрибут 0xFFFE — это специфический для Tuya механизм. Его считывание сообщает устройству: «Я — Tuya-совместимый координатор, пожалуйста, начни отправлять мне данные через стандартные ZCL-кластеры». Без этого считывания устройство остается без отклика на EP2. Это хорошо задокументировано в кодовой базе zigbee2mqtt как configureMagicPacket.

Подтвержденные рабочие значения

После применения этого quirk вот реальные значения, полученные от устройства (из отладочных логов ZHA):

  • TemperatureMeasurement (EP2) — measured_value: 2640 → 26,40 °C
  • RelativeHumidity (EP2) — measured_value: 4100 → 41,00 %
  • IlluminanceMeasurement (EP1) — measured_value: 0 → 0 люкс
  • PowerConfiguration (EP1) — battery_percentage_remaining: 200 → 100%

Значения температуры и влажности обновляются примерно каждую минуту или при обнаружении значительного изменения (>=0,5 °C или >=5 % влажности).

Часто задаваемые вопросы

Работает ли это с моделью NAS-TH02B2?

Neo NAS-TH02B2 — самая распространённая физическая модель, которая по Zigbee идентифицирует себя как _TZ3000_qaaysllp / TS0201. Да, этот quirk предназначен именно для этого устройства.

Не возникнет ли при этом конфликт с quirk «upstream»?

Нет. Пользовательские quirks custom_zha_quirks имеют приоритет над встроенными quirks, когда сигнатура устройства совпадает. Апстримовый quirk будет проигнорирован в пользу вашего.

Нужен ли мне для этого zigbee2mqtt?

Нет. Этот фикс предназначен исключительно для ZHA (встроенной Zigbee-интеграции Home Assistant). Если вы используете zigbee2mqtt, поддержка устройств Tuya реализована иначе — через их систему конвертеров, где configureMagicPacket он уже встроен.

Устройство сопряглось, но температура по-прежнему показывает ноль

Подождите 2–3 минуты после сопряжения. Устройству необходимо завершить свой первый цикл отчетности. Если через 5 минут показатель по-прежнему равен нулю, проверьте свои логи ZHA на наличие magic packet:

[zha.zigbee.cluster_handlers] [0xABCD](tuya_alarm): bind 'Tuya Temperature and Humidity Alarm Cluster' cluster

Если вы видите это, а вслед за ним — считывание кластера Basic, значит, magic packet был отправлен.

Могу ли я использовать это с другими вариантами TS0201?

Эта особенность предназначена именно для _TZ3000_qaaysllp. Другие варианты TS0201 (например _TZ3000_fllyghyj, _TZ3000_lfa05ajd, _TZ3210_ncw88jfq) ведут себя иначе и могут потребовать других quirk. Сопоставление сигнатур гарантирует, что этот quirk применяется только к нужному устройству.

Мой показатель влажности застрял на отметке 5%

Это известная проблема, о которой сообщают некоторые пользователи даже с работающими quirks. Она может указывать на аппаратный дефект самого датчика (чипа Sensirion SHTC3), а не на проблему с quirk. Попробуйте заменить батарейки и выполнить сопряжение заново.

Связанные ресурсы

Если вы сталкиваетесь с похожим датчиком Tuya, который сопрягается, но не передает данные в ZHA, описанный здесь паттерн — отсутствующий эндпоинт, активация через magic packet, кешированные чтения для предотвращения UNSUPPORTED_ATTRIBUTE — применим ко многим устройствам Tuya, а не только к TS0201. Надеюсь, это сэкономит вам те часы, которые я потратил, чтобы в этом разобраться.

Включите комментарии, приняв куки.

Необходимые куки работают всегда. Куки для статистики и комментариев используются только с вашего согласия. Подробнее