Python: Publishing messages to MQTT topic

The objective of this post is to explain how to connect to a MQTT broker and post some messages to a topic, using Python.


Introduction

The objective of this post is to explain how to connect to a MQTT broker and post some messages to a topic, using Python.

For this example, we will be using paho-mqtt for Python. Paho-mqtt is a MQTT Python client library which implements versions 3.1 and 3.1.1 of the MQTT protocol [1].

As usual, the easiest way to install this library is by using pip, a tool for installing Python packages. To do so, we just need the following command:

pip install paho-mqtt

As MQTT broker, we will use CloudMQTT, which offers a free plan, amongst other options. You can check here how to create an account and how to create a broker instance.

After completing the procedure, check the instance information page, which should be similar to the one shown in figure 1. The important credentials that we will be using are the server, the user, the password and the port.

ESP8266 CloudMQTT Credentials

Figure 1 – CloudMQTT instance information.


The code

First, we need to import the client class, to have access to all the functionality needed to connect to the broker and publish some messages to topics. This class provides a very simple interface, which means we don’t need to worry about the low level details of the MQTT protocol. We will alias it as mqttClient.

Additionally, we will also import Python’s time module, so we can have access to the sleep function, for introducing some delays in our code.

import paho.mqtt.client as mqttClient
import time

In order to control the state of the connection to the broker, we will declare a global variable called Connected, initialized with “false”. After the connection is established, we will change it to “true”. As we will see later, we will change the value to “true” in a callback function that is executed when the connection is established.

Connected = False #global variable for the state of the connection

Next, we will declare 4 variables to hold the information needed to connect to the server. This will be the information mentioned in the introduction section, shown in figure 1. You should use the information from your instance.

broker_address= "m11.cloudmqtt.com"
port = 12948
user = "yourUSer"
password = "yourPass"

Now, we will create a new client instance. We will pass as argument of the constructor a unique client identifier in format of a string. You can check here other optional arguments that the constructor takes.

client = mqttClient.Client("Python")

Next, we will call the username_pw_set method, which allows to specify a username and optionally a password. This method should be called before the connect method [2], which we will call in a moment.

client.username_pw_set(user, password=password)

We also need to specify a on_connect callback function, which is called when the broker responds to the connection request [3]. We will just assign the function for now and define the actual code latter.

client.on_connect= on_connect

Finally, we will call the connect method, for establishing the connection to the broker. Note that this is a blocking call [4]. It will receive as input the broker address and the port.

client.connect(broker_address, port=port)

Now, we will call a method called loop_start, which will run a thread in background to handle the network connection and sending/receiving data. On the background, it calls a method called loop.

client.loop_start()

Since establishing the connection may take a while, we will do a loop until the previously declared Connected variable is set to true. As we said, this will be done in our callback function, which we still need to specify.

We will insert a small delay between each iteration of the loop.

while Connected != True:    #Wait for connection
    time.sleep(0.1)

After that, we will run a continuous loop in a try except block, that will catch a keyboard interrupt. This way, we can end the loop by sending a ctrl+C command on Python shell.

In this loop, we will use the raw_input function to get an input string from the command line, which we will use to publish to a topic.

To send a message to a topic, we just need to call the publish method, passing as first argument the topic where we want to publish, and has second argument the message to be sent. We will be posting on the “python/test” topic.

In the except block, since the program will finish, we call the disconnect method, to disconnect from the broker. Note that this generates a on_disconnect callback [5], which we are not using in this example.

After that, we also need to call the loop_stop method, to stop the previously launched background thread.

try:
    while True:

        value = raw_input('Enter the message:')
        client.publish("python/test",value)

except KeyboardInterrupt:

    client.disconnect()
    client.loop_stop()

To finish the coding, we just need to specify the on_connect callback function. It receives 4 arguments, as can be seen here. In this example we are only going to use the argument specified in the previous link as rc, which contains the result of the connection. It has the value 0 when the connection is successful.

So, on execution, if rc is equal to 0, we will print a success message and set the value of the Connected variable to “true”. Otherwise, we will print a error message.

Don’t forget to declare the variable as global to modify it outside the scope of the function.

def on_connect(client, userdata, flags, rc):

    if rc == 0:

        print("Connected to broker")

        global Connected                #Use global variable
        Connected = True                #Signal connection 

    else:

        print("Connection failed")

Check the full code bellow:

import paho.mqtt.client as mqttClient
import time

def on_connect(client, userdata, flags, rc):

    if rc == 0:

        print("Connected to broker")

        global Connected                #Use global variable
        Connected = True                #Signal connection 

    else:

        print("Connection failed")

Connected = False   #global variable for the state of the connection

