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

基于Flask的GPIO温湿度监控:多线程启停与无JS页面更新实现

Solution for Flask-Based GPIO温湿度 Monitoring Without JavaScript

I'll walk you through implementing the thread-based sensor reading and page updates using server-side logic only. Here's a complete, tested solution tailored to your requirements:

Step 1: Backend Python Code (app.py)

This handles thread management, sensor reading, and route handling with thread-safe state management:

from flask import Flask, render_template, request
import threading
import time
# Replace with your actual sensor library (e.g., Adafruit_DHT for DHT11/DHT22)
import Adafruit_DHT

app = Flask(__name__)

# Sensor configuration - adjust to match your hardware
SENSOR_TYPE = Adafruit_DHT.DHT11
GPIO_PIN = 4

# Thread-safe shared state
latest_temperature = None
latest_humidity = None
is_running = False
sensor_thread = None
data_lock = threading.Lock()

def sensor_reading_loop():
    """Infinite loop to read sensor data and update shared state"""
    global latest_temperature, latest_humidity, is_running
    while is_running:
        # Read sensor data (retry on failure)
        humidity, temp = Adafruit_DHT.read_retry(SENSOR_TYPE, GPIO_PIN)
        
        # Update shared state with lock to prevent race conditions
        with data_lock:
            if humidity is not None and temp is not None:
                latest_temperature = round(temp, 1)
                latest_humidity = round(humidity, 1)
            else:
                latest_temperature = "读取失败"
                latest_humidity = "读取失败"
        
        # Wait before next reading (adjust interval as needed)
        time.sleep(2)

@app.route('/', methods=['GET', 'POST'])
def index():
    global is_running, sensor_thread
    
    # Handle Start/Stop button clicks
    if request.method == 'POST':
        if 'start' in request.form:
            if not is_running:
                is_running = True
                # Start sensor thread (daemon mode exits with main app)
                sensor_thread = threading.Thread(target=sensor_reading_loop, daemon=True)
                sensor_thread.start()
        elif 'stop' in request.form:
            is_running = False
            # Wait for thread to exit gracefully (timeout to avoid hanging)
            if sensor_thread is not None:
                sensor_thread.join(timeout=1)
    
    # Get latest sensor data with thread safety
    with data_lock:
        temp = latest_temperature
        humidity = latest_humidity
    
    return render_template(
        'index.html',
        temperature=temp,
        humidity=humidity,
        running=is_running
    )

if __name__ == '__main__':
    # Enable threading to handle HTTP requests and sensor thread simultaneously
    app.run(debug=False, threaded=True)

Step 2: HTML Template (templates/index.html)

This includes conditional page refresh (only when running) and dynamic button states:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>温湿度监测系统</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            max-width: 500px;
            margin: 3rem auto;
            padding: 0 20px;
            text-align: center;
        }
        .sensor-display {
            margin: 2rem 0;
            padding: 2rem;
            border: 2px solid #e0e0e0;
            border-radius: 10px;
            background-color: #f8f9fa;
        }
        .reading {
            font-size: 1.5rem;
            margin: 1rem 0;
        }
        button {
            padding: 0.8rem 1.5rem;
            font-size: 1.1rem;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            transition: background-color 0.2s;
        }
        .start-btn {
            background-color: #28a745;
            color: white;
        }
        .start-btn:hover {
            background-color: #218838;
        }
        .stop-btn {
            background-color: #dc3545;
            color: white;
        }
        .stop-btn:hover {
            background-color: #c82333;
        }
    </style>
    <!-- Conditional page refresh: only when sensor is running -->
    {% if running %}
    <meta http-equiv="refresh" content="1">
    {% endif %}
</head>
<body>
    <h1>GPIO温湿度监测</h1>
    <div class="sensor-display">
        <div class="reading">温度: {{ temperature if temperature else "未启动" }}°C</div>
        <div class="reading">湿度: {{ humidity if humidity else "未启动" }}%</div>
    </div>
    <form method="POST">
        {% if not running %}
        <button type="submit" name="start" class="start-btn">Start</button>
        {% else %}
        <button type="submit" name="stop" class="stop-btn">Stop</button>
        {% endif %}
    </form>
</body>
</html>

Key Features Explained

  1. Thread Safety: Uses threading.Lock() to protect shared sensor data from race conditions between the sensor thread and HTTP request threads.
  2. Thread Management:
    • Starts a daemon thread (exits automatically when the Flask app stops) when clicking Start
    • Uses a boolean flag (is_running) to gracefully stop the sensor loop when clicking Stop
  3. Automatic Page Updates: The <meta> tag refreshes the page every 1 second only when the sensor is running, avoiding unnecessary requests when stopped.
  4. Robust Sensor Reading: Uses read_retry to handle common sensor read failures (adjust retry logic based on your sensor's reliability).

Important Notes

  • Sensor Library: Replace Adafruit_DHT with your specific sensor library (e.g., smbus2 for I2C sensors, or RPi.GPIO for other GPIO-based sensors).
  • GPIO Permissions: On Raspberry Pi, ensure your user has access to GPIO pins (add user to gpio group or run with sudo if needed).
  • Production Deployment: Disable debug mode (debug=False) and use a production WSGI server like Gunicorn instead of the built-in Flask server.

内容的提问来源于stack exchange,提问作者a.b_om

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:03:57