Делаем секционные гаражные ворота более удобными

В данном топике решил описать пример автоматизации одной из типовых задач. Имеются автоматические секционные ворота (Came V900E), необходимо организовать управление ими через интернет и дополнительно кнопками. Все управление требуется связать в единую систему вдобавок обеспечить удобную индикацию состояния системы. Под катом вас ждет разработка законченного устройства (плата, корпус, провода), а также подход к разработке логики и программного обеспечения. В общем, все как вы любите, осторожно — много фото.
Все описанное применимо ко многим типам приводов, в частности все работает на воротах фирмы Hormann.

Краткое описание исходной ситуации.
Имеется подземный гараж с двумя воротами. Одни ворота располагаются вверху (при въезде на спуск), вторые ворота располагаются внизу (непосредственно, при въезде в сам гараж). Ворота оснащены электрическими приводами, управляются с радио брелоков. Чтобы было понятнее, приведу иллюстрацию:
Кнопки, изображенные на картинке, в исходной системе отсутствуют, но их хотелось бы иметь.
Недостатки исходного решения:
— ограниченная дальность работы брелоков (даже в доме не везде возможно нажать кнопку брелока и открыть/закрыть ворота)
— отсутствие обратной связи (открылись или закрылись ворота можно выяснить только визуальным контролем, что усугубляет первый недостаток)
— необходимость носить брелок (например при походе в магазин или еще куда-то, наличие связки ключей с брелоком может существенно ухудшить впечатление от похода)
— брелоки работают на частоте 433 МГц без обратной связи, данные передают в нешифрованном виде, что может привести к копированию кода брелока и неприятным последствиям
— даже находясь в гараже требуется применять брелок чтобы выйти на улицу и зайти обратно, а брелоки имеют тенденцию к потерям/поломкам, просадке батарейки и тп…
— потеря брелока на улице требует провести процедуру стирания всех брелоков и прописывания только существующих и дополнительного
— приглашение сторонних работников (например на ремонтные работы), требует выдачи им брелоков для доступа на территорию в отсутствии хозяев, что также не добавляет безопасности
Все эти недостатки по отдельности как-то решаются и без разработки своего решения, но либо дороги, либо создают нагромождения устройств, либо неудобны, либо требуют специфической эксплуатации.
Например, некоторые производители продают свои решения для управления воротами через интернет, но цена у таких решений весьма высока (особенно учитывая что в данном случае 2 независимых механизма ворот), они требуют установки своих приложений, завязаны на серверную инфраструктуру производителя ворот (а в наше время это тоже риски), имеют ряд ограничений (например, интерфейс уже сделан и его нельзя изменить). По брелокам без переменного кода — тоже есть решения, заменить на модули с переменным кодом и/или обратной связью. В качестве кнопок, например, можно использовать беспроводные выключатели — но останется проблема безопасности радио эфира. По обратной связи — можно конечно поставить какие-то датчики, не связанные с приводом ворот — но они опять потребуют какую-то инфраструктуру. Кнопки можно подключить напрямую к приводам ворот, но как показали тесты они чувствительны к времени нажатия и дребезгу контактов.
В итоге принято решение, сделать свое решение, максимально подходящее под конкретные условия. В качестве базы следует выбрать типовые компоненты, которые сравнительно легко поддаются замене и доступны на рынке.

