python3异步MQTT库HBMQTT(3) - 客户端API使用说明

温馨提示:这个包本人在实际使用中会遇到莫名其妙的bug,而且难以解决,如有其他选择建议还是不要使用HBMQTT了。

HBMQTT

简介

开源的Mqtt客户端和broker,使用python标准异步库asyncio实现,提供协程并发程序开发的直接API。

  • GitHub:https://github.com/beerfactory/hbmqtt
  • 文档:https://hbmqtt.readthedocs.io/en/latest/

Feature

HBMQTT实现了完整的MQTT 3.1.1协议规范,并提供了以下特性:

  • Support QoS 0, QoS 1 and QoS 2 messages flow
  • 客户端断线自动重连
  • 通过密钥文件认证(其他方法可通过插件系统实现)
  • 基础的$SYS topics 支持
  • TCP 和 websocket 支持
  • TCP 和 websocket 的 SSL 支持
  • 插件系统

依赖

要求Python >=3.4.3

安装

pip install hbmqtt==0.9.6

客户端API用法

MQTTClient 类实现了MQTT协议,用于订阅、发布消息,通过普通TCP或者websocket协议,也可选择安全或者不安全的方式。

1. 订阅并接收

订阅并且打印每条从broker接收到的消息

import asyncio
import logging

from hbmqtt.client import MQTTClient, ClientException
from hbmqtt.mqtt.constants import QOS_1, QOS_2

logger = logging.getLogger('test_sub')

my_config = {
    'keep_alive': 10,
    'ping_delay': 1,
    'default_qos': 0,
    'default_retain': False,
    'auto_reconnect': True,  # 开启自动重连
    'reconnect_max_interval': 90,  # 最大重试间隔 秒
    'reconnect_retries': -1,  # 一直重试,直到连上
}


async def uptime_coro():
    # 创建客户端实例
    C = MQTTClient(client_id='test1', config=my_config, loop=None)
    await C.connect('mqtt://test.mosquitto.org/',
                    cleansession=True,
                    cafile=None,
                    extra_headers={})
    # 订阅 $SYS/broker/uptime'  QOS=1
    # 订阅 $SYS/broker/load/#'  QOS=2
    await C.subscribe([
        ('$SYS/broker/uptime', QOS_1),
        ('$SYS/broker/load/#', QOS_2),
    ])
    try:
        # 接收100条消息
        for i in range(0, 100):
            # 等待接收消息, 超时时间为None表示一直等待,返回message对象
            message = await C.deliver_message(timeout=None)
            packet = message.publish_packet
            print("%d:  %s => %s" % (i, packet.variable_header.topic_name,
                                     str(packet.payload.data)))
        # 取消订阅
        await C.unsubscribe(['$SYS/broker/uptime', '$SYS/broker/load/#'])
        # 客户端主动断开连接
        await C.disconnect()
    except ClientException as ce:
        logger.error("Client exception: %s" % ce)


if __name__ == '__main__':
    formatter = "[%(asctime)s] %(name)s {%(filename)s:%(lineno)d} %(levelname)s - %(message)s"
    logging.basicConfig(level=logging.DEBUG, format=formatter)
    asyncio.get_event_loop().run_until_complete(uptime_coro())

2. 发布消息

异步发布3条消息,每条消息的服务质量都不同。

import logging
import asyncio

from hbmqtt.client import MQTTClient, ConnectException
from hbmqtt.mqtt.constants import QOS_0, QOS_1, QOS_2

logger = logging.getLogger('test_pub')


async def test_coro():
    C = MQTTClient()
    await C.connect('mqtt://test.mosquitto.org/')
    tasks = [
        asyncio.ensure_future(C.publish('a/b', b'TEST MESSAGE WITH QOS_0')),
        asyncio.ensure_future(C.publish('a/b', b'TEST MESSAGE WITH QOS_1', qos=QOS_1)),
        asyncio.ensure_future(C.publish('a/b', b'TEST MESSAGE WITH QOS_2', qos=QOS_2)),
    ]
    await asyncio.wait(tasks)
    logger.info("test_coro messages published")
    await C.disconnect()


async def test_coro2():
    try:
        C = MQTTClient()
        ret = await C.connect('mqtt://test.mosquitto.org:1883/')
        message = await C.publish('a/b', b'TEST MESSAGE WITH QOS_0', qos=QOS_0)
        message = await C.publish('a/b', b'TEST MESSAGE WITH QOS_1', qos=QOS_1)
        message = await C.publish('a/b', b'TEST MESSAGE WITH QOS_2', qos=QOS_2)
        # print(message)
        logger.info("test_coro2 messages published")
        await C.disconnect()
    except ConnectException as ce:
        logger.error("Connection failed: %s" % ce)
        asyncio.get_event_loop().stop()


if __name__ == '__main__':
    formatter = "[%(asctime)s] %(name)s {%(filename)s:%(lineno)d} %(levelname)s - %(message)s"
    logging.basicConfig(level=logging.DEBUG, format=formatter)
    asyncio.get_event_loop().run_until_complete(test_coro())
    asyncio.get_event_loop().run_until_complete(test_coro2())

