Commit def9ff11dd7727f5b11ed76e8cf12a9d6f9382da
1 parent
f05470e6
review:【IoT 物联网】OTA 相关实现
Showing
3 changed files
with
12 additions
and
0 deletions
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/job/ota/IotOtaUpgradeJob.java
| @@ -46,6 +46,7 @@ public class IotOtaUpgradeJob implements JobHandler { | @@ -46,6 +46,7 @@ public class IotOtaUpgradeJob implements JobHandler { | ||
| 46 | return null; | 46 | return null; |
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | + // TODO 芋艿:可以优化成批量获取 原因是:1. N+1 问题;2. offline 的设备无需查询 | ||
| 49 | // 2. 遍历推送记录 | 50 | // 2. 遍历推送记录 |
| 50 | int successCount = 0; | 51 | int successCount = 0; |
| 51 | int failureCount = 0; | 52 | int failureCount = 0; |
| @@ -54,6 +55,10 @@ public class IotOtaUpgradeJob implements JobHandler { | @@ -54,6 +55,10 @@ public class IotOtaUpgradeJob implements JobHandler { | ||
| 54 | try { | 55 | try { |
| 55 | // 2.1 设备如果不在线,直接跳过 | 56 | // 2.1 设备如果不在线,直接跳过 |
| 56 | IotDeviceDO device = deviceService.getDeviceFromCache(record.getDeviceId()); | 57 | IotDeviceDO device = deviceService.getDeviceFromCache(record.getDeviceId()); |
| 58 | + // TODO 芋艿:【优化】当前逻辑跳过了离线的设备,但未充分利用 MQTT 的离线消息能力。 | ||
| 59 | + // 1. MQTT 协议本身支持持久化会话(Clean Session=false)和 QoS > 0 的消息,允许 broker 为离线设备缓存消息。 | ||
| 60 | + // 2. 对于 OTA 升级这类非实时性强的任务,即使设备当前离线,也应该可以推送升级指令。设备在下次上线时即可收到。 | ||
| 61 | + // 3. 后续可以考虑:增加一个“允许离线推送”的选项。如果开启,即使设备状态为 OFFLINE,也应尝试推送消息,依赖 MQTT Broker 的能力进行离线缓存。 | ||
| 57 | if (device == null || IotDeviceStateEnum.isNotOnline(device.getState())) { | 62 | if (device == null || IotDeviceStateEnum.isNotOnline(device.getState())) { |
| 58 | continue; | 63 | continue; |
| 59 | } | 64 | } |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/mq/consumer/device/IotDeviceMessageSubscriber.java
| @@ -67,6 +67,7 @@ public class IotDeviceMessageSubscriber implements IotMessageSubscriber<IotDevic | @@ -67,6 +67,7 @@ public class IotDeviceMessageSubscriber implements IotMessageSubscriber<IotDevic | ||
| 67 | IotDeviceDO device = deviceService.validateDeviceExistsFromCache(message.getDeviceId()); | 67 | IotDeviceDO device = deviceService.validateDeviceExistsFromCache(message.getDeviceId()); |
| 68 | devicePropertyService.updateDeviceReportTimeAsync(device.getId(), LocalDateTime.now()); | 68 | devicePropertyService.updateDeviceReportTimeAsync(device.getId(), LocalDateTime.now()); |
| 69 | // 1.2 更新设备的连接 server | 69 | // 1.2 更新设备的连接 server |
| 70 | + // TODO 芋艿:HTTP 网关的上行消息,不应该更新 serverId,会覆盖掉 MQTT 等长连接的 serverId,导致下行消息无法发送。 | ||
| 70 | devicePropertyService.updateDeviceServerIdAsync(device.getId(), message.getServerId()); | 71 | devicePropertyService.updateDeviceServerIdAsync(device.getId(), message.getServerId()); |
| 71 | 72 | ||
| 72 | // 2. 未上线的设备,强制上线 | 73 | // 2. 未上线的设备,强制上线 |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/message/IotDeviceMessageServiceImpl.java
| @@ -117,6 +117,12 @@ public class IotDeviceMessageServiceImpl implements IotDeviceMessageService { | @@ -117,6 +117,12 @@ public class IotDeviceMessageServiceImpl implements IotDeviceMessageService { | ||
| 117 | 117 | ||
| 118 | // 2.2 情况二:发送下行消息 | 118 | // 2.2 情况二:发送下行消息 |
| 119 | // 如果是下行消息,需要校验 serverId 存在 | 119 | // 如果是下行消息,需要校验 serverId 存在 |
| 120 | + // TODO 芋艿:【设计】下行消息需要区分 PUSH 和 PULL 模型 | ||
| 121 | + // 1. PUSH 模型:适用于 MQTT 等长连接协议。通过 serverId 将消息路由到指定网关,实时推送。 | ||
| 122 | + // 2. PULL 模型:适用于 HTTP 等短连接协议。设备无固定 serverId,无法主动推送。 | ||
| 123 | + // 解决方案: | ||
| 124 | + // 当 serverId 不存在时,将下行消息存入“待拉取消息表”(例如 iot_device_pull_message)。 | ||
| 125 | + // 设备端通过定时轮询一个新增的 API(例如 /iot/message/pull)来拉取属于自己的消息。 | ||
| 120 | if (StrUtil.isEmpty(serverId)) { | 126 | if (StrUtil.isEmpty(serverId)) { |
| 121 | serverId = devicePropertyService.getDeviceServerId(device.getId()); | 127 | serverId = devicePropertyService.getDeviceServerId(device.getId()); |
| 122 | if (StrUtil.isEmpty(serverId)) { | 128 | if (StrUtil.isEmpty(serverId)) { |