Базовое описание решения
В качестве ядра системы решено использовать контроллер esp8266, который весьма бюджетен, имеет достаточную производительность, достаточное количество выводов, удобные среды разработки и встроенный интерфейс сетевого взаимодействия по WiFi. Большинство приводов ворот имеют встроенные кнопки для управления воротами, либо отдельные выводы для подключения устройств управления, изменение состояние происходит замыканием на короткий промежуток времени контактов, привод при этом меняет свое состояние (при закрытых воротах — начинается открывание, при открытых закрывание, при движении — происходит остановка привода. Для воздействия на эти контакты достаточно маломощного реле. Для отслеживания состояния ворот удобно использовать внешние герконы, которые весьма надежны, компактны и не требуют обслуживания. Наличие кнопок подключенных к контроллеру позволит на месте удобно управлять приводами. Наличие WiFi обеспечит связь нашего решения с внешним миром, интеграцию в инфраструктуру «умного дома» и поддержку нужного веб-интерфейса.
Устройство должно уметь работать с обоими приводами ворот, иметь малое энергопотребление.

Создание «железной» части устройства
В данном случае, нам потребуется контроллер (возьмем модуль esp-07), обвязка модуля согласно документации, два маломощных надежных реле (например HF49FD), подтягивающие резисторы датчиков и кнопок, питаться устройство будет от 5 Вольт постоянного тока, поэтому требуется понижающий преобразователь для питания контроллера от 3.3 Вольт, можно взять AMS1117. Для стабилизации питания установим электролитический и керамический конденсаторы. Для управления реле используем маломощные биполярные транзисторы 2N2222, управляющие выводы реле зашунтируем диодами M1. Принципиальная схема устройства выглядит таким образом:
R1, R2, R3 — подтягивающие резисторы, необходимы для корректной работы ESP-07
R4, R5, R9, R12 — подтягивают соответствующие выводы ESP-07 к питанию для корректной работы кнопок.
VR1(AMS1117) — линейный стабилизатор на 3.3 В
C1, C2 — электролитический и керамический конденсаторы для питания модуля
R6, HL3 — светодиодный сигнал наличия связи модуля по wifi
VT1, VT2 — биполярные транзисторы 2n2222, нужны для управления реле
R10, R11 — ограничивают ток управления транзисторами
R7, HL1 и R8, HL2 — для световой индикации состояния реле
S1, S2, S3, S4 — будущие кнопки: выключатели и герконы состояния ворот.

Разрабатываем нехитрую печатную плату, на которой предусмотрим все вышеописанное:
Платка универсальная, поэтому предусмотрены:
— 6 выводов питания 5 Вольт
— 8 выводов земли (-)
— 6 выводов питания питания 3.3 В
— 2 вывода модуля ESP-07: 4 и 5 задействованы в управлении реле
— выводы 13, 12, 14, 2 и аналоговый вывод подключены к общему разъему с возможностью подтяжки к питанию
— 0 вывод расположен между подтяжками к земле и к питанию, для обеспечения заданных подтяжек, в зависимости от режима (программирование, обычная работа)
— также на общий разъем выведены TX и RX для взаимодействия с внешним миром
— питание устройства и выводы реле подключены к винтовым клемникам
— добавлена индикация включения реле в виде светодиодов с токоограничительными резисторами
— шелкография платы позволяет легко ориентироваться в расположении контактов
— круглые отверстия позволяют легко производить фиксацию платы в корпусе
Печатная плата в виде герберов была отправлена производителю плат (JLCPCB) и получены вот такие изделия:
Первым делом требуется произвести монтаж SMD-элементов, поэтому берем паяльную пасту в шприце и наносим с помощью пневматического дозатора (решение по кнопке дозатора описано здесь).
Нажимая кнопку на шприце получаем капельки и колбаски такого вида:
Далее расставляем детальки на плату, мне удобно это делать с помощью такого пинцета:
После расстановки помещаем плату в «печку» и производим запекание согласно термопрофилю:
Можно конечно это проделать феном, но практика показывает, что качество изделия выше при использовании сего чудо-агрегата.
Результат запекания:
Сам модуль контроллера и ряд даталек я предпочитаю пропаять еще паяльником. Для этого задействуем паяльную станцию:
Результат получился вот такой:
Далее нужно припаять выводные элементы и контактные штыри. Я уже говорил об используемом реле, выглядит оно так:
Итог пайки выглядит так:
Переходим к водным процедурам, нужно смыть флюс, оптимальным для этого является ультразвуковая ванна, с последующим полосканием в дистиллированной воде. В качестве средства отмывки я использую Solins FA+ или Solins US:
Итог после мойки платы и сушки бытовым феном:
В итоге имеем компактное симпатичное устройство (на мой взгляд), в которое нужно вдохнуть жизнь заливкой кода.
Пару слов про перемычки. Мне гораздо удобнее вот такие удлиненные перемычки, особенно на этапе отладки:

Подготовка модуля
Первым делом подключим USB-to-Serial конвертер и переведем перемычку в положение заливки программы:
Так как у нас будут датчики на герконах и кнопки, то для отладки удобно использовать вот такой набор кнопочек на одной плате:
Геркон в пластиковом корпусе хорошо себя зарекомендовал, поэтому будем использовать его, предварительно проверив:
Удобный магнитик для подвижной части:

Прежде чем что-то делать, заливаем пустой файл, чтобы убрать все программные ценности идущие от производителя:
Процесс пошел:
Имеем готовый к новому коду модуль и приступаем к разработке логики.
Для разработки я буду использовать среду Visual Studio Code, вполне адекватная среда с большим количеством возможностей. Описывать подробно как настроить среду разработки для работы с PlatformIO я не буду. Скажу только что настроенная среда позволяет:
— компилировать программу под заданную архитектуру
— загружать как прошивку в модуль
— собирать образ файловой системы
— загружать образ в модуль
— вести отладку программы через встроенный терминал
Так выглядит панелька через которую все это делается:
Мой файлик platformio.ini:
[env:esp07]
platform = espressif8266
board = esp07
framework = arduino
board_build.filesystem = littlefs
monitor_speed = 115200

Требования
Нам требуется:
— работа с сетью (WiFi как в режиме Station, так и в режиме AP)
— интерфейс должен быть адаптирован под мобильные устройства, легким и отображать все необходимое
— хочется связать web-интерфейс с модулем, чтобы оперативно понимать текущее состояние ворот (открыли кнопкой или на другом устройстве, а наш интерфейс оперативно отрисовал нужные изменения без перезагрузки страницы)
— работа с кнопками (изменение состояния ворот), в нашем случае 2 кнопки (по количеству ворот), также 2 датчика закрытого состояния ворот (герконы), которые условно можно считать кнопками
— управление нагрузками (2 реле и светодиод индикации состояния wifi-соединения)
— работа с конфигурационной информацией, которую требуется хранить в энергонезависимой памяти (сетевые настройки, настройка таймера реле)
— манипуляции с состоянием устройства во время его работы (safe-mode, закрыты или открыты ворота, доступна ли сеть)
— обеспечение API для того чтобы другие устройства могли общаться с нашим
— связать все перечисленное в единую систему решающую комплексную задачу управления воротами

Программная реализация
Структура проекта и рабочая область выглядят так:
Чтобы удобнее было что-то рассказывать, приведу содержимое файлика main.cpp
#include "button_control.h"
#include "config.h"
#include "load_control.h"
#include "network.h"
#include "state.h"

ADC_MODE(ADC_VCC);

Config CFG;
State ST;
LoadsControl LC;
ButtonControl BC;
NetManager NM;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// init
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void setup() {
  // init state
  ST.init();
  // read config from EEPROM
  CFG.get();
  // init loads
  LC.init();
  // init buttons
  BC.init();
  // init network
  NM.init();
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// main loop
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void loop() {
  // update time
  ST.updateClock();
  // loads control
  LC.control();
  // reaction fo change buttons state
  BC.logic();
  // controlling change state buttons
  BC.check();
  // network control
  NM.control();
}

Конструкция ADC_MODE(ADC_VCC); нужна для корректного программного измерения напряжения питания, что особенно актуально при питании от батарей.
Основные сущности нашей программы представлены объектами:
— CFG — хранит конфигурационную информацию и позволяет манипулировать ей
— ST — содержит текущее состояние системы и обеспечивает доступ к нему на запись/чтение из вне в разных формах
— LC — содержит информацию о нагрузках, позволяет менять их состояние и управлять поведением
— BC — манипулятор кнопок
— NM — менеджер сети (инициализация, контроль, обработка запросов)
В функции setup, которая выполняется один раз при старте программы, производится инициализация всех объектов.
В функции loop, которая выполняется в бесконечном цикле, реализовано поведение объектов в процессе жизни устройства.
Далее покажу некоторые принципиальные моменты по работе программы.
Объявление и реализация работы с конфигурационными файлами:
Заголовочный файл config.h
#ifndef CONFIG_H
#define CONFIG_H

#include <Arduino.h>

// Config
class Config {
 public:
  char host[32];
  char user[16];
  char pass[16];
  bool wifimode;
  char ssid[16];
  char ssidpass[16];
  bool ipmode;
  char ip[16];
  char gateway[16];
  char subnet[16];
  char primaryDNS[16];
  char secondaryDNS[16];
  uint32_t maxon;

  // read config from EEPROM, if this is the first start, then write
  void get();
  // write config to EEPROM
  void put();
};

extern Config CFG;

#endif  // CONFIG_H

Видим что и как хранится в энергонезависимой памяти нашего модуля.
Файл реализации config.cpp
#include "config.h"
#include <EEPROM.h>

#define INIT_EEPROM_ADDR 0
#define INIT_EEPROM_KEY 1
#define SAVE_EEPROM_ADDR 1
#define EEPROM_MAX_SIZE 512

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// read config from EEPROM, if this is the first start, then write the value in
// EEPROM
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Config::get() {
  EEPROM.begin(EEPROM_MAX_SIZE);
  if (EEPROM.read(INIT_EEPROM_ADDR) != INIT_EEPROM_KEY) {  // first start
    EEPROM.write(INIT_EEPROM_ADDR, INIT_EEPROM_KEY);       // write key
    // set default values
    strcpy(host, "WIFI-RELAY");
    strcpy(user, "user");
    strcpy(pass, "pass");
    wifimode = 1;
    strcpy(ssid, "xxx");
    strcpy(ssidpass, "xxxxxxx");
    ipmode = 1;
    strcpy(ip, "192.168.1.189");
    strcpy(gateway, "192.168.1.1");
    strcpy(subnet, "255.255.255.0");
    strcpy(primaryDNS, "192.168.1.1");
    strcpy(secondaryDNS, "8.8.8.8");
    maxon = 2000;
    // save
    put();
  }
  EEPROM.get(SAVE_EEPROM_ADDR, CFG);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// write config to EEPROM
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Config::put() {
  EEPROM.put(SAVE_EEPROM_ADDR, CFG);
  EEPROM.commit();
}

Показаны особенности работы с энергонезависимой памятью для esp8266. Здесь требуется задать объем выделяемой памяти. Также имеется механизм проверки актуальности данных. В специальную ячейку записывается некое число и если при чтении получено иное, то данные перезаписываются значениями по умолчанию.
Заголовочный файл класса состояния устройства - state.h
#ifndef STATE_H
#define STATE_H

#include <Arduino.h>

#include "network.h"

#undef DEBUG
#define DEBUG  // for debug: DPRINT & DPRINTLN
#ifdef DEBUG
#define DPRINT(...) Serial.print(__VA_ARGS__)      // debug print
#define DPRINTLN(...) Serial.println(__VA_ARGS__)  // debug print with new line
#define DPRINTF(...) Serial.printf(__VA_ARGS__)    // debug printf
#else
#define DPRINT(...)    // blank line
#define DPRINTLN(...)  // blank line
#define DPRINTF(...)   // blank line
#endif

// return amount object
template <typename T, size_t n>
inline size_t arraySize(const T (&arr)[n]) {
  return n;
}

class State {
 public:
  // set start state
  void init();

  // get safe mode
  inline bool isSafeMode() { return FLAGS.safeMode; }

  // get safe mode text
  inline String getSafeModeText() { return FLAGS.safeMode ? "ON" : "OFF"; }

  // set open gate by num
  inline void open(uint8_t num) {
    extern NetManager NM;
    if (num == 0)
      FLAGS.firstState = true;
    else if (num == 1)
      FLAGS.secondState = true;
    NM.sendEvents(getData(num), "change");
  }

  // set close gate by num
  inline void close(uint8_t num) {
    extern NetManager NM;
    if (num == 0)
      FLAGS.firstState = false;
    else if (num == 1)
      FLAGS.secondState = false;
    NM.sendEvents(getData(num), "change");
  }

  // get state gate by num
  inline char* getData(uint8_t num) {
    static char _return[24];
    sprintf(_return, "{\"num\":%d,\"state\":%d}", (num + 1),
            (uint8_t)getState(num));
    return _return;
  }

  // get state gate by num
  inline bool getState(uint8_t num) {
    if (num == 0)
      return FLAGS.firstState;
    else if (num == 1)
      return FLAGS.secondState;
    return false;
  }
  
  // get state gate Text by num
  inline String getStateText(uint8_t num) {
    bool flag = FLAGS.firstState;
    if (num == 1) flag = FLAGS.secondState;
    return flag ? "ОТКРЫТО" : "ЗАКРЫТО";
  }

  // get color gate by num
  inline String getColor(uint8_t num) {
    bool flag = FLAGS.firstState;
    if (num == 1) flag = FLAGS.secondState;
    return flag ? "#F08080" : "#98FB98";
  }

  // on flag wifi connect
  inline void setConnect() { FLAGS.connectWIFI = true; }

  // off flag wifi connect
  inline void setDisconnect() { FLAGS.connectWIFI = false; }

  // get flag wifi connect
  inline bool isConnect() { return FLAGS.connectWIFI; }

  // fill current time
  void updateClock();

  // get low part current time
  inline uint32_t getTime() { return lowPartCurrentTime; }

  // get full current time
  inline uint64_t getFullTime() {
    return (uint64_t)highPartCurrentTime << 32 | lowPartCurrentTime;
  }

  // get uptime string
  char *getUptimeText();

 private:
  // low part uptime
  uint32_t lowPartCurrentTime;
  // high part uptime
  uint32_t highPartCurrentTime;
  // flags state
  struct {
    bool safeMode : 1;     // run without password in AP mode
    bool firstState : 1;   // state near gate
    bool secondState : 1;  // state far gate
    bool connectWIFI : 1;  // is connect to WIFI
  } FLAGS;
};

extern State ST;
#endif  // STATE_H

Так как заголовочный файл класса состояний подключается во всем проекте, то я сюда вынес немногочисленные общие для всего проекта элементы. В частности:
— механизм включения и выключения отладочной информации
— универсальную функцию подсчета элементов в массиве любого типа
Кроме этого, конечно, в файлике содержится описание класса состояния с методами доступа к состояниям, причем часто в нескольких форматах, включая текстовый, это нужно для удобной работы с шаблонами клиентских файлов, где вместо переменных подставляются их значения.
Реализация методов состояния устройства - state.cpp
#include "state.h"

#define SERIAL_SPEED 115200
#define SERIAL_DATA 45
#define SERIAL_TIME_SLEEP 1000
#define SERIAL_TIME_WAIT 10

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// first init state
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void State::init() {
  Serial.begin(SERIAL_SPEED);
#ifdef DEBUG
  // Serial.setDebugOutput(true);
  delay(SERIAL_TIME_SLEEP);
#endif
  DPRINTLN(F("start"));
  Serial.write(SERIAL_DATA);
  delay(SERIAL_TIME_WAIT);
  uint8_t incomingByte = 0;
  if (Serial.available() > 0) {
    incomingByte = Serial.read();
    if (SERIAL_DATA == incomingByte)
      FLAGS.safeMode = true;
    else
      FLAGS.safeMode = false;
  }
  updateClock();
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// set current time
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void State::updateClock() {
  uint32_t newCurrentTime = millis();
  if (newCurrentTime < lowPartCurrentTime) highPartCurrentTime++;
  lowPartCurrentTime = newCurrentTime;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// get string uptime
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
char* State::getUptimeText() {
  uint64_t mills = getFullTime();
  static char _return[32];
  uint32_t secs = mills / 1000;
  uint32_t mins = secs / 60;
  uint16_t hours = mins / 60;
  uint16_t days = hours / 24;
  mills -= secs * 1000;
  secs -= mins * 60;
  mins -= hours * 60;
  hours -= days * 24;
  sprintf(_return, "%d days %2.2d:%2.2d:%2.2d %3.3d", (uint8_t)days,
          (uint8_t)hours, (uint8_t)mins, (uint8_t)secs, (uint16_t)mills);
  return _return;
}

Пара неочевидных моментов. Для определения находится ли наше устройство в защищенном режиме или нет используется следующий подход. Сам перевод устройства в защищенный режим осуществляется замыканием перемычкой выводов TX и RX. При старте мы посылаем в последовательный некое число и если выводы соединены, то ожидаем считать, то же самое число, если так происходит, значит ставим флаг работы в защищенном режиме (в этом режиме все доступно без пароля и модуль работает в режиме точки доступа без пароля). Второй момент заключается в счетчике времени. Захотелось знать время непрерывной работы устройства. Стандартный счетчик времени основанный на типе uint32_t переполняется и нам не подходит. Поэтому введем еще одну переменную типа uint32_t, при переполнении первой меняем на 1 вторую. Такого времени хватит на долго :). Также имеется функция которая возвращает время непрерывной работы (UPTIME) устройства в понятном текстовом виде.
Заголовочный файл класса сетевого менеджера - network.h
#ifndef NETWORK_H
#define NETWORK_H

#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>

class NetManager {
 private:
  static String processor(const String &var);
  void connect();
  void setAnsvers();

 public:
  void init();
  void control();
  void sendEvents(const char *data, const char *tag);
  void postProcessing(AsyncWebServerRequest *request);
};

#endif  // NETWORK_H

Методов здесь не много. Следует сказать, что я предпочитаю асинхронную обработку http запросов, поэтому и используются соответствующие библиотеки.
Реализация метода устанавливающего обработчики запросов NetManager::setAnsvers
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// setting ansvers for network requests
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void NetManager::setAnsvers() {
  // Route for root / web page
  server.on("/", HTTP_GET, [](AsyncWebServerRequest* request) {
    if (!request->authenticate(CFG.user, CFG.pass) && !ST.isSafeMode())
      return request->requestAuthentication();
    request->send(LittleFS, "/index.html", String(), false, processor);
  });

  // Route for /set web page
  server.on("/set", HTTP_ANY, [this](AsyncWebServerRequest* request) {
    if (!request->authenticate(CFG.user, CFG.pass) && !ST.isSafeMode())
      return request->requestAuthentication();
    if (request->method() == HTTP_POST) {
      postProcessing(request);
    }
    request->send(LittleFS, "/settings.html", String(), false, processor);
  });

  // Route for /reset web page
  server.on("/reset", HTTP_GET, [](AsyncWebServerRequest* request) {
    if (!request->authenticate(CFG.user, CFG.pass) && !ST.isSafeMode())
      return request->requestAuthentication();
    request->send(LittleFS, "/settings.html", String(), false, processor);
    ESP.restart();
  });

  // Button 1 control
  server.on("/button1", HTTP_GET, [](AsyncWebServerRequest* request) {
    if (!request->authenticate(CFG.user, CFG.pass) && !ST.isSafeMode())
      return request->requestAuthentication();
    LC.on(L_NEAR);
    request->send(200, "application/json", "{'ok':1}");
  });

  // Button 2 control
  server.on("/button2", HTTP_GET, [](AsyncWebServerRequest* request) {
    if (!request->authenticate(CFG.user, CFG.pass) && !ST.isSafeMode())
      return request->requestAuthentication();
    LC.on(L_FAR);
    request->send(200, "application/json", "{'ok':1}");
  });

  // api
  server.on("/sensors", HTTP_GET, [](AsyncWebServerRequest* request) {
    if (!request->authenticate(CFG.user, CFG.pass) && !ST.isSafeMode())
      return request->requestAuthentication();
    String answer = "hostname:" + String(CFG.host);
    answer += ";GATE1:" + String(ST.getState(0));
    answer += ";GATE2:" + String(ST.getState(1));
    answer += ";";
    request->send(200, "text/html", answer);
  });

  // route roe all static files
  server.serveStatic("/", LittleFS, "/").setCacheControl("max-age:6000000");

  // if page not found
  server.onNotFound([](AsyncWebServerRequest* request) {
    request->send(404, "404: Not found");
  });
}

Как видно, все запросы, которые выдают какие-то полезные данные, либо меняют состояние системы требуют авторизации. Авторизация требуется только в том случае, если не включен защищенный режим. Для хранения файлов я использовал файловую систему LittleFS.
По запросу '/set' выдается страница с настройками, при этом, если запрос типа 'POST', то осуществляется обработка принятых от клиента данных. При запросе файлов index.html и settings.html они прогоняются через простенький шаблонизатор, где переменные заменяются своими значениями.
Заголовочный файл класса работы с нагрузками - load_control.h
#ifndef LOAD_CONTROL_H
#define LOAD_CONTROL_H

#include <Arduino.h>

class LoadsControl {
 public:
  // init load control
  void init();

  // set on
  void on(uint8_t num);

  // set off
  void off(uint8_t num);

  // check
  void control();

  // get state load
  inline bool isOn(uint8_t num) { return L[num].flag.state; }

 private:
  // one load
  struct Load {
    uint8_t pin;     // pin load
    uint32_t start;  // start time
    // flags for load
    struct LoadFlag_t {
      bool state : 1;
      bool autoOff : 1;
    } flag;  // load's flags
  };

  // array loads
  static Load L[];

  // amount loads
  uint8_t countL = 0;
};

extern LoadsControl LC;

enum loadNum_t {
  L_NEAR,  // 0
  L_FAR,   // 1
  L_LED,   // 2
};

#endif  // LOAD_CONTROL_H

Собственно, видны методы инициализации нагрузок, включения и выключения нагрузки по номеру. Каждая нагрузка имеет пару флагов: состояние и нуждается ли она в автоматическом отключении.
Метод обработки нагрузок, вызываемый в loop - LoadsControl::control
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// control loads
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void LoadsControl::control() {
  // auto off relay
  for (uint8_t i = 0; i < countL; i++) {
    if (L[i].flag.state && L[i].flag.autoOff && CFG.maxon &&
        ((ST.getTime() - L[i].start) > CFG.maxon)) {
      off(i);
    }
  }

  // switching the connection led
  if (ST.isConnect() && !L[L_LED].flag.state) {
    on(L_LED);
  } else if (!ST.isConnect() && L[L_LED].flag.state) {
    off(L_LED);
  }
}

Здесь после заданного в конфигурации времени снимается напряжение с реле подключенного к приводу ворот. Также в этом методе в зависимости от состояния сети, включается и выключается светодиод выведенный на крышку устройства.
Заголовочный файл класса работы с кнопками - button_control.h
#ifndef BUTTON_CONTROL_H
#define BUTTON_CONTROL_H

#include <Arduino.h>

struct Button {
  uint8_t pin;
  bool state;            // current state
  uint32_t startChange;  // time begin change
  uint32_t timeProtect;  // bounce protect timer
  bool change;
};

class ButtonControl {
 private:
  uint8_t countB;
  static Button B[];

 public:
  void init();
  void check();
  void logic();
  
  inline uint8_t getCount() { return countB; }

  inline bool isChangeDown(uint8_t num) {
    return B[num].change && !B[num].state;
  }
  inline bool isChangeUp(uint8_t num) {
    return B[num].change && B[num].state;
  }
};

enum buttonNum_t {
  BT_FIRST,       // 0
  BT_SECOND,      // 1
  BT_FIRST_SENS,  // 2
  BT_SECOND_SENS, // 3
};

#endif  // BUTTON_CONTROL_H

Метод check проверяет наличие изменений состояния кнопок, а метод logic — реализует логику в зависимости от этих изменений. Про работу с кнопками я как то писал тут.

Я кратко описал основные моменты работы программы на серверной стороне. Теперь про клиент.
Для того, чтобы интерфейс выглядел более-менее нормально и в то же время не занимал много места и работал быстро, я взял набор стилей PureCSS. Обработку логики на стороне клиента реализовал на чистом javascript, без использования сторонних библиотек.
Основной файлик интерфейса нашей системы - index.html
<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <title>Управление воротами</title>
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <link rel="stylesheet" type="text/css" href="style.css" />
  <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
  <link rel="manifest" href="/site.webmanifest">
</head>

<body>
  <div class="pure-menu pure-menu-horizontal">
    <ul class="pure-menu-list">
      <li class="pure-menu-item pure-menu-selected">
        <a href="/" class="pure-menu-link">Управление</a>
      </li>
      <li class="pure-menu-item">
        <a href="/set" class="pure-menu-link">Настройки</a>
      </li>
    </ul>
  </div>

  <div class="pure-g">
    <div class="pure-u-2-3">
      <div>

        <h1>СОСТОЯНИЕ ВОРОТ</h1>
        <table class="pure-table pure-table-bordered">
          <tbody>
            <tr>
              <td>УЛИЦА</td>
              <td id="gate1" style="background-color:%BGCOLOR1%;">%GATE1%</td>
            </tr>
            <tr>
              <td>ГАРАЖ</td>
              <td id="gate2" style="background-color:%BGCOLOR2%;">%GATE2%</td>
            </tr>
          </tbody>
        </table>

        <h1>УПРАВЛЕНИЕ ВОРОТАМИ</h1>
        <p>
          <button name="button1" class="pure-button pure-button-primary button-xlarge">УЛИЦА</button>
        </p>
        <p>
          <button name="button2" class="pure-button pure-button-primary button-xlarge">ГАРАЖ</button>
        </p>
      </div>
    </div>
  </div>
</body>
<script>
  const buttons = document.querySelectorAll(".pure-button");
  buttons.forEach(function (bt) {
    bt.addEventListener('click', function (event) {
      bt.classList.remove("pure-button-primary");
      fetch('/' + bt.name).then(function (response) {
        if (response.status == 200) {
          setTimeout(() => {
            bt.classList.add("pure-button-primary");
          }, 800);
        } else {
          alert("Error HTTP: " + response.status);
        }
      })
        .catch(function (err) {
          alert("Error network: " + err);
        });
    })
  })
  if (!!window.EventSource) {
    var source = new EventSource('/events');
    source.addEventListener('open', (e) => {
      console.log("Events Connected");
    }, false);
    source.addEventListener('error', (e) => {
      if (e.target.readyState != EventSource.OPEN) {
        console.log("Events Disconnected");
      }
    }, false);
    source.addEventListener('change', (e) => {
      console.log(e.data);
      const data = JSON.parse(e.data);
      const { num, state } = data;
      const id = 'gate' + num;
      document.getElementById(id).innerHTML = state ? 'ОТКРЫТО' : 'ЗАКРЫТО';
      document.getElementById(id).style.backgroundColor = state ? '#F08080' : '#98FB98';
    }, false);

  }
</script>
</html>

У нас имеется небольшое верхнее меню состоящие из 2-х пунктов: Управление и Настройки, выбранный пункт меню подсвечивается. Далее идет небольшая табличка с текущим состоянием ворот. Данный файл, как и файл настроек на стороне сервера обрабатывается простеньким шаблонизатором, где на место %VAR% подставляется значение VAR. В данном файле подставляется состояние ворот и цвет состояний, для удобного визуального контроля. Так сказазать «Server-Side Rendering». После этого расположены две кнопки изменения состояния ворот.
Клиентская часть кода, как уже писал ранее написана на javascript. В данном файле всем кнопкам с классом ".pure-button" ставится обработчик нажатия, по нажатию на сервер с помощью функции fetch уходит запрос с именем кнопки. Во время нажатия кнопка меняет свой цвет, чтобы визуально понять что произошло нажатие. При получении ответа с кодом 200 исходный цвет кнопки восстанавливается через 800мс (иначе трудно уловить, что что-то произошло.
Далее идет код обработки реалтайм сообщений от сервера, с которым поддерживается связь все время пока страница открыта. При поступлении соответствующих сообщений текст состояния ворот и цвет ячейки состояния ворот меняются.
Интерфейс настройки устройства - settings.html
<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <title>Управление воротами</title>
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <link rel="stylesheet" type="text/css" href="style.css" />
  <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
  <link rel="manifest" href="/site.webmanifest">
</head>

<body>
  <div class="pure-menu pure-menu-horizontal">
    <ul class="pure-menu-list">
      <li class="pure-menu-item">
        <a href="/" class="pure-menu-link">Управление</a>
      </li>
      <li class="pure-menu-item pure-menu-selected">
        <a href="/set" class="pure-menu-link">Настройки</a>
      </li>
    </ul>
  </div>

  <div class="pure-g">
    <div class="pure-u-2-3">
      <div>

        <h1>STATE</h1>
        <table class="pure-table pure-table-bordered">
          <tbody>
            <tr>
              <td>Safe mode</td>
              <td>%SAFEMODE%</td>
            </tr>
            <tr>
              <td>RSSI</td>
              <td>%RSSI% dBm</td>
            </tr>
            <tr>
              <td>Free memory</td>
              <td>%MEM% B</td>
            </tr>
            <tr>
              <td>Voltage</td>
              <td>%VOLTAGE% mV</td>
            </tr>
            <tr>
              <td>Uptime</td>
              <td>%UPTIME%</td>
            </tr>
          </tbody>
        </table>


        <h1>SETTINGS</h1>
        <form class="pure-form pure-form-aligned" method="post" action="/set" onsubmit="return validate()">
          <fieldset>

            <legend>Base</legend>
            <div class="pure-control-group">
              <label for="host">Host</label>
              <input name="host" type="text" id="host" placeholder="Host name" value="%HOST%">
            </div>

            <legend>HTTP basic authentication</legend>
            <div class="pure-control-group">
              <label for="name">Username</label>
              <input name="name" type="text" id="name" placeholder="Username" value="%USER%">
            </div>
            <div class="pure-control-group">
              <label for="password">Password</label>
              <input name="password" type="password" id="password" placeholder="Password" value="%PASSWORD%">
              <button class="pure-button toggle-button" type="button">show</button>
            </div>

            <legend>WIFI settings</legend>
            <div class="pure-control-group">
              <label for="wifimode">WIFI mode</label>
              <select name="wifimode" id="wifimode">
                <option %APSELECTED% value="ap">AP</option>
                <option %STSELECTED% value="station">STATION</option>
              </select>
            </div>
            <div class="pure-control-group">
              <label for="ssid">SSID</label>
              <input name="ssid" type="text" id="ssid" placeholder="SSID" value="%SSID%">
            </div>
            <div class="pure-control-group">
              <label for="ssidpass">WIFI-Password</label>
              <input name="ssidpass" type="password" id="ssidpass" placeholder="WIFI password" value="%SSIDPASS%">
              <button class="pure-button toggle-button" type="button">show</button>
            </div>
            <div class="pure-control-group">
              <label for="ipmode">IP mode</label>
              <select name="ipmode" id="ipmode">
                <option %DHCPSELECTED% value="dhcp">DHCP</option>
                <option %FIXSELECTED% value="static">STATIC</option>
              </select>
            </div>
            <div class="pure-control-group">
              <label for="ip">IP</label>
              <input name="ip" type="text" id="ip" placeholder="xxx.xxx.xxx.xxx" value="%IP%" class="ipaddress">
            </div>
            <div class="pure-control-group">
              <label for="gateway">Gateway</label>
              <input name="gateway" type="text" id="gateway" placeholder="xxx.xxx.xxx.xxx" value="%GATEWAY%"
                class="ipaddress">
            </div>
            <div class="pure-control-group">
              <label for="subnet">Subnet</label>
              <input name="subnet" type="text" id="subnet" placeholder="xxx.xxx.xxx.xxx" value="%SUBNET%"
                class="ipaddress">
            </div>
            <div class="pure-control-group">
              <label for="primaryDNS">Primary DNS</label>
              <input name="primaryDNS" type="text" id="primaryDNS" placeholder="xxx.xxx.xxx.xxx" value="%PRIMARYDNS%"
                class="ipaddress">
            </div>
            <div class="pure-control-group">
              <label for="secondaryDNS">Secondary DNS</label>
              <input name="secondaryDNS" type="text" id="secondaryDNS" placeholder="xxx.xxx.xxx.xxx"
                value="%SECONDARYDNS%" class="ipaddress">
            </div>

            <legend>Device settings</legend>
            <div class="pure-control-group">
              <label for="maxon">On time</label>
              <input name="maxon" type="text" id="maxon" placeholder="On time" value="%MAXON%">
            </div>

            <div class="pure-controls">
              <button type="submit" class="pure-button pure-button-primary">Save</button>
            </div>

          </fieldset>
        </form>
      </div>
      <p>
       <a href="/reset">reset</a>
      </p>
    </div>
  </div>

  <script>
    const toggleButtons = document.querySelectorAll(".toggle-button");
    toggleButtons.forEach(function (tb) {
      tb.addEventListener('click', function () {
        if (this.previousElementSibling.type === 'password') {
          this.previousElementSibling.type = 'text';
          this.textContent = 'hide';
        } else if (tb.previousElementSibling.type === 'text') {
          this.previousElementSibling.type = 'password';
          this.textContent = 'show';
        }
      })
    })

    function validate() {
      const ips = document.querySelectorAll(".ipaddress");
      const ipformat = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
      let retval = true;
      ips.forEach(function (ip) {
        if (!ip.value.match(ipformat)) {
          ip.classList.add("invalid");
          retval = false;
          ip.onfocus = function () {
            if (this.classList.contains('invalid')) {
              this.classList.remove('invalid');
            }
          }
        }
      })
      return retval;
    }
  </script>
</body>
</html>

Страница настроек содержит то же меню что и страница управления. За меню следуют текущие свойства устройства, такие как:
— включен ли защищенный режим
— уровень WIFI сигнала
— количество свободной памяти
— напряжение питания
— время непрерывной работы устройства.
Далее идет форма, позволяющая изменять настройки устройства:
— имя хоста
— имя пользователя для авторизации на странице
— пароль пользователя для авторизации на странице
— режим WIFI (либо точка доступа, либо подключение к существующей точке)
— имя точки доступа к которой будет подключение, либо которая будет создана, зависит от режима
— пароль точки доступа к которой будет подключение, либо которая будет создана, зависит от режима
— режим IP адреса (статический или динамический)
— сетевые настройки
— время включенного состояния реле (определяет через сколько миллисекунд реле на плате будет выключено и контакты на приводе ворот разомкнуться).
Рядом с полями паролей расположена кнопка скрытия/показа паролей, нехитрый программный код на javascript реализует данное поведение. Помимо этого, на javascript реализуется валидация ip адресов формы, так как появление там некорректных данных может потребовать лишних телодвижений.

Вид интерфейса
Так выглядит основная страница управления:
Так выглядит страница с настройками:
Здесь можно посмотреть как интерфейс реагирует на изменение состояния ворот:

На видео виден механизм Server-Sent Events (SSE) в действии, когда браузер поддерживает открытым соединение с сервером и мгновенно реагирует на присылаемую сервером информацию.

Корпус
Многие из вас отлично понимают, что устройство без корпуса, это полуфабрикат.  Нужно сделать корпус максимально подходящий нашему устройству, с отверстиями в нужных местах. Я считаю, что вполне разумно прибегнуть к 3Д-печати. Рисуем модель нижней части корпуса. Предусмотрев отверстия для ввода проводов, крепежные отверстия и стойки для нашей платы. В одной части корпуса будет располагаться наше устройство, в другой уложенные провода. Результат вот такой:
Чтобы сделать крышечку, нужно отступить 0.2 мм, чтобы она плотно покрывала
наше устройство. В крышечке предусматриваем отверстие для светодиода индикации состояния сети:
Результат печати:
Помимо корпуса для самого устройства, требуются корпуса для герконов и механика крепления магнитика к воротам. Так как корпус геркона требуется крепить к криволинейной направляющей ворот, то прибегнем к моделированию используя пластилин:
Заодно сделал примерный слепок ответной части, которую будем крепить к естественно торчащему болту конструкции ворот. Слепки выглядят так:
Чтобы иметь возможность регулировки расстояния от магнита до геркона предусмотрим крепежное отверстие в виде овала.
Далее по точкам, с помощью сплайна нетрудно воспроизвести криволинейную поверхность:
Как можно видеть, с обратной стороны крепежа геркона я выдавил углубление под сам геркон и под провода для его подключения.
Запускаем печать:
Результат:
Сравниваем кривизну со слепком и убеждаемся, что все норм:

Монтаж
Приводы ворот закреплены на потолке. Кроме приводов имеются уже смонтированные датчики препятствия в проеме ворот, соединенные витой парой. Задействованы только 4 проводка в сетевом кабеле. Чтобы не тянуть лишние провода, достаточно присоединиться к существующим свободным парам. Всего для каждых ворот нам требуется 4 провода: два провода будут замыкать нужные контакты привода и два провода пойдут к выключателю. Кинем еще одну витую пару от одного привода к нашему устройству, для управления вторым приводом расположим наше устройство в непосредственной близости от датчика.
Привод на картинке:
Вот так выглядит привод уличных ворот без крышки:
Вот так ближе интересующее нас место:
Колодка управления воротами:
Согласно документации, нам требуется к реле подключать выводы 2 и 7 колодки привода.
Монтируем выключатель данного привода, оставляя провод для геркона:
Выключатель используем кнопочного типа, без фиксации (часто используются для звонков). Теперь подойдя к воротам, можно легко их открыть нажатием кнопки, уходя, достаточно нажать кнопку с улицы и ворота закроются.
Возле нижних ворот монтируем наше устройство и два выключателя. Провода подходят к устройству сквозь стену. Ближний к воротам выключатель позволит управлять нижними воротами, второй дублирует верхний выключатель, позволяя, например, проветрить не поднимаясь наверх и не прибегая к пульту.
Как и было задумано, крышечка хорошо закрыла устройство вместе с проводами коммутации, по светодиоду видно что подключение к сети произошло и все норм:
На состояние стен не обращайте внимание, в гараже предстоит ремонт.

Монтаж осуществлен (осталось только приклеить герконы в корпусах и ответные магнитики), ворота управляются, как и задумано. Далее можно через VPN вынести интерфейс наружу, либо реализовать в какой-то системе (типа OpenHub) управление, благо api есть, или дописать взаимодействие по mqtt. В крайнем случае можно просто пробросить порт из внутренней сети наружу. По моему, получилось вполне полезное устройство, которое облегчит взаимодействие с воротами своему владельцу.

На этом заканчиваю. Спасибо тем кто дочитал до конца, надеюсь кому-то информация окажется полезной!
Добавить в избранное +88 +137
+
avatar
+1
Хороший подход к решению задачи.
К ТЗ есть вопросы. И мелкие спорные моменты по конструкции. К примеру, индикация срабатывания реле нафиг не нужна в итоговом изделии, а для отладки положить на плату пару деталек не проблема. В качестве итоговой индикации я бы использовал звуковое оповещение, огонек не всегда информативен. Ну или более заметный проблесковый.

ЗЫ. Вроде паста нормальная, но на фото припой не очень блестит.
+
avatar
  • yurok
  • 01 ноября 2023, 09:29
+1
Индикация иногда удобна в процессе эксплуатации, при возникновении непонятных ситуаций, а так она и не особо нужна, кроме разве что подключения модуля к сети. А звук на какое событие? При нажатии и так будет видно что ворота открываются :).
Может ракурс фото не очень, паста блестит.
+
avatar
0
С непонятными ситуациями все не просто — все возможные ситуации одним индикатором не обозначить. Ключевое — ворота не открываются. А это и так видно.
А недоступность модуля лучше мониторить внешними средствами. И оперативно информировать пользователя.
+
avatar
  • yurok
  • 01 ноября 2023, 09:41
0
конечно это внешними средствами можно контролировать — на роутере например, но находясь рядом — видно что ворота подключены к сети — тоже не плохо
+
avatar
0
Шанс, что стоя в машине у ворот обнаружить неработающую коробочку, думаю, выше.
+
avatar
  • yurok
  • 03 ноября 2023, 11:56
0
что ж, делайте как вам нравится… я ж никого ни к чему не призываю, поделился своей поделкой
+
avatar
  • yurok
  • 01 ноября 2023, 10:05
0
звук кстати там и так есть в виде щелчка реле :) на видео слышно когда в конце я нажимал на кнопки — которые станут выключателями )
+
avatar
0
Тепличные условия не в счет.
+
avatar
  • ACE
  • 01 ноября 2023, 12:48
+1
ЗЫ. Вроде паста нормальная, но на фото припой не очень блестит.
Вот, кстати, у меня такой же результат после жидкости solins и УЗ ванны. Отмывать — отмывает, но припой становится мутным, как на платах подвальных китайских устройств. А другой отмывочной жидкости особо и не купить в розницу.
+
avatar
  • infino
  • 01 ноября 2023, 16:52
0
Это нормально, отмытое от флюса и не должно блестеть.
+
avatar
0
Правильный припой отлично блестит.
+
avatar
  • infino
  • 03 ноября 2023, 12:33
0
После отмывки, любой правильный припой, перестанет блестеть,
И про какой правильный припой вы говорите?
Но если применить безотмывоочный флюс и припой и не мыть. Все будет блестеть.
+
avatar
-1
Не любой. Марку своего не знаю. Да и пофигу. Меня максимально устраивает. Паяю с канифолью, когда флюса в припое не хватает.
+
avatar
0
Интересное наблюдение. Сам мою только спиртом, вручную и в ванне. Всегда блестит.
+
avatar
  • mrBlue
  • 01 ноября 2023, 09:50
+1
Сразу скажу что вопросы вероятно глупые, но хорошо если поясните.
1. Вариант вайфай реле с поддержкой чего-то типа Tuya делает не то же самое?
2. «VT1, VT2 — биполярные транзисторы 2n2222, нужны для управления реле» а для чего так? Я не спец в радиоэлектронике, просто любопытно. Что такое и для чего подтягивающие резисторы я понимаю, а это вот зачем?
+
avatar
  • yurok
  • 01 ноября 2023, 09:56
+1
все норм
1 если сделать прошивку под эти модули (нам требуется на короткое время включить реле и выключить) то будет похоже (в том варианте что продается не подходит), но там придется повозиться с выводом gpio и их подтяжкой, реле там большое силовое и одно, а здесь двое ворот ну и еще ряд моментов
2 во первых реле 5 вольтовые, во вторых ток удержания реле превышает возможности контроллера
+
avatar
  • baksser
  • 01 ноября 2023, 15:09
0
Я поставил четырёх кнопочный сонофф и кайф. Настроить реле на режим кнопки все программно делается легко
Этот геморрой с выдумыванием велосипеда нужен только когда это гараж с большим количеством людей.
+
avatar
+2
Стоит такое двухканальное реле на ворота и калитку, питание от 220 или 5В. Через радио подключается к домашнему серверу, через интернет к Алисе, также вывел две физические кнопки.
+
avatar
  • yurok
  • 01 ноября 2023, 22:29
+1
можно и это использовать вместо моей платки, но тоже есть нюансы…
датчики реального положения ворот и калитки вы как реализовали?
второй момент — там реле силовые — они имеют ограничения на ток как снизу так и сверху… и им может стать нехорошо от отсутствия нагрузки через время.
ну и это менее компактно, к тому же без своей прошивки зависит от облака вендора и без интернета совсем не будет работать
+
avatar
  • Burann
  • 01 ноября 2023, 09:52
+3
Всё конечно круто.
Но почти уверен что повторяемости не будет.
Это же всё надо делать или на работе или убивать выходные на это дело.
Или вообще быть безработным.

Какой смысл в этом.
Все блоки готовые продаются.
Осталось только собрать и потратить на это день.
А так конечно молодец
+
avatar
  • Nekto
  • 01 ноября 2023, 10:20
+17
Пластид? С4? Взрыватель интересный, не встречался с таким. Вывести из строя механизм хватит, но чтобы вынести ворота — маловато будет.
+
avatar
  • yurok
  • 01 ноября 2023, 10:23
0
:)
+
avatar
0
У меня возникла точно такая же ассоциация от этого фото, видимо боевиков много смотрю.
+
avatar
  • DJV
  • 03 ноября 2023, 18:21
0
Тут достаточно чтобы ни ворот, ни окон в гараже не было…
+
avatar
+3
Какие же нынче крутые технари! Хороший обзор! Не пойму почему система привязывается к интернету? В чем преимущество перед простым радиоуправлением с брелока, который пристегнут к ключу и быстро доступен.
+
avatar
  • yurok
  • 01 ноября 2023, 11:24
+7
Преимуществ много
1 — к вам приехала доставка, вас нет — открыли ворота (хоть из другого города) доставка выложила все — сам многократно этим пользовался
2 — пришли например строители (гости, родственники и тп), в ваше отсутствие — вы им открыли ворота — они делают работу, не нужно им давать брелок
3 — брелок занимает место в кармане и нужно следить за батарейками — пошли вы в магазин — взяли телефон, в нем уже есть ключ от ворот
и так можно продолжать довольно долго, к тому же брелок то не перестал работать, появились альтернативы
+
avatar
0
прочитал обзор с удовольствием (хоть и не умею, но логика на месте)
пс п.1 и 2 у меня по старинке: дети или супруга)))
+
avatar
  • yurok
  • 01 ноября 2023, 14:56
