Files
ponics-protocol/DEVICE_BEHAVIOR.md
T

6.5 KiB

Device Behavior

Конечный автомат устройства

stateDiagram-v2
    [*] --> Booting: Включение питания
    Booting --> WiFiConnect: Инициализация периферии
    WiFiConnect --> MQTTConnect: WiFi OK
    WiFiConnect --> WiFiConnect: Retry (exponential backoff)
    MQTTConnect --> Connected: MQTT OK
    MQTTConnect --> MQTTConnect: Retry (exponential backoff)

    Connected --> Publishing: Таймер сбора данных
    Publishing --> Connected: Данные отправлены

    Connected --> ExecutingCmd: Получена команда MQTT
    ExecutingCmd --> Connected: Команда выполнена

    Connected --> OTA: Получена cmd/ota
    OTA --> [*]: Перезагрузка после обновления

    Connected --> Disconnected: Потеря связи
    Disconnected --> MQTTConnect: Reconnect (exponential backoff)

    Connected --> [*]: cmd/reboot или WDT reset

Последовательность запуска

  1. Boot — инициализация I2C, SPI, OneWire, MCP23017
  2. WiFi — подключение, получение IP (exponential backoff при неудаче)
  3. MQTT connect — handshake с брокером
  4. LWT настройка{UID}/availability = "offline" при разрыве
  5. Publish {UID}/status = "connected" — уведомление сервера
  6. Получить preferences — сервер отвечает {UID}/set/preferences/all
  7. Применить калибровку — записать коэффициенты в NVS/RAM без перезагрузки
  8. Запуск основного цикла — периодический сбор и публикация данных

Периодичность публикации данных

Датчик Интервал
pH, EC, wNTC ~10 сек
AirTemp, AirHum, AirPress ~30 сек
RootTemp (DS18B20) ~15 сек
RSSI, CPUTemp, FreeHeap, Vcc ~60 сек
uptime ~60 сек
MixerWeight ~5 сек (если mixer_enabled)
mcp/gpio при изменении состояния

Обработка команд

Все команды fire-and-forget — ответ не отправляется.

cmd/reboot

  1. Завершить активные операции помп (стоп)
  2. ESP.restart()

cmd/gpio/{pin}

  • Проверить pin ∈ [0, 15], payload ∈ {"0", "1"}
  • MCP23017 → setPin(pin, state)

set/pump/{id}/run

  • Проверить id ∈ [1, 8], time ∈ [1, 60000]
  • Включить помпу → таймер → выключить

set/pump/{id}/dispense

  • Проверить id ∈ [1, 8], grams ∈ [0.1, 1000]
  • Рассчитать время через ml/sec калибровку помпы
  • Включить → таймер → выключить
  • Обновить счётчик total_dispensed

cmd/pump/{id}/stop

  • Проверить id ∈ [1, 8]
  • Немедленно выключить помпу, сбросить таймер

set/preferences/all

  • Разобрать JSON, обновить только пришедшие поля в NVS / RAM
  • Применить новые коэффициенты без перезагрузки

cmd/ota

  • Payload: пустой (использует preferences.updateUrl) или URL строка (override)
  • Скачать и прошить firmware.bin
  • Перезагрузиться

cmd/ota-storage

  • Аналогично cmd/ota но для LittleFS (preferences.updateFsUrl)

Pump ID: единый стандарт 1–8

Сервер и прошивка используют 1-based индексацию (1–8).
Исправлено в прошивке: commit aa5db288 — валидация 0-71-8 в mqtt_callbacks.cpp.


Reconnect логика

  • WiFi: встроенный авто-реконнект ESP-IDF
  • MQTT: экспоненциальный backoff (1s → 2s → 4s → ... → max 60s)
  • При восстановлении: публикует {UID}/status = "connected" → сервер снова шлёт preferences

Важно: Публикация status = "connected" должна происходить в колбэке подключения MQTT,
а не только при первом старте. Иначе после реконнекта устройство не получит настройки с сервера.


Типичные ошибки реализации

1. Неверный payload в {UID}/status

❌ "online", "Online", "connected\n", "1"
✅ "connected"

Сервер проверяет точное совпадение байт. Неверный payload → push_box_settings не вызывается →
устройство работает без калибровок из БД до следующей перезагрузки.

2. status публикуется только при первом старте

При реконнекте MQTT (после обрыва WiFi, перезапуска брокера) нужно снова опубликовать
{UID}/status = "connected". Иначе после восстановления связи настройки не придут.

3. Pump ID отсчёт

API использует 1-based индексацию (1–8). Прошивка внутренне хранит 0-based, но
MQTT-команды и HTTP API принимают 1-based. Проверять валидацию: id ∈ [1, 8].

4. HTTP API требует Accept: application/json

При обращении к ponics.online API без этого заголовка сервер может вернуть 302 (редирект
на страницу логина) вместо JSON. Клиенты должны явно указывать Accept: application/json.


Home Assistant интеграция (отдельный канал)

Прошивка поддерживает параллельную интеграцию с Home Assistant через MQTT.
Топики (не используются сервером ponics.online):

  • {UID}/availability — online/offline
  • {UID}/pin/{i}/cmd — управление GPIO
  • {UID}/pin/{i}/state — состояние GPIO
  • {UID}/mixer/cmd — управление миксером
  • Autodiscovery топики для HA