如何在MQTT消息处理函数中渲染Flask模板展示数据?
问题分析与解决方案
你的核心问题在于:handle_mytopic是MQTT的回调函数,不是Flask的HTTP请求处理函数。当MQTT收到消息时,这个函数执行并返回模板,但没有任何客户端会接收这个返回结果——HTTP是请求-响应模式,只有客户端主动发起请求,服务器才会返回内容,服务器无法主动给已打开的网页推送更新。
要实现网页实时展示MQTT数据,需要用到双向通信技术,最适合的方案是用Flask-SocketIO配合Flask-MQTT实现实时推送。
步骤1:安装依赖
先安装所需的包:
pip install flask-socketio flask-mqtt eventlet
步骤2:修改Python代码
替换原来的代码,加入SocketIO支持:
from flask import Flask, render_template from flask_mqtt import Mqtt from flask_socketio import SocketIO app = Flask(__name__) app.config['MQTT_BROKER_URL'] = 'MY_BROKER' app.config['MQTT_BROKER_PORT'] = 1883 app.config['MQTT_USERNAME'] = '' app.config['MQTT_PASSWORD'] = '' app.config['MQTT_KEEPALIVE'] = 5 app.config['MQTT_TLS_ENABLED'] = False mqtt = Mqtt(app) # 初始化SocketIO,允许跨域(开发环境用) socketio = SocketIO(app, cors_allowed_origins="*") @app.route('/') def home(): return render_template('home.html') @mqtt.on_connect() def handle_connect(client, userdata, flags, rc): if rc == 0: print('Connected successfully') mqtt.subscribe("iot/dht_cds") else: print('Bad connection. Code:', rc) @mqtt.on_topic('iot/dht_cds') def handle_mytopic(client, userdata, message): print('Received message on topic {}: {}' .format(message.topic, message.payload.decode())) light_value = message.payload.decode() # 通过SocketIO把数据推送给所有连接的客户端 socketio.emit('update_light', {'light_value': light_value}) if __name__ == '__main__': print('Starting Webserver...') # 用socketio.run启动服务器,而非app.run socketio.run(app, host='0.0.0.0', debug=True)
步骤3:修改前端模板(home.html)
在模板中引入SocketIO的JS客户端,监听服务器推送的事件并更新页面:
<!DOCTYPE html> <html> <head> <title>光照数据实时展示</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js"></script> <script type="text/javascript"> // 连接到SocketIO服务器 const socket = io(); // 监听服务器发送的update_light事件 socket.on('update_light', function(data) { // 更新页面上的数值显示 document.getElementById('light-value').textContent = data.light_value; }); </script> </head> <body> <h1>光照传感器数据</h1> <p>当前数值: <span id="light-value">等待数据...</span></p> </body> </html>
关键说明
- SocketIO的作用:打破HTTP的请求-响应限制,实现服务器主动向客户端推送数据,完美适配MQTT消息的实时展示需求。
- 启动方式:必须用
socketio.run(app)启动服务器,因为SocketIO需要异步服务器支持,eventlet会被自动加载使用。 - 数据推送逻辑:当MQTT收到消息时,通过
socketio.emit把数据广播给所有已连接的客户端,前端监听对应事件后更新DOM。
内容的提问来源于stack exchange,提问作者wok1909
相关产品推荐
相关产品推荐