+3
Спасибо
Дети и супруга дороже описанного решения :) к тому же и они могут отлучиться
+
avatar
+2
Спорить не буду, но право надумано: доставка… как часто доставка без проверки привезенного товара и подписания документов?; строители, гости… также не часто в отсутствие хозяев; батарейка… раз в 5 лет? место в кармане… что так много места занимает? по крайней мере размер не больше телефона, а движений, чтобы открыть ворота по-более (вытащить телефон, включить, найти приложение, открыть его, отключить телефон, спрятать телефон). У меня две связки ключей: от дома и от машины с брелоком на ворота въездные и в гараж. Ну и дубль в доме для всей семьи. «Приценивался» к вашей разработке, ну совсем не вдохновило. Хотя, подобные «ключи» давно реализованы во всех многоквартирных домах с общим въездом. В этом случае это очень даже полезно
+
avatar
  • yurok
  • 01 ноября 2023, 19:42
+2
СДЭК, ЕМС и прочие спокойно сами расписываются если попросить… проблем не было.
У всех по разному — мне удобнее так.
Брелок у меня лежит в машине — там быстрее на нем, а в остальных случаях предпочту достать телефон. Телефон то вы все-равно берете.
Впрочем я никого ни к чему не призываю, кому то удобнее так, кому то иначе. Я только показал как сделал и мне это подходит.
+
avatar
+1
У меня въездные ворота Дорхан. Родной радиопульт их открывает с расстояния 50м, если батарейка свежая. А я открываю через 200м, как на свою улицу сворачиваю, с Андроид-магнитолы с установленным на ней клиентом Опенхаба. И как раз как подъезжаю, то ворота уже открыты, а не стою и не жду, когда они откроются.
+
avatar
  • Anris
  • 01 ноября 2023, 11:33
