Интегрируем брелки от откатных ворот Nice Flor-S с HomeAssistant

И опять про умный дом. На этот раз расскажу про то, как интегрировать брелки от откатных ворот Nice Flor-S с HomeAssistant, используя подручные средства, а именно EspHome, RTL-SDR и платку с релешками с Aliexpress.

Стремное вышло решение, но ведь работает!

Разбираем пациента

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

Внутри мы видим радио на 433 мегагерца вместе с Motorola HC08 микроконтроллером. Прям сразу вспоминаются лабы по ассеблеру для этой дряни в мои институтские годы.

План A. Где мой RTL-SDR?

Начал я с того, что воткнул RTL-SDR брелок, запустил gqrx и увидел что передача и впрямь происходит на 433Mhz и красиво отрисоввывается на “водопаде”. Теперь это надо как-то декодировать, так?

The signal looks like drifting a little bit, but it’s there

План таков: декодируем протокол и пробуем сэмулировать на 433Mhz беспроводных GPIO с нашей любимой радиоэлектронной помойки под названием Aliexress.

433 Mhz USB-GPIO. Широко известны за то,что при помощи них можно эмулировать множество разных пультиков

Следующим этапом я запустил rtl-433 и увидел… Ничегошеньки. Собственно, программа определила что что-то там на этой частоте происходил, но декодера протокола на nice flor-s у нее не было.

Пришлось загуглить, и я откопал частичную документацию протокола nice flor-s. А еще узнал, что у них есть пара уязвимостей… Упсь 😉

Протокол документирован не полностью, но статья все равно описывает достаточно много подробностей для быстрого старта. По ней мне удалось быстренько накидать простой плагинчик для rtl-433 который смог декодировать номера кнопок пульта, которые я нажимал. С некоторой удачей, можно было также декодировать таймкод (т.е. время удержания кнопки). Но что дальше? Для написания полного эмулятора брелка данных не хватало.

RTL433 декодирует пакетики Nice Flor-S. Пока еще далеко не полностью.

Проблема была в том, что протокол был документирован только частично, и в имеющейся документации не было самого важного: алгоритма по которому получается роллинг-код, которым шифруется серийный номер. По сути, кроме номера кнопки и времени удержания я больше не мог ничего получить. Загадки, загадки, загадки… Можно было попробовать сдампить прошивку HC08. Но что-то мне подсказывало, что защита от ридбэка там была включена.

Была мысль собрать полный дамп всех возможных значений счетчика через rtl-sdr, а дальше попытаться проанализировать его. Но это займет очень много времени и нет гарантии успеха. Было жалко почему-то отказываться от этого квеста, но он требовал слишком много ценного ресурса, которого у меня совершенно не было: времени.

План Б. Давайте тупо возьмем несколько релешек, чтобы они жали на кнопки!

Я аккуратно прозвонил пультик мультиметром. Его питала маленькая 12V баттарейка. Линия +12V от батарейки заходила напрямую на 4 кнопки, которые замыкали питание. Когда ни одна кнопка не нажата – схема полностью обесточена. По сути можно туда посадить транзистор/мосфет и замыкать им. Но это значило, что придется либо лепить жуткие сопли, либо разводить плату, что потребует опять много ценного ресурса: ‘времени’. Потому я сделал проще, открыл Aliexpress и заказал несколько 4-канальных модулей с реле и esp8266. Некая LC-tech компания выпускает их в 12в и 5в вариантах. После заказа 12в варианта пришлось отложить все и подождать, пока до меня доедет посылка.

Разбираемся с 4х-канальными модулями от LC-tech

Вот один из них
А вот линейные регуляторы напряжения, которые обычно закрывает esp8266

Мои впечатления от инженерных решений были смешанными. С одной стороны на плате была честная опторазвязка, а прорезь на плате около одного из контактов должно было увеличить сопротивление на случай, если мы будем коммутировать высокое напряжение. Но с другой стороны, схема питания была сделана дебильно. Возможно, уже приходилось читать у меня в блоге про линейный стабилизатор в миллиметре от термодатчика на 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 кнопки, то четвертый реле я подцепил к разъему и вывел на корпус.

Подключение просто до безобразия
Конструкция в собранном виде

Материалы

Как обычно материалы от этой заметки можно скачать:

Добавить комментарий

Этот сайт использует Akismet для борьбы со спамом. Узнайте как обрабатываются ваши данные комментариев.