Дисклеймер. В проекте есть работа с сетевым напряжением 220 В и с радиопередачей. Первое может убить, второе — только ваши нервы. Всё, что касается сети, делайте при выключенном автомате в щитке, а не просто при выключенном выключателе. Если не уверены — зовите электрика. А перехватывать и воспроизводить радиосигналы допустимо только для своих собственных устройств.
Исходный сетап
Новый дом, типовые настенные выключатели, которые управляют фазой, приходящей на потолок, и, как следствие, светом там.
Со временем была куплена недорогая люстра на AliExpress, которая тем не менее дорога нам как память нравится. (На самом деле две люстры.) Как и большинство люстр с Алика, поддерживает множество режимов работы, но с пульта.
В результате простой установки получается управление светом из двух мест. Либо настенным переключателем просто включить/выключить, либо, если хочется расширенных режимов, сначала включить настенным переключателем, а потом управлять с пульта.
В идеале хотелось бы объединить оба устройства управления в одно. А ещё — интегрировать всё это в существующую систему умного дома. В моём случае это Home Assistant (HA). Как минимум для того, чтобы удалённо видеть, что забыли выключить свет, и иметь возможность выключить его (когда все уехали куда-нибудь). Ну или, например, для управления светом голосовым помощником — хоть Алисой, хоть ещё чем-то.
Несмотря на кажущуюся простоту, задача так просто не решается. Я подступался к ней дважды. И успеха удалось добиться только на второй раз.
Проблем, по сути, две:
-
Основная — как передать управляющий сигнал на лампу.
-
Вспомогательная, технически не сложная, но выматывающая из-за многообразия выбора, — выбор настенного переключателя с достаточным количеством кнопок или жестов. Чтобы можно было не просто включить/выключить, а ещё включить дневной или ночной режим, изменить температуру света (хотя кто её меняет в реальной жизни?? Но ведь есть же такая возможность! А вдруг когда-то понадобится), затемнять или добавлять яркость. Всё то, что есть на пульте.
Общий подход
Собрать устройство которое с одной стороны сможет управлять люстрой (или двумя) вместо пульта и настенного выключателя. А с другой будет интегрированно в умный дом. Настенный переключатель меняется на умный. Поддерживающий все варианты, которые нам нужны.
Обычно сердце такого устройства — процессор ESP32 в любой его модификации. У него уже есть WiFi, и он замечательно дружит с HA через ESPHome. То есть ESP с одной стороны интегрирован с умным домом, а с другой — управляет нашей люстрой.
Но для того, чтобы собрать такое устройство нужно для начала разобраться как пульт управляет люстрами. Для этого:
-
В зависимости от типа сигнала на ESP32 собирается приёмник, который перехватывает сигнал пульта.
-
Потом ИИ (ну куда же без него в наши дни 😉 ) анализирует перехваченное и помогает разобраться с протоколом.
-
А дальше дело техники — на том же ESP32 собираем передатчик, который шлёт такие же сигналы на люстру. Уже без пульта.
На самом деле всё проще, чем кажется. Основная сложность — во «вломе» сигнала.
Часть 1. Что за пульт?
Для начала нужно понять, какого типа у меня пульт, и убедиться, что совершенно случайно он не поддерживает уже реализованный стандарт — с открытым API и готовым приложением. Тогда интеграция свелась бы к паре кликов. К сожалению, не повезло. Поэтому начинаем разбираться.
Пульт у меня выглядит обычно, как примерно все дешёвые пульты с Алиэкспресса. Кнопки, светодиод, который загорается при нажатии. Самый обычный пульт с Алика. Ничего не предвещало.
Пульты для передачи сигнала могут использовать инфракрасный диапазон (IR), Bluetooth или радио (2,4 ГГц и не только). Для каждого типа — своё решение. Начинаем отсекать лишнее.
Инфракрасный? Нет. Проверяется элементарно: направьте пульт в сторону от люстры или закройте рукой светодиод. Если пульт всё равно работает — значит, это не ИК, которому нужна прямая видимость.
Bluetooth? Тут я чуть не наступил на грабли. Я был уверен, что это не Bluetooth, ведь пульт нигде не нужно «сопрягать» с телефоном, он не появляется в списке устройств. Но есть подвох. Многие такие китайские люстры используют BLE очень необычно: пульт не подключается к люстре, а просто «выкрикивает» в эфир короткие BLE-пакеты, а люстра их слушает. Никакого сопряжения нет, и снаружи такой пульт выглядит как обычный радиопульт.
Так что прежде чем лезть внутрь, стоит потратить пять минут и проверить гипотезу «это BLE» приложениями вроде LampSmart Pro, FanLamp Pro, ApplianceSmart. Если повезёт и люстра привяжется — считайте, что выиграли: для BLE-люстр есть готовые интеграции, и отдельный радиомодуль не нужен, хватит самого ESP32.
Мне не повезло: через LampSmart Pro люстра не привязалась. Значит, не BLE.
Вскрываем пульт
Остаётся радио. Чтобы понять, какое именно, я открыл пульт и посмотрел, что написано на плате.
Show Image Шёлкография «格美智能电源» и маркировка GM-2.4G. Уже теплее.
На плате нашлась надпись GM-2.4G и наименование производителя драйверов. Плюс изогнутая дорожка-антенна в углу — характерный признак диапазона 2,4 ГГц (для 433 МГц антенна была бы заметно длиннее). То есть это радио 2,4 ГГц.
Но тут есть нюанс. 2,4 ГГц бывает двух сортов: «честный» BLE (который мы уже отмели) и проприетарные протоколы на чипах семейства nRF24 / XN297 и их клонах. Какой именно — по этой надписи не понять, решает маркировка главного чипа. А на моём чипе маркировки не было вовсе — обычное дело для дешёвых пультов.
Кварц на 16 МГц косвенно намекал на семейство XN297/nRF24. Так что я решил: покупаем модуль nRF24L01+ для приёма и передачи радиосигнала, конденсатор, и идём «вынюхивать» (sniffing) протокол.
Часть 2. Собираем «вынюхиватель»
Идея такая: ESP32 с модулем nRF24L01+ переводится в особый режим и ловит из эфира пакеты, которые пульт шлёт на люстру.
Нам понадобится:
-
ESP32 (у меня был ESP32-S3-DevKitC-1 с прошлого проекта);
-
модуль nRF24L01+ с антенной на плате (лучше взять 2 штуки — среди дешёвых модулей много клонов, которые не поддерживают нужный «трюк», а то и 250 кбит/с не тянут);
-
электролитический конденсатор 10–100 мкФ — ставится прямо на выводы питания модуля, без него nRF24 работает нестабильно;
-
провода.
Все достаточно быстро собирается на макетной плате. Питание и управление (прошивка) через USB разъем от компьютера.
Важные мелочи, на которых легко споткнуться:
-
модуль питается только от 3,3 В, от 5 В он умрёт;
-
конденсатор нужен обязательно, и чем ближе к выводам модуля, тем лучше;
-
на модуле есть обведённый на плате вывод — это вывод 1 (GND), по нему удобно ориентироваться в распиновке.
Как работает «вынюхивание» 2,4 ГГц
Тут самое интересное. На 433 МГц сигнал можно записать «как есть» любым дешёвым приёмником. А на 2,4 ГГц чип примет пакет, только если заранее знает четыре вещи: канал, скорость, адрес (синхрослово) и параметры CRC. Без адреса приёмник просто глух.
Хитрость в так называемом «промискуитетном» режиме: nRF24 настраивают на короткий 2-байтный адрес, совпадающий с преамбулой любого пакета, отключают CRC — и он начинает ловить всё подряд, включая шум. Среди мусора попадаются повторяющиеся последовательности. Это и есть настоящие пакеты пульта.
Процесс по шагам:
-
Сканируем каналы. Нажимаем кнопку пульта и смотрим, на каких каналах появляется активность выше фона. Пульт обычно работает на нескольких фиксированных каналах.
-
Ловим пакеты на найденном канале, перебирая скорости и варианты «адреса-приманки».
-
Собираем материал: нажимаем каждую кнопку по многу раз, помечая в логе, что именно нажимали.
Часть 3. Расшифровка
Вот тут началось самое весёлое. Первые пойманные пакеты выглядели как каша: правильные байты, но «съехавшие» по битам, с разным сдвигом в каждом пакете. Это оказалось верным признаком чипа в стиле XN297 — он перемешивает (скремблирует) биты, и обычный nRF24 ловит пакет с произвольным смещением.
Дальше несколько вечеров ушло на то, чтобы:
-
понять, что скорость не 1 Мбит/с, а 250 кбит/с (на другой скорости биты «размазывались»);
-
применить правильную модель дескремблирования XN297;
-
проверять каждый декодированный кадр по CRC — совпала контрольная сумма, значит декод верный и выровненный.
Когда CRC начал сходиться, протокол раскрылся. Привожу его целиком — вдруг кому-то с такой же люстрой это сэкономит недели.
|
Параметр |
Значение |
|---|---|
|
Чип / скорость |
XN297L-подобный, 250 кбит/с, скремблирование вкл. |
|
Адрес |
5 байт, |
|
Полезная нагрузка |
8 байт + стандартный CRC16 XN297 |
|
Формат |
|
-
Фаза:
00для первой серии пакетов,01для повторной (во второй к байту команды добавляется0x40). -
Команды: ВКЛ
05, ВЫКЛ09, НОЧЬ10, ДЕНЬ11, ТЕМПЕРАТУРА07, ЯРЧЕ02, ТЕМНЕЕ03. -
Контрольная сумма: сумма байтов 0–6 по модулю 256.
-
Каждое нажатие — это серия примерно из 10 пакетов, с интервалом ~13 мс, которая «пробегает» по нескольким каналам.
Важная деталь про яркость и температуру: они относительные. Пульт не говорит «яркость 60 %», он говорит «на шаг ярче» или «следующая температура по кругу». Это потом повлияет на то, как всё выглядит в умном доме.
На самом деле перехватывал пакеты и анализировал их ИИ. Я тут работал только умным нажимателем кнопок на пульте люстры. ИИ мне писал, какие кнопки нажимать и сколько раз. Примерно так: к моему компьютеру через USB подключен собранный блочок. Через него же он и питается. На компе стоит Visual Studio Code. Расширение Claude Code с платной подпиской. А также расширение PlatformIO. Чтобы можно было работать с ESP. Прошивать её, подключаться к терминалу и так далее. Для желающих код прошивки как в режиме анализатора, так и в режиме готового управляющего устройства доступен в моем репозитории на гитхабе.
Часть 4. Собираем передатчик
Дальше, как я наивно написал в черновике, «дело техники». На том же ESP32 с nRF24 поднимается передатчик, который шлёт такие же пакеты, но по команде из Home Assistant. Код оформляется как внешний компонент ESPHome, и в HA каждая люстра появляется как обычная лампа плюс набор кнопок.
Пара вопросов, которые пришлось решить по дороге:
-
Счётчик. В пакете есть счётчик. Если люстра его проверяет (защита от повтора), придётся вести его в ESP и хранить между перезагрузками. У меня первая люстра счётчик игнорирует — повезло.
-
Надёжность. Радио одностороннее, подтверждений нет. Поэтому, как и родной пульт, передатчик шлёт каждую команду пачкой с повторами. Опытным путём я остановился на 60 кадрах в серии — на этом в пределах комнаты всё стало работать стабильно.