+1
Отличная работа. Также делал под себя пару уст-с управлением через веб-интерфейс. Но как пожилой энергетик в С не силен, нам ближе FBD или релейная логика :). Пользуюсь flprog.ru/. Вот веб-интерфейс из блоков для ESP8266, ESP32 без необходимости изучения различных языков для создания web-страниц: веб-интерфейс из блоков для ESP8266, ESP32.
+
avatar
  • Anris
  • 01 ноября 2023, 13:43
0
+
avatar
0
Пора слезать с этой глючной шляпы. Вот вам нормальный -https://www.arduino.cc/pro/software-plc-ide
+
avatar
  • Alta
  • 01 ноября 2023, 11:50
0
Круто!
Я такое фиг соберу ))) хотя пригодилось бы тоже.
я правильно понимаю, что теперь можно и со смартфона управлять воротами?
И про выключатели не очень понял: выключателем внутри можно и открыть и закрыть, а выключателем снаружи только закрыть?
+
avatar
  • yurok
  • 01 ноября 2023, 11:54
+1
Снаружи нет выключателя:)
Внутри первых ворот можно их открыть и закрыть, но выйдя на улицу при открытых воротах можно нажать на выключатель и закрыть
Внутри вторых открыть и закрыть можно как первые так и вторые ворота
Конечно, со смартфона можно управлять и динамически видеть состояние ворот — для этого все и затевалось
+
avatar
  • router
  • 01 ноября 2023, 11:50
