Wishlist

Итак, MVP моей ZigBee-поделки на ESP32 готов, и поделка введена в эксплуатацию. Потому, пришло время отчитаться.

Какова цель поделки?

Время близилось к весне, и жена попросила: "сделай мне подсветку для рассады".
В принципе, отрезать кусок диодной ленты, припаять к ней разъём для подключения блока питания, который вставить в розетку с таймером - дело на 10 минут. Но никакого дополнительного опыта эта задача мне не принесет, поэтому пришлось её дополнить дополнительными требованиями:

  • регулировка яркости
  • с датчиком температуры, влажности, давления (BME280)
  • с влагозащитным датчиком температуры (DS18B20)
  • с датчиком влажности почвы
  • управление с инфракрасного пульта
  • управлением и сбор данных с датчиков через систему Умного Дома по протоколу ZigBee
  • управление через Telegram
  • экспорт метрик с датчиков для последующего анализа в Grafana
  • применимость поделки в иных задачах
    У меня есть пару мест где еще нужно управлять диодной лентой, но нет необходимости во всех датчика. А так же где нет надобности управлять лентой, но нужны датчики.

У меня уже был опыт создания одного ZigBee прототипа на ESP32-C6-Devkit с двумя датчиками температуры DS18B20. На тот момент для меня было досадной неожиданностью то, что SDK ESP-IDF представляет C-интерфейс, и в коде моего проекты вышла смесь C и C++. С точки зрения эстетики и сопровождаемости - вышло так себе. И в данном проекте было решено отказаться от C++, и использовать только C.

Получилось как-то так...

  • Устройство выступает в роли Router. Т.е. расширяет зону действия ZigBee сети.
  • Управлять диодной лентой можно с ИК-пульта, ZigBee выключателя, из дашборда Zigbee2Mqtt, через Telegram бота, по расписанию системы умного дома, по модулю присутствия системы умного дома.
  • Состояние (вкл/выкл) и яркость ленты сохраняется в NVRAM. Т.е. после восстановления питания - останется в том состоянии, которое было до отключения.
  • ZigBee выключатель можно забиндить. Т.е. в случае недоступности координатора и самой системы Умного Дома - можно будет управлять напрямую. Правда, как показал эксперимент, после выключения координатора, выключатель может не работать (не находить прямой маршрут) в течение часа.
  • Из Telegram бота можно посмотреть текущие данные датчиков, включить/выключить ленту, установить яркость, а так же установить режим, который не может быть переопределен с другого модуля управления (расписание, датчик присутствия и тп.)
  • В расписании, помимо указания конкретного времени (и опционально даты), можно использовать синтаксис вроде "sunrise+10" или "sunset-10", которое устанавливает время в минутах относительно восхода/заката для текущего (или последующего) дня, для данных координат.
  • К модулю присутствия может быть подключено несколько датчиков движения/присутствия. При обнаружении движения на любом датчике - лампа включается на определенное время с указанной яркостью. При "потере движения" одним из датчиков - ничего не происходит.
    Если же напрямую завязать несколько датчиков движения к свету, то при "потере движения" на одном из датчиков - свет будет отключаться, что не удобно.
  • Один из кейсов использования следующий:
    Включаем подсветку на полную яркость с 18:00 до 22:00.
    В 22:00 активируется модуль присутствия, и при обнаружении движения, если подсветка не включена - будет её включать на 10 минут на минимальной яркости. Т.е. режим дополнительного ночника для ребенка, если ночью пойдет в туалет.

Что дальше?

  • Смоделировать и заказать изготовление PCB-версии
  • В первой PCB-версии буду использовать ESP32 Devkit, но в последующей хочу попробовать чисто модуль
  • Сделать корпус
  • Сделать клиентское ZigBee устройство (с кнопками, и возможно дисплеем), и попробовать групповой биндинг, и сцены.

Интересные моменты, которые всплыли в ходе реализации

  • Важнейший документ для разработки ZigBee устройства: ZigBee Cluster Library Specification. Заказать его или другие полезные спецификации можно тут, или найти прямые ссылку в гугле.
  • В упомянутой выше Cluster Library Specification описано огромное количество всевозможных кластеров. Однако, SDK ESP-IDF на данный момент поддерживает всего 40 стандартных кластеров. Актуальное количество можно грепнуть по CLUSTER_FN_ENTRY в файле czl.c. И судя по истории коммитов, разработчики не спешат их добавлять. И самому не добавишь - публичны только хидеры, а не исходники. 😢
    И кастомный кластер, используя ID стандартного кластера, не создашь. Получаешь ошибку:
    E (1609) ESP_ZIGBEE_CLUSTER: esp_zb_cluster_list_check(74): Custom cluster id is not within specified range!
    ESP_ERROR_CHECK failed: esp_err_t 0x102 (ESP_ERR_INVALID_ARG) at 0x4200df86
    Т.е., ты покупаешь их модуль, а полноценное ZigBee устройство, соответсвующее спецификации, без ухищрений, используя их SDK сделать не можешь! 🤬
    Так, например, SDK не поддерживает кластер Soil Moisture (влажность почвы). Так что, мне пришлось использовать кластер Humidity на отдельном эндпоинте. Для данного проекта вариант, конечно, работоспособный. Но совсем не эстетичный!
  • Одной из проблем было - невозможность произвести сопряжение с сетью, когда находишься в другой комнате от координатора. Что бы выполнить сопряжение, нужно было подойти на расстояние меньше метра к координатору. При этом в логе писало: "Network steering was not successful (status: ESP_FAIL)", и, если включить debug логирование, список отсканированных устройств типа роутер или координатор с уровнем их сигнала. Так вот, этот уровень сигнала зачастую был 0. Иногда прыгал до 20-30. А минимальный уровень, при котором ESP32 произведет сопряжение по умолчанию равен 32 (это значение можно получить вызовом esp_zb_secur_network_min_join_lqi_get()).
    Я не знаю почему на этапе сопряжения, при сканировании, определяет такой низкий уровень сигнала. При этом, проблема воспроизводится на обоих моих устройствах, в разных сетях (квартира и деревня). Но проблема решается вызовом esp_zb_secur_network_min_join_lqi_set(0);. После этого - сопряжение происходит моментально вдали от координатора.
    Я пробовал восстанавливать Min Join LQI в 32, после сопряжения, но у меня есть подозрения, что он так же влияет на подключение конечных устройств к тебе, т.к. при установке значение в 0 - чаще видел подключенный выключатель прямо к своему устройству на карте сети.

Стек технологий проекта

  • Разработка принципиальной схемы, ESP32-C6-Devkit, ZigBee, ESP-IDF, C++
  • Довольно большим куском вышла доработка и рефакторинг своей ядра "умного дома": Golang, PostgreSQL
  • Telegram Bot Api, Telegram WebApps, gRPC (обмен данными между Telegram ботом в облаке и "умным домом" в квартире), Prometheus, Grafana