Плата поднимает страницу + JSON API (/api/state, /api/command) на порту 80
для наблюдения и управления актуаторами независимо от MQTT/Laravel.
Команда с веб-UI публикует тот же ack в devices/{id}/ack, что и MQTT-команда,
поэтому device shadow платформы не расходится с реальным состоянием.
Включается/выключается флагом ENABLE_WEB_UI в config.h.
В README добавлены ASCII-схема подключения DHT22/реле и раздел про сборку
через arduino-cli (включая обходной путь для проблемы с правами на
~/Documents/Arduino на macOS).
142 lines
8.3 KiB
Markdown
142 lines
8.3 KiB
Markdown
# 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, если он не
|
||
встроен в конкретный модуль.
|
||
|
||
### Схема подключения
|
||
|
||
```
|
||
ESP32 DevKitC
|
||
┌───────────────────────┐
|
||
DHT22 DATA ───────┤ GPIO4 │
|
||
(+10к подтяжка │ │
|
||
DATA -> 3V3) │ │
|
||
│ │
|
||
Реле LIGHT IN ────┤ GPIO16 │
|
||
Реле PUMP IN ────┤ GPIO17 │
|
||
Реле FAN IN ────┤ GPIO18 │
|
||
│ │
|
||
3V3 ────┤ 3V3 │
|
||
GND ────┤ GND │
|
||
USB/5V ─┤ VIN │
|
||
└───────────────────────┘
|
||
|
||
DHT22: VCC -> 3V3 GND -> GND DATA -> GPIO4
|
||
Реле-модуль: VCC -> 5V (VIN) или 3V3 (смотри маркировку модуля)
|
||
GND -> GND (общий с ESP32)
|
||
IN -> GPIO16 / GPIO17 / GPIO18
|
||
|
||
⚠️ Реле коммутируют цепь самой нагрузки (свет/насос/вентилятор, обычно
|
||
12V/220V) через контакты COM/NO/NC — это ОТДЕЛЬНАЯ силовая цепь со своим
|
||
источником питания, к GPIO ESP32 она не подключается. К плате идёт
|
||
только сигнальный IN каждого реле-модуля.
|
||
```
|
||
|
||
## Библиотеки
|
||
|
||
Через Arduino Library Manager (Sketch → Include Library → Manage Libraries):
|
||
|
||
- `PubSubClient` (Nick O'Leary) — MQTT-клиент
|
||
- `ArduinoJson` (Benoit Blanchon, v7) — сериализация/парсинг JSON
|
||
- `DHT sensor library` (Adafruit) + зависимость `Adafruit Unified Sensor`
|
||
- Board support: `esp32` (Espressif Systems) через Boards Manager
|
||
|
||
`WebServer` (веб-интерфейс) и `WiFi` идут в комплекте с board support
|
||
`esp32` — отдельно ставить не нужно.
|
||
|
||
## Веб-интерфейс
|
||
|
||
Каждая плата поднимает у себя простую страницу и JSON API на порту 80 —
|
||
удобно наблюдать/управлять локально, не дожидаясь Laravel/MQTT:
|
||
|
||
- `GET /` — HTML-страница: показания DHT22 + кнопки Вкл/Выкл для
|
||
light-1/pump-1/fan-1.
|
||
- `GET /api/state` — JSON `{"sensor":{"has_reading","temperature","humidity"},"devices":{"light-1":{"power"},...}}`.
|
||
- `POST /api/command` — JSON-тело `{"device_id","action","level"?}`, тот же
|
||
формат, что и в MQTT-команде.
|
||
|
||
Команда с веб-UI применяется через тот же код и публикует тот же ack в
|
||
`devices/{id}/ack`, что и команда из device-control-service — device shadow
|
||
платформы (Redis) не расходится с реальным состоянием железа независимо от
|
||
того, кто его переключил.
|
||
|
||
Включается/выключается флагом `ENABLE_WEB_UI` в `config.h` (`1`/`0`) — при
|
||
`0` HTTP-сервер не поднимается вообще, порт 80 не слушается. У сервера нет
|
||
авторизации — только для локальной сети, как и mosquitto платформы; для
|
||
выхода за пределы LAN сначала нужно добавить хотя бы Basic Auth.
|
||
|
||
## Настройка и прошивка
|
||
|
||
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/веб-сервера и каждой публикации телеметрии/команды, а
|
||
также IP платы для похода в веб-интерфейс.
|
||
|
||
### Сборка через `arduino-cli` (если не через IDE)
|
||
|
||
```bash
|
||
arduino-cli core install esp32:esp32
|
||
arduino-cli lib install "PubSubClient" "ArduinoJson" "DHT sensor library"
|
||
arduino-cli compile --fqbn esp32:esp32:esp32 growbox
|
||
arduino-cli upload --fqbn esp32:esp32:esp32 -p /dev/cu.usbserial-XXXX growbox
|
||
```
|
||
|
||
На macOS `arduino-cli` по умолчанию ставит библиотеки в
|
||
`~/Documents/Arduino/libraries` — если этот каталог защищён sandbox'ом
|
||
(Operation not permitted при установке библиотек, встречалось в среде этого
|
||
агента), перенаправьте sketchbook в доступное место:
|
||
`arduino-cli config set directories.user ~/путь/без/ограничений`. Через саму
|
||
Arduino IDE (GUI-приложение) это обычно не требуется — она сама запрашивает
|
||
нужные разрешения у macOS.
|
||
|
||
## Проверка 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.
|