0
Приводов у вас 2 (по числу ворот). Они управляются одним комплектом брелков?
+
avatar
  • yurok
  • 01 ноября 2023, 11:54
+1
Да, брелоки универсальные с несколькими кнопками, на разные кнопки можно садить разные ворота
+
avatar
+2
Хотел бы напомнить автору, что существуют аппаратные ватчдоги. Но если вы уверены, что ваш контроллер никогда не зависнет, то не напрягайтесь.
+
avatar
0
Я тоже за аппаратный ватчдог. Брал для этих целей STWD100 с таймаутом 1.6 секунды.
+
avatar
0
Так внутри контроллера тоже аппаратный, главное его правильно использовать. А то дизассемблировал недавно какое-то китайское поделие, ватчдог кормится в прерывании от RTC.
+
avatar
+2
Читайте datasheet на esp8266. У него нет аппаратного watchdog и много чего ещё. Например i2c и pwm.
+
avatar
0
Извиняюсь, с ESP8266 не работал. Даже представить не мог, что такое (контроллер без WDT) бывает.
+
avatar
+1
Угу, сам в шоке. Поэтому с грустью смотрю на людей делающих на esp8266 управление котлом и другой потенциально опасной техники.
+
avatar
  • ACE
  • 01 ноября 2023, 18:36
