9.0 KiB
Энергомониторинг v2: LoRa + LAN, сервер учёта, интерфейс (Егорин / ORBIT)
1. Архитектура
┌─ LoRa-узлы (869 МГц) ──→ Шлюз gw1 (ESP32 + RA-01H + W5500, RJ45) ─┐
│ Ethernet
┌─ LAN-узлы (WT32-ETH01, RJ45) ─────────────────────────────────────┤
▼
Mosquitto (Proxmox srv001, :1883)
│
┌───────────────────────────────┼──────────────────┐
▼ ▼ ▼
provisioner.js Home Assistant n8n
(учёт устройств, API :8090, (MQTT Discovery — (алерты в
Postgres, HA Discovery) сущности сами) @Svetdo_bot)
▲
│ REST
Веб-интерфейс (ui-prototype.html → далее React)
Правило выбора транспорта узла: есть розетка RJ45 в щите → LAN-узел (WT32-ETH01, надёжнее, чаще телеметрия, LWT-статус). Кабеля нет → LoRa-узел через шлюз. Протокол данных у обоих одинаковый.
2. Железо (дополнение к v1)
| Позиция | Модель | Цена | Прим. |
|---|---|---|---|
| LAN-узел | WT32-ETH01 (ESP32 + LAN8720, RJ45) | 700–900 ₽ | вместо DevKit+RA-01H |
| Шлюз v2 | ESP32 DevKit + RA-01H + W5500 mini | +250 ₽ к v1 | Ethernet вместо WiFi |
| PoE-вариант | Olimex ESP32-POE | ~2500 ₽ | питание по одному кабелю, для мачт/удалённых щитов |
Распиновка WT32-ETH01: PZEM на IO5/IO17 (UART2); входы реле IO32/IO33 (внутренний pullup) и IO35/IO36 (только вход — внешний pullup 10к на 3.3V); выходы реле IO2/IO4/IO14/IO15. Шлюз: LoRa и W5500 на общей шине VSPI (SCK18/MISO19/MOSI23), CS: LoRa=5, W5500=4.
3. Единое пространство топиков (v2)
| Топик | Направление | Содержимое |
|---|---|---|
nodes/<id>/info |
узел → сервер, retained | паспорт: {"id","fw","hw":"lan|lora","caps":{"pzem":true,"relays":4,"ctl":true},"ip","mac","gw"} |
nodes/<id>/data |
узел → сервер | телеметрия: v, a, w, kwh, pf, hz, r[], seq (+rssi/snr/gw для LoRa) |
nodes/<id>/status |
LAN-узел → сервер | online/offline (LWT). LoRa-узлам статус ставит сервер по таймауту last_seen |
nodes/<id>/cmd |
сервер → узел | {"cmd":"relay","n":0,"s":1} · {"cmd":"poll"} · {"cmd":"info"} |
gateways/<id>/status |
шлюз | online/offline (LWT) |
LAN-узлы публикуют напрямую; LoRa-узлы шлют JSON с полем "t":"info"|"d",
шлюз раскладывает по тем же топикам и добавляет rssi/snr/gw.
4. Механизм добавления устройств на сервер
Принцип: узел регистрируется сам, человек только подтверждает.
Прошивка одинаковая для всех узлов, отличается только NODE_ID — на объекте
монтажнику ничего настраивать не нужно.
- Выход в эфир. При включении узел публикует
nodes/<id>/info(retained). LoRa-узел делает то же через шлюз. Повтор раз в 10 минут. - Регистрация.
provisioner.jsвидит неизвестныйnode_id→ создаёт запись вdevicesсоstatus='pending'. Паспорт (транспорт, IP/MAC или шлюз+RSSI, прошивка, число реле) сохраняется автоматически. - Интерфейс. На экране «Устройства» появляется янтарная полоса «Обнаружены новые устройства» со списком pending-узлов.
- Мастер добавления (3 шага):
- Паспорт — проверка, что это ожидаемый узел (ID, транспорт, RSSI/IP, реле);
- Параметры — название, проект (Егорин/ORBIT), объект, имена реле;
- Подтверждение —
POST /api/devices/<id>/approve.
- Автопубликация в HA. При approve сервис публикует retained-конфиги
MQTT Discovery (
homeassistant/sensor|switch/.../config) — датчики V/A/W/кВт·ч и выключатели реле появляются в Home Assistant без правки yaml. - Жизненный цикл.
pending → active → disabled. Disabled-узел данные пишет, но скрыт с борда и не публикуется в HA. Повторное включение — снова approve.
Замена узла в поле: новый узел с тем же NODE_ID подхватывает старую карточку
(info обновит fw/mac), история сохраняется.
5. REST API (provisioner.js, :8090)
| Метод | Путь | Назначение |
|---|---|---|
| GET | /api/devices?status=pending|active&project=egorin|orbit |
список + последняя телеметрия (view v_devices_board) |
| POST | /api/devices/:id/approve |
{name, project, object, relay_names[]} → active + HA Discovery |
| POST | /api/devices/:id/disable |
скрыть/отклонить |
| POST | /api/devices/:id/cmd |
команда узлу, пишется в журнал commands |
| GET | /api/devices/:id/history?hours=24 |
ряды для графиков |
| GET | /api/devices/:id/relay-events |
журнал переключений реле |
Запуск: npm i mqtt pg express && node provisioner.js
(ENV: MQTT_URL, PG_URL, PORT). Схема БД — schema.sql (Postgres).
6. Структура интерфейса (ORBIT design system)
Стиль: фон #070a10, акцент #4ADE80, Unbounded + Onest + JetBrains Mono,
glassmorphism-карточки. Desktop ≥1024: левый рейл 80px; mobile: нижний таб-бар
(паттерн ORBIT GPS). Рабочий прототип — ui-prototype.html.
├─ Обзор сводка по проектам: Σ кВт·ч сегодня/месяц, узлы в сети,
│ последние события реле, состояние шлюзов
├─ Устройства ★ основной экран (реализован в прототипе):
│ ├─ фильтр-чипы Все / Егорин / ORBIT
│ ├─ полоса «Обнаружены новые устройства» (pending) → мастер добавления
│ ├─ сетка карточек: статус-точка с пульсацией, бейдж LAN/LoRa+RSSI,
│ │ метрики В·А·Вт·кВт·ч (mono), тумблеры реле с именами, last seen
│ └─ карточка узла (drill-down, след. итерация): графики W/kWh за 24ч/30д,
│ журнал реле, паспорт, кнопки poll / перезапрос info / disable
├─ Шлюзы gw1..N: online, IP, число узлов, средний RSSI по узлам
├─ Журнал relay_events + commands: кто переключил, что, когда, источник
└─ Настройки MQTT-брокер, таймаут offline, частота/SF сети, ретенция БД
7. Порядок внедрения
- Postgres: применить
schema.sql(LXC на srv001). - Запустить
provisioner.js(Docker/LXC, systemd). - Прошить шлюз
gateway_lora_eth.ino, воткнуть в свитч щитовой. - Прошить узлы: LAN —
node_lan_energy.ino, LoRa —node_lora_energy_v2.ino(уникальные NODE_ID: eg01…, orb01…, eg-lan1…). - Узлы появятся в pending → добавить через мастер → проверить сущности в HA.
- n8n: подписка на
nodes/+/data, алерты в @Svetdo_bot (узел offline >5 мин, ток выше порога, внеплановое отключение реле).