通过MQTT订阅发布,实现当关注的数据变动时,获取对应的推送消息
减少定时轮询请求HTTP带来的各种性能消耗和反应不及时
ESP32+TFT-LCD显示屏
显示当前博客在线人数和今日总访问人数
粉丝计数器
从定时10分钟请求一次,改为只在粉丝变动的时候收到通知并刷新
减少屏幕刷新
实时在线人数统计
方案思路
-
统计当前登录态有效的session,存储到Redis ,在这个数据库上用 dbsize()获取数据
-
使用websocket,保持心跳的连接数统计
-
使用MQTT,统计某个订阅主题的连接数
本文使用的是第三种
使用MQTTJS
github地址
https://github.com/mqttjs/MQTT.js#readme
步骤拆解
-
优先检测当前浏览器本地永久存储localStorage中的指定key的数据
-
如果没有,则生成对应的uuid作为mqtt的clientId并存储到localStorage
-
如果有,则动态加载mqttjs的库,并监听加载完成设置回调函数
-
加载mqttjs完成后,根据当前的uuid作为mqtt的clientId建立连接(这样无论打开几个tab,都只会有一个唯一连接)
-
设置mqtt连接成功回调中订阅指定主题和推送消息(如主题为域名)
-
设置mqtt停止连接后回调中推送主题消息(如主题为域名)
-
设置遗嘱消息(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
此时,已经可以通过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
本文的显示屏驱动没有这个模块,所以需要自己写入
引入模块
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会收到,然后做出刷新操作,显示当前实时人数即可
当ESP32同时使用lvgl和mqtt以及http时
-
会因为内存分配不足导致进程堵塞或者重启
-
在进行mqtt建立连接或者http请求时,动态画面会卡住,直到请求结束才恢复正常(也是内存分配性能原因)
-
ESP32中,使用http get请求,目前只能使用http协议,使用https会报错(硬件或者驱动本身问题)
-
ESP32中,使用ip和mqtt建立连接,使用域名未响应,无法连接成功(原因未知)
错误提示一
MemoryError: memory allocation failed, allocating 12300 bytes
错误提示二
RuntimeError: Not enough DMA-able memory to allocate display buffer
同理,哔哩哔哩的粉丝计数也从原来的定时请求改为mqtt订阅通知
需要一个在服务器上的定时任务,定时请求api,比如数据变化,如有变化,推送订阅通知到ESP32,进行刷新操作
END