0
Как это нет? Есть. В даташите на esp8266 про него не сказано, я думаю, потому что аппаратный wdt относится к готовому процессорному ядру от tensilica. Другое дело, что у него тоже есть глюки и нюансы, это да.
+
avatar
0
Нету. Вместо этого программный костыль. Если проц зависнет, то зависнет и software wdt. Дальше как повезет…
+
avatar
  • ACE
  • 01 ноября 2023, 19:15
0
Есть hardware и software wdt. Посмотрите, например, список reset cause.
+
avatar
+1
Действительно появился и аппаратный i2c завезли. Но только в ESP8266EX от 2020 года.

Спасибо за инфу. Пощупаю.
+
avatar
  • ACE
  • 01 ноября 2023, 19:56
0
Могу ошибаться, конечно, но esp8266 и esp8266EX — одно и то же. Полное наименование (по маркировке на чипе) и сокращенное.
Как минимум в качестве пруфа можно найти даташит на ЕХ от 2015го года
cdn-shop.adafruit.com/product-files/2471/0A-ESP8266__Datasheet__EN_v4.3.pdf
И он уже версии 4.3 к тому времени был. Значит ЕХ шли ещё раньше.
И уже тогда был аппаратный вотчдог:
When in sleep mode, only the calibrated real-time clock and watchdog remains active
+
avatar
+3
Значит я не прав. Прошу прощения у всех.
+
avatar
0
У меня около 20 esp8266 стоят по дому и участку. За 7 лет их работы, я не помню такого, чтобы у них проц завис.
+
avatar
0
Мои наблюдения по использованию esp8266 в течении года+. Если не использовать software i2c (ногодрыг) или SSL шифрование, то да работает без перезагрузок уже больше 12 месяцев — mySKU.me/blog/aliexpress/88409.html

Как только в проекте или i2c или SSL или оба, то каждые 3..4 месяца глюки и перезагрузка.
+
avatar
0
SSL ни разу на ESP не использовал. По айтуси много разного подключено.
+
avatar
  • infino
  • 01 ноября 2023, 12:44
0
В далеком 90 году, мой коллега по работе, делал частным образом систему управления гаражными воротами, так ему сказал заказчик и так он рассказывал в КГБ, там выяснилось, что ему заказали устройство дистанционного управления взрывным устройством.
Для него все закончилось хорошо, даже не сильно били.
+
avatar
0
Не били сильно потому, что там немного по другому. Система свой-чужой как в авиации.
+
avatar
  • infino
  • 01 ноября 2023, 16:41
+1
В те времена не было столько садистов сколько сейчас в системе наказания.
+
avatar
0
я одного понять не могу, зачем в проекте классы? масштабировать (дополнять) вы его все равно не будете. имхо хватило бы обычного функционального программирования.

за прямые руки 5.

пы.сы. сам разочаровался в esp8266 и потихоньку перевожу проекты на esp32.
+
avatar
  • yurok
  • 01 ноября 2023, 13:49
0
Дополнять расширять можно в других проектах, используя куски этого. Но конкретно здесь можно было бы обойтись структурами с методами. Функционально все же многое было бы неудобно
+
avatar
0
… расширять можно в других проектах, используя куски этого
Вот именно куски, а не сами классы. Поэтому они бесполезны в таких проектах. Да я имел в виду структуры и методы (не силен с теории, тк самоучка).

Пы.сы. Я не критикую, просто спрашиваю тк постоянно учусь на чужом коде. Вот и интересно стало почему у вас так.
+
avatar
0
я одного понять не могу, зачем в проекте классы?
Классы дают определенную изоляцию. Невозможно случайно «чужую» переменную изменить.
Да и масштабировать проще, объявив несколько экземпляров.
Хотя я и для одного экземпляра всовываю все в класс. Если критично (время исполнения / размер кода) — делаю все члены статичными.
+
avatar
0
понял спасибо. есть два вопроса.

так переменные тоже можно спрятать, просто объявив их не в заголовке *.h, а в *.cpp. функцию тоже не проблема — объявив ее static.

Если критично (время исполнения / размер кода) — делаю все члены статичными.
поясните пожалуйста, не понял что вы имели ввиду?
+
avatar
0
так переменные тоже можно спрятать, просто объявив их не в заголовке *.h, а в *.cpp. функцию тоже не проблема — объявив ее static.
Это Вы спрячете переменную/функцию для остальных компилируемых единиц. Но вы все равно не сможете использовать то же имя в других файлах, линковщик будет материться.
поясните пожалуйста, не понял что вы имели ввиду?
При вызове метода класса (да и при обращении к переменной класса), компилятор, через скрытый указатель this, передает указатель на конкретный экземпляр класса. Можно уменьшить накладные расходы на вызов/обращение, указав static. Тогда этот объект будет общий для всех экземпляров (и адрес будет известен уже на этапе линковки, т.е. можно сразу брать адрес переменной/метода, а не вычислять через указатель_на_экземпляр+смещение_переменной)
+
avatar
0
Спасибо понял. Очень многое прояснилось. Посоветуйте что почитать по C, C++? Заранее спасибо.
+
avatar
0
Да что зайдет. Нет смысла себя насиловать книгой, если стиль изложения автора не нравится.
Всякие там потоки, работу с файлами можно пропускать. Наследование, виртуальные функции можно отложить на потом.
Я начал переползать на С++ в микроконтроллерах в тот момент, когда понял что на С «переизобретаю» С++. Кстати, переход с ассемблера на С происходил аналогичным образом.
+
avatar
+1
Возможно глупый вопрос… Но почему S1, S2, S3, S4 без опторазвязки? На сколько я понимаю во время майских гроз подобные устройства без опторазвязок мрут пачками. Или я не прав?
+
avatar
  • yurok
  • 01 ноября 2023, 15:37
