Как избежать цикла повторного подключения MQTT
У меня есть следующий код, позволяющий мне управлять своим устройством с моего веб-сайта с помощью mqttbroker, пока доступен Интернет. Я также встроил локальный веб-сервер для управления устройством в случае отключения Интернета, поскольку я все еще подключен к тому же маршрутизатору, к которому подключено мое устройство.
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
int ledPin = 2;
const char* ssid = "SSID";
const char* password = "PASS";
const char* mqtt_server = "MQTTSERVER";
const char* mqtt_user = "MQTTUSER";
const char* mqtt_pass = "MQTTPASS";
const char* mqtt_topic = "topic";
String mqttpayload;
WiFiServer server(80);
WiFiClient espClient;
PubSubClient client(espClient);
void setup() {
Serial.begin(115200); pinMode(ledPin, OUTPUT); digitalWrite(ledPin, LOW);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) { delay(100); Serial.print("."); } Serial.println("");
Serial.print("Connected to WiFi");
client.setServer(mqtt_server, 1883); server.begin();
}
void loop() {
client.setCallback(callback);
reconnect();
if ( mqttpayload == "OFF" ) { digitalWrite(ledPin, HIGH); Serial.println("Switced OFF"); }
if ( mqttpayload == "ON" ) { digitalWrite(ledPin, LOW); Serial.println("Switced ON"); }
mqttpayload = "";
WiFiClient cclient = server.available();
if (!cclient) { return; } while(!cclient.available()){ }
String request = cclient.readStringUntil('\r'); Serial.println(request); cclient.flush();
int value = HIGH;
if (request.indexOf("/LED=ON") != -1) {
digitalWrite(ledPin, LOW); value = LOW; Serial.println("Publish message: ON"); reconnect(); client.publish(mqtt_topic, "ON", true);
}
if (request.indexOf("/LED=OFF") != -1) {
digitalWrite(ledPin, HIGH); value = HIGH; Serial.println("Publish message: OFF"); reconnect(); client.publish(mqtt_topic, "OFF", true);
}
cclient.println("HTTP/1.1 200 OK");
cclient.println("Content-Type: text/html");
cclient.println("");
cclient.println("<!DOCTYPE HTML>");
cclient.println("<html>");
cclient.print("LED status: ");
if(value == HIGH) { cclient.print("OFF"); } else { cclient.print("ON"); }
cclient.println("<br><br>");
cclient.println("Turn <a href=\"/LED=ON\">ON</a><br>");
cclient.println("Turn <a href=\"/LED=OFF\">OFF</a><br>");
cclient.println("</html>");
Serial.println("");
}
void callback(char* topic, byte* payload, unsigned int length) {
for (int i = 0; i < length; i++) { mqttpayload += (char)payload[i]; }
}
void reconnect() {
if (!client.connected()) {
while (!client.connected()) {
Serial.print("MQTT..");
if (client.connect("2021", mqtt_user, mqtt_pass)) {
Serial.println("MQTT connected"); client.subscribe(mqtt_topic);
} else { error(); }
}
}
client.loop();
}
void error() { Serial.print("failed, rc="); Serial.print(client.state()); Serial.println(" try again in 5 seconds"); delay(5000); }
Проблема заключается в том, что я тестирую его при подключении к маршрутизатору без без Интернета. Код зацикливается, пытаясь подключиться к серверу MQTT, и зависает, что не позволяет мне отправлять локальные HTTP-запросы.
Я попытался изменить цикл повторного подключения MQTT на приведенный ниже, который решает проблему, но создает другую проблему, заключающуюся в задержке HTTP-запросов до 6–9 секунд.
void reconnect() {
if (client.connect("2021", mqtt_user, mqtt_pass)) {
Serial.println("MQTT connected");
client.subscribe(mqtt_topic);
} else { error(); }
client.loop();
}
Итак, вопрос: что мне делать, чтобы обойти эту проблему?
@ASH, 👍1
Обсуждение1 ответ
В цикле сначала проверьте сеть. Вы также можете выполнить проверку связи с Интернетом, чтобы убедиться, что Интернет доступен. Если отрицательный результат, просто пропустите повторное подключение и попробуйте проверить подключение к Интернету или попробуйте другой способ подключения к MQTT или esp.
- Несколько клиентских серверов через Wi-Fi
- WebSocketsServer.h: No such file or directory
- Как получить данные из базы данных моего сервера в переменную в моем Arduino?
- Как получить параметры запроса от ESPAsyncWebServer?
- контент» не захватывается
- ESP32 в Arduino-IDE с FS.h и SPIFFS
- Как подключиться к MQTT брокеру с помощью TLS?
- Веб-сервер Arduino: более быстрая альтернатива «indexof» для разбора запросов GET?
Вам следует пытаться подключиться к вашему серверу MQTT только при отсутствии активного соединения. С помощью второго фрагмента кода вы (повторно) подключаете каждую итерацию вашего
loop()
, и это может привести к задержке, с которой вы, по-видимому, сталкиваетесь. Поместитеif (!client.connected) { ... }
вокруг кодаif (client.connect()) { .. }
., @StarCat@StarCat, если вы посмотрите на основной код, он там есть, и это меня беспокоит. если подключение к Интернету будет потеряно, Arduino не сможет получать мои HTTP-запросы., @ASH
Вы можете ограничить количество попыток повторного подключения, вызывая reconnect() каждые несколько секунд, а не постоянно. У меня были хорошие результаты при проверке каждые 30 секунд. Если вы это сделаете, вам следует вызвать
client.loop()
из вашего основногоloop()
, а не изreconnect()
., @StarCatЭто довольно просто: на каждой итерации цикла() *если* клиент не подключен, *то* пытайтесь подключиться. Не *пока* клиент не подключен *тогда* попытайтесь подключиться. Каждый раз пробуйте только один раз., @Majenko
Вы можете посмотреть пример PubSubClient
mqtt_reconnect_nonblocking
, который может быть тем, что вы ищете. Он пытается подключиться только тогда, когда соединения нет (я предполагал, что ваш код уже сделал это, но похоже, что это не так)., @StarCat