实际上这个脚本执行发布代码通过异步事件循环,先执行完 test_coro()函数,后执行 test_coro2()函数。两者完成的同样的任务。test_coro2() 是按先后顺序发送了3条,而test_coro() 是异步发送了3条。通过日志可发现发送的MQTT消息顺序的区别。

详细日志信息请自己运行查看。

test_coro() 异步发布消息的效率更高一些,(官方文档错了,还是我错了?😱)

3. api参数说明

1. 构造参数 [source]

用于创建客户端实例。

class hbmqtt.client.MQTTClient(client_id=None, config=None, loop=None)

参数:

  • client_id: 客户端id,如果是None,则通过hbmqtt.utils.gen_client_id() 生成随机id

  • config: 客户端配置参数,python字典类型,默认为:

    {
        'keep_alive': 10,
        'ping_delay': 1,
        'default_qos': 0,
        'default_retain': False,
        'auto_reconnect': True,
        'reconnect_max_interval': 10,
        'reconnect_retries': 2,
    }
    

    详细配置说明,请看下文

  • loop: asynio模块的loop对象

2. MQTTClient.connect

该方法为协程,用于连接到broker

client.connect(uri=None, cleansession=None, cafile=None, capath=None, cadata=None, extra_headers={})

参数:

  • uri:Broker 地址,格式见上一篇介绍
  • cleansession:是否清除原有会话
  • cafile: 服务证书文件(可选,用于安全连接)
  • capath: 服务证书路径(可选,用于安全连接)
  • cadata: 服务证书数据(可选,用于安全连接)
  • extra_headers:用于websocket初始化连接附加的http请求头

返回值:

CONNACK 消息返回值

异常:

连接失败抛出hbmqtt.client.ConnectException

3. MQTTClient.disconnect

协程,断开连接

client.disconnect()

4. MQTTClient.reconnect

协程,重连功能。重试次数和间隔可以通过reconnect_max_intervalreconnect_retries 参数控制

client.reconnect(cleansession=None)

参数

  • cleansession:是否清除以前会话

返回值:

CONNACK 消息返回值

异常:

连接失败抛出hbmqtt.client.ConnectException

5. MQTTClient.ping

协程,发送 ping 消息

client.ping()

6. MQTTClient.publish

协程,发布消息。并根据服务质量等待确认消息

client.publish(topic, message, qos=None, retain=None)

参数:

  • topic: 主题
  • message:消息载荷,bytes类型
  • qos:服务质量,取值0, 1, 2. 默认值根据连接配置中的 default_qos 决定
  • retain:retail 标志位,默认值根据连接配置中的default_retain 决定

7. MQTTClient.subscribe

协程,订阅topic,发送订阅消息,并等待broker的确认包。

client.subscribe(topics)

参数:

  • topics: 主题和QoS 的元组 组成的列表,如
  [
    ('$SYS/broker/uptime', QOS_1),
    ('$SYS/broker/load/#', QOS_2)
   ]

返回:

SUBACK 确认消息返回值

8. MQTTClient.unsubscribe

协程,取消订阅。

client.unsubscribe(topics)

参数:

  • topics:主题列表,如:
['$SYS/broker/uptime', '$SYS/broker/load/#']

9. MQTTClient.deliver_message

协程,等待从broker 接收下一条消息,如果没有收到消息,则会一直等待,或者指定等待的超时时间 timeout

client.deliver_message(timeout=None)

参数:

  • timeout: 等待消息到达时间,单位:秒。None:一直等待

返回:

hbmqtt.session.ApplicationMessage 实例,包含消息的所有属性。

异常:

如果timeout参数超时,抛出 asyncio.TimeoutError

4. 连接配置参数

MQTTClient.__init__ 接收一个 config 参数,python的字典类型,包含以下字段:

  • keep_alive:keep alive时间,单位秒(默认10秒),客户端会自动发送 ping消息给broker,以维持客户端不掉线。
  • ping_delay 在keep alive 超时之前自动发送 ping 消息的延迟,默认 1秒
  • default_qos:默认消息质量,在publish() 方法未指定qos参数时起作用
  • default_retain:默认 retain值(False),在publish() 方法未指定qos参数时起作用。
  • auto_reconnect:是否自动重连,默认 True
  • reconnect_max_interval: 两次重连之间的最大间隔,默认为10s
  • reconnect_retries:最大重试次数,默认2次

默认QoS等级和retain值,可以被额外的topic 参数重写,例如

config = {
    'keep_alive': 10,
    'ping_delay': 1,
    'default_qos': 0,
    'default_retain': False,
    'auto_reconnect': True,
    'reconnect_max_interval': 5,
    'reconnect_retries': 10,
    'topics': {
        '/test': { 'qos': 1 },
        '/some_topic': { 'qos': 2, 'retain': True }
    }
}

以上配置会设置所有消的默认QoS为0,retain值为False,除了:

  • 发送到topic 为 /test 的消息,QoS默认值为1
  • 发送到topic 为 /some_topic的消息,QoS默认值为2, retain值为True
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值