0
внутри помещения с ними проблем не замечено, у меня подобная схема работает 4 года
уличные устройства лучше делать с опторазвязкой, хотя они тоже не 100% помогают
+
avatar
  • redcap
  • 01 ноября 2023, 16:16
0
Но почему S1, S2, S3, S4 без опторазвязки?
Они даже без конденсаторов :)
+
avatar
  • robbadd
  • 01 ноября 2023, 16:46
0
Автор, а не думали сделать в телеграме управление — тогда точно все под рукой?
Собираюсь делать такое де для шлагбаума, прочитал про герконы, надо видимо тоже добавить, но выходит что магнит на палке будет, в геркон внутри ящика где привод и управление. Так вот вопрос — будет работать геркон через металлический корпус?
+
avatar
0
Если планируете телеграм то сразу берите esp32 — ssl шифрование тяжеловато для esp8266. Проверено на этом проекте — mySKU.me/blog/aliexpress/91068.html
+
avatar
  • robbadd
  • 01 ноября 2023, 17:01
0
А что значит тяжеловато? С реле я не делал, но с датчиком температуры 8266 долго работало, все норм
+
avatar
+1
Угу. Оно поначалу работает нормально, но где-то через полгода дефрагментация памяти берет своё (от нее никак не избавится, как бы вы не старались, можно только замедлить ее развитие) и начинаются глюки, зависания и тд и тп. SSL шифрование на esp требует 16КБ памяти одним куском. Через полгода ее просто нет. Там кусок в 1КБ, тут в 3КБ. Если все сложить то да 16КБ есть, но не одной областью. ESP8266 от такого клинит и пошли глюки китайских программистов. Понимаете?

Вот что по этому поводу пишут профи на профильном сайте:
Перезагрузка — единственное решение для моделей CPU без MMU использующих heap память. Других вариантов нет — после нескольких действий вы должны проверить heap на запрос большого непрерывного куска, а если такого уже нет из-за дефрагментации, то идем на перезагрузку.
Все имеющиеся у меня «умные розетки» и прочие WiFi от разных производителей на ESP и прочих тупеньких контроллерах WiFi периодически отваливаются от сети или перезагружаются.
+
avatar
+1
Все же «фрагментация». «Дефрагментация» — противоположный по эффекту процесс.
Хорошо хоть есть возможность проверки на необходимость перегрузки, а не просто «раз в N часов».
+
avatar
+2
Да перепутал. Имел ввиду — фрагментация.
+
avatar
  • yurok
  • 01 ноября 2023, 17:04
0
Конкретно для esp8266 я бы не стал с телеграммом конектиться, лучше тогда какой то одноплатник и с него. Но я не вижу большого смысла, иконка в телефоне и быстрее и удобнее, как по мне
+
avatar
  • infino
  • 01 ноября 2023, 16:51
0
Везде где подключаются длинные шлейфы, надо делать грозозащиту на плате и «разводить иголки» что бы в случае чего стекал набранный заряд.
+
avatar
0
А какое расстояние делать между иголками?
+
avatar
  • infino
  • 01 ноября 2023, 17:14
0
Вопрос хороший, я бы закладывал расстояние в два раз меньшее от стандартного расстояния между дорожками на плате в части клавиатуры, и соответственно эта часть должна быть без маски.
+
avatar
  • Eeyore
  • 01 ноября 2023, 16:58
0
Мощный проект. У меня есть «умные» двери в гараже, они определяют состояние «открыто/закрыто» считая обороты мотора.Еще в систему завязан оптодатчик препятствия, есть оповещение, если не смогла закрыть дверь. Естественно, все завязано на облако, интеграция с Home Assistant на милости производителя (сейчас не работает), нет веб интерфейса (только апп) и синхронизировать две двери нельзя, только вручную. Но зато стоит все это дело не слишком дороже «тупого» привода двери.
+
avatar
0
… интеграция с Home Assistant на милости производителя (сейчас не работает), нет веб интерфейса (только апп) и синхронизировать две двери нельзя, только вручную
God bless America. Потом они вообще забьют на поддержку и скажут покупайте новую улучшенную модель, а старую рабочую на свалку. CEO фирмы гаражных ворот, в пресс-релизе, будет рассказывать, как они заботятся об окружающей среде. Занавес.
+
avatar
  • Eeyore
  • 01 ноября 2023, 17:40
0
Именно в этом случае риск не сильно велик- компания старая и солидная, стандарты и протоколы гаражных дверей меняются медленно, а весь «ум»- в отдельном модуле Ethernet to RF, который заменить легко и дешево.
Но проблема жесткой привязи к своему облаку есть, и она везде. Америку тут пинать нет резона- в случае чего, ваша Алиса превратится в такую же тыкву, как и наша Алекса.
+
avatar
0
Угу. Все хорошо, но почему то не работает :)
Ясно, понятно. Штош, так и запишем.
+
avatar
  • Eeyore
  • 01 ноября 2023, 18:24
0
В своем маленьком мирке оно работает. А на форуме HomeAssistant постоянные страдания, что какие-то фирмы не дают доступ к API.
В принципе это ожидаемо. Если облако компании сдохнет, то 90% пользователей все равно не стали бы заморачиваться с локальным интерфейсом. К тому же дохлое облако скорее всего означает смерть всей фирмы, и судьба девайсов уже никого не волнует. Я стараюсь не покупать зависящее от облака железо, но обычно такого просто нет в природе.
+
avatar
  • yurok
  • 01 ноября 2023, 18:27
+1
Устройство из обзора не зависит от облаков :)
+
avatar
  • Eeyore
  • 02 ноября 2023, 04:59
0
Зато оно зависит от вас :)
+
avatar
  • yurok
  • 02 ноября 2023, 06:59
0
я про процесс работы
+
avatar
  • Eeyore
  • 03 ноября 2023, 05:30
0
Я понимаю, У нас же комменты с :)
+
avatar
  • mooni73
  • 01 ноября 2023, 17:22
+3
Просто пугает основательность автора, хотя схема устройства порадовала — исполнена в классическом стиле, это теперь редкость.
+
avatar
0
Свое решение это конечно хорошо) Но в чем смысл, если есть готовые решения на Али для управления воротами? Цена доступная. В том числе и с поддержкой динамических кодов, и управлением откуда угодно) С весьма симпатичным интерфейсом. Также эти решения прекрасно интегрируются в HomeAssistant и различные сценарии.
+
avatar
  • yurok
  • 01 ноября 2023, 18:34
+1
Примеры таких решений для 2х ворот, с вебом, плиз
И как всегда там будет целый букет «нюансов», здесь же решение которое четко соответствует поставленной задаче и легко модифицируется под изменяемые требования. Себестоимость его, думаю, сами можете прикинуть
+
avatar
+1
Я создал около 16 брелоков в аппке для уточнения возможностей, потом надоело)
Ищите по ключевым словам Wifi RF converter
Себестоимость ~20$ Нюансов не обнаружил. Работает локально и через интернет.
Вот и прикиньте по вашим затратам) Но плюс есть — ваше решение это и хобби, и решение проблемы)
+
avatar
  • yurok
  • 01 ноября 2023, 18:50
+1
а! про это я знаю — это совсем иное )
по сути в приложение перетащит брелок — ни обратной связи ни кнопок… ничего
останется открытый эфир…
это мимо
+
avatar
0
Для этого есть обычная камера наблюдения, которая отдаст статус в HomeAssistat) Вместе с фото события. Достаточно задать «шторку» периметра охраны и добавить в сценарий. Также статус дублируется с помощью триггеров ворот и смарт контроллера. Это плюс 5$)
Кнопки просто дублируются дешёвыми переключателями с поддержкой Tuya. Но их я не делал, так как не видел для себя обходимости. Мне проще голосом)
+
avatar
  • yurok
  • 01 ноября 2023, 19:08
0
ну я писал, что можно нагородить разного
а можно решить что нужно этим устройством
+
avatar
0
Почему нагородить? Такое же рабочее решение) Тем более камеры установлены давным давно. И просто получили дополнительную нагрузку по функционалу)
+
avatar
  • yurok
  • 01 ноября 2023, 19:20
+1
главное чтобы вас устраивало
сами же знаете недостатки всего этого
+
avatar
0
Правильно настроенное плюс регулярные бекапы, равно залог успеха. Плюс простая повторяемость на аналогичном или отличном оборудовании)
+
avatar
+1
обычная камера наблюдения, которая отдаст статус в HomeAssistat)
А как статус ворот от камеры получить?
+
avatar
0
Именно так как описал в третьем предложении из скопированного вами)
+
avatar
0
Ребусы — не самая сильная моя сторона. Третье предложение — это которое начинается после второй точки?
Также статус дублируется с помощью триггеров ворот и смарт контроллера.
— это оно?
Я так умею. Но не умею именно от камеры статус получать. Хочу научиться. Или камера какая-то специальная нужна? Мои вводные: frigate, home assistant, камеры реолинк. Направьте, пожалуйста, в какую сторону мне читать?
+
avatar
  • router
  • 03 ноября 2023, 01:15
