Как я вызволил увлажнитель воздуха из экосистемы Xiaomi и подключил его к домашней сети

Однажды я заметил, что моя кошка часто бьется током. Причина этому — сухой воздух, поэтому приобрел увлажнитель от Xiaomi. Но сбои их серверов портили общее впечатление о покупке. И вот у меня возник вопрос: почему дом — мой, а серверы — чужие? Так я и познакомился с Home Assistant, MQTT, Z2M и селфхостингом.

<i>Знакомьтесь, Амидала (в честь персонажа из «Звездных войн»).</i>
Знакомьтесь, Амидала (в честь персонажа из «Звездных войн»).

О нюансах

Если zigbee-устройства без проблем работают локально благодаря zigbee2mqtt (Z2M), то с увлажнителем возникли сложности. Казалось бы, у Xiaomi есть проприетарный протокол miIO для управления устройствами в локальной сети. Значит ли это, что можно обойтись без чужих серверов?

Home Assistant — это платформа с открытым исходным кодом для управления умным домом, создания сценариев автоматизации и т. д. Она позволяет интегрировать устройства разных производителей с разными типами подключения и не быть привязанным к одной экосисте.

Home Assistant (далее — HA) действительно умеет работать с протоколом miIO, но есть несколько нюансов.

  • Для управления нужен токен. Чтобы его получить, следует зарегистрировать устройство в приложении. Нам же не нужны посредники, правда?
  • Даже если получить токен и добавить увлажнитель в HA, то... все заработает. Победа? Увы, но работать все будет только пока есть интернет. Хоть мы и управляем устройством локально, выгоды от этого немного, ведь без облаков мы получим тыкву через несколько минут.

Есть решение

А вдруг нашлись умельцы, разобрались, написали прошивку и выложили в открытый доступ? После недолгих поисков я нашел нужный репозиторий, кодом которого мы сегодня и воспользуемся.

Альтернативный сценарий — использование ESPHome и написание несложных yaml-файлов. Вероятно, я займусь этим в будущем, когда влажность дома перестанет проседать ниже 50%.

Подготовка

На самом деле, указанный выше репозиторий подходит только для устройств, выпущенных в первые годы производства. После того как производитель решил поменять протокол, по которому плата общалась с железом, появилось несколько форков (подробнее можете почитать в issue от декабря 2022 года).

Я буду использовать форк другого форка, так как именно эта версия заработала c HA без написания лишних yaml-файлов для подписки на mqtt-топики. К слову, имя автора наталкивает на мысли о его происхождении. Быть может, он читает эту статью?

Итак, нам понадобятся:

  • 3.3v USB TTL UART — адаптер для прошивки впаянной в плату микросхемы ESP8266,
  • несколько проводов разных цветов радуги,
  • паяльник, отвертка,
  • прямые руки (хотя я обошелся и без них).
Автор лишь делится своим опытом и не несет ответственности за манипуляции с техникой. Стоит помнить, что гарантия производителя может перестать действовать после внесения некоторых изменений. Однако представленная реализация достаточно проста и не предполагает особых вторжений в аппаратную часть.

Железо

Снимаем нижнюю крышку увлажнителя Xiaomi Deerma Air Humidifier 5L (ZNJSQ01DEM):

Как я вызволил увлажнитель воздуха из экосистемы Xiaomi и подключил его к домашней сети

Нас интересует серая платка у стенки корпуса, к которой идет шлейф из белых проводов. Достаем и видим, что она действительно работает на популярной ESP8266:

Как я вызволил увлажнитель воздуха из экосистемы Xiaomi и подключил его к домашней сети

Цепляем GND, VCC 3.3v (это важно!), TX и RX к программатору (RX в TX и наоборот). GPIO 0 тянем к земле (GND), он нужен для загрузки микроконтроллера в режим загрузки по UART.

<i>Адаптер для прошивки впаянной в плату микросхемы.</i>
Адаптер для прошивки впаянной в плату микросхемы.

Для прошивки и запуска понадобится дополнительное питание схемы, так как мощности программатора, скорее всего, не хватит. Я особо не заморачивался — подключил плату во включенный увлажнитель. Выглядело это так:

Как я вызволил увлажнитель воздуха из экосистемы Xiaomi и подключил его к домашней сети

Со стороны железа у нас все готово, перейдем к софту.

Софт

Сперва ставим Arduino IDE любым удобным способом. Подойдет как привычная первая версия, так и обновленная вторая. Следом необходимо добавить поддержку ESP8266. Открываем IDE, переходим в меню File ⟶ Preferences, вставляем ссылку https://arduino.esp8266.com/stable/package_esp8266com_index.json в поле Additional Boards Manager URLs и нажимаем OK. С подробным описанием процесса вы можете ознакомиться в инструкции.

Как я вызволил увлажнитель воздуха из экосистемы Xiaomi и подключил его к домашней сети

После этого можем скачать необходимые пакеты в Tools ⟶ Board ⟶ Board Manager:

Как я вызволил увлажнитель воздуха из экосистемы Xiaomi и подключил его к домашней сети

Наконец, выбираем нашего красавца Generic ESP8266 Module в том же меню.

На данном этапе мы можем «послушать» UART. Подключаем программатор к ПК (GPIO 0 нужно отцепить от земли), выбираем его в Tools ⟶ Port, открываем консоль Serial Monitor в правом верхнем углу.

Если все получилось, мы должны увидеть сообщения о событиях (снятие крышки, включение увлажнителя и т. д.):

properties_changed 2 1 true properties_changed 2 1 false properties_changed 7 1 false

Если же в консоли что-то другое, быть может, ваш увлажнитель из первых ревизий, либо нужно «поиграться» со скоростью передачи данных.

