Python MQTT客户端 paho-mqtt

Python中MQTT

Python有许多优秀的MQTT客户端,比较有代表性的有paho-mqtt、hbmqtt、gmqtt等,各有特色

  • paho-mqtt 有着最优秀的文档,代码风格易于理解,同时有着强大的基金会支持,目前新版本支持 MQTT 5.0

  • hbmqtt 使用 asyncio 库实现,可以优化网络 I/O 带来的延迟,但是代码风格不友好,文档较少,不支持 MQTT 5.0,且不再维护,被原作者弃用,有一个分支amqtt正在由不同的人积极开发

  • gmqtt 同样通过 asyncio 库实现,相比 HBMQTT ,代码风格友好,最重要的是支持 MQTT 5.0

    paho-mqtt 可以说是 Python MQTT 开源客户端库中的佼佼者, 支持5.0、3.1.1 和 3.1 的MQTT 协议,由 Eclipse 基金会主导开发.在基金会的支持下,以每年一个版本的速度更新,稳定、持续,本文使用新版本paho-mqtt v1.6.1

    pypi地址

    开源地址

    参考文章

paho-mqtt安装

使用pip安装

pip3 install paho-mqtt
# virtualenv安装和完整代码参考官方文档

paho-mqtt已知的一些限制

截止1.6.1版本,当 clean_session 为 False 时,session 只存储在内存中,不持久化。这意味着当客户端重新启动时(不仅仅是重新连接,通常是因为程序重新启动而重新创建对象)会话丢失。这可能导致消息丢失。

客户端会话的以下部分丢失:

  • 已从服务器收到但尚未完全确认的 QoS 2 消息。

    由于客户端将盲目地确认任何 PUBCOMP(QoS 2 事务的最后一条消息),它不会挂起但会丢失此 QoS 2 消息。

  • 已发送到服务器但尚未完全确认的 QoS 1 和 QoS 2 消息。

    这意味着传递给 publish() 的消息可能会丢失。这可以通过注意传递给 publish() 的所有消息都有相应的 on_publish() 调用来缓解。

    这也意味着代理可能在会话中有 Qos2 消息。由于客户端从一个空会话开始,它不知道它并将重新使用中间。这还没有确定。

此外,当 clean_session 为 True 时,该库将在网络重新连接时重新发布 QoS > 0 消息。这意味着 QoS > 0 消息不会丢失。但是标准规定我们是否应该丢弃发送了发布数据包的任何消息。我们的选择意味着我们不符合标准,并且 QoS 2 有可能被接收两次。如果只需要一次交付的 QoS 2 保证,应该 clean_session = False

paho-mqtt使用

使用paho-mqtt实现客户端相关功能简单步骤如下:

  • 构造Client客户端实例
  • 使用connect相关方法将创建的客户端连接到代理
  • 使用loop相关方法维护和broker的通信
  • 使用subscribe()方法订阅主题、接收消息
  • 使用publish()方法发送消息
  • 使用disconnect()断开连接

Client客户端

使用客户端连接代理、订阅等,首先我们需要先创建一个客户端,paho-mqtt使用Client()创建客户端实例

Client类的构造参数
# Client 源码 参数如下
def __init__(self, client_id="", clean_session=None, userdata=None,
           protocol=MQTTv311, transport="tcp", reconnect_on_failure=True):
Client类构造参数讲解
# 参数示意
client_id = '客户端ID,str类型,可自定义'
'''
如果长度为零或者为空,则会随机生成一个,这种情况下,clean_session参数必须为True清除会话,因为持久会话需要client_id为唯一标识来恢复会话
'''

clean_session = '会话清除状态,bool类型,设为True,broker在断开连接的时候删除该client的信息,为False,则相当于是持久会话'
'''
clean_session在官方文档示例默认值为True,查看1.6.1版本源码默认值为None,看逻辑应该是支持mqttv5之后做的的变化
源码中判断如果protocol是MQTT V5版本 clean_session不是None的话则抛出ValueError,就是mqtt5的clean_session必须持久会话,
如果不是mqtt5的话如果clean_session is None 则将clean_session设置为True,这块就与官方文档的默认逻辑对应上了
'''

userdata = 'client用户数据,传递给回调函数,可以是任意类型,可以使用Clinet的 user_data_set()函数进行更新数据'

protocol = '客户端协议的版本,默认是MQTTv311就是3.1.1版本,也可以是MQTTv31、MQTTv5版本'
'''
protocol的参数在源码中是以下对应关系,理论上直接传入对应int值或者导入MQTTv** 字段传入都可
MQTTv31 = 3
MQTTv311 = 4
MQTTv5 = 5
'''

transport = '底层传输协议,默认是使用原始tcp,值可以设置为websockets通过ws发送mqtt'

reconnect_on_failure = 'bool类型, 连接失败后是否自动重新connect,默认为True'
'''
官方文档没有reconnect_on_failure相关示例和解释,不确定老版本有没有该字段
'''
创建客户端
# -*- coding: utf-8 -*-
# @Time:     2023/5/10 16:09
# @Author:   LiQi
# @Describe:

import paho.mqtt.client as mqtt  # 导入clinet 别名 mqtt

# 创建一个客户端实例赋值client,client_id自定义,其他参数根据需要设定
client = mqtt.Client(client_id='muziqi')
重置客户端
'''paho-mqtt提供reinitialise方法重新初始化已经构造好的客户端'''
# 上面创建的客户端clinet,直接调用reinitialise
client.reinitialise()
'''
reinitialise方法拥有下面三个参数
client_id="", clean_session=True, userdata=None
'''
Clinet选项函数

选项函数的作用是给构造好的客户端添加附加选项,一般情况下在使用content连接broker前完成,比如设置Client的证书、回调、账号密码等,根据具体业务使用,设置完成后使用conten连接到broker

max_inflight_messages_set

当QoS> 0的时候,可以存在的部分完成(已经发送,还没有确认成功的消息)的消息的最大数量,这些消息可以同时通过网络流,默认为20.增加此值将消耗更多内存,但可以增加吞吐量

# inflight参数为要修改的数量,最小为1,小于1则抛出ValueError
client.max_inflight_messages_set(inflight)
max_queued_messages_set

设置传出消息队列中等待处理的QoS> 0的传出消息的最大数量,默认为0表示无限制,当队列已满时,其他传出的消息都将被丢弃,实际使用中0实际上并不是无限,目前实现最大可为65555,包括队列中的65535条消息+inflight的默认20条消息,如果inflight默认值被消息,队列中的实际消息数量被减少

# queue_size是要修改的最大数量
client.max_queued_messages_set(queue_size)
message_retry_set-废弃

QoS>0 的消息,如果发送之后超过一定时间broker没有响应,重发消息的时间,单位是s,默认5s

'''
 源码注释该方法不再使用,在2.0版本删除
 '''
ws_set_options

设置WebSocket的连接选项,构造Client时transport="websockets"才会使用,connect相关方法之前调用

import paho.mqtt.client as mqtt

# 传输协议设置为ws
client = mqtt.Client(client_id='muziqi',transport='websockets')

'''
path:broker的mqtt 路径,以/开头的字符串
headers:头部信息可以是字典或者是可调用对象。如果是字典的话字典中额外的项被添加到websocket头中。如果是一个可调用的对象,默认的websocket的头部信息被传递到这个函数,将函数结果当做新的头不新鲜'''
client.ws_set_options(path="/mqtt"
  • 7
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值