技术架构与 API 接口
本文档详细介绍系统的技术架构、数据模型和 API 接口定义。
一、整体架构
系统分层
┌─────────────────────────────────────────────────────┐
│ 前端应用层(Vue 3 + Vite) │
│ Dashboard | Monitor | Data | Control | Settings │
└─────────────────────────────────────────────────────┘
│ HTTP/REST
│ WebSocket
│
┌─────────────────────────────────────────────────────┐
│ 后端应用层(FastAPI + SQLAlchemy) │
│ ├─ API 路由层 │
│ ├─ 业务逻辑层(Service) │
│ └─ 数据访问层(DAO) │
└─────────────────────────────────────────────────────┘
│ │
┌────▼────┐ ┌──────▼──────┐
│ MQTT │ │ Broker & │
│ Publisher│ │ Message │
└────┬────┘ │ Queue │
│ └──────┬──────┘
│ │
┌────▼──────────────────────────▼────┐
│ 消息队列(MQTT Broker) │
│ 订阅/发布核心数据主题 │
└────┬───────────────────────────────┘
│
┌────▼──────────┬──────────────────┐
│ │ │
┌───▼──┐ ┌─────▼──┐ ┌──────▼──┐
│Influx│ │SQLite │ │缓存层 │
│DB │ │(配置)│ │(Redis) │
└──────┘ └────────┘ └─────────┘数据流向
传感器数据流
物理传感器 → MQTT Topic: greenhouse/sensors/* → 后端 MQTT 订阅器接收 → 数据校验与处理 → 写入 InfluxDB(时序数据) → 缓存最新值到 Redis → 前端通过 API 查询或 WebSocket 推送设备控制流
前端 POST /api/devices/{id}/control → 后端收到控制指令 → 校验权限与参数 → 发布 MQTT 消息: greenhouse/devices/*/command → 设备接收指令并执行 → 设备反馈状态到 MQTT → 后端更新 SQLite 中的设备状态 → 前端收到反馈显示结果
技术栈详解
| 层级 | 技术 | 版本 | 用途 |
|---|---|---|---|
| 前端 | Vue | 3.5.24 | UI 框架 |
| TypeScript | 5.0+ | 类型检查 | |
| Vite | 5.0+ | 构建工具 | |
| Naive UI | 2.34+ | 组件库 | |
| Pinia | 2.1+ | 状态管理 | |
| Axios | 1.6+ | HTTP 客户端 | |
| MQTT.js | 4.3+ | MQTT 客户端 | |
| 后端 | FastAPI | 0.104+ | 框架 |
| Python | 3.8+ | 语言 | |
| SQLAlchemy | 2.0+ | ORM | |
| Pydantic | 2.0+ | 数据验证 | |
| MQTT | 3.1.1 | 消息协议 | |
| 数据库 | SQLite | 3.0+ | 配置存储 |
| InfluxDB | 2.0+ | 时序数据库 | |
| Redis | 6.0+ | 缓存 | |
| 部署 | Docker | 20.10+ | 容器化 |
| docker-compose | 2.0+ | 编排 |
二、数据模型
1. 传感器数据模型
InfluxDB 时序数据:
measurement: sensor_data
tags:
- greenhouse_id (温室ID)
- sensor_type (温度/湿度/土壤/光照/CO2)
fields:
- value (数值)
- unit (单位)
- status (正常/异常/失连)
timestamp: UTC 时间戳示例数据点:
greenhouse,greenhouse_id=gh001,sensor_type=temperature value=25.3,unit="°C",status="normal" 1705315200000000000
greenhouse,greenhouse_id=gh001,sensor_type=humidity value=65.2,unit="%",status="normal" 17053152000000000002. 设备数据模型(SQLite)
表结构:
sql
-- 设备表
CREATE TABLE device (
id INTEGER PRIMARY KEY,
name VARCHAR(100) NOT NULL, -- 设备名称
device_type VARCHAR(50) NOT NULL, -- 类型: fan/pump/light/heater
mqtt_topic VARCHAR(200) NOT NULL, -- MQTT 主题
status BOOLEAN DEFAULT FALSE, -- 当前状态
auto_mode BOOLEAN DEFAULT FALSE, -- 自动模式
last_updated TIMESTAMP, -- 最后更新时间
created_at TIMESTAMP
);
-- 设备日志表
CREATE TABLE device_log (
id INTEGER PRIMARY KEY,
device_id INTEGER,
action VARCHAR(50), -- open/close/toggle
triggered_by VARCHAR(100), -- manual/auto/system
result VARCHAR(50), -- success/failed/timeout
timestamp TIMESTAMP,
FOREIGN KEY (device_id) REFERENCES device(id)
);3. 配置和阈值模型
sql
-- 环境阈值表
CREATE TABLE environment_threshold (
id INTEGER PRIMARY KEY,
metric VARCHAR(50), -- temperature/humidity/soil/light/co2
upper_limit FLOAT, -- 上限
lower_limit FLOAT, -- 下限
unit VARCHAR(20), -- 单位
alert_enabled BOOLEAN DEFAULT TRUE, -- 是否启用告警
severity VARCHAR(20), -- critical/warning/info
updated_at TIMESTAMP
);
-- 自动策略表
CREATE TABLE automation_strategy (
id INTEGER PRIMARY KEY,
name VARCHAR(100), -- 策略名称
trigger_condition VARCHAR(500), -- 触发条件(JSON)
action_command VARCHAR(500), -- 执行动作(JSON)
enabled BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP,
updated_at TIMESTAMP
);4. API 数据模型(Pydantic)
python
# 传感器数据模型
class SensorData(BaseModel):
timestamp: datetime
temperature: float # °C
humidity: float # %
soil_moisture: float # %
light_level: float # Lux
co2: Optional[float] # ppm
class HistoryDataPoint(BaseModel):
timestamp: datetime
value: float
unit: str
status: str # normal/abnormal
class DataQueryParams(BaseModel):
start_time: datetime
end_time: datetime
metrics: List[str] # 要查询的指标列表
interval: str # 聚合间隔: 1m/5m/15m/1h/1d
# 设备模型
class Device(BaseModel):
id: int
name: str
device_type: str # fan/pump/light/heater
status: bool # 开/关
auto_mode: bool # 自动模式
online: bool # 在线状态
last_updated: datetime
class DeviceControlRequest(BaseModel):
status: bool # true=打开, false=关闭
class DeviceAutoModeRequest(BaseModel):
auto_mode: bool
# 配置模型
class EnvironmentThreshold(BaseModel):
temperature_high: float
temperature_low: float
humidity_high: float
humidity_low: float
soil_moisture_high: float
soil_moisture_low: float
light_high: float
light_low: float
co2_high: Optional[float]
co2_low: Optional[float]
# 系统状态模型
class SystemHealth(BaseModel):
mqtt_connected: bool
mqtt_status: str # connected/disconnected/error
api_status: str # healthy/degraded/error
database_status: str # connected/error
devices_online: int
devices_total: int
last_check: datetime三、REST API 接口
基础信息
- 基础 URL:
http://localhost:8000/api - 响应格式:JSON
- 认证:JWT(可选,后续版本添加)
- 超时:10 秒
API 端点列表
传感器数据接口
1. 获取实时传感器数据
GET /sensors/current请求参数:无
响应示例:
json
{
"timestamp": "2024-01-15T10:30:00Z",
"temperature": 25.3,
"humidity": 65.2,
"soil_moisture": 45.8,
"light_level": 550,
"co2": 420,
"status": "normal"
}状态码:
- 200:成功
- 503:MQTT 不可用
2. 查询历史数据
POST /sensors/history请求体:
json
{
"start_time": "2024-01-15T00:00:00Z",
"end_time": "2024-01-15T23:59:59Z",
"metrics": ["temperature", "humidity", "soil_moisture"],
"interval": "1h"
}响应示例:
json
{
"data": [
{
"timestamp": "2024-01-15T00:00:00Z",
"temperature": 22.1,
"humidity": 58.5,
"soil_moisture": 42.3
},
{
"timestamp": "2024-01-15T01:00:00Z",
"temperature": 21.8,
"humidity": 59.2,
"soil_moisture": 41.9
}
],
"total_points": 24,
"query_time_ms": 145
}聚合间隔说明:
1m:1分钟聚合(最多查询 7 天)5m:5分钟聚合(最多查询 30 天)1h:小时聚合(最多查询 90 天)1d:天聚合(最多查询 1 年)
设备管理接口
1. 获取设备列表
GET /devices请求参数:
type(可选):筛选设备类型 (fan/pump/light/heater)online_only(可选):true = 仅显示在线设备
响应示例:
json
{
"devices": [
{
"id": 1,
"name": "风机 A",
"device_type": "fan",
"status": true,
"auto_mode": true,
"online": true,
"last_updated": "2024-01-15T10:30:00Z"
},
{
"id": 2,
"name": "灌溉泵",
"device_type": "pump",
"status": false,
"auto_mode": false,
"online": true,
"last_updated": "2024-01-15T10:29:50Z"
}
],
"total": 2,
"online_count": 2
}2. 控制单个设备
POST /devices/{device_id}/control请求参数:
device_id(路径参数):设备 ID
请求体:
json
{
"status": true
}响应示例:
json
{
"success": true,
"message": "风机 A 已打开",
"device_id": 1,
"new_status": true,
"executed_at": "2024-01-15T10:31:00Z"
}错误响应:
json
{
"success": false,
"error": "设备离线",
"error_code": "DEVICE_OFFLINE",
"device_id": 1
}3. 切换设备自动模式
POST /devices/{device_id}/auto请求体:
json
{
"auto_mode": true
}响应示例:
json
{
"success": true,
"device_id": 1,
"auto_mode": true,
"message": "已切换为自动模式"
}4. 批量控制设备
POST /devices/batch/control请求体:
json
{
"device_ids": [1, 2, 3],
"action": "open" // open/close/toggle
}响应示例:
json
{
"success": true,
"results": [
{
"device_id": 1,
"status": "success",
"new_state": true
},
{
"device_id": 2,
"status": "success",
"new_state": true
},
{
"device_id": 3,
"status": "failed",
"error": "设备离线"
}
]
}配置接口
1. 获取环境阈值
GET /config/thresholds响应示例:
json
{
"temperature": {
"high": 28.0,
"low": 20.0,
"unit": "°C"
},
"humidity": {
"high": 75.0,
"low": 45.0,
"unit": "%"
},
"soil_moisture": {
"high": 70.0,
"low": 35.0,
"unit": "%"
},
"light": {
"high": 8000.0,
"low": 200.0,
"unit": "Lux"
},
"co2": {
"high": 1000.0,
"low": 350.0,
"unit": "ppm"
}
}2. 更新环境阈值
POST /config/thresholds请求体:
json
{
"temperature": {"high": 30.0, "low": 18.0},
"humidity": {"high": 80.0, "low": 40.0},
"soil_moisture": {"high": 75.0, "low": 30.0},
"light": {"high": 9000.0, "low": 100.0},
"co2": {"high": 1200.0, "low": 300.0}
}响应示例:
json
{
"success": true,
"message": "阈值已更新",
"updated_at": "2024-01-15T10:32:00Z"
}系统接口
1. 获取详细系统状态
GET /health/detailed响应示例:
json
{
"status": "healthy",
"timestamp": "2024-01-15T10:30:00Z",
"components": {
"mqtt": {
"status": "connected",
"message": "MQTT Broker 连接正常",
"response_time_ms": 5
},
"api": {
"status": "healthy",
"message": "API 服务正常",
"response_time_ms": 10
},
"database": {
"status": "connected",
"message": "SQLite 连接正常",
"size_mb": 245.3
},
"influxdb": {
"status": "connected",
"message": "InfluxDB 连接正常",
"latest_data_age_seconds": 15
}
},
"devices": {
"online": 8,
"total": 10,
"offline": ["device_05", "device_10"]
}
}四、WebSocket 接口(可选)
实时数据推送
连接:ws://localhost:8000/ws/live
消息格式:
json
{
"type": "sensor_update",
"data": {
"timestamp": "2024-01-15T10:30:00Z",
"temperature": 25.3,
"humidity": 65.2
}
}事件类型:
sensor_update:传感器数据更新device_status_change:设备状态变化alert_triggered:告警触发system_status_change:系统状态变化
五、错误处理
标准错误响应
json
{
"error": {
"code": "INVALID_REQUEST",
"message": "请求参数错误",
"details": {
"field": "start_time",
"reason": "时间格式不合法"
}
}
}常见错误码
| 错误码 | HTTP 状态码 | 描述 |
|---|---|---|
INVALID_REQUEST | 400 | 请求参数错误 |
UNAUTHORIZED | 401 | 未授权 |
FORBIDDEN | 403 | 无权限 |
NOT_FOUND | 404 | 资源不存在 |
CONFLICT | 409 | 资源冲突 |
DEVICE_OFFLINE | 503 | 设备离线 |
MQTT_UNAVAILABLE | 503 | MQTT 不可用 |
DATABASE_ERROR | 500 | 数据库错误 |
INTERNAL_ERROR | 500 | 服务器内部错误 |
六、认证与授权(后续版本)
计划在 M5 阶段添加:
- JWT Token 认证
- 基于角色的访问控制(RBAC)
- API Key 机制
- 请求签名验证
七、性能优化建议
查询优化
- 使用 InfluxDB 的聚合查询而非全量查询
- 前端分页加载大数据集
- 实时数据使用 WebSocket 推送替代轮询
缓存策略
- 最新传感器数据缓存 Redis(TTL 1 分钟)
- 设备状态缓存(TTL 5 分钟)
- 配置缓存(TTL 10 分钟)
限流与熔断
- API 限流:100 req/min per client
- 超时时间:10 秒
- 重试策略:指数退避
最后更新:2025年11月18日