Python_MQTT发布/订阅封装

前言

   本文介绍了如何使用Python编写一个简单的MQTT发布者和订阅者类来封装MQTT客户端。通过这两个类,我们可以轻松地连接到MQTT服务器并发布/订阅消息到指定主题。封装MQTT客户端可以简化开发过程,使得连接和发布/订阅消息变得更加简单。

一、安装paho-mqtt

pip install paho-mqtt

二、发布封装

import paho.mqtt.client as mqtt
import json


class MQTTPublisher:
    """MQTT发布消息的类"""

    def __init__(self, host, port=1883, client_id="", username=None, password=None):
        """
        构造函数,用于初始化 MQTT 客户端的连接信息

        :param host: str,MQTT 服务器地址
        :param port: int,MQTT 服务器端口,默认为1883
        :param client_id: str,MQTT 客户端 ID,默认为空
        :param username: str,MQTT 服务器用户名(可选)
        :param password: str,MQTT 服务器密码(可选)
        """
        self.host = host
        self.port = port
        self.client = mqtt.Client(client_id=client_id)

        # 如果提供了用户名和密码,就设置 MQTT 客户端的认证信息
        if username and password:
            self.client.username_pw_set(username, password)

    def on_connect(self, client, userdata, flags, rc):
        """
        连接成功回调函数,会在 MQTT 客户端连接成功时被调用

        :param client: MQTT 客户端实例
        :param userdata: 用户数据
        :param flags: 标志位
        :param rc: 返回码

        - 返回码说明:
            * 0:连接成功
            * 1:协议版本不正确
            * 2:客户端标识符无效
            * 3:服务器不可用
            * 4:用户名或密码不正确
            * 5:未经授权
        """
        rc_status = [
            "连接成功", "协议版本不正确", "客户端标识符无效", "服务器不可用", "用户名或密码不正确", "未经授权"]
        print("connect:", rc_status[rc], rc)

    def connect(self):
        """
        连接 MQTT 服务器
        """
        # 设置连接成功回调函数
        self.client.on_connect = self.on_connect

        # 连接MQTT服务器,keepalive为60秒
        self.client.connect(self.host, self.port, keepalive=60)

        # 启动一个单独的线程来处理网络流量和消息接收
        self.client.loop_start()

    def disconnect(self):
        """
        断开 MQTT 服务器连接
        """
        self.client.disconnect()

    def publish(self, topic, message, qos=0):
        """
        发布 MQTT 消息到指定主题

        :param topic: MQTT 消息主题
        :param message: MQTT 消息内容,需要将其转换成JSON字符串
        :param qos: MQTT 消息质量等级,默认为0

        - qos说明:
            * 0:最多一次,不保证消息能够被接收到
            * 1:至少一次,确保消息至少被接收到一次,可能会重复发送
            * 2:恰好一次,确保消息只被接收到一次,但可能会增加网络负载
        """
        # 连接 MQTT 服务器
        self.connect()

        # 将消息内容转换成JSON字符串,然后使用'gb2312'编码
        message_str = json.dumps(message, ensure_ascii=False).encode('gb2312')

        # 发布MQTT消息到指定主题,并指定质量等级
        self.client.publish(topic, message_str, qos=qos)

        # 停止循环处理网络流量和消息接收
        self.client.loop_stop()


if __name__ == "__main__":
    # 设置MQTT服务器地址,客户端 ID
    publisher = MQTTPublisher("test.mosquitto.org", client_id="my_client_id")

    # 发布MQTT消息到指定主题(项目中mqtt协议如果有固定部分,建议封装到publish方法中,传入data即可), 质量等级为1
    message = {
        "user": "admin",
        "password": 123
    }
    publisher.publish("topic/test", message, 1)

    # 主线程结束,子线程会自动断开MQTT连接,如主线程一直运行,需要关闭mqtt连接时,调用disconnect()方法断开连接
    publisher.disconnect()

三、订阅封装

import paho.mqtt.client as mqtt
import json


