dobrovolskiy.com
EN
← Заметки2026-08-30 · Дмитрий Добровольский

Как я сделал облачные контроллеры FOURLEDS: ESP32-C3 + LTE, сервер управления парком и дашборд

Кейс: система управления архитектурной подсветкой через сотовую сеть — шесть плат в KiCad, прошивка ESP-IDF с лестницей восстановления модема (PPP поверх CMUX), mesh ESP-NOW, сервер на FastAPI/TimescaleDB. Около 18 объектов в продакшене.

Облачные контроллеры FOURLEDS — законченный продукт для управления подсветкой, который я спроектировал и собрал один: платы в KiCad (ядро на ESP32-C3 + SimCom A7672E, релейный, сенсорный и DALI-модули), прошивка ESP-IDF на C++ с пятиступенчатой лестницей восстановления связи, mesh ESP-NOW между платами и сервер FastAPI + TimescaleDB + EMQX с дашбордом на SvelteKit. Работает примерно на 18 объектах подсветки исторических зданий.

Задача

Архитектурная подсветка исторических зданий включается из уличного щита — на стене во дворе, иногда на мосту. Проводной сети там нет, Wi-Fi обычно тоже. Заказчику (световая компания, где я работаю техническим директором) нужно было, чтобы каждый щит работал по расписанию восход/закат, включался с телефона и сам сообщал о проблеме — выбитом автомате, мёртвом контакторе, тёмном фасаде — раньше, чем позвонят жители.

Готовые GSM-реле умеют коммутировать, но не умеют остального: нет подтверждения, что свет действительно горит, нет общей картины по парку, нет обновления прошивки в поле. Поэтому я сделал весь стек сам.

Железо: один форм-фактор 87 мм, несколько плат

Все платы шириной 87 мм, чтобы вставать в стандартный DIN-щит. Спроектированы в KiCad, изготовлены в нескольких ревизиях (шелкография текущего ядра — FOURLEDS Online controller v. 2.11.7):

Ранний монолитный All-in-One (ESP32-S3 + SIM800C + измерение энергии BL0937, 229 компонентов) и Simple LED Controller 2025 года показывают, откуда выросла модульная схема.

Прошивка: считать, что сеть упадёт

Прошивка на ESP-IDF 5.4, C++17, сборка PlatformIO. Сотовая связь — PPP поверх CMUX (3GPP 27.010), что оставляет параллельный AT-канал для SMS и опроса уровня сигнала при поднятой сессии данных. Выше — MQTT к брокеру EMQX.

Больше всего полевого времени ушло на лестницу восстановления. Сети операторов за CGNAT молча роняют простаивающие сессии; модем может выглядеть подключённым и быть в «чёрной дыре». Контроллер эскалирует по порядку: переподключение MQTT → повторная активация PDP-контекста → переинициализация DCE/DTE модема → цикл питания через PWRKEY → аппаратный RESET. Каждый шаг измеряется и считается.

Чтобы видеть, что реально происходит в поле, каждая плата ведёт журнал стабильности в памяти RTC_NOINIT — он переживает сбросы — и отправляет его на сервер. Многонедельный разбор этих журналов свёл аварии к двум причинам — «чёрным дырам» CGNAT у оператора и исчерпанию кучи при штормах переподключений — и дал точечные исправления: backoff с учётом шторма, подавление всплесков реконнектов и keepalive по нисходящему каналу.

Между платами внутри одного щита Wi-Fi-сети нет вообще: ядро общается с релейной и сенсорной платами по ESP-NOW с кольцами подтверждений и дедупликации, идемпотентным повтором команд и передачей прошивки зависимым платам (dependency OTA). Релейные платы держат локальное расписание — свет переключается, даже если ядро потеряло сеть.

SMS — транспорт последней надежды: команды и статусы запечатаны AES-GCM, подделанное сообщение фасад не переключит.

Сервер и дашборд

Сервер парка — FastAPI с асинхронным SQLAlchemy и Alembic (58 миграций, 40 тестовых модулей), PostgreSQL 17 с TimescaleDB под телеметрию, EMQX Enterprise как MQTT-брокер. В нём MQTT-консьюмер, сервис команд со сторожевым таймером, планировщик восход/закат (astral), OTA-движок, библиотека артефактов которого публикуется автоматически из сборки PlatformIO, и аналитика питания, реле и соблюдения расписания — сравнение того, что запланировано, с тем, что реально увидела сенсорная плата. Telegram-бот отчитывается и принимает команды.

Дашборд — SvelteKit 2 / Svelte 5: карта парка на MapLibre, страницы устройств (пинг, журнал стабильности, история реле, соблюдение расписания), редактор расписаний, OTA, аудит и служебные виды сырого MQTT/ESP-NOW, на двух языках.

Цифры

Около 109 000 строк в прошивке, сервере и дашборде; девять проектов KiCad с герберами, интерактивными BOM и 3D-выгрузками; примерно 18 объектов в продакшене, включая фасады памятников архитектуры в нескольких городах.

Что сделал бы иначе

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

Вопросы

Почему PPP поверх CMUX, а не просто AT-команды?

CMUX мультиплексирует один UART на виртуальные каналы: сессия данных PPP и AT-канал для SMS и уровня сигнала работают одновременно. Без него, чтобы отправить SMS или прочитать CSQ, пришлось бы разрывать сессию данных.

Почему ESP-NOW между платами, а не RS-485?

Платы стоят в сантиметрах друг от друга внутри щита, но шина к каждому модулю — это разъёмы и лишние операции при сборке. ESP-NOW не требует ни сети, ни проводов; слой надёжности (подтверждения, дедупликация, повтор) делает его достаточно предсказуемым для команд реле. RS-485 на релейной плате остался для внешних устройств.

Можно заказать похожий контроллер?

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

Нужно что-то похожее?

Делаю это вживую на звонке в Zoom / Яндекс Телемост, вы смотрите на экран, таймер останавливается по вашему слову. Первые 15 минут бесплатно.

Ещё проекты

Облачные контроллеры FOURLEDSКонтроллеры освещения с сотовой связью для фасадов исторических зданий: шесть плат в KiCad, прошивка на ESP-IDF, сервер управления парком, дашборд