Messages are received by the on_message callback and so this callback must be defined and bound in the main script.
All callbacks rely on the client loop and this must also have been started using loop_start() or loop_forever(), or run manually within the main script.
Provided this is the case it is easy to receive the messages and display them on the console using the example code below:
def on_message(client, userdata, message): print("received message =",str(message.payload.decode("utf-8")))
However to access the message from you main script requires a little more work as the on_message callback is asynchronous and also usually run in a separate thread.
There are three common methods of doing this:
- global variable
- queue object
Using a Global Variable
You could use an on message callback as show below:
def on_message(client, userdata, message): global message_received time.sleep(1) message_received=str(message.payload.decode("utf-8"))
The message received variable is defined in the main script and can be used there.
However how do you test that you have a message and what happens if you get another message before you can process the first message?
Use a List
We can declare a list in the main loop and use it in the callback . It doesn’t need to be a global variable.
The callback would look like this:
def on_message(client, userdata, message): received_messages.append(message)#use an array
and in the main script we would have code like this
received_messages= message=received_messages.pop() print("received in array",str(message.payload.decode("utf-8")))
However this will cause problems when the on_message callback is in another thread as they use a shared array.
Use the Queue object
This is by far the best option as the queue object is thread safe.
To use the queue object you must import it.
We use it very much like an array as shown in the code.
In the main loop we create a queue and extract messages from it using:
from queue import Queue q=Queue() #later in code while not q.empty(): message = q.get() if message is None: continue print("received from queue",str(message.payload.decode("utf-8")))
The on_message callback would look like this:
def on_message(client, userdata, message): q.put(message)
If you want to learn more about the queue object I recommend this pymow tutorial
This is the technique I use in my data logger scripts listed in the resources below.
- Paho Python MQTT Client – Understanding Callbacks
- Paho Python MQTT Client-Understanding The Loop
- How to Log MQTT Sensor Data by Topic Using Python