1. 项目背景与需求分析
去年夏天,我养了三个月的绿萝突然开始大面积黄叶。作为程序员,我本能地想到:能不能用技术手段解决这个问题?这就是"基于Flask的植物养护系统"的起源——一个通过传感器数据采集和环境调控来实现智能植物养护的Web应用。
这个系统要解决的核心痛点是:
- 植物养护依赖主观经验,缺乏量化指标
- 环境变化难以及时感知和响应
- 养护记录分散,难以形成有效参考
典型使用场景包括:
- 家庭阳台/客厅的绿植养护
- 办公室桌面植物的自动化管理
- 小型植物培育实验的环境监控
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术架构设计
2.1 为什么选择Flask?
相比Django等全功能框架,Flask的轻量级特性更适合本项目:
- 微内核架构方便按需扩展(我们只需要REST API和简单前端)
- 与硬件交互的灵活性更高(通过GPIO库直接控制传感器)
- 开发部署更轻量化(Raspberry Pi等设备也能流畅运行)
核心技术栈组合:
python复制Flask(后端框架)
SQLAlchemy(ORM)
Vue.js(前端可选)
Raspberry Pi + 传感器(硬件层)
2.2 系统模块划分
mermaid复制graph TD
A[传感器模块] --> B[数据采集服务]
B --> C[Flask后端]
C --> D[Web前端]
C --> E[报警服务]
D --> F[用户操作]
E --> G[邮件/短信提醒]
(注:实际实现时应替换为文字描述)
3. 硬件集成方案
3.1 必备传感器选型
| 传感器类型 | 推荐型号 | 测量范围 | 精度 | 接口方式 |
|---|---|---|---|---|
| 土壤湿度 | DFRobot SEN0193 | 0-100%RH | ±3% | 模拟量 |
| 光照强度 | BH1750 | 1-65535lux | ±20% | I2C |
| 温湿度 | DHT22 | -40~80℃/0-100%RH | ±0.5℃/±2% | 单总线 |
注意:DHT22需要上拉电阻(4.7KΩ),接线长度建议不超过20cm
3.2 树莓派GPIO配置示例
python复制# 传感器初始化
import Adafruit_DHT
dht_sensor = Adafruit_DHT.DHT22
dht_pin = 4 # GPIO4
def read_dht():
humidity, temperature = Adafruit_DHT.read_retry(dht_sensor, dht_pin)
return {
'temp': round(temperature, 1),
'humi': round(humidity, 1)
}
常见问题排查:
- 读取返回None:检查接线是否松动,尝试降低读取频率
- 数据跳变剧烈:增加软件滤波(如滑动平均算法)
- GPIO冲突:使用
gpio readall命令检查引脚状态
4. Flask后端实现
4.1 数据模型设计
python复制from datetime import datetime
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
class Plant(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(80), nullable=False)
species = db.Column(db.String(80))
created_at = db.Column(db.DateTime, default=datetime.now)
class SensorData(db.Model):
id = db.Column(db.Integer, primary_key=True)
plant_id = db.Column(db.Integer, db.ForeignKey('plant.id'))
timestamp = db.Column(db.DateTime, default=datetime.now)
soil_moisture = db.Column(db.Float)
temperature = db.Column(db.Float)
humidity = db.Column(db.Float)
light_intensity = db.Column(db.Float)
4.2 REST API设计
python复制from flask import Flask, jsonify, request
app = Flask(__name__)
@app.route('/api/plants/<int:plant_id>/data', methods=['POST'])
def add_sensor_data(plant_id):
data = request.get_json()
new_data = SensorData(
plant_id=plant_id,
soil_moisture=data['soil_moisture'],
temperature=data['temperature'],
humidity=data['humidity'],
light_intensity=data['light']
)
db.session.add(new_data)
db.session.commit()
return jsonify({"status": "success"}), 201
@app.route('/api/plants/<int:plant_id>/stats', methods=['GET'])
def get_plant_stats(plant_id):
# 获取最近24小时数据
records = SensorData.query.filter(
SensorData.plant_id == plant_id,
SensorData.timestamp > datetime.now() - timedelta(days=1)
).all()
return jsonify([r.to_dict() for r in records])
5. 前端交互实现
5.1 实时数据看板
使用Chart.js实现动态图表:
javascript复制// 在Vue组件中
methods: {
async fetchData() {
const res = await fetch(`/api/plants/${this.plantId}/stats`)
const data = await res.json()
this.renderChart(data)
},
renderChart(data) {
const ctx = document.getElementById('sensorChart')
new Chart(ctx, {
type: 'line',
data: {
labels: data.map(d => new Date(d.timestamp).toLocaleTimeString()),
datasets: [
{
label: '土壤湿度(%)',
data: data.map(d => d.soil_moisture),
borderColor: 'rgb(75, 192, 192)'
}
]
}
})
}
}
5.2 预警通知配置
后端定时任务示例:
python复制from apscheduler.schedulers.background import BackgroundScheduler
def check_conditions():
plants = Plant.query.all()
for plant in plants:
latest = SensorData.query.filter_by(
plant_id=plant.id
).order_by(SensorData.timestamp.desc()).first()
if latest.soil_moisture < 30: # 土壤湿度低于30%
send_alert(plant, f"需要浇水!当前湿度{latest.soil_moisture}%")
scheduler = BackgroundScheduler()
scheduler.add_job(check_conditions, 'interval', minutes=30)
scheduler.start()
6. 部署与优化
6.1 生产环境部署
推荐使用Gunicorn + Nginx组合:
bash复制# 安装Gunicorn
pip install gunicorn
# 启动命令(4个工作进程)
gunicorn -w 4 -b 0.0.0.0:8000 app:app
Nginx配置要点:
nginx复制location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
6.2 性能优化技巧
- 传感器数据缓存:使用Redis缓存频繁访问的实时数据
- 数据库索引优化:为timestamp和plant_id字段创建复合索引
- 异步任务:将报警邮件等耗时操作交给Celery处理
- 前端数据压缩:配置Flask-Compress减少传输量
7. 扩展方向
- 植物识别功能:集成TensorFlow Lite实现拍照识花
- 养护知识图谱:用Neo4j构建植物病症与解决方案的关系网络
- 自动化控制:连接继电器模块实现自动浇水补光
- 多用户支持:增加用户系统实现家庭多成员协作养护
在实现过程中,我发现几个值得注意的细节:
- DHT22在高温环境下需要增加通风散热
- 土壤湿度传感器长期使用会产生电解腐蚀,建议每半年更换
- Flask的development server不适合直接暴露在公网
- 前端图表更新频率建议不超过10秒,避免浏览器性能问题
