核心业务流程
1. 设备上行:数据上报 (Telemetry)
这是设备主动向平台汇报状态的流程。
时序图
详细步骤
- 采集:设备(如四路继电器)检测到开关状态变化或周期性读取传感器数据。
- 发布:设备将数据封装为 JSON 格式,发布到 Topic
sys/{product_id}/{device_id}/thing/event/property/post。 - 接收:后端服务作为 MQTT 客户端,通过 TCP 长连接实时收到订阅的消息。
- 处理:
- 后端服务校验数据格式与设备身份。
- 更新 Redis 影子缓存(热缓存,用于 WebSocket 实时推送)。
- 更新 Redis 在线状态(
SET device:online:{id} = 1 EX 120)。 - 写入 PostgreSQL 设备影子(权威源,用于 API 查询和审计)。
- 将时序数据写入 InfluxDB 存档。
- 推送:如果用户正在查看小程序,后端通过 WebSocket/SSE 将最新状态实时推送给前端。
2. 设备在线状态(属性上报驱动)
平台维护设备在线状态,由属性上报消息驱动 + Redis TTL 自动过期实现,不使用 EMQX Webhook。
原理
每次设备属性上报 → 后端 SET device:online:{id} = 1, EX 120s
120 秒内无新上报 → Redis key 过期 → 判定离线设计理由
- 解耦:不依赖 EMQX Webhook 配置,EMQX 和后端各自独立运行
- 语义准确:"在线" = "设备在主动上报数据",比"TCP 连接存在"更有业务意义
- 部署零配置:切换测试/生产环境不需要改 EMQX 配置
在线状态查询
API 查询设备列表时,后端优先从 Redis 读取在线状态。key 存在 = 在线,key 不存在 = 离线。同时将在线状态同步回 PostgreSQL(isOnline 字段)以保持持久化层一致。
对于设备刚连接但尚未发第一条属性上报的窗口(通常 2-5 秒),设备显示为离线。这在业务场景中不构成问题——设备上报第一条数据后立即变更为在线。
3. 应用下行:指令控制 (Command)
这是用户通过手机控制设备的流程。
时序图
详细步骤
- 操作:用户在小程序点击"开启继电器 1"。
- 请求:小程序发送 HTTPS 请求
POST /device/control携带目标设备 ID 和指令参数。 - 鉴权:后端服务验证用户是否有权限控制该设备。
- 下发:
- 后端生成控制指令 Payload。
- 后端通过 MQTT 发布到 Topic
sys/{product_id}/{device_id}/thing/service/property/set。
- 执行:设备收到 MQTT 消息,解析指令,驱动继电器动作。
- 反馈:
- 设备动作完成后,发布响应消息到
sys/.../set_reply确认执行结果。 - 后端收到确认后,更新数据库状态,并返回操作成功给小程序(或通过异步通知)。
- 设备动作完成后,发布响应消息到
4. 设备首次注册与激活 (Device Registration)
设备配网时,后端提前在数据库创建设备记录。设备上电后使用预置凭证连接,EMQX 直连 PostgreSQL 进行认证。
时序图
详细步骤
第一阶段:配网时预先注册
- 配网:用户通过小程序 BLE 配网,扫描设备并写入 WiFi 信息(详见第 6 节)。
- 创建设备:配网成功后,小程序调用后端 API 创建设备记录。后端在 PostgreSQL 中写入设备物理 ID(MAC)、ProductKey、DeviceSecret(随机生成)。
- 返回凭证:后端将 DeviceSecret 返回给小程序,小程序通过 BLE 写入设备或提示用户。
第二阶段:设备上电连接
- 连接:设备上电后,以 MAC 作为 ClientId,ProductKey 为 Username,DeviceSecret 为 Password,向 EMQX 发起 MQTT CONNECT。
- 认证:EMQX 直接查询 PostgreSQL
devices表,比对凭证。查询到匹配记录则允许连接。
第三阶段:配置下发
- 下发配置:后端通过
sys/{pid}/{did}/thing/config/setTopic 下发逻辑 ID 和 MQTT Topic 列表。 - 保存:设备收到配置后,将逻辑 ID 写入 NVS(非易失存储),回复 set_reply 确认。
第四阶段:开始上报
- 首次上报:设备通过
sys/{pid}/{did}/thing/event/property/post上报属性。 - 标记在线:后端收到首次属性上报后,在 Redis 设置在线标记(TTL 120s),更新 PostgreSQL 最后上线时间。
- 后续通信:设备所有通信均使用逻辑 ID,不再暴露物理 MAC 地址。
5. OTA 固件升级 (Firmware OTA)
设备固件远程升级的端到端流程,涵盖固件上传、升级通知、下载校验、安装重启和状态上报。
时序图
详细步骤
- 上传固件:运维人员在 Web 后台上传新固件,后端存储到 OSS/MinIO,并在 PostgreSQL 记录版本号、下载 URL、文件大小和 MD5 校验值。
- 触发升级:运维人员选择目标设备(单设备或批量),触发升级任务。
- 通知设备:后端通过
sys/{pid}/{did}/thing/ota/upgradeTopic 向设备推送升级通知。 - 下载固件:设备收到通知后,通过 HTTP/HTTPS 从 OSS 下载固件文件。
- 进度上报:设备每下载 10%,通过
thing/ota/progressTopic 上报进度。后端通过 WebSocket 推送到 Web 后台实时展示。 - 校验:下载完成后,设备计算文件 MD5 并与通知中的 MD5 比对。
- 安装:校验通过后,设备将固件写入 OTA 分区,设置启动标记,上报 progress=100, desc="flashing"。
- 重启:设备自动重启,运行新固件,重新连接 MQTT 后上报新版本号。
- 记录:后端更新设备的固件版本记录,标记升级任务完成。
- 异常处理:若 MD5 校验失败,设备上报 desc="verify_failed",后端记录失败日志并通知运维人员。
离线设备处理:若设备在 OTA 通知下发时未在线(Redis 在线标记已过期),后端将 OTA 任务标记为 pending。设备下次上线后首次属性上报触发后端检查 pending 任务,重新生成 OTA 通知并下发。
6. 设备配网与绑定流程 (Device Provisioning)
用户通过微信小程序 BLE 配网,将新设备连接 WiFi 并注册到平台。
时序图
详细步骤
- 设备广播:设备上电后开启 BLE 广播,广播名称包含产品标识(如
YunStack-4CH-),等待配网。 - 发起配网:用户在小程序点击"添加设备",选择"BLE 配网"。
- 扫描设备:小程序调用
wx.startBluetoothDevicesDiscovery扫描附近的 BLE 设备,按广播名称过滤出目标设备。 - 建立连接:用户选择设备后,小程序通过 BLE GATT 建立连接。
- 输入 WiFi:用户在小程序输入当前环境的 WiFi SSID 和密码。
- 写入配网信息:小程序通过 BLE 将 WiFi SSID 和密码写入设备的配网特征值(UUID: 0xFF01)。
- 连接结果:设备通过 BLE 回复连接结果。
- 预注册设备:WiFi 连接成功后,小程序调用后端 API 创建设备记录。后端生成 DeviceSecret 并返回。
- 写入凭证:小程序通过 BLE 将 DeviceSecret 写入设备。
- MQTT 认证:设备用凭证连接 EMQX,EMQX 直连 PostgreSQL 认证通过。
- 配置下发:后端通过 MQTT 下发逻辑 ID,设备保存到 NVS。
- 上线通知:设备首次属性上报后,后端通过 WebSocket 推送上线通知到小程序。
- 命名设备:小程序显示配网成功,引导用户为设备命名。
- 超时处理:若 30 秒内未收到设备上线通知,小程序提示配网失败,引导重试。
