Блог

Как добавить неподдерживаемое устройство в Zigbee2mqtt

В последнее время, благодаря опытным умельцам стали один за одним появляться интересные DIY устройства для умного дома, работающие на протоколе Zigbee. Многие из них можно найти на сайте проекта https://modkam.ru/, а многие появляются в единичных экземплярах и часто не имеют официальной поддержки в zigbee2mqtt или поддерживают работу только с SLS шлюзом. Встает вопрос, как добавить их поддержку? Есть официальная документация об этой процедуре, но она весьма поверхностна, а русскоязычных подробных инструкций я лично не встречал.

И вот попалась мне в руки плата от уважаемого Grigory, реализующая zigbee датчик CO2 на базе популярных датчиков MH-Z19B или Senseair S8. Плата изначально предназначалась для работы с SLS шлюзом и поддержки zigbee2mqtt не имела. Встал вопрос как ее туда добавить так, чтобы датчик полноценно был интегрирован в HomeAssistant.

Внимательно изучив официальную документацию я решил, что попробую это сделать сам и не ждать, пока кто-то когда-то добавит эту поддержку. Или не добавит.

У меня работает Supervised HomeAssistant на базе Raspbian, или, как этот вариант называется в документации - Hass.io.

Первым делом нам нужно получить дебаг лог нашего неподдерживаемого устройства после спаривания его с вашей сетью zigbee. Для этого в аддоне zigbee2mqtt включаем опцию дебаг логирования и разрешаем новым устройствам подключаться:

permit_join: true..... advanced: log_level: debug

Включаем устройство в режим спаривания и перезапускаем аддон zigbee2mqtt. Вскоре, после того, как устройство подключится к сети, в логе аддона мы должны увидеть искомое, в моем случае что-то вроде:

zigbee2mqtt:debug 2020-07-02 23:20:35: Received Zigbee message from '0x00124b001ed13438', type 'attributeReport', cluster 'genAnalogInput', data '{"presentValue":38,"description":"C"}' from endpoint 1 with groupID 0 zigbee2mqtt:debug 2020-07-02 23:20:35: Received Zigbee message from '0x00124b001ed13438', type 'attributeReport', cluster 'genAnalogInput', data '{"presentValue":577,"description":"ppm"}' from endpoint 2 with groupID 0 zigbee2mqtt:debug 2020-07-02 23:20:35: Received Zigbee message from '0x00124b001ed13438', type 'attributeReport', cluster 'genAnalogInput', data '{"presentValue":35,"description":"C"}' from endpoint 2 with groupID 0

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

Тем, кто пользуется Supervised HomeAssistant, добавлять поддержку устройства придется внутрь докер контейнера zigbee2mqtt. Для начала нужно найти его ID. Это делается командой:

$ docker ps

Далее, согласно документации, нам нужно добавить сами конвертеры в файл /app/node_modules/zigbee-herdsman-converters/converters/fromZigbee.js но на самом деле, в реальности, внутри докер контейнера файл находится по пути node_modules/zigbee-herdsman-converters/converters/fromZigbee.js

Для этого входим внутрь докер контейнера с помощью команды:

$ sudo docker exec -it 34f23bae5977 bash

Внимательный читатель заметил, что ID контейнеров на картинке выше и в приведенной выше команде отличаются. Действительно, в этом основная проблема этого метода - после каждого перезапуска аддона zigbee2mqtt в интерфейсе вашего HomeAssistant, контейнер создается заново с новым ID и все ваши изменения внутри него пропадают. Как этого избежать я напишу ниже.

Итак, мы внутри докер контейнера и нам нужно добавить наши конвертеры. Я совершенно не умею писать код, я никогда не был программистом, но с помощью примеров и советов Grigory я написал код на JavaScript для конвертеров CO2 и температуры, которые все-таки заработали. Открываем файл node_modules/zigbee-herdsman-converters/converters/fromZigbee.js на редактирование (это делается с помощью редактора vi внутри контейнера) и вставляем следующий код между какими-нибудь уже существующими контейнерами:

airqmon_co2: { cluster: 'genAnalogInput', type: ['attributeReport', 'readResponse'], convert: (model, msg, publish, options) => { if (msg.endpoint.ID == 2 && msg.data['presentValue'] >= 400) { return ; } }, }, airqmon_temperature: { cluster: 'genAnalogInput', type: ['attributeReport', 'readResponse'], convert: (model, msg, publish, options) => { if (msg.endpoint.ID == 1) { return ; } }, },

Далее в файл node_modules/zigbee-herdsman-converters/devices.js необходимо добавить описание нашего нового zigbee устройства. Делаем это также с помощью редактора vi, добавляя следующий код:

{ zigbeeModel: ['AirQMon'], model: 'AirQMon', vendor: 'DIY', description: 'CO2 sensor', supports: 'Temperature & CO2', fromZigbee: [fz.airqmon_co2, fz.airqmon_temperature], toZigbee: [], },

И для того, чтобы наши датчики распознались в HomeAssistant с помощью discovery, в файл lib/extension/homeassistant.js добавляем сенсор для CO2 и описание. Для температуры сенсор добавлять не нужно, будет использоваться уже существующий там:

'sensor_co2': { type: 'sensor', object_id: 'co2', discovery_payload: { unit_of_measurement: 'ppm', icon: 'mdi:periodic-table-co2', value_template: '{{ value_json.co2 }}', }, },........ 'AirQMon': [cfg.sensor_co2, cfg.sensor_temperature],

После этого осталось перезапустить докер контейнер (но ни в коем случае не аддон zigbee2mqtt!!!) со всеми нашими изменениями и убедиться, что наше устройство добавилось:

$ sudo docker restart 34f23bae5977

Мы добавили поддержку нового zigbee устройства. Вышенаписанное предлагаю рассматривать лишь как достаточно подробный пример, не более. Описывать код не задача этой сугубо практической статьи.

Осталась проблема, состоящая в том, что для сохранения поддержки, необходимо перезапускать именно докер, и ни в коем случае не аддон в интерфейсе HomeAssistant,

Проблема решена в последнем апдейте zigbee2mqtt версии 1.14.1, где разработчики добавили очень крутую вещь - возможность внешних подключаемых конвертеров с помощью опции external_converters в конфигурационном файле zigbee2mqtt.

С помощью уважаемого Аноним я даже написал внешний конвертер в виде отдельного файла airqmon.js помещенного внутрь директории zigbee2mqtt, там, где находятся конфигурационный файл, база данных и важный файл devices.yaml. Его содержимое такое:

const fz = { airqmon_co2: { cluster: 'genAnalogInput', type: ['attributeReport', 'readResponse'], convert: (model, msg, publish, options) => { if (msg.endpoint.ID == 2 && msg.data['presentValue'] >= 400) { return ; } }, }, airqmon_temperature: { cluster: 'genAnalogInput', type: ['attributeReport', 'readResponse'], convert: (model, msg, publish, options) => { if (msg.endpoint.ID == 1) { return ; } }, }, }; const device = { zigbeeModel: ['AirQMon'], model: 'AirQMon', vendor: 'DIY', description: 'CO2 sensor', supports: 'Temperature & CO2', fromZigbee: [fz.airqmon_co2, fz.airqmon_temperature], toZigbee: [], }; module.exports = device;

В конфигурацию zigbee2mqtt добавил загрузку этого внешнего конвертера с помощью новейшей опции:

external_converters: - airqmon.js

Но проблема оказалась там, где ее не ждали. Оказывается, текущая версия аддона zigbee2mqtt никак, к сожалению, не поддерживает в конфигурации эту саму новейшую опцию external_converters и воспользоваться внешним конвертером в итоге пока не удалось. Остается только ждать выпуска новой версии аддона, где уже зарепорченая проблема будет решена.

После этого, писать внешние конвертеры для новых zigbee устройств станет намного проще. Хотя тем, у кого zigbee2mqtt работает не как аддон Hass.io, этой новой фичей можно пользоваться уже сейчас :)


Где можно найти информацию о самом датчике?

Я же давал в тексте ссылку на телеграм автора. 

Прошу помощи. У меня HA стоит на распбери. 

zigbee2mqttCurrent version: 1.14.1

Создал файл

airqmon.js в 

/share/zigbee2mqtt/

Добавил строчку external_converters: - airqmon.js в конфиг 

zigbee2mqtt

Перегрузил 

zigbee2mqtt

В логе вижу zigbee2mqtt:warn 2020-07-11 23:13:14: Received message from unsupported device with Zigbee model 'AirQMon'

Вопрос в том, как стоит z2m? Как аддон HomeAssistant? В таком случае, дочитайте статью до конца внимательно.

Подскажите, если я поставлю 

zigbee2mqtt через docker и сделаю по инструкции, будит все работать? Или я что-то опять неправильно понял и сейчас нет рабочего решения?

Любой другой вариант инсталляции z2m, кроме как аддоном HA должен работать. Но я не проверял.

Подскажите, есть ли какие то новости по решению для 

zigbee2mqtt на HASS.io?

В последней версии аддона поддержку внешних конвертеров так и не сделали. Я поднял z2m отдельным докером и там все как надо подключил. 

