Ви не увійшли.
Здравствуйте,
у меня контроллер MEGA2560 + WiFi R3 запитан через блок питания 9В/1А, написал простой скетч для отображения в Monitor Port входящих сообщений от локального MQTT брокера. Работает все хорошо, но не долго, очень часто происходит переподключение к MQTT брокеру => mqtt_client.publish("/logs", "ReConnect");.
Вопрос: в чем можеть быть проблема?
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <DNSServer.h>
#include <WiFiManager.h>
#include <PubSubClient.h>
WiFiClient wifi_client;
PubSubClient mqtt_client(wifi_client);
byte server[] = { 192, 168, 0, 1 };
unsigned long lastMqtt = 0;
void callback(char* topic, byte* payload, unsigned int length) {
	payload[length] = '\0';
	//
	String strTopic = String(topic);
	String strPayload = String((char*)payload);
	//
	Serial.print(F("topic: "));
	Serial.println(strTopic);
	Serial.print(F("message: "));
	Serial.println(strPayload);
}
void setup()
{
	Serial.begin(115200);
	Serial.println(F("start"));
	//
	wifi();
	//
	mqtt_client.setServer(server, 1883);
	mqtt_client.setCallback(callback);
	//
	if (mqtt_client.connect("ESP8266_test", "user", "pass")) {
		mqtt_client.subscribe("/logs");
		mqtt_client.publish("/logs", "Connect");
	}
}
void loop()
{
	if (lastMqtt > millis()) {
		lastMqtt = 0;
	}
	//
	mqtt_client.loop();
	//
	if (millis() > (lastMqtt + 5000)) {
		if (!mqtt_client.connected()) {
			if (mqtt_client.connect("ESP8266_test", "user", "pass")) {
				mqtt_client.subscribe("/logs");
				mqtt_client.publish("/logs", "ReConnect");
			}
		}
		// 
		lastMqtt = millis();
	}
}
void wifi()
{
	WiFiManager wifiManager;
	//
	IPAddress _ip = IPAddress(192, 168, 1, 0);
	IPAddress _gw = IPAddress(192, 168, 1, 0);
	IPAddress _sn = IPAddress(255, 255, 255, 0);
	//
	wifiManager.setAPStaticIPConfig(_ip, _gw, _sn);
	//
	if (!wifiManager.autoConnect("ESP8266", "1234567890")) {
		Serial.println(F("Error"));
		delay(3000);
		ESP.reset();
		delay(5000);
	}
	//
	Serial.println(F("Connected"));
	Serial.print(F("local ip: "));
	Serial.println(WiFi.localIP());
}Неактивний
Из чего Вы взяли что сервер самостоятельно должен Вам (клиенту) что то сообщить, какие то "входящие сообщения"? Он что знает кому и что он должен, даже если к нему не обращаются с "вопросом"? И что значит коннект "не долго"? А с чего Вы взяли что сервер mqtt должен постоянно держать "коннект"? А сервер web постоянно держит какой то "коннект"? Серверам больше делать нечего, да? И в конце концов что такое коннект к серверу? Это что по Вашему коннект к роутеру или хабу? А не кажется ли Вам что инициатором "коннекта" есть клиент? А наличие "коннекта" есть определенный пакет ответа сервера о готовности "обслужить клиента", тогда почему у Вас в скетче как в примерах к библиотеке нет обработчика reconnect? Ну и еще, где и какой используется mqtt сервер, в последних версиях некоторых серверов mqtt особенно тех которые реализованы на Node JS есть особенность- не учитывать длину пакета IP, а библиотека PubSubClient.h (не знаю какая у Вас версия) как раз и учитывает эту длину, поэтому могут и возникнуть всякого рода глюки.
Остання редакція Nefreemen (2018-08-09 23:19:38)
Неактивний
Сервер у меня Mosquitto 3.1 и с моим андроид клиентом идеально держит постоянную связь, в этом и суть данного протокола: один раз соединился, подписался на нужную тему и как тока появилось новое сообщение сразу получил его, а на стороне MEGA из-за постоянных переподключений сообщения попросту в этот период не доходят.
У меня есть проверка в loop() состояния клиента и если клиент по какой-то причине разорвал соединение, значит он не сможет получат сообщения по подписке и не будет работать callback, то идёт повторное соединение и повторная подписка. После этого, сообщения снова приходят пару минут, а потом снова разрыв и через 3-5 попыток получаеться снова соединиться, но сообщения в этот период будут потеряны, а значит контроллер не выполнит команды от андроид-клиента
Неактивний
Добавил комментарии))
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <DNSServer.h>
#include <WiFiManager.h>
#include <PubSubClient.h>
 