0
На некоторых камерах бывает контакт для считывания состояния датчика (чаще всего одного). Встречал такое на ранних панасониковских ИП камерах, и на некоторых дешовых китайских

Как этот сигнал будет обрабатываться камерой — другой вопрос. Можно поставить на ворота нормально закрытый геркон в крайнем нижнем положении ворот. Все остальные положения, кроме полностью закрытых ворот, будут считаться тревогой
+
avatar
0
Да датчиками можно всё решить, я понимаю и пользуюсь этим. Но датчики — это и трудоёмко, и много точек отказа появляется. Мне вот нужно знать в любой момент времени на какой процент ворота открыты — придумал датчик, но там придется городить всякие коромысла и шкивы. А тут весь вопрос сводится к анализу изображения с камеры — именно так я понял из комментария monomaxxp — вот тут мне непонятно. К примеру, обнаружить машину, человека, кошку, направление их движения — это все успешно решает frigate. А вот как отслеживать состояние ворот — для меня загадка.
+
avatar
  • router
  • 03 ноября 2023, 12:13
0
В тех же камерах, о которых я писал, были и выходы на исполнительное устройство. Камера определяла движение, и могла включить, например, сирену или фонарь. Или замкнуть контакты датчика отдельной сигнализации.
Но камера определяла просто движение во всём кадре или на участке кадра.
Статус «процент открытия ворот» оно не выдаст.
Но статус «закрыто»\«не закрыто» камера отдаст
+
avatar
  • andgon
  • 01 ноября 2023, 20:19
0
Ключевые слова ewelink, tuya реле.

Цена от 4 до 8 долларов за шт, есть и на 4,8,16 каналов. Свои приложения и агрегация с Алисой, Алехой, самсунг, и тп


+
avatar
  • yurok
  • 01 ноября 2023, 20:28
+1
Ну я же писал, только частично решит это задачу
+
avatar
+1
ТС у вас неточность. В сетевом кабеле задействованы 4 пары, и вы еще подключаетесь к свободным. Или у вас 8-ми парная мегаUTP? :)
+
avatar
  • yurok
  • 01 ноября 2023, 20:48
0
В сетевом кабеле, который используется по прямому назначению, при гигабитной сети задействованы 4 пары. Но у нас кабель то сетевой, но используется для общения привода ворот с датчиком препятствия в воротах. Там задействовано 4 провода, то есть 2 пары. Остальные проводки я и задействовал для своих целей. Так что неточность в вашем комменте :)
+
avatar
0
Пр гигабитную сеть я в курсе, и про количество пар тоже, по этому я и указал вам на неточность. В целом конечно понятно, что вы хотели сказать, но рекомендую все же еще раз внимательно вчитаться в то, что написано в вашем обзоре:
Кроме приводов имеются уже смонтированные датчики препятствия в проеме ворот, соединенные витой парой. Задействованы только 4 пары в сетевом кабеле. Чтобы не тянуть лишние провода, достаточно присоединиться к существующим свободным парам.
+
avatar
  • yurok
  • 02 ноября 2023, 07:48
+1
А ну это опечатка
+
avatar
+1
автор топика безусловно, молодец, так заморочиться… Вот будет когда-нибудь и у меня на даче интернет нормальный, тоже будет повод задуматься о дополнительной автоматизации.
А вот у меня почему-то возник вопрос совершенно не в тему, глядя на фото гаража — а это у Вас гараж теплый? Если теплый, то почему крыша только жестяным профлистом защищает от окружающей среды?
+
avatar
  • yurok
  • 02 ноября 2023, 00:06
0
Спасибо
теплый сам гараж, а показан привод тамбура, см первый рисунок
+
avatar
  • Boing
  • 01 ноября 2023, 23:51
+1
Автор красавец. Жаль, что самому не повторить просто из-за отсутствия указанных девайсов.
Будь мне нужно что-то такое — с удовольствием бы вам понес тенге)
+
avatar
  • ABATAPA
  • 02 ноября 2023, 08:29
0
Жаль, что самому не повторить просто из-за отсутствия указанных девайсов.

Выше же выкладывали ссылки на готовые устройства. Купите Sonoff, прошейте Tasmota, настройте. Нужно больше GPIO (например, для датчиков) — придётся браться за паяльник.
Ну, или купите готовую плату ESP32, плату с реле, соедините проводочками… И дерзайте! :)
+
avatar
  • Boing
  • 02 ноября 2023, 08:40
0
Спасибо за ответ) я стал смотреть на это более оптимистично) но я скорее про возможность написания кода, создания корпуса, вмешательства в существующий came.
Я со всякими Ардуинами, еспшками и пиками как-то не взлетел..)
+
avatar
0
а что за плата? можно ссылку?
+
avatar
  • ABATAPA
  • 03 ноября 2023, 00:26
0
Какая из? Это Sonoff Basic.
+
avatar
-1
я правильно понимаю, что ворота сможет открыть любой прохожий, получивший доступ к домашней сети?
+
avatar
  • yurok
  • 02 ноября 2023, 07:01
0
и знающий пароль для досупа к устройству,
который задается в интерфейсе
+
avatar
-1
статический пароль который передаётся в эфир? да уж, «граница на замке» (
+
avatar
  • yurok
  • 02 ноября 2023, 12:31
+1
Бвопрос безопасности можно решать поразному. Выделить для устройст отдельную сеть, выключить ее видимость их вне и тп…
Но зачастую достаточно парооль и доступ из внутренней сети, из вне впн.
С брелоками вон вообще открытым текстом все в эфир
+
avatar
-2
это вообще ни разу не про топологию сети. замок с wifi перестаёт быть замком по определению.
а брелоки разные бывают.
+
avatar
  • yurok
  • 02 ноября 2023, 16:04
+1
конкретно здесь и у большинства описывающих тут свои решения именно простые брелки без шифрования 433 МГц
+
avatar
-1
переход с брелков на на wifi безопасности не добавляет, скорее наоборот. навскидку не припомню таких промышленных реализаций, это ж неспроста. впрочем, колхоз — дело добровольное.
+
avatar
  • SerbIu
  • 06 ноября 2023, 23:56
0
Содержание гаражей самоделкиных, как правило, заинтересованной публике абсолютно никакого интереса не представляют. А вот те что представляют, как правило, на простейших открытых 433. Редкие индивиды с патологическими отклонениями покупают что-то более надёжное. Либо опять же технари понимающие, но у которых нет ничего стоящего для прохиндеев)
+
avatar
+3
Подход — нет слов. Очень круто! Электронщик, промдизайнер, программист. Кто ты, воин?!©. Просто шикарно!
Когда сравниваю свое решение с вашим, у меня текут слезы. Понижайка, блок реле, esp8266 — завернуты в пупырку(иначе висло в сильные морозы) и втиснуты в стандартную монтажную коробку 80*80. Зашита тасмота, управляется из Home Assistant. Соседи (ворота общие на въезд) задолбали просьбами поработать швейцаром — прикрутил им открытие из телеги(обратная связь сообщением о событии и/или кнопка снапшота с камеры). Вроде бы и работает все это «и так сойдёт» несколько лет, но такие вот посты заставляют задуматься, что я где-то свернул не туда.
+
avatar
  • ABATAPA
  • 02 ноября 2023, 08:17
0
Сравнивая свое решение с вашим у меня текут слезы.
«Подъезжая к сией станцыи и глядя на природу в окно, у меня слетела шляпа » ©
+
avatar
+2
Согласен, комично получилось. Поправил.
+
avatar
  • karimm
  • 02 ноября 2023, 18:26
0
Подскажите, открытие через телерам на самой esp реализовано или через HA?
+
avatar
0
Телега вся через ХА. Я не знаю, как организовывать отправку с esp, если много user_id(или как там этот номер абонента называется?).
+
avatar
0
Красиво, аккуратно, но выглядит как лютый оверкилл (и как проект человека, у которого есть много свободного времени, извинити)))

Сейчас стоит примерно такая же задача — наружные ворота + две гаражные двери (через гараж можно войти в дом, то есть безопасность критична).
Планирую всё управление сделать исключительно по knx, и радиоканал тоже гонять через knx, купил контроллер с rolling code, завязал ради пробы с homelink в машине — отлично работает, надо теперь будет просто подключить к бинарным входам.
Ну а из полезного что пока сделал — вместо блокировочной перемычки на гаражных воротах воткнул реле, которые отключают возможность открытия ворот если включена сигнализация (у меня ring с z-wave, так что это было достаточно просто).
+
avatar
0
Как ваша солнечная панель с батареями? Если уже какие-то выводы после года+ эксплуатации. Стоит, не стоит? Выгодно, не выгодно? Чтобы поменяли, добавили? Заранее спасибо.
+
avatar
0
Выгодно очень, особенно учитывая подскочившие цены на электричество.
Летом вообще бесплатно всё, даже доплачивают за электричество сданное в сеть (не смотрел сколько начислили, если честно), зимой платим треть от того что должны были бы.

Не, ничего не меняли и не переделывали, в этом году много других забот было, к сожалению.

Давеча четырёхзначный счёт за воду пришёл за несколько месяцев. Оказывается дюймовую стальную трубу, проложенную к дому почти 60 лет назад, где-то прорвало. Кинули по верху времянку пока, но до декабря надо бы полноценно закопать, а то придут минусовые температуры и всё.
Ну и можно запросить от компании-поставщика воды чтобы списали эти потери, потому что никто не заметил и это неумышленная трата, но вначале надо оплатить всё и починить всё.
Ну и чот весь год в таком духе.
+
avatar
0
Спасибо. Не знаю ваших цен. Поэтому задам доп вопрос. С учётом экономии и доплат, сколько приблизительно срок окупаемости всей системы?
+
avatar
0
Два-три года примерно сейчас получается. Мы в идеальный момент поставили всё. Сейчас и на фотовольтаику цены подскочили тоже.
+
avatar
0
3 года — это отличный результат