Тот самый передатчик. Выглядит скромно, но именно он управляет люстрой.
Несколько слов по поводу собранного передатчика.
Где его разместить? Как запитать? Ну и собственно их чего собрать?
Разместить решено было в корпусе одной из люстр. Удобно, глаза не мозолит. Есть постояное питание. Но есть пара нюансов. Корпус люстры металлический (латунный). Он экранирует электромагнитные волны. Из-за него качество управления несколько ухудшилось. Пришлось увеличить число пакетов в управляющем блоке (от 30 до 60). На счастье в корпусе люстры, по бокам были отверстия для вентиляции. Рядом с ними и постарался разместить антену устройства. Второй нюанс питание. В корпусе люстры есть или переменные 220В или постоянные… те же около 200В. Я не знаю зачем китайцы используют такие блоки питания для LED люстр. Но у моей оказался именно такой. По моему от 160 до 260 В постоянного напряжения. Запитать таким блок управления не получится. На счастье есть простое и дешевое решение — Hi-Link HLK-PM01.
Плата на которой все это паялось готовая, односторонняя. Для пущей безопасности отделил высоковольтную часть от низковольтной спиливанием пару дорожек.
И вот он, момент истины: нажимаешь в приложении HA на телефоне — люстра загорается. Первая люстра полностью подчинилась: включение/выключение, ночной и дневной режимы, температура, яркость. Всё то, что было на пульте, теперь в умном доме.
Часть 5. Настенный выключатель
Пока ехали детали, я занялся второй, «простой» задачей — настенным управлением. Простой она только кажется.
Ключевая мысль: раз люстры теперь слушают радио, питание на них должно быть всегда. Значит, настенный выключатель больше не должен рвать фазу. Его задача — не коммутировать нагрузку, а слать события в Home Assistant.
Я перебрал кучу вариантов (сенсорные панели NSPanel, клавишные выключатели Aqara, отдельные платы-реле) и в итоге взял Zigbee-диммер Sonoff Orb-ZBDIM. Старый выключатель при этом соединяется напрямую через клеммник Wago, чтобы фаза на люстры шла постоянно, а диммер работает только как источник событий.
Тут выяснилась неприятная особенность именно этого диммера: он не шлёт «нажатия» как таковые. Home Assistant видит только изменение его собственного состояния (вкл/выкл) и яркости. Пришлось изворачиваться в автоматизациях, опираясь на эти два сигнала:
-
одиночное нажатие центральной кнопки — включить/выключить выбранную люстру;
-
двойное нажатие — сменить выбранную люстру (их две, храню выбор в хелпере
input_select); -
+ / − — ярче/темнее у выбранной люстры;
-
двойное + / двойное − — дневной/ночной режим.
Получилось немного «на спичках и изоленте», но работает: одна точка управления на стене плюс телефон и голос. А «выбранную люстру» видно в хелпере.
Выбранный переключатель — пробный камень. Попробуем пожить с ним, а там посмотрим, как понравится.
Из выявленных недостатков.
Работа через HA с задержкой в 1-2 секунды. Это вам не обычный переключатель, где вы просто «вырубаете» фазу. Двойные нажатия, из-за особенностей выбранного переключателя, нужно делать медленно, осмысленно, примерно как из автомата стрелять короткими очередями. Быстрый double click «не прокатит». 🙂
Часть 6. Счастливый конец? Почти
А теперь обещанная грустная часть. Помните, я всё время писал «люстра (или две)»?
Первая люстра работает идеально. Вторая — нет.
И вот что обидно: по радио с неё удалось снять ровно тот же протокол, те же команды, тот же ID. Родные пульты ею управляют прекрасно. А мой передатчик — нет. При том что первой, точно такой же люстрой, он управляет без проблем.
Я перебрал всё, что можно поменять в прошивке, и каждый раз первая люстра служила контролем — на том же сигнале она послушно мигала:
-
тот же ID — не помогло;
-
все каналы 0–125 — не помогло;
-
все значения счётчика 0–255 — не помогло;
-
точная форма серии пакетов, как у пульта, — не помогло;
-
максимальная и минимальная мощность передачи — не помогло.
Разгадка, похоже, в железе. В какой-то момент у второй люстры я менял драйвер (он же радиоприёмник), потому что из-за моей же ошибки в проводке спалил старый. Новый драйвер — другой ревизии. И его приёмник, видимо, принимает сигнал настоящего чипа XN297L, но не принимает имитацию, которую выдаёт nRF24. Скорее всего, дело в небольшом уходе частоты — меньше 1 МГц, а nRF24 мельче 1 МГц настраиваться не умеет, так что и проверить-то это им нельзя.
Так что у истории пока открытый финал. Пока думаю как поступить. Из вариантов, которые мне нравится только
Взять модуль на чипе CC2500, который умеет точно подстраивать частоту, и попробовать попасть в приёмник второй люстры. Красивое решение, но нужен новый драйвер.
Пока вторая люстра управляется по старинке, с пульта. А первая живёт в умном доме и радует.
Вместо вывода
Задача, которая на старте выглядела как «ну это же просто, перехватил сигнал да повторил», обернулась несколькими вечерами реверс-инжиниринга, одним спаленным драйвером, стопкой логов и очень предметным знакомством с протоколом XN297.
Но результат того стоил. Любимая люстра тёщи теперь часть умного дома, управляется из одного места, с телефона и голосом, со всеми своими режимами. И даже если вторая пока сопротивляется — это уже вопрос упорства, а не принципиальной невозможности. Родной пульт ею управляет, значит, и мы сможем. Рано или поздно 🙂
ссылка на оригинал статьи https://habr.com/ru/articles/1095488/