You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

树莓派Zero上Flask-socketIO无法工作问题求助

问题分析与解决方案

你的核心问题是后端SocketIO事件处理函数被阻塞,导致无法正常处理WebSocket连接和数据推送,同时前端存在重复创建Socket实例的问题,具体修复如下:

后端(MPU9250.py)修复

@socketio.on('connect')中的while True+time.sleep(0.1)会完全阻塞SocketIO的事件循环,使得服务器无法响应新的连接请求,也无法推送数据。必须改用SocketIO的后台任务来处理持续的数据采集和推送:

from flask import Flask, render_template
from flask_socketio import SocketIO, emit
import smbus
import time

app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
async_mode = 'eventlet'
socketio = SocketIO(app, cors_allowed_origins="*", async_mode=async_mode)

### SENSOR CODE HERE(确保read_word_2c等函数已正确实现)

# 定义后台任务,负责持续采集并推送数据
def sensor_stream_task():
    while True:
        # 读取传感器数据
        accel_xout = read_word_2c(accel_xout_h)
        accel_yout = read_word_2c(accel_yout_h)
        accel_zout = read_word_2c(accel_zout_h)
        mag_xout = read_word_2c(mag_xout_h)
        mag_yout = read_word_2c(mag_yout_h)
        mag_zout = read_word_2c(mag_zout_h)

        print("X Accel: ", accel_xout, " | Y Accel: ", accel_yout, " | Z_Accel: ", accel_zout)

        # 推送数据到客户端
        socketio.emit('acceleration', {'x': time.time(), 'y': accel_xout})
        socketio.emit('magnetometer', {'x': time.time(), 'y': mag_xout})
        socketio.send('Test message')
    
        # 使用SocketIO的sleep,避免阻塞事件循环
        socketio.sleep(0.1)

@app.route('/')
def index():
    return render_template('index.html')

# 客户端连接时启动后台任务
@socketio.on('connect')
def handle_connect():
    print('Client connected')
    # 启动后台任务,每个连接可以单独启动或共享,这里按需求选择
    socketio.start_background_task(sensor_stream_task)

if __name__ == '__main__':
    socketio.run(app, debug=True, port=80, host='0.0.0.0')

关键修改:

  • 将数据采集逻辑移到独立的后台任务函数sensor_stream_task中
  • 使用socketio.start_background_task()启动任务,而非阻塞事件处理函数
  • 用socketio.sleep(0.1)替代time.sleep(0.1),保证事件循环正常运行

前端(index.html)修复

前端重复创建了io()实例,会导致多个WebSocket连接冲突,合并Socket实例并精简代码:

<!DOCTYPE html>
<html>
  <head>
    <title>MPU9250 Sensor Data</title>
    <script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js" integrity="sha512-bLT0Qm9VnAYZDflyKcBaQ2gg0hSYNQrJ8RilYldYQ1FxQYoCLtUjuuRuZo+fjqhx/qtq/1itJ0C2ejDxltZVFg==" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/3.0.4/socket.io.js" integrity="sha512-aMGMvNYu8Ue4G+fHa359jcPb1u+ytAF+P2SCb+PxrjCdO3n3ZTxJ30zuH39rimUggmTwmh2u7wvQsDTHESnmfQ==" crossorigin="anonymous"></script>
  </head>
  <body>
    <h1>MPU9250 Sensor Stream</h1>
    <h2>Acceleration</h2>
    <div id="acceleration-graph"></div>
    <h2>Magnetometer</h2>
    <div id="magnetometer-graph"></div>

    <script type="text/javascript" charset="utf-8">
      console.log("Page loaded");

      // 初始化图表数据和布局
      const accelerationData = {
        x: [],
        y: [],
        mode: "lines",
        name: "Acceleration",
      };
      const magnetometerData = {
        x: [],
        y: [],
        mode: "lines",
        name: "Magnetometer",
      };

      const accelerationLayout = {
        title: "Acceleration Data",
        xaxis: { title: "Time" },
        yaxis: { title: "Acceleration (raw)" },
      };
      const magnetometerLayout = {
        title: "Magnetometer Data",
        xaxis: { title: "Time" },
        yaxis: { title: "Magnetic field (raw)" },
      };

      const accelerationPlot = Plotly.newPlot(
        "acceleration-graph",
        [accelerationData],
        accelerationLayout
      );
      const magnetometerPlot = Plotly.newPlot(
        "magnetometer-graph",
        [magnetometerData],
        magnetometerLayout
      );

      // 只创建一个Socket实例
      var socket = io();
      socket.on("connect", function () {
        console.log("Connected to server");
        socket.emit("my_event", { data: "I'm connected!" });
      });

      // 监听加速度数据
      socket.on("acceleration", function (data) {
        console.log('X_Accel: ' + data.x, 'Y_Accel: ' + data.y);
        accelerationData.x.push(data.x);
        accelerationData.y.push(data.y);
        Plotly.update("acceleration-graph", [accelerationData], accelerationLayout);
      });

      // 监听磁力计数据
      socket.on("magnetometer", function (data) {
        console.log('X_Mag: ' + data.x, 'Y_Mag: ' + data.y);
        magnetometerData.x.push(data.x);
        magnetometerData.y.push(data.y);
        Plotly.update("magnetometer-graph", [magnetometerData], magnetometerLayout);
      });

      // 监听测试消息
      socket.on('message', function(msg) {
        console.log('Test message: ' + msg);
      });
    </script>
  </body>
</html>

关键修改:

  • 删除重复的$(document).ready中的Socket实例创建,只保留一个全局Socket实例
  • 优化日志输出,方便调试
  • 新增对message事件的监听,接收后端的测试消息

额外注意事项

  1. 确保已安装eventlet:pip install eventlet,因为你指定了async_mode='eventlet',必须安装对应的异步引擎
  2. 传感器代码中的read_word_2c、accel_xout_h等变量/函数必须正确实现,否则会抛出异常导致后台任务终止
  3. 如果多个客户端连接,当前代码会为每个客户端启动一个后台任务,若需要共享数据推送,可以改为全局后台任务(启动一次即可)

内容的提问来源于stack exchange,提问作者G.H.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 23:40:50