WiFiClient wifi_client;
PubSubClient mqtt_client(wifi_client);
 
byte server[] = { 192, 168, 0, 1 };
unsigned long lastMqtt = 0;
 
//callback для получения сообщений от MQTT брокера
void callback(char* topic, byte* payload, unsigned int length) {
    payload[length] = '\0';
    //
    String strTopic = String(topic);
    String strPayload = String((char*)payload);
    //
    Serial.print(F("topic: "));
    Serial.println(strTopic);
    Serial.print(F("message: "));
    Serial.println(strPayload);
}
 
void setup()
{
    Serial.begin(115200);
    Serial.println(F("start"));
    //
    wifi();
    //
	mqtt_client.setServer(server, 1883);
    mqtt_client.setCallback(callback);
	//
    //первичное подключение к MQTT брокеру
    if (mqtt_client.connect("ESP8266_test", "user", "pass")) {
		//подписка на нужную тему
        mqtt_client.subscribe("/logs");
		//публикациясообщения об успешном соединении
        mqtt_client.publish("/logs", "Connect");
    }
}
 
void loop()
{
    if (lastMqtt > millis()) {
        lastMqtt = 0;
    }
    //
	//нужно постоянно вызывать так как асинхронности нет
    mqtt_client.loop();
    //
	//таймер на 5сек.
    if (millis() > (lastMqtt + 5000)) {
		//если mqtt_client.connected == false, значит соединение разорвано
        if (!mqtt_client.connected()) {
			//повторное подключение
            if (mqtt_client.connect("ESP8266_test", "user", "pass")) {
				//повторная подписка, так как повторное подключение к MQTT ьрокеру
                mqtt_client.subscribe("/logs");
				//публикация сообщения о повторном подключении
                mqtt_client.publish("/logs", "ReConnect");
            }
        }
        //
        lastMqtt = millis();
    }
}
 
