Open mr2c12 opened 6 years ago
The publish function returns after the bytes have been passed to the underlying network client, but it does not call flush for you.
You can call flush yourself on the client object you pass into PubSubClient.
Unfortunately the flush() on the WiFiClient does not fix the problem of missing Publish. The only approach that work so far is to use some delay after the publish() call.
A small delay after the disconnect() let the esp8266 to explicitly disconnect from the MQTT server.
I second this strange behaviour. I pretty much use the same sequence as above. All went perfectly, until I added a single value to my JSON message. Suddenly no message arrives the broker anymore.
I even increased the buffer size, without any effect. Something's strange with the publish method. BTW, I use PlatformIO, not Arduino.
I too see this behaviour... I do flush both on the pubsub-client & the wifi-client, but still no message.
So it seems that the wifi-disconnect happens before the messages get sent, even tho I do flush...
As far as I remember, this problem occurs due to how the esp8266 wifi library handle disconnection/deepsleep. It seems that, even if the flush() method is called, the connection closes leaving something behind. So far, the only safe approach is to use some delay before calling disconnect().
I have been using this method for months now, never missed a message. At this point, I think this issue does not represent a problem of the pubsubclient library.
I came to the same problem with publishing a message to the broker from an Firebeetle32 and going to deepsleep afterwards without getting the message to the broker without waiting for 500ms. I didn't find a nice solution until I read the suggestion from mr2c12, that flush() would help, but there is something left behind before closing the connection. In the API I read, that client.disconnect() closes the connection cleanly. But this method does not wait for the clean disconnection where all buffered messages are sent.
My (now working) approach was to check the state of the client and wait until a clean disconnection was performed.
// trigger disconnection from MQTT broker
client.disconnect();
espClient.flush();
// delay(10);
// wait until connection is closed completely
while( client.state() != -1){
delay(10);
}
Now each message was transmitted within about 14ms without having to wait for 500ms to ensure that the message is transmitted reliable. A huge improvement to save energy in a battery driven application. Since I also made some other changes on the code may also other reasons led to the faster transmission but for me this solution works really well.
Edit: Had to wait for additional 10ms after the disconnect, since I still lost some messages without the delay(10). In a further step I added the espClient.flush(); what made the delay(10); obsolete. But against the first impression I still had minor issues with the solution from the initial post without the solutions from the edit. I will monitor this solution further and post updates if any problems occur.
Works like a charm Roland! Disconnect after a client.disconnect() takes roughly 100mS in my case. Seems like a lot, but I didn't want to use a silly 500mS delay. The Last MQTT message does arrive now consistently before my esp8266 goes into DeepSleep. Thanks Gents !
i hadnt realize it was a quick deepSleep problem until i read this issue.. (i thought i had to do client.loop or reconnect etc) @rolandschmidt solution worked perfectly!
In a further step I added the espClient.flush()
Latest version of PubSubClient calls client flush in the disconnect method, so not sure it is necessary separately now. There may have been changes to ESP8266 and PubSubClient that means it is sufficient to call client.disconnect() before the deep sleep and nothing else (no need to check disconnected status). Does it matter how many messages are queued in the buffer?
Hi!
This is a big issue for us and we currently loose messages when we have issues with the connection. I have currently only seen this when our device uses WiFi but the PupSubclient will not know what type of client it gets and it could be either a WiFi, Ethernet or TinyGSM client so the fix must work for all f them. Is there some way to verify that the server has recieved the message or do I have to build that myself with a another topic?
In a further step I added the espClient.flush();
Does anyone have an idea on how to implement this using the ESP-IDF stack? (in C)
I have a complex sketch that check for changes on an input pin and, when it happens:
The sketch is running on a Nodemcu ESP8266.
My problem is that publish() returns true while the message never get to the MQTT server. It seems to me that the problems are the step 5 and 6. When I use a softer approach to power saving and wait ~5 seconds to disconnect from wifi, than everything works, even if it seems that the message is not immediately published to the broker.
If I keep the deep-sleep approach, I can get the mqtt message delivered if a small delay (500ms) is added just after the publish().
Probably related: even the disconnect() method seems to have problems: I can see in the Mosquitto log the connection from the ESP8266, and after like 15 seconds a disconnection due to timeout, like the disconnect() has never been sent.
Is there a method to "flush" (like a Serial communication) everything related to MQTT before disconnecting from the WiFi?