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

求助:基于Flask实现PySerial数据实时更新的问题

Fixing Real-Time PySerial Data Refresh in Flask

Hey James, I’ve tackled this exact problem before when building a Flask app to monitor serial port data—let’s get that real-time refresh working for you.

The core issue here is that standard Flask routes return a one-time response. Your page doesn’t know when new serial data comes in unless you explicitly check for it, or set up a way for the server to push updates to the frontend. Here are two solid solutions, from easiest to implement to more efficient:

1. Frontend Polling (Quickest to Get Running)

This is the simplest approach: have your frontend periodically ask the server for the latest serial data. It’s not the most efficient, but it’s dead easy to set up and debug.

Backend Code (app.py)

from flask import Flask, render_template, jsonify
import serial
import threading
from datetime import datetime

app = Flask(__name__)
# Update these to match your serial port settings
ser = serial.Serial('COM3', 9600, timeout=1)
latest_serial_data = "Waiting for serial data..."
data_lock = threading.Lock()

def serial_reading_thread():
    """Background thread to continuously read from the serial port"""
    global latest_serial_data
    while True:
        if ser.in_waiting > 0:
            # Read and clean up the incoming line
            raw_line = ser.readline().decode('utf-8').strip()
            # Add a timestamp for clarity
            formatted_data = f"{datetime.now().strftime('%H:%M:%S')} - {raw_line}"
            # Use a lock to avoid race conditions with the Flask route
            with data_lock:
                latest_serial_data = formatted_data

# Start the background thread when the app launches
threading.Thread(target=serial_reading_thread, daemon=True).start()

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

@app.route('/get_latest_data')
def get_latest_data():
    with data_lock:
        return jsonify({"data": latest_serial_data})

Frontend Template (templates/index.html)

<!DOCTYPE html>
<html>
<head>
    <title>Serial Data Monitor</title>
</head>
<body>
    <h1>Real-Time Serial Data</h1>
    <div id="data-display" style="font-size: 1.2em; margin-top: 20px;">
        Waiting for data...
    </div>

    <script>
        // Check for new data every 1 second (adjust the interval as needed)
        setInterval(() => {
            fetch('/get_latest_data')
                .then(response => response.json())
                .then(result => {
                    document.getElementById('data-display').textContent = result.data;
                })
                .catch(error => console.error('Error fetching data:', error));
        }, 1000);
    </script>
</body>
</html>

2. Server-Sent Events (SSE) - More Efficient

If you want a smoother, more efficient solution (no repeated requests), use Server-Sent Events. This sets up a persistent connection where the server pushes new data to the frontend as soon as it arrives.

Backend Code (app.py for SSE)

from flask import Flask, render_template, Response
import serial
import threading
from datetime import datetime ​​
际式test表述�`距离acklot subject,我需要重新调整一下代码,确保正确。

app = Flask(__name__)
ser = serial.Serial('COM3', 9600, timeout=1)
connected_clients = []

def serial_reader():
    """Background thread that reads serial data and pushes it to clients"""
    while True:
        if ser.in_waiting > 0:
            raw_line = ser.readline().decode('utf-8').strip()
            formatted_data = f"{datetime.now().strftime('%H:%M:%S')} - {raw_line}"
            # Send data to all connected clients
            for client in connected_clients[:]:
                try:
                    client(f"data: {formatted_data}\n\n")
                except:
                    # Remove clients that disconnected
                    connected_clients.remove(client)
        time.sleep(0.1)

threading.Thread(target=serial_reader, daemon=True).start()

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

@app.route('/stream_data')
def stream_data():
    def generate_stream():
        # Tell the client to reconnect after 1 second if the connection drops
        yield 'retry: 1000\n\n'
        # Add this client to our list
        client = yield
        connected_clients.append(client)
        try:
            # Keep the connection alive
            while True:
                time.sleep(1)
        finally:
            # Remove the client when they disconnect
            connected_clients.remove(client)
    return Response(generate_stream(), mimetype='text/event-stream')

Frontend Template (templates/sse_index.html)

<!DOCTYPE html>
<html>
<head>
    <title>SSE Serial Monitor</title>
</head>
<body>
    <h1>Real-Time Serial Data (SSE)</h1>
    <div id="data-display" style="font-size: 1.2em; margin-top: 20px;">
        Waiting for data...
    </div>

    <script>
        const eventSource = new EventSource('/stream_data');
        
        // Handle incoming data from the server
        eventSource.onmessage = function(event) {
            document.getElementById('data-display').textContent = event.data;
        };

        // Handle connection errors and retry
        eventSource.onerror = function() {
            console.log('SSE connection lost, reconnecting...');
            eventSource.close();
            setTimeout(() => window.location.reload(), 2000);
        };
    </script>
</body>
</html>

Key Notes to Avoid Headaches

  • Serial Port Settings: Double-check your port name (COM3 on Windows, /dev/ttyUSB0 on Linux/macOS) and baud rate match your device.
  • Thread Safety: Always use a lock when accessing shared variables between threads to prevent race conditions.
  • Daemon Threads: Setting daemon=True on the serial thread ensures it shuts down when the Flask app stops.
  • Timeout: Adding a timeout to the serial.Serial initialization prevents the thread from getting stuck waiting for data.

内容的提问来源于stack exchange,提问作者james hall

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 07:14:02