broker_address=	"m11.cloudmqtt.com"
port = 12948
user = "yourUser"
password = "yourPassword"

client = mqttClient.Client("Python")               #create new instance
client.username_pw_set(user, password=password)    #set username and password
client.on_connect= on_connect                      #attach function to callback
client.connect(broker_address, port=port)          #connect to broker

client.loop_start()        #start the loop

while Connected != True:    #Wait for connection
    time.sleep(0.1)

try:
    while True:

        value = raw_input('Enter the message:')
        client.publish("python/test",value)

except KeyboardInterrupt:

    client.disconnect()
    client.loop_stop()


Testing the code

The easiest way to test the code is by using an application that can subscribe to the topic where the Python program will be posting, such as MQTTlens, a Google Chrome application, which connects to a MQTT broker and is able to subscribe and publish to MQTT topics [6].  So, open it and subscribe to the “python/test”.

Then run the Python code, for example, on IDLE, the Python IDE. On the command line, insert the message you want, such as exemplified in figure 2.

Python command line raw input

Figure 2 – Publishing the messages.

In MQTTlens, you should now see the messages sent to the topic, such as shown in figure 3.

MQTTlens Python topic

Figure 3 – Messages received from the subscribed topic.


Related posts


References

[1] https://pypi.python.org/pypi/paho-mqtt/

[2] https://github.com/eclipse/paho.mqtt.python#username_pw_set

[3] https://github.com/eclipse/paho.mqtt.python#on_connect

[4] https://github.com/eclipse/paho.mqtt.python#connect-reconnect-disconnect

[5] https://github.com/eclipse/paho.mqtt.python#disconnect

[6] https://chrome.google.com/webstore/detail/mqttlens/hemojaaeigabkbcookmlgmdigohjobjm

 

Technical details

  • Python version: 2.7.8

11 thoughts on “Python: Publishing messages to MQTT topic”

  1. Reblogged this on The Technology Tinker and commented:
    MQTT is almost a must for everyone who’s interested in home automation. I must admit, I’m reblogging this as much to share with everyone, as to be able to find it easily myself later! I’ve connected using a library on an ESP8266, but not from Python. That’s something that I was planning to figure out anyways…it will make propagating a unified date/time to all of the devices on the network that don’t have access to NTP in an easy way…like ESP8266, arduino, etc, for one thing. And that’s just off the top of my head! If it works for MicroPython as well, then it’s even more useful.

    1. Update: Works great on my Raspberry Pi that I keep up as a little print server in back. So now it’s my MQTT server as well, keeping up with full date, full time, and broken out hour, minute, month, day, and year so I can retrieve just what I need, when I need it. Thanks!

      1. Hi! Awesome news, this opens up the possibility of more complex IoT systems, since it can be used by multiple devices. Thanks for sharing!

        As soon as I have some time, I will try to test it on the LinkItSmart, which runs OpenWRT and also supports Python. It would be another great addition to the list of devices that can use MQTT.

  2. Reblogged this on The Technology Tinker and commented:
    MQTT is almost a must for everyone who’s interested in home automation. I must admit, I’m reblogging this as much to share with everyone, as to be able to find it easily myself later! I’ve connected using a library on an ESP8266, but not from Python. That’s something that I was planning to figure out anyways…it will make propagating a unified date/time to all of the devices on the network that don’t have access to NTP in an easy way…like ESP8266, arduino, etc, for one thing. And that’s just off the top of my head! If it works for MicroPython as well, then it’s even more useful.

    1. Update: Works great on my Raspberry Pi that I keep up as a little print server in back. So now it’s my MQTT server as well, keeping up with full date, full time, and broken out hour, minute, month, day, and year so I can retrieve just what I need, when I need it. Thanks!

      1. Hi! Awesome news, this opens up the possibility of more complex IoT systems, since it can be used by multiple devices. Thanks for sharing!
        As soon as I have some time, I will try to test it on the LinkItSmart, which runs OpenWRT and also supports Python. It would be another great addition to the list of devices that can use MQTT.

  3. Pingback: Python: Subscribing to MQTT topic | techtutorialsx

  4. Pingback: Python: Subscribing to MQTT topic | techtutorialsx

  5. Pingback: ESP32: Publishing messages to MQTT topic | techtutorialsx

  6. Pingback: ESP32: Publishing messages to MQTT topic | techtutorialsx

  7. Pingback: ESP32: Subscribing to MQTT topic | techtutorialsx

  8. Pingback: ESP32: Subscribing to MQTT topic | techtutorialsx

  9. Pingback: LinkIt Smart 7688 Duo: Subscribing to MQTT topic | techtutorialsx

  10. Pingback: LinkIt Smart 7688 Duo: Subscribing to MQTT topic | techtutorialsx

Leave a Reply