Начальный каркас: прошивка ESP32 для зоны "Гроубокс"

Реализованы sensor-1 (DHT22, телеметрия temperature/humidity) и
реле-актуаторы light-1/pump-1/fan-1 (turn_on/turn_off/set_level) по
протоколу MQTT платформы home_automatization (devices/{id}/telemetry|commands|ack).
This commit is contained in:
2026-08-11 18:46:37 +05:00
commit a645737927
14 changed files with 482 additions and 0 deletions
+68
View File
@@ -0,0 +1,68 @@
# growbox (ESP32-контроллер)
Прошивка для реального ESP32, обслуживающая зону "Гроубокс" платформы
[home_automatization](../../home_automatization). Одна плата владеет четырьмя
устройствами: `sensor-1` (DHT22) и три реле-актуатора — `light-1`, `pump-1`,
`fan-1`.
## Протокол (MQTT, mosquitto из docker-compose платформы, порт 1883)
- `devices/{device_id}/telemetry` — публикует контроллер, JSON
`{"device_id","zone_id","sensor_type","value","timestamp"}`, timestamp —
RFC3339 UTC. `sensor-1` шлёт по одному сообщению на `temperature` и
`humidity` раз в `TELEMETRY_INTERVAL_MS`.
- `devices/{device_id}/commands` — подписывается контроллер (wildcard
`devices/+/commands`, фильтрует по своим 3 актуаторам), JSON
`{"action":"turn_on"|"turn_off"|"set_level","level"?}`.
- `devices/{device_id}/ack` — публикует контроллер после применения команды,
JSON `{"state":{"power":"on"|"off","level"?}}`.
Реального диммирования нет (обычные реле), поэтому `set_level` трактуется как
порог: `level > 0` включает реле, `level <= 0` выключает.
device_id в конфиге должны совпадать с `devices.external_id`, засеянными в
Laravel (`DemoGrowboxSeeder` использует `sensor-1`/`fan-1`), а `zone_id`с
`zones.id` зоны "Гроубокс" в Postgres.
## Железо
| Назначение | Пин (по умолчанию) |
|-----------------|---------------------|
| DHT22 data | GPIO4 |
| Реле — light-1 | GPIO16 |
| Реле — pump-1 | GPIO17 |
| Реле — fan-1 | GPIO18 |
Реле-модули по умолчанию считаются активными по LOW (`RELAY_ACTIVE_LOW` в
`config.h`) — типично для дешёвых китайских модулей на оптопаре. Если ваши
реле активны по HIGH — поменяйте флаг.
DHT22 требует подтягивающий резистор ~10кОм между data и VCC, если он не
встроен в конкретный модуль.
## Библиотеки (Arduino Library Manager)
- `PubSubClient` (Nick O'Leary) — MQTT-клиент
- `ArduinoJson` (Benoit Blanchon, v7) — сериализация/парсинг JSON
- `DHT sensor library` (Adafruit) + зависимость `Adafruit Unified Sensor`
- Board support: `esp32` (Espressif Systems) через Boards Manager
## Настройка и прошивка
1. `cp config.h.example config.h`, заполнить Wi-Fi SSID/пароль, IP хоста, на
котором поднят `docker compose` платформы (mosquitto слушает `0.0.0.0:1883`
— доступен по IP машины в локальной сети), `zone_id` и `device_id`.
2. Открыть `growbox.ino` в Arduino IDE, выбрать плату (ESP32 Dev Module или
конкретную модель), порт.
3. Прошить. Открыть Serial Monitor на 115200 бод — там лог подключения к
Wi-Fi/NTP/MQTT и каждой публикации телеметрии/команды.
## Проверка end-to-end
При работающем `docker compose` в `home_automatization` и засеянных
Postgres-данных (зона + `sensor-1`/`light-1`/`pump-1`/`fan-1`):
- телеметрия должна доходить до ClickHouse через ingest-service;
- команда через Laravel UI (или напрямую через `grpcurl` в
device-control-service) должна прийти на плату и вызвать щелчок реле, а
затем ack — обновить `reported_state`/`last_seen` в Redis device shadow.