diff --git a/growbox/README.md b/growbox/README.md index e994cb5..95b43a2 100644 --- a/growbox/README.md +++ b/growbox/README.md @@ -137,6 +137,23 @@ DHT22 (готовый модуль, 3 провода): авторизации — только для локальной сети, как и mosquitto платформы; для выхода за пределы LAN сначала нужно добавить хотя бы Basic Auth. +## Автономная работа без платформы + +Плате не нужен запущенный `docker compose` (`home_automatization`), чтобы +показывать датчики и включать/выключать свет/насос/вентилятор — для этого +достаточно Wi-Fi и веб-интерфейса выше (`http:///`). MQTT-брокер +нужен только для синхронизации с платформой (телеметрия в ClickHouse, +команды из Laravel/rule-engine, device shadow в Redis) — если он недоступен, +эта синхронизация просто не происходит, но локальное управление продолжает +работать. + +Важная деталь реализации: `mqttEnsureConnected()` пробует переподключиться к +брокеру не чаще раза в 5 секунд (`RECONNECT_INTERVAL_MS` в `mqtt_link.cpp`) +— без этой паузы блокирующий `mqttClient.connect()` при недоступном брокере +съедал бы почти весь `loop()` на каждой итерации, и веб-интерфейс с опросом +датчиков подвисали бы. Serial-лог в этом случае пишет `failed, rc=...` раз в +5 секунд — это ожидаемо, если платформа сейчас не поднята, а не поломка. + ## Настройка и прошивка через Arduino IDE 1. **Поддержка ESP32.** Arduino IDE → Settings → «Additional boards manager diff --git a/growbox/mqtt_link.cpp b/growbox/mqtt_link.cpp index f552601..4e6411d 100644 --- a/growbox/mqtt_link.cpp +++ b/growbox/mqtt_link.cpp @@ -63,11 +63,25 @@ void mqttBegin() { mqttClient.setCallback(onMessage); } +// mqttClient.connect() блокирует на время TCP-таймаута, если брокер +// недоступен. Без паузы между попытками это съедало бы почти весь loop() — +// а значит и веб-интерфейс, и опрос датчиков/реле, которые от MQTT не +// зависят и обязаны работать даже без связи с платформой (см. README, +// "Автономная работа без платформы"). +static unsigned long lastConnectAttempt = 0; +static const unsigned long RECONNECT_INTERVAL_MS = 5000; + void mqttEnsureConnected() { if (mqttClient.connected()) { return; } + unsigned long now = millis(); + if (now - lastConnectAttempt < RECONNECT_INTERVAL_MS && lastConnectAttempt != 0) { + return; + } + lastConnectAttempt = now; + Serial.print("[mqtt] connecting to "); Serial.print(MQTT_BROKER_HOST); if (mqttClient.connect(MQTT_CLIENT_ID)) { @@ -75,7 +89,8 @@ void mqttEnsureConnected() { mqttClient.subscribe("devices/+/commands", 1); } else { Serial.print(" failed, rc="); - Serial.println(mqttClient.state()); + Serial.print(mqttClient.state()); + Serial.println(" (это ок, если платформа сейчас не поднята — веб-интерфейс и реле работают локально)"); } }