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. See Understanding the loop for more details
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")))
Message is an object and the payload property contains the message data which is binary data.
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:
- Use a global variable
- Use a list
- Use the 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 also 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 potentially 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.
The Message Payload
The actual message payload is a binary buffer. In order to decode this payload you need to know what type of data was sent.
If the payload was text data then it is decoded using the appropriate decoder (normally utf-8) as show below:
If it is JSON formatted data then you decode it as a string and then decode the JSON string as follows:
If it is binary data e.g a file then it doesn’t need decoding.
- Introduction to the Paho Python MQTT Client
- Introduction to the Client Class
- Connecting to a Broker
- Publishing Using The Paho Python MQTT Client
- –Subscribing using The Paho Python Client
- Receiving Messages with the Paho MQTT Python Client
- Understanding The Loop
- Understanding Callbacks
- Handling Multiple Client Connections