Скачиваем необходимые пакеты в Sketch ⟶ Include Library ⟶ Manage Libraries:

  • ArduinoOTA 1.1.0 — для получения обновлений по воздуху,
  • ArduinoJSON 7.0.3,
  • PubSubClient 2.8.0 — MQTT клиент,
  • WiFiManager 2.0.17 (если вы используете код из оригинального репозитория — 0.16.0),
  • Uptime Library 1.0.0 (если используете форк от yobushka).

Клонируем нужный репозиторий и открываем в IDE. Теперь мы готовы прошивать.

git clone https://github.com/yobushka/esp8266-deerma-humidifier cd esp8266-deerma-humidifier/src/esp8266-deerma-humidifier arduino esp8266-deerma-humidifier.ino

Пробуем собрать проект, нажав на галочку в левом верхнем углу. Ждем некоторое время, и, если все прошло успешно, получаем информацию о скомпилированной прошивке:

. Variables and constants in RAM (global, static), used 50420 / 80192 bytes (62%) ║ SEGMENT BYTES DESCRIPTION ╠══ DATA 1648 initialized variables ╠══ RODATA 11100 constants ╚══ BSS 37672 zeroed variables . Instruction RAM (IRAM_ATTR, ICACHE_RAM_ATTR), used 62440 / 65536 bytes (95%) ║ SEGMENT BYTES DESCRIPTION ╠══ ICACHE 32768 reserved space for flash instruction cache ╚══ IRAM 29672 code in IRAM . Code in flash (default, ICACHE_FLASH_ATTR), used 385796 / 1048576 bytes (36%) ║ SEGMENT BYTES DESCRIPTION ╚══ IROM 385796 code in flash

По-хорошему, конечно же, стоит сделать дамп существующей прошивки, иначе пути обратно не будет (подробнее можете узнать из официальной документации esp8266). Ну а я нажимаю Upload (не забыв при этом подцепить упомянутый GPIO 0 к земле), заливая тем самым прошивку на контроллер, после чего он перезагружается:

esptool.py v3.0 Serial port /dev/ttyUSB0 Connecting.... Chip is ESP8266EX Features: WiFi Crystal is 26MHz MAC: b4:60:ed:4a:93:52 Uploading stub... Running stub... Stub running... Configuring flash size... Auto-detected Flash size: 2MB Flash params set to 0x0330 Compressed 432368 bytes to 304004... Writing at 0x00000000... (5 %) Writing at 0x00004000... (10 %) Writing at 0x00008000... (15 %) Writing at 0x0000c000... (21 %) Writing at 0x00010000... (26 %) Writing at 0x00014000... (31 %) Writing at 0x00018000... (36 %) Writing at 0x0001c000... (42 %) Writing at 0x00020000... (47 %) Writing at 0x00024000... (52 %) Writing at 0x00028000... (57 %) Writing at 0x0002c000... (63 %) Writing at 0x00030000... (68 %) Writing at 0x00034000... (73 %) Writing at 0x00038000... (78 %) Writing at 0x0003c000... (84 %) Writing at 0x00040000... (89 %) Writing at 0x00044000... (94 %) Writing at 0x00048000... (100 %) Wrote 432368 bytes (304004 compressed) at 0x00000000 in 26.5 seconds (effective 130.4 kbit/s)... Hash of data verified. Leaving... Hard resetting via RTS pin...

Отсоединяем GPIO от земли и перезагружаем увлажнитель.

Настройка

Через какое-то время после перезагрузки у вас должна появиться открытая Wi-Fi сеть «SETUPME». Подключаемся к ней и переходим к настройке:

Как я вызволил увлажнитель воздуха из экосистемы Xiaomi и подключил его к домашней сети

Обязательно вводим Hostname и Location, они нужны для формирования сообщений в MQTT брокер. Выбираем нашу домашнюю сеть, вводим пароль и нажимаем Submit. Увлажнитель подключается к нашей точке, получает ip-адрес, а мы переходим по нему в браузере.

Далее нужно подключить увлажнитель к MQTT брокеру (предполагается, что он есть). Я использую Mosquitto, де-факто стандарт в IoT. При желании этот брокер можно поставить даже на роутер, однако в HA для этого уже есть соответствующий аддон.

Как я вызволил увлажнитель воздуха из экосистемы Xiaomi и подключил его к домашней сети

Сохраняем настройки и ждем подключения. HA сам нашел увлажнитель и добавил его:

Как я вызволил увлажнитель воздуха из экосистемы Xiaomi и подключил его к домашней сети

Заключение

У нас получилось простое и бюджетное решение для «вызволения» увлажнителя воздуха из недоверенных серверов Xiaomi. Стоимость может варьироваться от небольшой до нулевой, ведь мы не интегрируем новые компоненты в систему, а перепрошиваем уже имеющуюся плату. В моем случае реализация вышла бесплатной, так как получилось одолжить паяльник и программатор у коллег.

Решение работает уже несколько месяцев, никаких проблем замечено не было. И теперь почти все, что происходит в моем доме, остается в моем доме. В дальнейшем я бы хотел вызволить из внешних облаков еще несколько устройств. Например, робот-пылесос при помощи программы Valetudo.

Возможно, вы сталкивались с Valetudo или подобными реализациями? Поделитесь опытом в комментариях, будет интересно узнать.

Читайте также:

1616
15 комментариев

Как будто статью с хабра прочитал

4

на хабре коментаторы более поехавшие)

на озоне можно купить готовый настроенный набор (с наценкой x4 по железу)

капец вы заморочились конечно) что не сделаешь ради своей котейки )

2

Это точно! Как-никак, член семьи)

Ахахах, да кожаный, постарался ты знатно, подумал кот. Ну заморочку конкретную ты придумал, но мне нравится, молодец!

1

Аж митинским радио-рынком запахло

1