knolleary / pubsubclient

A client library for the Arduino Ethernet Shield that provides support for MQTT.
http://pubsubclient.knolleary.net/
MIT License
3.83k stars 1.47k forks source link

ESP hangs when MQTT broker is offline for extended period. #787

Open rocket59 opened 4 years ago

rocket59 commented 4 years ago

My issue is a bit different to wifi disconnection. Occasionally I take my raspberry pi based MQTT broker offline to backup the SD card. As a result of the broker going off line for such an extended period the ESP simply hangs and never recovers even when the pi is started again. Only solution is to physically restart the ESP.

Any solutions to this?

Urs-Eppenberger commented 4 years ago

There are certainly more experienced programmers out there. But since I had to find a way around a similar issue with unstable connections due to bad WiFi or whatever, I share part of my solution here. Maybe other join in to improve on this.

Basically I use state machine to track the various states of the network services: uint8_t connStat = 0; // Connection status for WiFi and MQTT: // // status | WiFi | MQTT // -------+----------+---------- // 0 | down |  down // 1 | starting | down // 2 | up | down // 3 | up | starting // 4 | up | up

In the loop() section I then check for mqttClient.state() to figure out, if I need to restart the device. The WiFi is somewhat easier, since there are callbacks: WiFi.onStationModeDisconnected(onDisconnect) WiFi.onStationModeGotIP(onGotIP) There I handle everything when the WiFi is connected the first time to the access point, or when it lost the connection. It would be interesting to have similar callbacks for the MQTT connection.

rocket59 commented 4 years ago

Thanks for the pointers. I think I should be able to this. What value for mqttClient.state() should I be testing for?

Urs-Eppenberger commented 4 years ago

Check out the documentation here: https://pubsubclient.knolleary.net/api

I test for mqttClient.state() < 0 and if this is the case, then try to reconnect If the error is > 0, then you might have a problem where a simple reconnect might not work anyway.

Since I publish a measurement every 10 seconds, I also do something like this: bool sent = mqttClient.publish(pubTopic.c_str(), payloadStr.c_str()); if (!sent) { connStat = 2; }

If a post to the broker fails, then I set the state machine to state = 2, which means, that the MQTT connection should be re-established.

My guess is, that doing both is overkill, but so far it works.

rocket59 commented 4 years ago

Thanks I will try that!

TuxTroll commented 4 years ago

Hi, i have a similar Problem. It always occures, if the MQTT Broker goes down. It also occures, if MQTT Broker goes down for short time and then goes high again. My PubSubClients ESP8266 changes vom MQTT_State 'disconnected' to 'connected' again. Publishing is OK, but the client did not receive. PubSubClient-Loop()-Function is called in Arduino-loop() but no Data-Receive. I tried to re-subscribe to topics after reconnection, but no solution. I treit to set the CallbackFuction again, but no solution. Only Reset of ESP helps. MQTT-Client always on Connected-State.

TuxTroll commented 3 years ago

Got the problem. Did a mistake in ReSubscribing function after reconnect...