基于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
- Thread Safety: Uses
threading.Lock()to protect shared sensor data from race conditions between the sensor thread and HTTP request threads. - 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
- Automatic Page Updates: The
<meta>tag refreshes the page every 1 second only when the sensor is running, avoiding unnecessary requests when stopped. - Robust Sensor Reading: Uses
read_retryto handle common sensor read failures (adjust retry logic based on your sensor's reliability).
Important Notes
- Sensor Library: Replace
Adafruit_DHTwith your specific sensor library (e.g.,smbus2for I2C sensors, orRPi.GPIOfor other GPIO-based sensors). - GPIO Permissions: On Raspberry Pi, ensure your user has access to GPIO pins (add user to
gpiogroup or run withsudoif 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
相关产品推荐
相关产品推荐

