前言
paho-mqtt是一个Python实现的MQTT客户端库,它提供了MQTT协议的基本功能。使用paho-mqtt,你可以在Python应用程序中创建MQTT客户端,连接到MQTT代理(broker),并发布消息和订阅主题。
paho-mqtt具有以下优点:
- 支持多种MQTT版本 - paho-mqtt支持MQTT v3.1和v3.1.1两个版本的协议,可以方便地满足不同项目或设备的需求。
- 可靠性高 - paho-mqtt使用异步I/O,可确保消息在通信时即使网络中断或断开连接也能够被正确处理。
- 容易集成 - paho-mqtt提供了完备、清晰的API,使用非常容易。
- 广泛的平台支持 - paho-mqtt适用于各种不同平台、操作系统和Python版本,包括Windows、Linux、macOS等。
- 社区活跃 - paho-mqtt是一个活跃的开源项目,在GitHub上有很多开发者参与维护和更新,可以及时获得技术支持和问题解答。
一、安装paho-mqtt
1、通过命令安装
pip install paho-mqtt
二、实现MQTT发布和订阅
1、发布消息
from paho.mqtt import client as mqtt
import uuid
def on_connect(client, userdata, flags, rc):
"""
一旦连接成功, 回调此方法
rc的值表示成功与否:
0:连接成功
1:连接被拒绝-协议版本不正确
2:连接被拒绝-客户端标识符无效
3:连接被拒绝-服务器不可用
4:连接被拒绝-用户名或密码不正确
5:连接被拒绝-未经授权
6-255:当前未使用。
"""
rc_status = ["连接成功", "协议版本不正确", "客户端标识符无效", "服务器不可用", "用户名或密码不正确", "未经授权"]
print("connect:", rc_status[rc])
def mqtt_connect():
"""连接MQTT服务器"""
mqttClient = mqtt.Client(str(uuid.uuid4()))
mqttClient.on_connect = on_connect # 返回连接状态的回调函数
MQTTHOST = "IP" # MQTT服务器地址
MQTTPORT = 1883 # MQTT端口
mqttClient.username_pw_set("username", "password") # MQTT服务器账号密码, 无密码时注释即可
mqttClient.connect(MQTTHOST, MQTTPORT, 60)
mqttClient.loop_start() # 启用线程连接
return mqttClient
def mqtt_publish():
"""发布主题为'mqtt/demo',内容为'Demo text',服务质量为2"""
mqttClient = mqtt_connect()
text = "Demo text"
mqttClient.publish('mqtt/demo', text, 2)
mqttClient.loop_stop()
if __name__ == '__main__':
mqtt_publish()
2、订阅消息
from paho.mqtt import client as mqtt
import uuid
def on_connect(client, userdata, flags, rc):
"""一旦连接成功, 回调此方法"""
rc_status = ["连接成功", "协议版本不正确", "客户端标识符无效", "服务器不可用", "用户名或密码不正确", "未经授权"]
print("connect:", rc_status[rc])
def on_message(client, userdata, msg):
"""一旦订阅到消息, 回调此方法"""
print("主题:"+msg.topic+" 消息:"+str(msg.payload.decode('gb2312')))
def mqtt_connect():
"""连接MQTT服务器"""
mqttClient = mqtt.Client(str(uuid.uuid4()))
mqttClient.on_connect = on_connect # 返回连接状态的回调函数
mqttClient.on_message = on_message # 返回订阅消息回调函数
MQTTHOST = "IP" # MQTT服务器地址
MQTTPORT = 1883 # MQTT端口
mqttClient.username_pw_set("username", "password") # mqtt服务器账号密码
mqttClient.connect(MQTTHOST, MQTTPORT, 60)
mqttClient.loop_start() # 启用线程连接
return mqttClient
def on_subscribe():
"""订阅主题:mqtt/demo"""
mqttClient = mqtt_connect()
mqttClient.subscribe("mqtt/demo", 2)
while True:
pass
if __name__ == '__main__':
on_subscribe()
3、通过queue获取订阅消息
- Queue类
Queue类是一种FIFO(先进先出)队列,它使用锁来实现线程安全。可以使用Queue(maxsize)创建一个新的队列对象,maxsize是可选参数,指定队列的长度。如果maxsize小于或等于零,则队列大小无限制。
常见方法:
- get(block=True, timeout=None): 从队列中取出并返回一个元素。如果队列为空,且block为True且timeout不为None,则会阻塞直到获取到一个元素或超时。否则,如果队列为空且block为False,则会引发Empty异常。
- put(item, block=True, timeout=None): 将item放入队列。如果队列已满,且block为True且timeout不为None,则会阻塞直到有空间或超时。否则,如果队列已满且block为False,则会引发Full异常。
- empty(): 如果队列为空,则返回True,否则返回False。
- full(): 如果队列已满,则返回True,否则返回False。
- qsize(): 返回队列中元素的数量。
# a.py文件
from paho.mqtt import client as mqtt
import uuid
import queue # 导入 queue 模块,该模块为实现多线程编程提供了队列数据结构
# 创建了一个 Queue 对象,该对象可用于多线程编程中线程间通信和数据共享
message_queue = queue.Queue()
class Subscription():
def __init__(self, mt_ip, mt_user, mt_pwd):
self.mt_ip = mt_ip
self.mt_user = mt_user
self.mt_pwd = mt_pwd
def on_connect(self, client, userdata, flags, rc):
"""一旦连接成功, 回调此方法"""
rc_status = ["连接成功", "协议版本不正确", "客户端标识符无效", "服务器不可用", "用户名或密码不正确", "未经授权"]
print("connect:", rc_status[rc])
def on_message(self, client, userdata, msg):
"""
msg.payload.decode('gb2312', 'ignore'):
表示将 msg.payload 使用 GB2312 进行解码,并指定当遇到无法解码的字符时使用 ignore 参数进行错误处理,即忽略无法解码的字符
msg.payload.decode('gb2312'):
则是指定当遇到无法解码的字符时,抛出 UnicodeDecodeError 异常并停止程序运行
"""
result = msg.payload.decode('gb2312', 'ignore')
# 将收到的消息放入到消息队列中
message_queue.put(result)
def mqtt_connect(self):
"""连接MQTT服务器"""
mqttClient = mqtt.Client(str(uuid.uuid4()))
mqttClient.on_connect = self.on_connect # 返回连接状态的回调函数
mqttClient.on_message = self.on_message # 返回订阅消息回调函数
mqttClient.username_pw_set(self.mt_user, self.mt_pwd) # MQTT服务器账号密码
mqttClient.connect(self.mt_ip, 1883, 60) # MQTT地址、端口、心跳间隔(单位为秒)
mqttClient.loop_start() # 启用线程连接
return mqttClient
def on_subscribe(self):
"""订阅主题:mqtt/demo"""
mqttClient = self.mqtt_connect()
mqttClient.subscribe("mqtt/demo", 2)
# b.py文件
from a import message_queue, Subscription
run = Subscription("IP", "username", "password")
run.on_subscribe()
while True:
if not message_queue.empty():
result = message_queue.get()
# 处理消息
print(f"获取数据:{result}")