umqtt get retained message

Discussion about programs, libraries and tools that work with MicroPython. Mostly these are provided by a third party.
Target audience: All users and developers of MicroPython.
Post Reply
sn81
Posts: 4
Joined: Thu Sep 05, 2019 1:39 pm

umqtt get retained message

Post by sn81 » Tue Oct 08, 2019 2:10 pm

Hi,

On my MQTT server there is a topic with a retained message.

When I try to get this message using [s]wait_msg()[/s] check_msg() in the non-blocking way, the message is not received.
However, using [s]check_msg()[/s] wait_msg(), I will receive the retained message. I would have expected that [s]wait_msg()[/s] check_msg() will get me the message also, if there is a retained message.

On the one hand I could use [s]check_msg()[/s] wait_msg(). But if the topic does not exist/has no retained message my program will wait forever for a message to arrive. Is there some kind of timeout I can set?

Basically what I want to achieve is: check if and what message (a boolean flag so to say) was published in the past (without the client listening at that time).

Any ideas?
Thank you!
Last edited by sn81 on Wed Oct 09, 2019 4:14 pm, edited 1 time in total.

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: umqtt get retained message

Post by pythoncoder » Wed Oct 09, 2019 6:17 am

I am quite confused by this report as check_msg() never blocks and wait_msg() always blocks; this is the reverse of what you seem to be saying.

Looking at the code for umqtt.simple the retained message bit is ignored. As far as I can see, retained messages are treated exactly the same as any other subscription. Unfortunately the code doesn't give you any means of distinguishing an incoming retained message from a normal publication.

I can see no reason why repeated calls to check_msg() won't trigger the subscription callback if a retained message arrives unless you have some kind of timing problem. Clearly the callback needs to be established before you subscribe to the topic as the retained message should arrive as soon as you subscribe.

I suggest you post a minimal example of something which exhibits the problem so we can try to replicate it.
Peter Hinch
Index to my micropython libraries.

sn81
Posts: 4
Joined: Thu Sep 05, 2019 1:39 pm

Re: umqtt get retained message

Post by sn81 » Wed Oct 09, 2019 4:21 pm

pythoncoder wrote:
Wed Oct 09, 2019 6:17 am
I am quite confused by this report as check_msg() never blocks and wait_msg() always blocks; this is the reverse of what you seem to be saying.
I am so sorry for the confusion... in my post, I totally mixed up check_msg() and wait_msg(). I edited the post accordingly.

Nevertheless, here is a minimal example:

Code: Select all

def sub_cb(t, m):
	print (t, m)

def get_msg(node, server, topic, blocking=False):
	c = MQTTClient(node, server)
	c.set_callback(sub_cb)
	c.connect()
	c.subscribe(topic)
	if blocking:
		# Blocking wait for message
		c.wait_msg()
	else:
		# Non-blocking wait for message
		c.check_msg()
	c.disconnect()
When I execute

Code: Select all

get_msg(node, server, topic, False)
I do not receive the retained message (message is sent before(!) code is executed!).
However, executing

Code: Select all

get_msg(node, server, topic, True)
will print the retained message.

kevinkk525
Posts: 969
Joined: Sat Feb 03, 2018 7:02 pm

Re: umqtt get retained message

Post by kevinkk525 » Wed Oct 09, 2019 6:34 pm

Are you executing

Code: Select all

get_msg(node, server, topic, False)
multiple times?
Kevin Köck
Micropython Smarthome Firmware (with Home-Assistant integration): https://github.com/kevinkk525/pysmartnode

sn81
Posts: 4
Joined: Thu Sep 05, 2019 1:39 pm

Re: umqtt get retained message

Post by sn81 » Wed Oct 09, 2019 7:21 pm

No, just once, as I expected that the retained message will be fetched at the first try.

Thanks to your suggestion I adapted the get_msg(node,server,topic,False):

Code: Select all

def get_msg(node, server, topic, blocking=False):
	c = MQTTClient(node, server)
	c.set_callback(sub_cb)
	c.connect()
	c.subscribe(topic)
	if blocking:
		# Blocking wait for message
		c.wait_msg()
	else:
		# Non-blocking wait for message
		for i in range(10):
			print(i)
			c.check_msg()
			time.sleep(1)
	c.disconnect()
Now I receive the retained message when the loop is executed the second time (i.e., i=1).

Is this the expected behavior?

kevinkk525
Posts: 969
Joined: Sat Feb 03, 2018 7:02 pm

Re: umqtt get retained message

Post by kevinkk525 » Wed Oct 09, 2019 8:32 pm

As this method uses non-blocking sockets it is possible that it doesn't have any data available at the first execution. You call that method many times in a continous loop to keep receiving messages so it doesn't really matter if you receive it at the first call or the 2nd or 3rd.
Kevin Köck
Micropython Smarthome Firmware (with Home-Assistant integration): https://github.com/kevinkk525/pysmartnode

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: umqtt get retained message

Post by pythoncoder » Thu Oct 10, 2019 8:09 am

Yes. In non blocking mode the code is running to completion before the broker has sent the message. A nonblocking application must repeatedly call check_msg in a loop - all the time until the application terminates. See the example script.
Peter Hinch
Index to my micropython libraries.

Post Reply