void wifi()
{
    WiFiManager wifiManager;
    //
    IPAddress _ip = IPAddress(192, 168, 1, 0);
    IPAddress _gw = IPAddress(192, 168, 1, 0);
    IPAddress _sn = IPAddress(255, 255, 255, 0);
    //
    wifiManager.setAPStaticIPConfig(_ip, _gw, _sn);
    //
    if (!wifiManager.autoConnect("ESP8266", "1234567890")) {
        Serial.println(F("Error"));
        delay(3000);
        ESP.reset();
        delay(5000);
    }
    //
    Serial.println(F("Connected"));
    Serial.print(F("local ip: "));
    Serial.println(WiFi.localIP());
}повторное соединение при достижении таймера в 5 сек. при условии что соединение разорвано
if (millis() > (lastMqtt + 5000)) {
		//если mqtt_client.connected == false, значит соединение разорвано
        if (!mqtt_client.connected()) {
			//повторное подключение
            if (mqtt_client.connect("ESP8266_test", "user", "pass")) {
				//повторная подписка, так как повторное подключение к MQTT ьрокеру
                mqtt_client.subscribe("/logs");
				//публикация сообщения о повторном подключении
                mqtt_client.publish("/logs", "ReConnect");
            }
        }
        //
        lastMqtt = millis();
    }Ужасное отображение кода при использовании тега <code> и нет нумерации строк((
API документацию брал с офф.сайта проекта pubsubclient.knolleary.net
Библиотека установлена через менеджер библиотек Arduino IDE, версия библиотеки 2.6.0.
Пробовал устанавливать и другие библиотеки и использовал их примеры, но ничего не изменяется.
Если у кого-то есть ESP8266 и MQTT брокер или время на его установку, то залейте пожалуйста мой код и протестируйте, а то складывается впечатление, что проблема в ESP8266, а не в коде((
Остання редакція Alex777Dark (2018-08-10 10:07:23)
Неактивний
В менеджере ардуино ИДЕ в описании к библиотеке ( да и в АПИ по Вашей сылке) указано что по умолчанию версия протокола mqtt 3.1.1. Ваш сервер 3.1. Там же написано что возможно надо указать в конфигурации версию 3.1. Вы указали MQTT_VERSION?
Неактивний
Переделал код по примеру Nick O’Leary (автор данной библиотеки), что позволило отлавливать состояние клиента
void reconnect() {
  //Переподключение
  while (!mqtt_client.connected()) {
    Serial.print(F("ReConnected..."));
    // Попытка подключения
    if (mqtt_client.connect("ESP8266_test", "", "")) {
      Serial.println(F("Connected"));
      //
      mqtt_client.publish("/logs", "Connected");
      mqtt_client.subscribe("/logs");
    }
    else {
      Serial.print(F("failed, rc="));
      Serial.print(mqtt_client.state());
      Serial.println(F(" try again in 5 seconds"));
      //
      delay(5000);
    }
  }
}переделал файл PubSubClient.h
#define MQTT_VERSION_3_1      3
//#define MQTT_VERSION_3_1_1    4
// MQTT_VERSION : Pick the version
//#define MQTT_VERSION MQTT_VERSION_3_1_1
#ifndef MQTT_VERSION
#define MQTT_VERSION MQTT_VERSION_3_1
#endifПолный код
/*
    Name:       MQTT_new.ino
    Created:  10.08.2018
    Author:     DARK\Admin
*/
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <DNSServer.h>
#include <WiFiManager.h>
#include <PubSubClient.h>
WiFiClient wifi_client;
PubSubClient mqtt_client(wifi_client);
byte server[] = { 192, 168, 0, 1 };
unsigned long lastMqtt = 0;
void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print(F("Message arrived ["));
  Serial.print(topic);
  Serial.print(F("] "));
  for (int i = 0; i<length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
}
void setup()
{
  Serial.begin(115200);
  Serial.println(F("start"));
  //
  wifi();
  //
  mqtt_client.setServer(server, 1883);
  mqtt_client.setCallback(callback);
  //
  delay(1500);
}
void loop()
{
  if (!mqtt_client.connected()) {
    reconnect();
  }
  mqtt_client.loop();
}
void wifi()
{
  WiFiManager wifiManager;
  //
  IPAddress _ip = IPAddress(192, 168, 0, 1);
  IPAddress _gw = IPAddress(192, 168, 0, 1);
  IPAddress _sn = IPAddress(255, 255, 255, 0);
  //
  wifiManager.setAPStaticIPConfig(_ip, _gw, _sn);
  //
  if (!wifiManager.autoConnect("ESP8266", "1234567890")) {
    Serial.println(F("Error"));
    delay(3000);
    ESP.reset();
    delay(5000);
  }
  //
  Serial.println(F("Connected"));
  Serial.print(F("local ip: "));
  Serial.println(WiFi.localIP());
}
void reconnect() {
  //Переподключение
  while (!mqtt_client.connected()) {
    Serial.print(F("ReConnected..."));
    // Попытка подключения
    if (mqtt_client.connect("ESP8266_test", "", "")) {
      Serial.println(F("Connected"));
      //
      mqtt_client.publish("/logs", "Connected");
      mqtt_client.subscribe("/logs");
    }
    else {
      Serial.print(F("failed, rc="));
      Serial.print(mqtt_client.state());
      Serial.println(F(" try again in 5 seconds"));
      //
      delay(5000);
    }
  }
}Получаю в Monitor Port
ReConnected...failed, rc=-2 try again in 5 seconds
ReConnected...failed, rc=-4 try again in 5 seconds
ReConnected...failed, rc=-2 try again in 5 seconds
ReConnected...failed, rc=-2 try again in 5 seconds
ReConnected...failed, rc=-2 try again in 5 seconds
ReConnected...failed, rc=-2 try again in 5 seconds
ReConnected...Connected
ReConnected...failed, rc=-2 try again in 5 seconds
ReConnected...failed, rc=-2 try again in 5 seconds
ReConnected...failed, rc=-2 try again in 5 seconds
ReConnected...Connected
ReConnected...failed, rc=-2 try again in 5 seconds
ReConnected...Connected
ReConnected...failed, rc=-2 try again in 5 seconds
ReConnected...failed, rc=-2 try again in 5 seconds
ReConnected...failed, rc=-2 try again in 5 seconds
ReConnected...failed, rc=-2 try again in 5 seconds
ReConnected...Connected
ReConnected...failed, rc=-2 try again in 5 seconds
ReConnected...failed, rc=-2 try again in 5 seconds
ReConnected...failed, rc=-2 try again in 5 seconds
ReConnected...failed, rc=-2 try again in 5 seconds
ReConnected...failed, rc=-2 try again in 5 seconds
ReConnected...failed, rc=-2 try again in 5 seconds
ReConnected...failed, rc=-2 try again in 5 seconds
ReConnected...failed, rc=-2 try again in 5 seconds
ReConnected...failed, rc=-2 try again in 5 seconds
ReConnected...failed, rc=-2 try again in 5 seconds
ReConnected...failed, rc=-2 try again in 5 seconds
ReConnected...failed, rc=-2 try again in 5 seconds
ReConnected...failed, rc=-2 try again in 5 seconds
ReConnected...failed, rc=-2 try again in 5 seconds
ReConnected...failed, rc=-2 try again in 5 seconds
ReConnected...failed, rc=-2 try again in 5 seconds
ReConnected...failed, rc=-2 try again in 5 seconds
ReConnected...failed, rc=-2 try again in 5 seconds
ReConnected...failed, rc=-2 try again in 5 seconds
ReConnected...failed, rc=-2 try again in 5 seconds
ReConnected...failed, rc=-2 try again in 5 seconds
ReConnected...failed, rc=-2 try again in 5 seconds
ReConnected...failed, rc=-2 try again in 5 seconds
ReConnected...failed, rc=-2 try again in 5 seconds
ReConnected...failed, rc=-2 try again in 5 seconds
ReConnected...failed, rc=-2 try again in 5 seconds
ReConnected...failed, rc=-2 try again in 5 seconds
ReConnected...failed, rc=-2 try again in 5 seconds
ReConnected...failed, rc=-2 try again in 5 seconds
ReConnected...failed, rc=-2 try again in 5 seconds
ReConnected...failed, rc=-2 try again in 5 seconds
ReConnected...failed, rc=-2 try again in 5 seconds
ReConnected...failed, rc=-2 try again in 5 seconds
ReConnected...failed, rc=-2 try again in 5 seconds
ReConnected...failed, rc=-2 try again in 5 seconds
ReConnected...failed, rc=-2 try again in 5 seconds
ReConnected...failed, rc=-2 try again in 5 seconds
ReConnected...Неактивний
Вот Вам и ответ
. Нет (плохое, неустойчивое) сетевое соединение. А на кой Вам библиотека вэб сервера? Она "тяжелая". А DNS сервер зачем?
Выбросил всё что можно + добавил проверку WiFi.status()
/*
Name:       MQTT_new.ino
Created:  10.08.2018
Author:     DARK\Admin
*/
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
WiFiClient wifi_client;
PubSubClient mqtt_client(wifi_client);
IPAddress mqtt_server(192, 168, 1, 77);
const char* ssid = "Zzz";
const char* password = "pass";
void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print(F("Message arrived ["));
  Serial.print(topic);
  Serial.print(F("] "));
  for (int i = 0; i<length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
}
void setup()
{
  Serial.begin(115200);
  Serial.println(F("start"));
  //
  wifi();
  //
  mqtt_client.setServer(mqtt_server, 1883);
  mqtt_client.setCallback(callback);
  //
  delay(1500);
}
void loop()
{
  if (!mqtt_client.connected()) {
    reconnect();
  }
  mqtt_client.loop();
}
void wifi()
{
  delay(50);
  //
  Serial.println();
  Serial.print(F("Connecting to "));
  Serial.println(ssid);
  //
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  //
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  //
  Serial.println(F("WiFi connected"));
  Serial.print(F("IP address: "));
  Serial.println(WiFi.localIP());
}
void reconnect() {
  while (!mqtt_client.connected()) {
    Serial.print(F("ReConnected..."));
    if (mqtt_client.connect("ESP8266_test", "", "")) {
      Serial.println(F("Connected"));
      //
      mqtt_client.publish("/logs", "Connected");
      mqtt_client.subscribe("/logs");
    } else {
      Serial.print(F("Error, rc="));
      Serial.println(mqtt_client.state());
      Serial.print(F("wifi_status="));
      Serial.println(WiFi.status());
      Serial.println(F("Try again in 5 seconds"));
      //
      delay(5000);
    }
  }
}Monitor Port
Connecting to Zzz
.WiFi connected
IP address: 192.168.1.144
ReConnected...Connected
ReConnected...Error, rc=-2
wifi_status=3
Try again in 5 seconds
ReConnected...Connected
ReConnected...Error, rc=-2
wifi_status=3
Try again in 5 seconds
ReConnected...Connected
ReConnected...Error, rc=-2
wifi_status=3
Try again in 5 seconds
ReConnected...Error, rc=-2
wifi_status=3
Try again in 5 seconds
ReConnected...Error, rc=-2
wifi_status=3
Try again in 5 seconds
ReConnected...Error, rc=-2
wifi_status=3
Try again in 5 seconds
ReConnected...Error, rc=-4
wifi_status=3
Try again in 5 seconds
ReConnected...Error, rc=-2
wifi_status=3
Try again in 5 seconds
ReConnected...Connected
ReConnected...Connected
ReConnected...Error, rc=-2
wifi_status=3
Try again in 5 seconds
ReConnected...Error, rc=-2
wifi_status=3
Try again in 5 seconds
ReConnected...Error, rc=-2
wifi_status=3
Try again in 5 seconds
ReConnected...Error, rc=-2
wifi_status=3
Try again in 5 seconds
ReConnected...Error, rc=-2
wifi_status=3
Try again in 5 seconds
ReConnected...Error, rc=-2
wifi_status=3
Try again in 5 seconds
ReConnected...ConnectedЧто я делаю не так ((
Неактивний
Попробуйте в конце сеанса передачи делать mqtt_client.disconnect();
if (mqtt_client.connect(...))
{
   ...
   mqtt_client.disconnect();
}
Неактивний
Попробуйте в конце сеанса передачи делать mqtt_client.disconnect();
if (mqtt_client.connect(...))
{
...
mqtt_client.disconnect();
}
Тогда не будет работать callback и теряется весь смысл подписки((
Неактивний
Тогда не производите повторного соединения когда оно уже открыто.
Неактивний
Тогда не производите повторного соединения когда оно уже открыто.
Я и не провожу, mqtt client сам теряет связь с сервером, а я лишь проверяю есть связь или нет и если нет, то повторно подключаюсь
Неактивний
Вряд ли в данном случае поможет дисконнект. Наверное причина в том что в описании стандарта протокола mqtt нет упоминания о транспортном протоколе и увязке с ним, по большему счету ему на транспорт плевать. Поэтому каждый разработчик сервера или клиента по собственному усмотрению "садит" не фиксированное число байт протокола на IP в пакете которого фиксированное число байт. Происходит за счет дискретности IP разрыв потока протокола mqtt. Отсюда наверное и клиент "не видит сервер" и выдает что нет сети. Вечером если будет время проверю, у меня есть остановленный (отключенный) на роутере москито. Посмотрю логи сервера 
. У меня таких проблем с сервером mqtt установленном на апельсинке сейчас нет, а когда то были, но автор серверную часть не трогал а как то сделал patch.
Неактивний
Издалека трудно сказать, я просто пытался догадаться. Проблема может быть и в сервере и в NAT, если он есть. Скорее всего для удержания соединения вы должны посылать сообщения каждые 15, или сколько там установлено, секунд. Изучайте первоисточники, за вас это никто не будет делать. https://github.com/knolleary/pubsubclient
Неактивний
Последний скетч рабочий. Все отлично работает, никаких реконектов. Проверил. Если будут вопросы свяжитесь через мыло напишу скайп.
Выходит, я гадал на кофейной гуще или искал черную кошку в черной комнате, когда ее там нет. 
 Извините, больше не в свое дело встрявать не буду.
Неактивний
Вячеслав, я тоже гадал 
. Ни Вы ни я всех обстоятельств данного случая не знаем, я как и Вы делал предположения. Но все дело в том что вспомнил один "забавный случай". В марте этого года ко мне обратился за помощью и консультацией один человек, где то из Сибири из под Красноярска (забыл от куда конкретно). Мы убили около трех вечеров (часов 8) по скайпу в поиске проблемы почему у него проблема с ESP8266WebServer.h. Проверяю у себя работает, отсылаю ему не работает и так по кругу раз пять в разных вариантах. А дело оказалось совсем банально. Оставлю интригу можно?
Остання редакція Nefreemen (2018-08-10 19:40:19)
Неактивний
Неактивний
... А дело оказалось совсем банально. Оставлю интригу можно?
Пожалуйста. Я все эти MQTT, CoAP, AMQP и др. пока отложил в долгий ящик, в пользу своих собственных, не сильно лицензионно зависимых, решений. Но хватит ли моих сил на все - незнаю.
Остання редакція Вячеслав Азаров (2018-08-10 23:43:52)
Неактивний
Извиняюсь за задержку. Гусей все таки надо кормить
.
Alex, отлично! А теперь версию ESP8266 Community в студию плиз
...
2.4.2
Я недавно начал программировать под микроконтроллеры, так что установил самые свежие версии
Остання редакція Alex777Dark (2018-08-10 21:24:37)
Неактивний
Установите версию 2.3 (можно 2.2). Скомпилируйте и загрузите 
 . Вы обратили внимание что я оставил 10%  
 , это потому что я не знаю где работает Ваш комарик и как он настроен, а на Вашей версии я не пробовал, у меня абсолютно нет желания ее устанавливать, последнее время индусы рулят всей IT индустрией  
.
Неактивний
Установите версию 2.3 (можно 2.2). Скомпилируйте и загрузите
. Вы обратили внимание что я оставил 10%
, это потому что я не знаю где работает Ваш комарик и как он настроен, а на Вашей версии я не пробовал, у меня абсолютно нет желания ее устанавливать, последнее время индусы рулят всей IT индустрией
.
А flash mode: DIO или QIO ?
Неактивний