class MQTTSubscriber:
    """MQTT订阅消息的类"""

    def __init__(self, host, port=1883, client_id="", username=None, password=None):
        """初始化 MQTT 客户端的连接信息"""
        # MQTT 服务器的地址
        self.host = host
        # MQTT 服务器的端口号,默认为 1883
        self.port = port
        # 创建一个 MQTT 客户端对象,传入客户端 ID
        self.client = mqtt.Client(client_id=client_id)

        # 如果提供了用户名和密码,就设置 MQTT 客户端的认证信息
        if username and password:
            self.client.username_pw_set(username, password)

        # 设置自动重连的时间间隔,最小为 1 秒,最大为 120 秒
        self.client.reconnect_delay_set(min_delay=1, max_delay=120)

    def on_connect(self, client, userdata, flags, rc):
        """连接成功回调函数"""
        # 打印连接结果,0 表示成功,其他值表示失败
        print("connect:", rc)

        # 订阅指定主题的消息,传入主题和消息质量等级
        self.client.subscribe(self.topic, self.qos)

    def on_message(self, client, userdata, msg):
        """
        订阅消息回调函数,当收到订阅的消息时被调用

        :param client: MQTT客户端实例
        :param userdata: 用户自定义数据
        :param msg: 收到的消息对象
        """
        try:
            # 将消息中的JSON字符串转换为Python字典对象
            message = json.loads(msg.payload.decode('gb2312'))
        except ValueError:
            # 如果无法转换为Python字典对象,则直接使用字符串格式
            message = msg.payload.decode('gb2312')

        # 打印收到的消息的主题和内容
        print(f"主题: {msg.topic} 消息: {message}")

    def subscribe(self, topic, qos=0):
        """连接 MQTT 服务器,并订阅消息"""
        # 订阅的主题
        self.topic = topic
        # 消息质量等级
        self.qos = qos
        # 设置连接成功回调函数
        self.client.on_connect = self.on_connect
        # 设置订阅消息回调函数
        self.client.on_message = self.on_message
        # 连接MQTT服务器,keepalive为60秒,表示每隔60秒发送一次心跳包
        self.client.connect(self.host, self.port, keepalive=60)
        # 使用loop_forever()方法保持连接并接收消息,直到断开连接或出现异常
        self.client.loop_forever()


if __name__ == "__main__":
    # 设置MQTT服务器地址,客户端 ID
    subscriber = MQTTSubscriber("test.mosquitto.org", client_id="my_client_id")

    # 连接MQTT服务器,并订阅消息,传入主题和消息质量等级
    subscriber.subscribe(topic="topic/test", qos=1)

四、获取订阅的数据

  • mqtt_subscriber.py
import paho.mqtt.client as mqtt
import json


class MQTTSubscriber:
    """MQTT订阅消息的类"""

    def __init__(self, host, port=1883, client_id="", username=None, password=None):
        """初始化 MQTT 客户端的连接信息"""
        # MQTT 服务器的地址
        self.host = host
        # MQTT 服务器的端口号,默认为 1883
        self.port = port
        # 创建一个 MQTT 客户端对象,传入客户端 ID
        self.client = mqtt.Client(client_id=client_id)

        # 如果提供了用户名和密码,就设置 MQTT 客户端的认证信息
        if username and password:
            self.client.username_pw_set(username, password)

        # 设置自动重连的时间间隔,最小为 1 秒,最大为 120 秒
        self.client.reconnect_delay_set(min_delay=1, max_delay=120)

        # 初始化消息
        self.message = None

    def on_connect(self, client, userdata, flags, rc):
        """连接成功回调函数"""
        # 打印连接结果,0 表示成功,其他值表示失败
        print("connect:", rc)

        # 订阅指定主题的消息,传入主题和消息质量等级
        self.client.subscribe(self.topic, self.qos)

    def on_message(self, client, userdata, msg):
        """订阅消息回调函数,当收到订阅的消息时被调用"""
        try:
            # 将消息中的JSON字符串转换为Python字典对象
            self.message = json.loads(msg.payload.decode('gb2312'))
        except ValueError:
            # 如果无法转换为Python字典对象,则直接使用字符串格式
            self.message = msg.payload.decode('gb2312')

        # 打印收到的消息的主题和内容
        print(f"主题: {msg.topic} 消息: {self.message}")

    def get_message(self):
        """获取最新的消息"""
        return self.message

    def subscribe(self, topic, qos=0):
        """连接 MQTT 服务器,并订阅消息"""
        # 订阅的主题
        self.topic = topic
        # 消息质量等级
        self.qos = qos
        # 设置连接成功回调函数
        self.client.on_connect = self.on_connect
        # 设置订阅消息回调函数
        self.client.on_message = self.on_message
        # 连接MQTT服务器,keepalive为60秒,表示每隔60秒发送一次心跳包
        self.client.connect(self.host, self.port, keepalive=60)
        # 启动一个新的线程来处理网络交互
        self.client.loop_start()

    def disconnect(self):
        """断开 MQTT 服务器连接"""
        # 断开连接
        self.client.disconnect()
        # 停止线程
        self.client.loop_stop()

from mqtt_publisher import MQTTPublisher
from mqtt_subscriber import MQTTSubscriber
import time

# 订阅消息
subscriber = MQTTSubscriber("test.mosquitto.org", client_id="my_client_id")
subscriber.subscribe(topic="topic/test", qos=1)

# 发布消息
publisher = MQTTPublisher("test.mosquitto.org", client_id="my_client_id_1")
publisher.publish("topic/test", "I posted a message", 1)

# 等待3秒以确保消息被接收
time.sleep(3)

# 获取最新的消息
message = subscriber.get_message()
print(message)
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值