You found a solution? Is it fixed? What is the solution to a robust connection??
umqtt.robust dies when MQTT broker gets restarted
Hi,
the umqtt.robust module is pretty reliable but I found a case when it stops sending:

As soon as I restart the MQTT broker, I have to connect via WebREPL and press CTRL+C.
I use the following minimal test code:
https://github.com/phieber/uPython-ESP8266-01-umqtt
Can you reproduce this issue when restarting the broker?
br
Patrick
umqtt.robust: check_msg() blocks after reconnect
By testing the issue described in #186 I found that check_msg() did not work as expected in case of reconnection. This isssue may be related to #102 ...
I can reproduce it with the ESP8266 and unix port. Broker is mosquitto 1.3.4 with persistence true.
import utime as time
from umqtt.robust import MQTTClient
def sub_cb(topic, msg):
print((topic, msg))
c = MQTTClient("umqtt_client", SERVER)
c.DEBUG = True
c.set_callback(sub_cb)
c.connect(clean_session=False)
c.subscribe(b"foo_topic")
Now you can call c.check_msg() multiple times and see the non-blocking behaviour and if you publish a message then sub_cb() is called, as expected.
But if you restart the broker and call c.check_msg() again, you get:
>>> c.check_msg()
mqtt: OSError(-1,)
and check_msg() blocks until a new message is published.
This behaviour is obviously, because during reconnect, connect() creates a new socket and do not set non-blocking mode.
IMHO blocking during reconnection is fine, since delay() can be overriden, but check_msg() should not block, without pending message.
can you try to pull #385 and see if it fixes your issue ?
Fixed by 4dc2d5e17f1dfa0ca8af731cb1b6eec437731b25
In the screenshot above, I have restarted the broker after two successful MQTT publish messages (two temperature values in this case)
I use code to avoid such problem:
try: retries = 0 while (retries < 20): retries += 1; client.check_msg() time.sleep(1); except OSError: connect_and_subscribe()def connect_and_subscribe():
global client
client = MQTTClient(CONFIG['client_id'], CONFIG['broker'], CONFIG['port'], "user", "pass", 120)
client.set_callback(callback)
client.connect(False)
print("Conn to {}".format(CONFIG['broker']))
client.subscribe(b"MBI/CURRENT_DATETIME")
time.sleep(1);
client.check_msg()
.....
So I always check if there any OsError and reconnect to MQTT.
You need to upgrade the robust by this PR: [https://github.com/micropython/micropython-lib/pull/117]
Is there a better way to go about handling this situation where the broker 'disappears' and then 're-appears' at some later time? The current implementation of umqtt.robust is not robust at all, even with the reconnect. check_msg never works even though it seems the client reconnected.
Should the umqtt.robust object include a list of subscribed topics to auto-resubscribe in the reconnect() function?
That last message as a microPython newby worries me... I don't want to start coding in microPython on the basis of unreliable MQTT as we have reliable MQTT in C......
Can someone give an example of this "robust" code which WILL stay connected and which will resubscribe on reconnection - i.e. so that it just works in the background.
Is this possible?
Yes, the current implementation of umqtt.robust does not handle the case when the broker is restarted and forgets all of its state (at least the state related to your client).
Prehaps. This is indeed how other libraries work (eg https://github.com/fusesource/mqtt-client). The robust MQTTClient class would need to override the "subscribe" method to record the topics (and qos), and then in the reconnect() method it would call subscribe() again after reconnecting.
See #186 for a fix which will resubscribe to all existing topics if a reconnect is made.
Damn, I was in the process of writing a fix for this. You win the day, sir!
@craftyguy I'd be interested to see your solution. And also if you want to test my solution and give feedback that would be great.
I literally started about less than an hour ago, but my approach was pretty much the same as yours. Your solution looks to be more elegant/robust. I'll give this a shot possibly as early as tomorrow, since I'm tired of hacking together a more robust robust mqtt :smile:
@dpgeorge
I tried your patch (#186), and it doesn't seem to work with this simple test program:
I should note that I am invoking the main() function here from main.py.
When I restart the mqtt broker, I get an
mqtt: OSError(-1,)printed to console. I can see the client reconnects to the broker since there's a message in the broker log about this, but the client doesn't respond to messages published to the IN topic, nor does it publish anything else to OUT topic.If my test is an invalid use of umqtt, please let me know since I am relatively new to using mqtt!
@craftyguy for your example to work I think you need to connect with clean_session=True, because you'll be explicitly resubscribing upon reconnection.
@dpgeorge I see, thank you for pointing that out. I also see the PR was merged :)
I will give it another try!
@craftyguy No it wasn't, so you'll need to pull the PR explicitly to test it.
Ugh, I guess I misinterpreted a notification I received, now I see it
was you just modifying the PR. Sorry!
On Tue, Jun 06, 2017 at 09:53:05PM -0700, Damien George wrote:
I tried the PR and it does recover from a broker restart but when the broker loses power and comes back, it doesn't recover. It is completely reproducible, happens every time I take the power out from my raspberry pi zero running the mosquitto broker. Does anyone else face this behaviour?
The problem seems to be that umqtt.robust does raise an error when killing my mqtt broker from the terminal but doesn't raise any error when broker dies from a power outage.
Is this still an issue on latest MicroPython and mqtt.robut? If so, we need minimal example code on how to reproduce.