И опять про умный дом. На этот раз расскажу про то, как интегрировать брелки от откатных ворот Nice Flor-S с HomeAssistant, используя подручные средства, а именно EspHome, RTL-SDR и платку с релешками с Aliexpress.
Разбираем пациента
Итак, откатные ворота штука удобная (когда дело не доходит до обслуживания, конечно). Они стояли у меня на даче уже очень и очень давно, еще до того, как HomeAssistant появился на свет, а я не поленился его развернуть. Потому по мере того, как я распробовал эту штуку, то и связать их вместе мне очень захотелось. Начал я, как водится, с того, что взял запасной пультик и разобрал его.
Внутри мы видим радио на 433 мегагерца вместе с Motorola HC08 микроконтроллером. Прям сразу вспоминаются лабы по ассеблеру для этой дряни в мои институтские годы.
План A. Где мой RTL-SDR?
Начал я с того, что воткнул RTL-SDR брелок, запустил gqrx и увидел что передача и впрямь происходит на 433Mhz и красиво отрисоввывается на «водопаде». Теперь это надо как-то декодировать, так?
План таков: декодируем протокол и пробуем сэмулировать на 433Mhz беспроводных GPIO с нашей любимой радиоэлектронной помойки под названием Aliexress.
Следующим этапом я запустил rtl-433 и увидел… Ничегошеньки. Собственно, программа определила что что-то там на этой частоте происходил, но декодера протокола на nice flor-s у нее не было.
Пришлось загуглить, и я откопал частичную документацию протокола nice flor-s. А еще узнал, что у них есть пара уязвимостей… Упсь 😉
Протокол документирован не полностью, но статья все равно описывает достаточно много подробностей для быстрого старта. По ней мне удалось быстренько накидать простой плагинчик для rtl-433 который смог декодировать номера кнопок пульта, которые я нажимал. С некоторой удачей, можно было также декодировать таймкод (т.е. время удержания кнопки). Но что дальше? Для написания полного эмулятора брелка данных не хватало.
Проблема была в том, что протокол был документирован только частично, и в имеющейся документации не было самого важного: алгоритма по которому получается роллинг-код, которым шифруется серийный номер. По сути, кроме номера кнопки и времени удержания я больше не мог ничего получить. Загадки, загадки, загадки… Можно было попробовать сдампить прошивку HC08. Но что-то мне подсказывало, что защита от ридбэка там была включена.
Была мысль собрать полный дамп всех возможных значений счетчика через rtl-sdr, а дальше попытаться проанализировать его. Но это займет очень много времени и нет гарантии успеха. Было жалко почему-то отказываться от этого квеста, но он требовал слишком много ценного ресурса, которого у меня совершенно не было: времени.
План Б. Давайте тупо возьмем несколько релешек, чтобы они жали на кнопки!
Я аккуратно прозвонил пультик мультиметром. Его питала маленькая 12V баттарейка. Линия +12V от батарейки заходила напрямую на 4 кнопки, которые замыкали питание. Когда ни одна кнопка не нажата — схема полностью обесточена. По сути можно туда посадить транзистор/мосфет и замыкать им. Но это значило, что придется либо лепить жуткие сопли, либо разводить плату, что потребует опять много ценного ресурса: ‘времени’. Потому я сделал проще, открыл Aliexpress и заказал несколько 4-канальных модулей с реле и esp8266. Некая LC-tech компания выпускает их в 12в и 5в вариантах. После заказа 12в варианта пришлось отложить все и подождать, пока до меня доедет посылка.
Разбираемся с 4х-канальными модулями от LC-tech
Мои впечатления от инженерных решений были смешанными. С одной стороны на плате была честная опторазвязка, а прорезь на плате около одного из контактов должно было увеличить сопротивление на случай, если мы будем коммутировать высокое напряжение. Но с другой стороны, схема питания была сделана дебильно. Возможно, уже приходилось читать у меня в блоге про линейный стабилизатор в миллиметре от термодатчика на esp-14 платах от diymore. Ну, тут та же фигня: Вход на 12 вольт, потом линейный преобразователь на 5 вольт, потом линейный преобразователь на 3.3 вольта. Энергоэффективность.
Если не использовать режим энергосбережения esp8266, то выходит тот еще кипятильник. К тому же винтовые колодки на 5mm — отвратное решение для крепления многожильных кабелей с 220 вольтами — кабель под действием времени и элекричества распушается и может коротнуть. Единственная защита от этого — залудить кабель.
Ну и самое любопытное на плате — это микроконтроллер Nuvoton n76e003at20. Я впервые напал на эту любопытную железку. ESP8266 подключается к ней по UART, а уже она заправляет 2 кнопками, тремя светодиодами и четырьмя реле. Судя по datasheet’у это еще один микроконтроллер на основе 8051 архитектуры. Возможно, я сделаю в скором времени еще один пост на тему, как его программировать, но пока буду использовать стоковую прошивку.
Родная прошивка ESP8266, как и многие китайцы подцепляется к какому-то ‘ai cloud’. Что это за хрень, я даже не стал разбираться, просто залил свою прошивку на основе esphome.
С ESPhome у нас есть два способа подключить реле на этой плате. Мы можем использовать компонент UART switch. Или написать свой кастомный компонент. Копипастить мне было лень, да и я заметил одну интересную особенность в протоколе.
Согласно документации, протокол обмена выглядит так. Эти последовательности надо послать по UART, чтобы включить/выключить разные реле.
Open relay 1:A0 01 01 A2
Close relay 1:A0 01 00 A1
Open relay 2:A0 02 01 A3
Close relay 2:A0 02 00 A2
Open relay 3:A0 03 01 A4
Close relay 3:A0 03 00 A3
Open relay 4:A0 04 01 A5
Close relay 4:A0 04 00 A4
Попробуем это переосмыслить
- Байт 1. A0 — начало пакета
- Byte 2. Номер реле (1-4)
- Byte 3. Желаемое состояние 0/1
- Byte 4. Контрольная сумма. Сумма первых трех байт
А это значит, что для управления этой махарайкой нам достаточно такого кода:
#include "esphome.h" using namespace esphome; class LCRelay : public Component, public UARTDevice, public switch_::Switch { public: int relayId; LCRelay(UARTComponent *parent, int relay): UARTDevice(parent) { relayId = relay; } void setup() override { } void write_state(bool state) override { uint8_t msg[4]; msg[0] = 0xA0; msg[1] = relayId; msg[2] = state; msg[3] = msg[0] + msg[1] + msg[2]; /* There are no ack/nack packets. Let's send the payload twice to be sure */ this->write_array(msg, sizeof(msg)); this->write_array(msg, sizeof(msg)); publish_state(state); } }; |
Теперь подцепим это в конфиг на yaml. Выйдет что-то подобное:
substitutions: devicename: "gatekeeper" esphome: name: $devicename platform: ESP8266 board: esp01_1m build_path: build/gatecontrol includes: - lcrelay.h uart: id: uart baud_rate: 115200 tx_pin: GPIO1 rx_pin: GPIO3 switch: - platform: custom lambda: |- auto r1 = new LCRelay(id(uart), 1); auto r2 = new LCRelay(id(uart), 2); auto r3 = new LCRelay(id(uart), 3); auto r4 = new LCRelay(id(uart), 4); App.register_component(r1); App.register_component(r2); App.register_component(r3); App.register_component(r4); return {r1, r2, r3, r4}; switches: - name: "${devicename} Relay 1" id: relay1 internal: true - name: "${devicename} Relay 2" id: relay2 internal: true - name: "${devicename} Relay 3" id: relay3 internal: true - name: "${devicename} Relay 4" id: relay4 internal: true |
Как легко заметить, я пометил все выключатели как internal. Так как мы будем имитировать нажатие кнопки, реле надо замкнуть на секунду и разомкнуть. В коде мы не можем воткнуть delay(1000), так как watchdog esp8266 прибьет наше приложение и перезагрузит все. Правильный способ с точки зрения философии esphome(Если, я конечно понял правильно идею) будет в задании этого в файле конфигурации. Для этого в секцию switch надо добавить по такому заклинанию на каждое реле, которое подключено к кнопке брелка.
- platform: template name: "${devicename} Main Gates" icon: mdi:gate lambda: |- if (id(relay1).state) { return true; } else { return false; } turn_on_action: - switch.turn_on: relay1 - delay: 1s - switch.turn_off: relay1 turn_off_action: switch.turn_off: relay1 |
Собираем все это хозяйство вместе
Как только прошивка задышала, я распечатал короб в который поместил модуль реле и подпаялся проводами к брелку. Так как я использовал только 3 кнопки, то четвертый реле я подцепил к разъему и вывел на корпус.
Материалы
Как обычно материалы от этой заметки можно скачать:
День добрый! Я в этой теме профан, но очень хочется спрятать брелки (2 шт.) внутри машины и вывести просто две кнопки. Ваша статья меня очень заинтересовала. Может быть Вы сможете мне помочь в решении такой задачи. Есть два брелка, один (не знаю системы) от шлагбаума и второй (NICE FLOR 2S) от ворот в гараже. Оба брелка работают от 12 вольтовой батарейки. Хочу установить их под торпедой, над пепельницей, вывести две кнопки и больше не париться на тему “а куда они делись, ведь только что были в руках?”. Вопрос в том нужно ли стабилизировать подаваемое от прикуривателя напряжение? Из предпологаемого места установки они не добивают до антен, можно ли подпаять к брелкам провода и вывести их в зону уверенного приема (рядом с зеркалом заднего вида). Заранее благодарен!
Только сейчас заметил комментарий! С Новым Годом! 😉
Я бы на всякий случай стабилизировал и фильтровал напряжение. Чем чище питание, тем лучше RF часть пашет. Мои брелки почему-то бьют очень и очень далеко, возможно дело в металле машины. Тут только эксперименты. Успехов.