From 988c574183de51c596fae2bd6e014ab0ae945550 Mon Sep 17 00:00:00 2001 From: Dmitry Gammel Date: Tue, 18 Aug 2026 13:09:15 +0500 Subject: [PATCH] =?UTF-8?q?=D0=9D=D0=B5=20=D0=B1=D0=BB=D0=BE=D0=BA=D0=B8?= =?UTF-8?q?=D1=80=D0=BE=D0=B2=D0=B0=D1=82=D1=8C=20loop()=20=D0=B1=D0=B5?= =?UTF-8?q?=D1=81=D0=BA=D0=BE=D0=BD=D0=B5=D1=87=D0=BD=D1=8B=D0=BC=D0=B8=20?= =?UTF-8?q?=D0=BF=D0=BE=D0=BF=D1=8B=D1=82=D0=BA=D0=B0=D0=BC=D0=B8=20=D0=BF?= =?UTF-8?q?=D0=BE=D0=B4=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D0=B8=D1=8F=20?= =?UTF-8?q?=D0=BA=20MQTT?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit mqttClient.connect() блокирует на время TCP-таймаута, если брокер недоступен. Без паузы между попытками это происходило на каждой итерации loop() — веб-интерфейс и опрос датчиков/реле (не зависят от MQTT и должны работать даже без платформы) подвисали. Теперь переподключение пробуется не чаще раза в 5 секунд. В README добавлен раздел "Автономная работа без платформы" — что именно работает локально без docker compose, а что требует брокера. --- growbox/README.md | 17 +++++++++++++++++ growbox/mqtt_link.cpp | 17 ++++++++++++++++- 2 files changed, 33 insertions(+), 1 deletion(-) 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(" (это ок, если платформа сейчас не поднята — веб-интерфейс и реле работают локально)"); } }