Checking MQTT Subscription Acknowledgements- Python Code Examples

When you subscribe to an MQTT topic there is always a change that the subscription will fail.

Therefore it is important that your code checks that the subscription succeeded.



MQTT provides message Ids for this purpose.

The subscribe function returns a tuple to indicate success, and also a message id which is used as a tracking code.

(result, mid)

Therefore the subscribe call need to check this.

This is what to docs say:

docs-subscribe-function

So in pseudo code we have

  • Try to subscribe and raise an error if it failed
  • check result for 0 and if not zero fail
  • If result =0 then store mid value so we can check it is acknowledged.

This is the python code I use:

def subscribe_topics(client,topics,qos=0):
   print("topic ",topics,"  ",qos)
   
   if type(topics) is not list: #topics should be list of tuples
      if type(topics) is not tuple: #topics isn't tuple?
         topic_list=[(topics,qos)]
      else:
         topic_list=[topics]
   else:
      topic_list=topics
   try:
      r=client.subscribe(topic_list)
      if r[0]==0:
          logging.info("subscribed to topic "+str(topic_list)+" return code" +str(r))
          client.topic_ack.append([topic_list,r[1],0]) #keep track of subscription

      else:
          logging.info("error on subscribing "+str(r))
          print("error on subscribing "+str(r))
          return -1

   except Exception as e:
      logging.info("error on subscribe"+str(e))
      return -1
   return r

Notes: when subscribing the topic and mid value are stored in a list. This list is updated by the on_subscribe callback function as shown below:

def on_subscribe(client,userdata,mid,granted_qos):
   """removes mid valuse from subscribe list"""
   logging.debug("in on subscribe callback result "+str(mid))
   if len(client.topic_ack)==0:
          #print("All subs acknowledged")
          return
   for index,t in enumerate(client.topic_ack):
      if t[1]==mid:
         client.topic_ack.pop(index)#remove it
         #print("removed from list")

Now all we need to do is wait for all subscriptions to be complete. I use a check_subs function that checks the subscribe acknowledgements. Here is the code:

def check_subs(client):
   wcount=0
   while wcount<10: #wait loop
      if len(client.topic_ack)==0:
          return True
      time.sleep(1)
      wcount+=1
      if not client.running_loop:
         client.loop(.01)  #check for messages manually
   return False

The code waits about 10 seconds before it gives up.

Flags and variable used that need to be assigned

client.running_loop #set False if running manual loop otherwise set true

client.topic_ack=[] #list for subscribe topics and mids.

To use the above code we do this:

  • subscribe
  • wait for all subscriptions

The code looks like this:

subscribe(client,"sensors/#")
if not check_subs(client):
   print("missing subscribe acknowledgements")

Subscribing to multiple topics

When you subscribe to multiple topics using a topic list then you only get a single acknowledgement for all topics. The screen shot below shows the mid values when subscribing to single topics, tuple and topic list

mqtt-subscription-acknowledge-example

Resources:

Demo Subscribe acknowledge Script

VideoChecking MQTT Subscribe Acknowledgements

Related Tutorials:

 

Facebooktwittergoogle_plusredditpinterestlinkedinmail

Leave a Reply

Your email address will not be published. Required fields are marked *