Добрый всем. Подскажите пожалуйста. Есп 8266 в исполнении NodeMcu, с подключенным дисплеем на MAX7219 и датчиком освещенности. Есп разговаривает по mqtt с другими девайсами, в частности сервером УД majordomo. Подписок на топики - 7. Шлет сообщения на 4 топика - настроены таймеры отправки. Так же настроена удаленная прошивка по веб. С неясной периодичностью есп теряет связь с mqtt - перестает слать\получать сообщения. Но пинг идет, прошивка "залетает". После перезагрузки модуль начинает работать нормально. Ниже прикладываю код (строки управляющие дисплеем выпилил), может что не так закодил: Код (C++): #include <WiFiUdp.h> #include <PubSubClient.h> #include <ESP8266WiFi.h> #include <ESP8266WebServer.h> #include <Adafruit_GFX.h> #include <ESP8266mDNS.h> // ======================================================================= // Конфигурация устройства: // ======================================================================= const char* host = "informer_in"; const char* ssid = "***"; // SSID const char* password = "***"; // пароль // ======================================================================= const char *mqtt_server = "192.168.1.70"; // Имя сервера MQTT const int mqtt_port = 1883; // Порт для подключения к серверу MQTT const char *mqtt_user = "****"; // Логи от сервер const char *mqtt_pass = "****"; // Пароль от сервера WiFiClient wclient; PubSubClient client(wclient); int clouds; float windSpeed; float temp = 0; String date; String line; String currencyRates; String scroll_String; String text1; //датчик света const int inRaw = A0; //вход датчик света int raw = 0; //сила света int raw_mean = 0; //сила света среднее int raw_old = 0; //сила света String t_out; String t_out_delta; String t_out_delta_sym; String t_banya; String t_banya_delta; String t_banya_delta_sym; String p_atm; String p_atm_delta; String p_atm_delta_sym; boolean mqtt_light_banya = false; //флаг включения света баня //подсчет времени long previousMillis_time = 0; // храним время последнего подключения long interval_time = 3600000; //интервал 1 час //raw long previousMillis_raw = 0; // храним время последнего подключения long interval_raw = 300000; //интервал //mqtt long previousMillis_mqtt = 0; // храним время последнего подключения long interval_mqtt = 10000; //интервал //mqtt raw long previousMillis_mqtt_raw = 0; // храним время последнего подключения long interval_mqtt_raw = 300000; //интервал //wifi long previousMillis_wifi = 0; // храним время последнего подключения long interval_wifi = 10000; //интервал unsigned long currentMillis_wifi = 0; // ======================================================================= // Функция получения данных от сервера void callback(char* topic, byte* payload, unsigned int length) { //-------------------------------------------------------------------------------------- //температура баня if (String(topic) == "ihouse/climat/banya/temp") { t_banya = ""; for (int i = 0; i < length; i++) { t_banya = t_banya +(char)payload[i]; } } if (String(topic) == "ihouse/climat/banya/tempDelta") { t_banya_delta = ""; for (int i = 0; i < length; i++) { t_banya_delta = t_banya_delta +(char)payload[i]; } } //-------------------------------------------------------------------------------------- //температура улица if (String(topic) == "ihouse/climat/out/temp") { t_out = ""; for (int i = 0; i < length; i++) { t_out = t_out +(char)payload[i]; } } if (String(topic) == "ihouse/climat/out/tempDelta") { t_out_delta = ""; for (int i = 0; i < length; i++) { t_out_delta = t_out_delta +(char)payload[i]; } } //-------------------------------------------------------------------------------------- //давление if (String(topic) == "ihouse/climat/out/pressAtm") { p_atm = ""; for (int i = 0; i < length; i++) { p_atm = p_atm +(char)payload[i]; } } if (String(topic) == "ihouse/climat/out/pressAtmDelta") { p_atm_delta = ""; for (int i = 0; i < length; i++) { p_atm_delta = p_atm_delta +(char)payload[i]; } } //-------------------------------------------------------------------------------------- //свет баня if (String(topic) == "ihouse/svet/banya/in") { if ((char)payload[0] == '1') mqtt_light_banya = true; if ((char)payload[0] == '0') mqtt_light_banya = false; } } // ======================================================================= void reconnect() { // подключаемся к MQTT серверу if (WiFi.status() == WL_CONNECTED) { if (!client.connected()) { Serial.print("Attempting MQTT connection..."); if (client.connect("informer_in",mqtt_user, mqtt_pass)) { //подписываемся по топики client.subscribe("ihouse/climat/out/temp"); client.loop(); client.subscribe("ihouse/climat/out/tempDelta"); client.loop(); client.subscribe("ihouse/climat/banya/temp"); client.loop(); client.subscribe("ihouse/climat/banya/tempDelta"); client.loop(); client.subscribe("ihouse/svet/banya/in"); client.loop(); client.subscribe("ihouse/climat/out/pressAtm"); client.loop(); client.subscribe("ihouse/climat/out/pressAtmDelta"); client.loop(); } } } } // ======================================================================= void setup_wifi() { if (currentMillis_wifi - previousMillis_wifi > interval_wifi) { WiFi.begin(ssid, password); //конектимся previousMillis_wifi = currentMillis_wifi; } } // ======================================================================= void setup() { // Удаляем предыдущие конфигурации WIFI сети WiFi.disconnect(); // обрываем WIFI соединения WiFi.softAPdisconnect(); // отключаем отчку доступа(если она была WiFi.mode(WIFI_OFF); // отключаем WIFI delay(500); // присваиваем статичесий IP адрес WiFi.mode(WIFI_STA); // режим клиента WiFi.config(IPAddress(192, 168, 1, 71), IPAddress(192, 168, 1, 1), IPAddress(255, 255, 255, 0), IPAddress(192, 168, 1, 1)); WiFi.begin(ssid, password); delay(10); client.setServer(mqtt_server, mqtt_port); client.setCallback(callback); pinMode(inRaw, INPUT); Serial.begin(115200); // Дебаг } // ======================================================================= // Функция отправки в mqtt void TempSend() { unsigned long currentMillis_mqtt = millis(); unsigned long currentMillis_mqtt_raw = millis(); if (currentMillis_mqtt - previousMillis_mqtt >= interval_mqtt) { previousMillis_mqtt = currentMillis_mqtt; client.publish("ihouse/work/informerIn", String(random(1000)).c_str()); } if (h != h_old) { client.publish("ihouse/clock/h", String(h).c_str()); h_old = h; } if (m != m_old) { client.publish("ihouse/clock/m", String(m).c_str()); m_old = m; } if (currentMillis_mqtt_raw - previousMillis_mqtt_raw >= interval_mqtt_raw) { previousMillis_mqtt_raw = currentMillis_mqtt_raw; client.publish("ihouse/raw", String(raw).c_str()); // отправляем в топик значение освещенности } delay(10); } // ======================================================================= void loop() { unsigned long currentMillis_time = millis(); unsigned long currentMillis_raw = millis(); unsigned long currentMillis_wifi = millis(); //-------------------------------------------------------------------------------------- if (WiFi.status() != WL_CONNECTED) //если нет подключения к вифи { setup_wifi(); } //-------------------------------------------------------------------------------------- if (!client.connected()) { reconnect(); } //-------------------------------------------------------------------------------------- raw = analogRead(inRaw); //запуск синхронизации времени if (currentMillis_time - previousMillis_time >= interval_time) { previousMillis_time = currentMillis_time; getTime(); } client.loop(); TempSend(); } благодарю
Не разобрались? У меня такого, чтобы совсем отвалилось, не было совсем т.т.т. Иногда бывают реконнекты по WiFi и MQTT на ESP, находящихся подальше от точек доступа. У Вас только на этой ESP теряется коннект по MQTT? Попробуйте добавить счетчик реконнектов по WiFi и MQTT и посмотреть, что вообще происходит на этой ESP.
Никогда не работал с открытым брокером iot.eclipse.org и не встречался с такой проблемой. И вот оказалось что так и есть - периодически при наличии коннекта отправка данных не проходит. Устройство в сети, пингуется, в порт гонит требуемую информацию, показывает коннект с брокером, а данные не уходят и не приходят. Как решил. Поставил счетчик неуспешных отправок. Если три раза подряд не уходят данные, уничтожаю объект соединения и устанавливаю соединение сначала. Вообще, в посылке у меня 7-11 топиков. Считаю не только неуспешные отправки в целом, но и неуспешные отправки в пакете. Их бывает тоже. Поскольку следующая отправка зависит от успеха предыдущей, приходится по таймеру, в случае остановки, уничтожать отправку неуспешного пакета. Такой вот ооогромный костыль. Работает. Уже пять дней без проблем. Раньше в течение суток 2-3 раза отправка останавливалась на 3-4 часа и восстанавливалась сама. Повторюсь, проблема только с публичным брокером. Видимо причина на его стороне - забывает о клиенте что ли. Принудительный переконнект - напоминание о себе. Код не привожу - он на Lua. Но логикой можно пользоваться. Код в соответствующей теме.
А какой у Вас таймаут меду получением, отправкой данных на MQTT сервер, когда теряется связь? Может потеря связи происходит из за отсутствия активности долгое время. Я знаю, что в протоколе есть периодический обмен, но, кто его знает... У меня максимальный таймаут - 5 минут, на некоторых устройствах чаще, но больше 5 минут нет. Устройства или что-то получают, или по таймауту, периодически, шлют свои данные. Потери связи - нет.