如何在Python中使用MQTT (Paho)
发表于2022年8月18日
Python是一种解释型、高级、通用的编程语言。由Guido van Rossum创建,并在1991年首次发布,Python的设计理念强调代码的可读性,其显著使用大量的空白。它的语言结构和面向对象的方法旨在帮助程序员为小型和大型项目编写清晰、有逻辑的代码。
MQTT是一种基于发布/订阅模型的轻量级物联网消息传输协议,它可以为物联网设备提供实时和可靠的消息传输服务,只使用很少的代码和带宽。它适用于硬件资源有限的设备和带宽有限的网络环境。因此,MQTT协议被广泛应用于物联网、移动互联网、物联网、电力等行业。
本文主要介绍了在Python项目中如何使用paho-mqtt客户端,并实现MQTT客户端和MQTT代理之间的连接、订阅、消息传递等功能。
项目初始化
本项目使用Python 3.6进行开发和测试。读者可以使用以下命令来确认Python的版本。
➜ ~ python3 --version
Python 3.6.7
选择MQTT客户端
Paho Python客户端提供了一个客户端类,支持Python 2.7或3.x上的MQTT v3.1和v3.1.1,它还提供了一些辅助函数,使发布一个消息到MQTT服务器非常简单。
使用Pip来安装Paho MQTT客户端
Pip是一个Python软件包的管理工具。这个工具为Python包提供查找、下载、安装和卸载的功能。
pip3 install paho-mqtt
Python MQTT的使用
连接到MQTT Broker
本文将使用EMQX提供的免费公共MQTT代理。这项服务是基于MQTT云服务--EMQX云来创建的。该经纪商的访问信息如下。
- 代理商:broker.emqx.io
- TCP端口:1883
- Websocket端口:8083
导入Paho MQTT客户端
from paho.mqtt import client as mqtt_client
设置MQTT代理连接的参数
设置MQTT Broker连接的地址、端口和主题。同时,我们调用Python函数random.randint
来随机生成MQTT客户端的ID。
broker = 'broker.emqx.io'
port = 1883
topic = "python/mqtt"
client_id = f'python-mqtt-{random.randint(0, 1000)}'
# username = 'emqx'
# password = 'public'
编写MQTT连接函数
编写连接回调函数on_connect
。这个函数将在连接客户端后被调用,我们可以根据这个函数中的rc
来确定客户端是否连接成功。通常情况下,我们会同时创建一个MQTT客户端,这个客户端会连接到broker.emqx.io
。
def connect_mqtt():
def on_connect(client, userdata, flags, rc):
if rc == 0:
print("Connected to MQTT Broker!")
else:
print("Failed to connect, return code %d\n", rc)
# Set Connecting Client ID
client = mqtt_client.Client(client_id)
client.username_pw_set(username, password)
client.on_connect = on_connect
client.connect(broker, port)
return client
发布消息
首先,我们定义一个while循环。在这个循环中,我们将设置MQTT客户端publish
函数,每秒钟向主题python/mqtt
发送消息。
def publish(client):
msg_count = 0
while True:
time.sleep(1)
msg = f"messages: {msg_count}"
result = client.publish(topic, msg)
# result: [0, 1]
status = result[0]
if status == 0:
print(f"Send `{msg}` to topic `{topic}`")
else:
print(f"Failed to send message to topic {topic}")
msg_count += 1
编写消息的回调函数on_message
。这个函数将在客户端收到来自MQTT Broker的消息后被调用。在这个函数中,我们将打印出订阅的主题的名称和收到的消息。
def subscribe(client: mqtt_client):
def on_message(client, userdata, msg):
print(f"Received `{msg.payload.decode()}` from `{msg.topic}` topic")
client.subscribe(topic)
client.on_message = on_message
完整的代码
发布消息的代码
# python 3.6
import random
import time
from paho.mqtt import client as mqtt_client
broker = 'broker.emqx.io'
port = 1883
topic = "python/mqtt"
# generate client ID with pub prefix randomly
client_id = f'python-mqtt-{random.randint(0, 1000)}'
# username = 'emqx'
# password = 'public'
def connect_mqtt():
def on_connect(client, userdata, flags, rc):
if rc == 0:
print("Connected to MQTT Broker!")
else:
print("Failed to connect, return code %d\n", rc)
client = mqtt_client.Client(client_id)
client.username_pw_set(username, password)
client.on_connect = on_connect
client.connect(broker, port)
return client
def publish(client):
msg_count = 0
while True:
time.sleep(1)
msg = f"messages: {msg_count}"
result = client.publish(topic, msg)
# result: [0, 1]
status = result[0]
if status == 0:
print(f"Send `{msg}` to topic `{topic}`")
else:
print(f"Failed to send message to topic {topic}")
msg_count += 1
def run():
client = connect_mqtt()
client.loop_start()
publish(client)
if __name__ == ' __main__':
run()
订阅的代码
# python3.6
import random
from paho.mqtt import client as mqtt_client
broker = 'broker.emqx.io'
port = 1883
topic = "python/mqtt"
# generate client ID with pub prefix randomly
client_id = f'python-mqtt-{random.randint(0, 100)}'
# username = 'emqx'
# password = 'public'
def connect_mqtt() -> mqtt_client:
def on_connect(client, userdata, flags, rc):
if rc == 0:
print("Connected to MQTT Broker!")
else:
print("Failed to connect, return code %d\n", rc)
client = mqtt_client.Client(client_id)
client.username_pw_set(username, password)
client.on_connect = on_connect
client.connect(broker, port)
return client
def subscribe(client: mqtt_client):
def on_message(client, userdata, msg):
print(f"Received `{msg.payload.decode()}` from `{msg.topic}` topic")
client.subscribe(topic)
client.on_message = on_message
def run():
client = connect_mqtt()
subscribe(client)
client.loop_forever()
if __name__ == ' __main__':
run()
测试
发布消息
运行发布消息的代码,我们将看到客户端成功连接并成功发布了消息。
python3 pub.py
运行订阅消息的代码,我们将看到客户端成功连接并成功接收发布的消息
python3 sub.py
到目前为止,我们已经完成了使用paho-mqtt客户端连接到免费的公共MQTT代理,并在测试客户端和MQTT代理之间实现了连接、发布消息和订阅消息。
Python与C++或Java等高级语言不同,它更适合于在设备端实现业务逻辑。使用Python可以减少代码的逻辑复杂性,降低与设备交互的成本。我们相信,Python在物联网领域将有更广泛的应用。