MicroPython[ESP32]:MQTT消息订阅与发布以及断联通知

NO.1
使用场景

通过MQTT订阅发布,实现当关注的数据变动时,获取对应的推送消息

减少定时轮询请求HTTP带来的各种性能消耗和反应不及时

ESP32+TFT-LCD显示屏

显示当前博客在线人数和今日总访问人数

此图片的alt属性为空;文件名为image-755-1024x500.png

粉丝计数器

从定时10分钟请求一次,改为只在粉丝变动的时候收到通知并刷新

减少屏幕刷新

此图片的alt属性为空;文件名为image-756.png

NO.2
博客统计

实时在线人数统计

方案思路

  1. 统计当前登录态有效的session,存储到Redis ,在这个数据库上用 dbsize()获取数据

  2. 使用websocket,保持心跳的连接数统计

  3. 使用MQTT,统计某个订阅主题的连接数

本文使用的是第三种

此图片的alt属性为空;文件名为image-758-1024x348.png

NO.3
博客MQTT

使用MQTTJS

github地址

https://github.com/mqttjs/MQTT.js#readme

步骤拆解

  1. 优先检测当前浏览器本地永久存储localStorage中的指定key的数据

  2. 如果没有,则生成对应的uuid作为mqtt的clientId并存储到localStorage

  3. 如果有,则动态加载mqttjs的库,并监听加载完成设置回调函数

  4. 加载mqttjs完成后,根据当前的uuid作为mqtt的clientId建立连接(这样无论打开几个tab,都只会有一个唯一连接)

  5. 设置mqtt连接成功回调中订阅指定主题和推送消息(如主题为域名)

  6. 设置mqtt停止连接后回调中推送主题消息(如主题为域名)

  7. 设置遗嘱消息(Will Message),当用户关闭网页失去连接时,推送主题消息

通过EMQX的API:/api/v5/subscriptions,可以获取当前主题的订阅数

参考文档地址

https://www.emqx.io/docs/zh/v5.0/admin/api.html

https://www.emqx.io/docs/zh/v5.0/admin/api-docs.html

此图片的alt属性为空;文件名为image-759-1024x500.png

此时,已经可以通过MQTT消息,在网页底部动态显示当前实时在线人数

NO.4
ESP32 MQTT

本文使用MicroPython

官方文档

https://mpython.readthedocs.io/en/master/library/mPython/umqtt.simple.html

github代码地址

https://github.com/micropython/micropython-lib/blob/master/micropython/umqtt.simple/umqtt/simple.py

如果提示没有umqtt,则需要自己复制代码并新建文件到ESP32

本文的显示屏驱动没有这个模块,所以需要自己写入

此图片的alt属性为空;文件名为image-760.png

引入模块

from umqtt.simple import MQTTClient

开始MQTT连接

# mqtt客户端ID
CLIENT_NAME = 'ESP32'
# MQTT IP地址
BROKER_ADDR = 'ip地址'
# 设置MQTT参数
mqttc = MQTTClient(CLIENT_NAME, BROKER_ADDR, keepalive=60)
# 建立MQTT连接
mqttc.connect()

设置监听消息回调函数

# 监听消息接收
def test_call(topic, msg):
    print("接收到消息")
    topic_str=topic.decode()
    msg_str=msg.decode()
    print("topic_str",topic_str)
    print("msg_str",msg_str)

注册回调函数并订阅主题

注意set_callback一定要放在subscribe上面,因为顺序放了会提示没有设置回调参数(看源码有提示和顺序)

# 订阅主题
TOPIC_STR = b"主题名称"
# 设置消息监听回调函数注册
mqttc.set_callback(test_call)
# 订阅指定主题
mqttc.subscribe(TOPIC_STR,1)

设置消息检测

主要是使用mqttc.check_msg()来检测消息

while True:
#   发送订阅消息
    # mqttc.publish(TOPIC_STR, "test" )
#     监听消息订阅
    #print("检测消息")
    try:
        # mqttc.wait_msg()
        mqttc.check_msg()
    except:
        pass
        #print("监听消息错误")
    else:
        pass
        #print("其他操作")
    time.sleep(1)

至此,ESP32已经可以建立MQTT连接

当博客建立MQTT连接发送订阅通知时,ESP32会收到,然后做出刷新操作,显示当前实时人数即可

NO.5
问题汇总

当ESP32同时使用lvgl和mqtt以及http时

  1. 会因为内存分配不足导致进程堵塞或者重启

  2. 在进行mqtt建立连接或者http请求时,动态画面会卡住,直到请求结束才恢复正常(也是内存分配性能原因)

  3. ESP32中,使用http get请求,目前只能使用http协议,使用https会报错(硬件或者驱动本身问题)

  4. ESP32中,使用ip和mqtt建立连接,使用域名未响应,无法连接成功(原因未知)

错误提示一

MemoryError: memory allocation failed, allocating 12300 bytes

错误提示二

RuntimeError: Not enough DMA-able memory to allocate display buffer
NO.5
Tips

同理,哔哩哔哩的粉丝计数也从原来的定时请求改为mqtt订阅通知

需要一个在服务器上的定时任务,定时请求api,比如数据变化,如有变化,推送订阅通知到ESP32,进行刷新操作

END