Files
home_automatization_control…/growbox/README.md
T
cacto bb85c617a4 Добавлен локальный веб-интерфейс и распиновка в README
Плата поднимает страницу + 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).
2026-08-11 19:27:41 +05:00

8.3 KiB
Raw Blame History

growbox (ESP32-контроллер)

Прошивка для реального ESP32, обслуживающая зону "Гроубокс" платформы 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)

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.