系统架构
分层架构
flowchart TB
subgraph 客户端层
Console["管理控制台 Console"]
Site["官方网站 Site"]
Client["第三方客户端"]
end
subgraph 云端服务层
CloudAPI["Cloud API (aiohttp + websockets)"]
Auth["Auth Middleware<br/>JWT 验证 · CORS · 角色鉴权"]
Hub["Hub<br/>WebSocket 连接管理 · 会话 · 心跳 · 消息分发"]
Proxy["Proxy<br/>REST API → 设备转发 · 异步响应等待"]
Routes["Route Handlers<br/>13 个功能模块"]
end
subgraph 设备层
Host["JanPNP Host<br/>树莓派上位机"]
Slave["JanPNP Slave Board<br/>STM32 下位机"]
end
客户端层 -->|HTTPS / REST API| CloudAPI
CloudAPI --> Auth
CloudAPI --> Hub
CloudAPI --> Proxy
CloudAPI --> Routes
Routes --> Proxy
Hub -->|WebSocket / JSON| Host
Host -->|USART1 / JPCLI| Slave
Cloud API 是三层架构中的中间层:上接管理控制台与用户,下连现场贴片机主机。设备通过 WebSocket 注册后,API 路由通过 Proxy 将请求转发给设备并等待响应。
核心模块
Hub — 设备连接管理
gateway/hub.py 中的 Hub 类是网关的核心。它维护 device_id → DeviceSession 映射,每个 DeviceSession 记录设备元数据、心跳时间、最后状态和待处理请求的 Future 表。
连接生命周期:
sequenceDiagram
participant Device as 设备
participant Hub as Hub
participant Proxy as Proxy
Device->>Hub: WebSocket 连接 (X-Device-ID)
Hub->>Hub: 创建/替换 Session
Device->>Hub: register {token, hostname, ip, version}
Hub->>Device: register_ack {success: true}
Device->>Hub: heartbeat (每 30s)
Hub->>Device: heartbeat_ack
Note over Proxy,Device: 代理请求示例
Proxy->>Device: request {id, method, path, params}
Device->>Hub: response {id, data}
Hub->>Proxy: Future.set_result(data)
关键特性:
- 心跳检测:超过
CLOUD_HEARTBEAT_TIMEOUT(默认 60 秒)未收到心跳标记为不活跃 - 消息分发:
handle_message()根据帧类型分发到注册/心跳/响应/状态上报处理 - 请求-响应解耦:
response帧通过msg_id匹配_pending字典中的 Future - 设备绑定:用户首次登录设备后记录绑定关系到 JSON 文件
Proxy — 请求代理转发
gateway/proxy.py 中的 proxy_request() 将 REST API 请求异步转发给设备:
- 检查设备 Session 存在且已注册
- 生成唯一的
msg_id并创建asyncio.Future - 通过 WebSocket 发送
request帧 - 等待设备回复对应的
response帧 - 超时(默认 15 秒)返回 504 错误
Auth — 认证与鉴权
auth/middleware.py 提供两层中间件:
- CORS 中间件:根据
CLOUD_CORS_ORIGINS配置允许跨域访问 - JWT 中间件:从
Authorization: Bearer <token>提取 JWT,验证后将用户信息注入request["user"]
白名单路由(免认证):
- GET /api/v1/health
- POST /api/v1/auth/login
- POST /api/v1/auth/wechat-login
- POST /api/v1/feedback
- 固件公开下载路径
Route Handlers — API 路由
所有路由在 server.py 中集中注册,每个路由模块接收 (hub, request) 参数。设备路由通过 _with_hub() 装饰器注入 Hub 实例并执行设备访问权限检查。
| 模块 | 前缀 | 核心职责 |
|---|---|---|
api_device |
/devices |
设备列表、在线发现、详情、状态、连接信息、设备登录与绑定 |
api_system |
/system |
设备系统状态、设置读写与重置、标定 |
api_task |
/tasks |
当前任务、板图像、启动/暂停/恢复/停止 |
api_warehouse |
/warehouse |
元件 CRUD、BOM 管理、飞达槽位、订单可用性校验 |
api_vision |
/vision |
视觉状态、模型切换、目标切换、元件检测 |
api_hardware |
/hardware |
位置查询、同步状态、运动/泵/阀/灯光/吸取控制 |
api_debug |
/debug |
串口列表、设备调试状态、串口日志、命令发送 |
api_firmware |
/firmware |
签名固件清单、镜像下载、版本发布管理、审计日志 |
api_order |
/orders |
工单创建、解析、取消、删除、历史查询 |
api_camera |
/cameras |
相机状态、帧获取 |
api_extension |
/extensions |
已安装扩展、扩展市场、统计、安装/卸载 |
api_auth |
/auth |
用户登录、微信登录、令牌刷新 |
api_feedback |
/feedback |
用户反馈提交 |
数据流示例:设备概览
sequenceDiagram
participant Client as 客户端
participant API as Cloud API
participant Proxy as Proxy
participant Device as 设备
Client->>API: GET /api/v1/devices/{id}/overview
API->>API: 检查 Session 存在
par 并发代理请求
API->>Proxy: GET /system/status
API->>Proxy: GET /tasks/current
API->>Proxy: GET /hardware/position
API->>Proxy: GET /vision/status
API->>Proxy: GET /cameras/status
API->>Proxy: GET /debug/status
end
Proxy->>Device: 转发请求 (×6)
Device->>Proxy: 响应 (×6)
API->>Client: 返回聚合概览 (部分失败不影响整体)
技术栈
| 组件 | 选型 | 说明 |
|---|---|---|
| HTTP 框架 | aiohttp | 异步 Web 框架,支持中间件和路由 |
| WebSocket | websockets | 轻量级 WebSocket 库,与 aiohttp 互补 |
| JWT | PyJWT | HS256 签名令牌 |
| 配置 | python-dotenv | 环境变量加载 |
| 并发 | asyncio | 全异步架构,Future 用于请求-响应匹配 |
项目结构
web-server/
├── api/ # Cloud API 主服务
│ ├── server.py # 应用入口、路由注册、HTTP + WebSocket 启动
│ ├── config.py # 环境变量配置与生产环境校验
│ ├── DEVICE_PROTOCOL.md # 设备 WebSocket 通信协议
│ ├── requirements.txt # Python 依赖
│ ├── .env.example # 生产环境变量模板
│ ├── auth/ # 用户认证
│ │ ├── jwt_utils.py # JWT 令牌签发与验证
│ │ └── middleware.py # CORS 与 JWT 认证中间件
│ ├── gateway/ # 设备网关
│ │ ├── hub.py # WebSocket Hub:设备连接与消息分发
│ │ └── proxy.py # 请求代理:HTTP→设备转发
│ ├── routes/ # RESTful API 路由模块 (13 个)
│ ├── firmware/ # 固件存储
│ │ └── slave/ # 下位机固件
│ └── tools/ # 开发与测试工具
├── console/ # 管理控制台前端
├── home/ # 官方网站
└── docs/ # 项目文档