Ви не увійшли.
Здравствуйте,
у меня контроллер 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 ?
Неактивний