0

I am implementing a paho mqtt client. Here is my code:

import paho.mqtt.client as mqtt


def mess(client, userdata, message):
   print("{'" + str(message.payload) + "', " + str(message.topic) + "}")


def subscribe(c_id, topic, server, port):
   cl = mqtt.Client(c_id)
   cl.connect(server, port)
   cl.subscribe(topic)
   cl.on_message = mess
   cl.loop_forever()

this works fine, but I don't want to print the data in 'mess'. I need to return the string inside print() to the calling function. I am calling subscribe() from another program. Any help, direct or recommended reading would be appreciated.

Viraj Jagale
  • 64
  • 1
  • 5
  • 11

3 Answers3

1

With what you have shown you need to use the global flag to update the data variable outside the function.

data = ''

def mess(client, userdata, message):
  global data
  data = "{'" + str(message.payload) + "', " + str(message.topic) + "}"

Also the subscribe function will never return as it is because it calls cl.loop_forever(). If you want it to return you should call cl.loop_start()

Printing data in subscribe won't work either because the client can't actually process the incoming message until you start the network loop (the line after you print it).

Also there is no guarantee when a message will be delivered after you subscribe to a topic.

With out knowing a lot more about exactly what you are trying to achieve I can't be more help, but I think you need to go back and look at your whole approach to take in the asynchronous nature of pub/sub messaging

hardillb
  • 54,545
  • 11
  • 67
  • 105
  • i tried to print/return the global variable after on_message, but it doesn't do anything, i guess because on_message is non-blocking. The print/return statement is executed before any message is received. Is there any way through this? – Viraj Jagale Jun 18 '16 at 15:06
  • Edit your original question with ALL the code you currently have, what you've described does not match the code you've shown – hardillb Jun 18 '16 at 15:09
0

I had exactly the same question and the answer from hardillb did help. I just want to give the complete example using loop_start() and loop_stop().

import paho.mqtt.client as mqtt
import time

current_pose = -1
def on_connect(client, userdata, flags, rc):
    print("Connected with result code "+str(rc))
    print("The position will will be printed in [mm]")
    client.subscribe("send position",qos=1)

def on_message(client, userdata, msg):
    global current_pose
    current_pose = msg.payload.decode('utf8')
    print("Position = ",current_pose)

client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.connect("localhost", 1883, 60)
client.loop_start()

for i in range(0,10):
    time.sleep(1) # wait 1s
    print('current_pose = ', current_pose)
    
client.loop_stop() 
print('the position will not be updated anymore') 

in this example the position is printed every second during ten seconds, additionally, the data will be printed by the callback on_message.

JDArango
  • 1
  • 1
-1

Instead of using the global variable method mentioned, it is also possible to use the Queue package.

import Queue
import paho.mqtt.client as mqtt

q = Queue.Queue() #initialises a first in first out queue

def mess(client, userdata, message):
    q.put(("{'" + str(message.payload) + "', " + str(message.topic) + "}"))

if not q.empty(): #check if the queue is empty
    msg = q.get()  #get the first message which was received and delete

This avoids missing any incoming data or any corruption of the accessed data being overwritten while being used.

bigglet
  • 51
  • 1
  • 2
  • I believe this approach has the same issue as the original question. Specifically, you need to find a way to get the Queue into the scope of the mess function. You would need to make the Queue global to access it outside of the function in order to call Q.get(). – Nick Settje Aug 31 '18 at 09:23
  • 1
    @Nick You can always use functools.partial to take care of that: `def mess(Q, ...): ... client.on_message = functools.partial(mess, Q)` – David Jablonski Feb 26 '19 at 11:53