Статья отличная, спасибо. PR для добавления опции в конфиг не прошёл тесты, и автор судя по всему это исправлять не собирается, поэтому опции мы можем не дождаться. Я сделал форк аддона и исправил проблему, чтобы не ждать. Но вскрылся ещё один момент. Добавление конвертера не освобождает от добавления сенсора и самого устройства для авто-дискавери в HA через lib/extension/homeassistant.js. Не находили решения?



Сам спросил, сам отвечаю. Всё можно сделать в конвертере.


https://sprut.ai/static/media/cache/00/61/60/5/4677231/64283/1000x_image.png?1597064577" alt="1000x_image.png?1597064577" />


Прикладываю https://raw.githubusercontent.com/alexeysitka/hassio-zigbee2mqtt/master/airqmon.js">готовый конвертер.


Если не добавлять датчик температуры, то он не появится ни в Z2M Ассистенте, ни в сенсорах HA.


Результат:


https://sprut.ai/static/media/cache/00/61/60/5/4677094/64280/1000x_image.png?1597063803" alt="1000x_image.png?1597063803" />
https://sprut.ai/static/media/cache/00/61/60/5/4677094/64281/1000x_image.png?1597063823" alt="1000x_image.png?1597063823" />


странно. использую ваш конвертор, но почему-то появилось только 1 сенсор со всеми атрибутами. а как сделать как у вас чтобы стало?

edit: перегрузил еще раз z2m и появилась температура. 


Так добавили же это прописывание из homeassistant.js в конвертер в последнем апдейте z2m. Я давно уже все сделал. 

  1. ура, вышла версия 14.4.1 теперь работает в hass.io
  2. всем спасибо!


Пока не забылось, описываю подключение для чайников.
Берём файл из комментариев выше: https://raw.githubusercontent.com/alexeysitka/hassio-zigbee2mqtt/master/airqmon.js">Файл не мой
Разместить его надо в папке, которую видно через самбу по сети: \\XXX.XXX.XXX.XXX\share\zigbee2mqtt\

https://sprut.ai/static/media/cache/00/66/84/5/5594018/69054/1000x_image.jpg?1603706061" alt="1000x_image.jpg?1603706061" />


В HA по меню: Supervisor -> 

Zigbee2mqtt -> 

Configuration


добавить в конфигурацию

external_converters: 
  - airqmon.js



Последняя актуальная версия конвертера со всеми фиксами находится https://github.com/IronButterfly/airqmon">тут.

Спасибо за статью. Все просто расписано и у меня вышло с первого раза получать данные с устройства, которое я сам запрограммировал как радиореле с датчиком температуры. Статус реле и температуру я выгребаю способом описанным в статье. И даже прикрутил MQTT Discovery. Отдельное спасибо
https://sprut.ai/client/user/profile/6160">(alexeysitka).

Но вот как управлять реле через свой конвертер я так и не знаю. Нигде не могу найти подобного урока (примера) что бы можно было дописать фенкцию toZigbee и отправлять через нее управляющие команды.

Исходил уже пол сотни страниц в нете, везде разрозненная информация, но собрать все до кучи у меня не выходит. Буду благодарен, если направите на подобный пример с управлением ZigBee устройства.

К сожалению, такого опыта не имею. Могу лишь посоветовать поспрашивать гуру в https://t.me/zigbeer">https://t.me/zigbeer

Спасибо, да, там живое общение, надеюсь почерпну нужную инфу.

Я сегодня поставил абсолютно свежий HomeAssistant и у меня airqmon.js не завелся. При рестарте zigbee2mqtt возникала ошибка

Converter field exposes is undefined

В итоге я поменял пару строчек в нем. Не уверен что все правильно сделал, но у меня заработало.

https://disk.yandex.ru/d/tNayKIts2coj7A">https://disk.yandex.ru/d/tNayK...

Ну, у меня та версия, что я выкладывал несколько комментариев выше, прекрасно работает.

Судя по коммитам в zigbee2mqtt они это добавили в январе и в релиз видимо вышло вот только что... И я сразу на это напоролся. Попробуйте обновить add-on и у вас тоже такая проблема проявится.

Самый последний стоит, версия 1.17.1-4

Игорь, добрый день, спасибо за статью!


У меня z2m установлен в openwrt на перепрошитом Xiaomi Gateway


У меня проблема с работой простой кнопки - она подключается, но при нажатии ничего не происходит.


Можно ли как то в z2m посмотреть - идут ли какие либо данные при нажатии на кнопку?


Вернуться назад
Вернуться назад