Files
egorin/lora/README_v2.md
T

123 lines
9.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Энергомониторинг 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` — на объекте
монтажнику ничего настраивать не нужно.
1. **Выход в эфир.** При включении узел публикует `nodes/<id>/info` (retained).
LoRa-узел делает то же через шлюз. Повтор раз в 10 минут.
2. **Регистрация.** `provisioner.js` видит неизвестный `node_id` → создаёт запись
в `devices` со `status='pending'`. Паспорт (транспорт, IP/MAC или шлюз+RSSI,
прошивка, число реле) сохраняется автоматически.
3. **Интерфейс.** На экране «Устройства» появляется янтарная полоса
«Обнаружены новые устройства» со списком pending-узлов.
4. **Мастер добавления** (3 шага):
- *Паспорт* — проверка, что это ожидаемый узел (ID, транспорт, RSSI/IP, реле);
- *Параметры* — название, проект (Егорин/ORBIT), объект, имена реле;
- *Подтверждение* — `POST /api/devices/<id>/approve`.
5. **Автопубликация в HA.** При approve сервис публикует retained-конфиги
MQTT Discovery (`homeassistant/sensor|switch/.../config`) — датчики V/A/W/кВт·ч
и выключатели реле появляются в Home Assistant без правки yaml.
6. **Жизненный цикл.** `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. Порядок внедрения
1. Postgres: применить `schema.sql` (LXC на srv001).
2. Запустить `provisioner.js` (Docker/LXC, systemd).
3. Прошить шлюз `gateway_lora_eth.ino`, воткнуть в свитч щитовой.
4. Прошить узлы: LAN — `node_lan_energy.ino`, LoRa — `node_lora_energy_v2.ino`
(уникальные NODE_ID: eg01…, orb01…, eg-lan1…).
5. Узлы появятся в pending → добавить через мастер → проверить сущности в HA.
6. n8n: подписка на `nodes/+/data`, алерты в @Svetdo_bot
(узел offline >5 мин, ток выше порога, внеплановое отключение реле).