fix(app): 修复 AppController 安全与查询问题

- 加强异常处理、类型安全和图片上传校验
- 优化设备相关查询,避免重复访问数据源
- 补充并记录并发测试与审查修复实施计划
This commit is contained in:
yuhaiming
2026-07-17 08:20:44 +08:00
parent 4a4aabf19e
commit 70e2356f22
82 changed files with 6070 additions and 583 deletions

View File

@@ -16,8 +16,8 @@
| --- | --- |
| Broker | `mqtt.broker-url` |
| QoS | `mqtt.qos`,当前默认 `1` |
| 设备标识 | 上行 Topic 第一段可为设备 **MAC**`deviceNo`;下行命令 Topic 第一段统一使用 `deviceNo`,仅 `registerDeviceNo` 例外仍使用 MAC |
| Topic 变量 | 上行文档中的 `{deviceNo}` 表示设备标识占位符;下行文档中的 `{deviceNo}` 设备编号 |
| 设备标识 | 首次注册 Topic 使用设备 **MAC**;注册完成后的上、下行业务 Topic 统一使用 `deviceNo`LWT 离线 Topic 兼容 MAC |
| Topic 变量 | 文档中的 `{deviceNo}` 指服务端分配的设备编号,`{mac}` 设备 MAC 地址 |
| JSON 编码 | UTF-8 |
| 时间格式 | `yyyy-MM-dd HH:mm:ss` |
@@ -26,6 +26,7 @@
```yaml
- /+/publish/finish/schedule
- /+/publish/register
- /+/publish/status
- /+/publish/power
- /+/publish/ack
- /+/publish/finish/key
@@ -38,8 +39,9 @@
| 功能名称 | 通信方向 | 订阅名称 / Topic | Payload 类型 | 后端处理 |
| --- | --- | --- | --- | --- |
| 排程任务完成上报 | 设备发布,后端订阅 | `/{deviceNo}/publish/finish/schedule` | JSON | 当前记录日志 |
| 设备注册 | 设备发布,后端订阅 | `/{deviceNo}/publish/register` | JSON | 注册或更新设备 |
| 电量上报 | 设备发布,后端订阅 | `/{deviceNo}/publish/power` | JSON | 更新设备电量 |
| 设备注册 | 设备发布,后端订阅 | `/{mac}/publish/register` | JSON | 注册、标记上线并下发 deviceNo |
| 设备离线遗嘱 | 设备发布,后端订阅 | `/{deviceNo}/publish/status` | JSON | 收到 offline 后立即标记离线 |
| 电量及在线心跳 | 设备发布,后端订阅 | `/{deviceNo}/publish/power` | JSON | 更新设备电量并刷新 10 分钟在线心跳 |
| 命令应答 ACK | 设备发布,后端订阅 | `/{deviceNo}/publish/ack` | JSON 或纯文本 | 清理待确认命令 |
| 按键浇水完成上报 | 设备发布,后端订阅 | `/{deviceNo}/publish/finish/key` | JSON | 当前记录日志 |
| 硬件故障上报 | 设备发布,后端订阅 | `/{deviceNo}/publish/error` | JSON | 当前记录日志 |
@@ -51,7 +53,7 @@
| --- | --- |
| 功能名称 | 设备注册 |
| 通信方向 | 设备发布,后端订阅 |
| Topic | `/{deviceNo}/publish/register` |
| Topic | `/{mac}/publish/register` |
| Payload 类型 | JSON |
后端以 Topic 中的设备标识作为解析入口payload 中的 `deviceNo` 即使传入也会被 Topic 覆盖。
@@ -106,6 +108,29 @@
| --- | --- | --- | --- |
| powerLevel | string | 是 | 电量值,后端当前按字符串保存 |
注册成功后后端会立即将设备标记为在线。之后收到包含 `powerLevel` 的有效消息,会把在线心跳有效期刷新为 600 秒。设备必须周期上报,即使电量没有变化也要发送,建议每 5 分钟一次;连续 10 分钟未收到电量或 ACK 刷新时将被判定为离线。ACK 仍保留现有的在线缓存刷新逻辑。
## 设备离线遗嘱
| 项目 | 内容 |
| --- | --- |
| 功能名称 | 设备离线遗嘱 |
| 通信方向 | 设备发布,后端订阅 |
| Topic | `/{deviceNo}/publish/status`,注册前可使用 `/{mac}/publish/status` |
| Payload 类型 | JSON 或纯文本 |
推荐将以下消息配置为 MQTT LWT并设置 `retain=false`
```json
{
"status": "offline"
}
```
后端收到 `offline``0` 后立即标记设备离线。`online``1` 不会标记在线,设备上线通过注册成功或电量心跳确认。
兼容设备可发送 `{"deviceMac":"AA:BB:CC:DD:EE:FF","offline":"true"}`,服务端会使用 `deviceMac` 解析设备并标记离线。
## 命令应答 ACK
| 项目 | 内容 |
@@ -306,9 +331,10 @@ JSON 示例:
## 嵌入式侧实现要点
1. 设备启动后发布注册消息到 `/{deviceNo}/publish/register`
2. 设备定时或电量变化时发布电量到 `/{deviceNo}/publish/power`
3. 设备订阅自己的命令 Topic`/{deviceNo}/subscriber/cmd` `/{deviceNo}/subscriber/schedule`
4. 设备收到命令后立即返回 ACK 到 `/{deviceNo}/publish/ack`,推荐返回 JSON 并携带 `commandId`
5. 排程或按键浇水完成后,分别发布`/{deviceNo}/publish/finish/schedule``/{deviceNo}/publish/finish/key`
6. 硬件异常时发布到 `/{deviceNo}/publish/error`
1. 设备启动后使用 MAC 发布注册消息到 `/{mac}/publish/register`,取得服务端分配的 deviceNo
2. MQTT 连接时配置离线遗嘱 `/{deviceNo}/publish/status`payload 为 `{"status":"offline"}``retain=false`
3. 设备至少每 5 分钟发布一次电量到 `/{deviceNo}/publish/power`,电量未变化也要上报
4. 设备订阅自己的命令 Topic`/{deviceNo}/subscriber/cmd``/{deviceNo}/subscriber/schedule`
5. 设备收到命令后立即返回 ACK `/{deviceNo}/publish/ack`,推荐返回 JSON 并携带 `commandId`
6. 排程或按键浇水完成后,分别发布到 `/{deviceNo}/publish/finish/schedule``/{deviceNo}/publish/finish/key`
7. 硬件异常时发布到 `/{deviceNo}/publish/error`