Files
home_automatization_control…/growbox/README.md
T
cacto 51c46bf8d6 Пошаговая инструкция по заливке через Arduino IDE в README
Разбита на конкретные шаги (Board Manager URL, ядро, библиотеки, конфиг,
выбор платы/порта, заливка) + типовые проблемы с портом/заливкой и как их
решить. Раньше раздел был в три пункта и не хватало конкретики для первой
прошивки.
2026-08-18 03:59:24 +05:00

165 lines
10 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.
# 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.
## Настройка и прошивка через Arduino IDE
1. **Поддержка ESP32.** Arduino IDE → Settings → «Additional boards manager
URLs» → добавить:
`https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json`
2. **Ядро.** Tools → Board → Boards Manager → найти `esp32` → установить
пакет `esp32 by Espressif Systems`.
3. **Библиотеки.** Tools → Manage Libraries → поставить по одной:
`PubSubClient`, `ArduinoJson` (v7), `DHT sensor library` (IDE предложит
доустановить зависимость `Adafruit Unified Sensor` — согласиться).
4. **Скетч.** File → Open → `controllers/growbox/growbox.ino` — остальные
`.h`/`.cpp` подхватятся вкладками автоматически.
5. **Конфиг.** `cp config.h.example config.h`, заполнить Wi-Fi SSID/пароль,
IP хоста с поднятым `docker compose` платформы (mosquitto слушает
`0.0.0.0:1883` — доступен по IP машины в локальной сети), `zone_id` и
`device_id`. Если IDE уже была открыта — переоткрыть скетч.
6. **Плата и порт.** Подключить ESP32 по USB (кабель именно с передачей
данных). Tools → Board → esp32 → `ESP32 Dev Module` (или точная модель).
Tools → Port → появившийся `/dev/cu.usbserial-*` /
`/dev/cu.SLAB_USBtoUART`.
7. **Заливка.** Кнопка Upload. Часть плат просит зажать кнопку `BOOT` на
плате до появления точек соединения в логе.
8. **Проверка.** Serial Monitor, 115200 бод — лог подключения к
Wi-Fi/NTP/MQTT/веб-сервера, публикации телеметрии/команд и IP платы для
похода в веб-интерфейс.
**Если не заливается:**
- порта нет в списке — нужен драйвер USB-UART моста платы (CP2102 обычно
ставится сам на современной macOS, CH340 — вручную);
- `Failed to connect to ESP32` / `No serial data received` — зажать `BOOT`
на плате на время заливки;
- заливка обрывается или очень долгая — Tools → Upload Speed → понизить с
921600 до 115200.
### Сборка через `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.