Commit 4746281df96b59c38d5f33ef940cc1b228414eb1
1 parent
4015e790
【功能完善】IoT: 更新 MQTT 主题配置,重构设备属性和事件上报处理逻辑,优化消息处理流程
Showing
2 changed files
with
72 additions
and
12 deletions
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/emqx/upstream/IotDeviceUpstreamServer.java
| ... | ... | @@ -4,6 +4,7 @@ import cn.hutool.core.util.IdUtil; |
| 4 | 4 | import cn.hutool.json.JSONObject; |
| 5 | 5 | import cn.hutool.json.JSONUtil; |
| 6 | 6 | import cn.iocoder.yudao.module.iot.api.device.IotDeviceUpstreamApi; |
| 7 | +import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.IotDeviceEventReportReqDTO; | |
| 7 | 8 | import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.IotDevicePropertyReportReqDTO; |
| 8 | 9 | import cn.iocoder.yudao.module.iot.plugin.common.config.IotPluginCommonProperties; |
| 9 | 10 | import cn.iocoder.yudao.module.iot.plugin.common.downstream.IotDeviceDownstreamServer; |
| ... | ... | @@ -24,13 +25,26 @@ import java.time.LocalDateTime; |
| 24 | 25 | * IoT 设备下行服务端,接收来自 device 设备的请求,转发给 server 服务器 |
| 25 | 26 | * <p> |
| 26 | 27 | * 协议:HTTP、MQTT |
| 28 | + * 参考:<a href= | |
| 29 | + * "https://help.aliyun.com/zh/iot/user-guide/device-properties-events-and-services?spm=a2c4g.11186623.0.0.97a72915vRck44#section-g4j-5zg-12b">...</a> | |
| 27 | 30 | * |
| 28 | 31 | * @author haohao |
| 29 | 32 | */ |
| 30 | 33 | @Slf4j |
| 31 | 34 | public class IotDeviceUpstreamServer { |
| 32 | 35 | |
| 33 | - private static final String PROPERTY_POST_TOPIC = "/event/property/post"; | |
| 36 | + // 设备上报属性 标准 JSON | |
| 37 | + // 请求Topic:/sys/${productKey}/${deviceName}/thing/event/property/post | |
| 38 | + // 响应Topic:/sys/${productKey}/${deviceName}/thing/event/property/post_reply | |
| 39 | + // 设备上报事件 标准 JSON | |
| 40 | + // 请求Topic:/sys/${productKey}/${deviceName}/thing/event/${tsl.event.identifier}/post | |
| 41 | + // 响应Topic:/sys/${productKey}/${deviceName}/thing/event/${tsl.event.identifier}/post_reply | |
| 42 | + | |
| 43 | + private static final String SYS_TOPIC_PREFIX = "/sys/"; | |
| 44 | + private static final String PROPERTY_POST_TOPIC = "/thing/event/property/post"; | |
| 45 | + private static final String EVENT_POST_TOPIC_PREFIX = "/thing/event/"; | |
| 46 | + private static final String EVENT_POST_TOPIC_SUFFIX = "/post"; | |
| 47 | + | |
| 34 | 48 | private static final int RECONNECT_DELAY = 5000; // 重连延迟时间(毫秒) |
| 35 | 49 | private static final int QOS_LEVEL = 1; |
| 36 | 50 | |
| ... | ... | @@ -111,26 +125,41 @@ public class IotDeviceUpstreamServer { |
| 111 | 125 | * 处理 MQTT 消息 |
| 112 | 126 | */ |
| 113 | 127 | private void handleMessage(String topic, String payload) { |
| 128 | + // 校验前缀 | |
| 129 | + if (!topic.startsWith(SYS_TOPIC_PREFIX)) { | |
| 130 | + log.warn("[handleMessage][未知的消息类型][topic: {}]", topic); | |
| 131 | + return; | |
| 132 | + } | |
| 133 | + | |
| 114 | 134 | // 处理设备属性上报消息 |
| 115 | - if (topic.contains(PROPERTY_POST_TOPIC)) { | |
| 135 | + if (topic.endsWith(PROPERTY_POST_TOPIC)) { | |
| 136 | + log.info("[handleMessage][接收到设备属性上报][topic: {}]", topic); | |
| 116 | 137 | handlePropertyPost(topic, payload); |
| 138 | + return; | |
| 117 | 139 | } |
| 140 | + | |
| 141 | + // 处理设备事件上报消息 | |
| 142 | + if (topic.contains(EVENT_POST_TOPIC_PREFIX) && topic.endsWith(EVENT_POST_TOPIC_SUFFIX)) { | |
| 143 | + log.info("[handleMessage][接收到设备事件上报][topic: {}]", topic); | |
| 144 | + handleEventPost(topic, payload); | |
| 145 | + return; | |
| 146 | + } | |
| 147 | + | |
| 148 | + // 未知消息类型 | |
| 149 | + log.warn("[handleMessage][未知的消息类型][topic: {}]", topic); | |
| 118 | 150 | } |
| 119 | 151 | |
| 120 | 152 | /** |
| 121 | 153 | * 处理设备属性上报 |
| 122 | 154 | */ |
| 123 | 155 | private void handlePropertyPost(String topic, String payload) { |
| 156 | + // /sys/${productKey}/${deviceName}/thing/event/property/post | |
| 124 | 157 | // 解析消息内容 |
| 125 | 158 | JSONObject jsonObject = JSONUtil.parseObj(payload); |
| 126 | 159 | String[] topicParts = topic.split("/"); |
| 127 | 160 | |
| 128 | 161 | // 构建设备属性上报请求对象 |
| 129 | - IotDevicePropertyReportReqDTO reportReqDTO = buildPropertyReportDTO( | |
| 130 | - jsonObject, | |
| 131 | - topicParts[1], // productKey | |
| 132 | - topicParts[2] // deviceName | |
| 133 | - ); | |
| 162 | + IotDevicePropertyReportReqDTO reportReqDTO = buildPropertyReportDTO(jsonObject, topicParts); | |
| 134 | 163 | |
| 135 | 164 | // 调用上游 API 处理设备上报数据 |
| 136 | 165 | deviceUpstreamApi.reportDeviceProperty(reportReqDTO); |
| ... | ... | @@ -139,21 +168,52 @@ public class IotDeviceUpstreamServer { |
| 139 | 168 | } |
| 140 | 169 | |
| 141 | 170 | /** |
| 171 | + * 处理设备事件上报 | |
| 172 | + */ | |
| 173 | + private void handleEventPost(String topic, String payload) { | |
| 174 | + // /sys/${productKey}/${deviceName}/thing/event/${tsl.event.identifier}/post | |
| 175 | + // 解析消息内容 | |
| 176 | + JSONObject jsonObject = JSONUtil.parseObj(payload); | |
| 177 | + String[] topicParts = topic.split("/"); | |
| 178 | + | |
| 179 | + // 构建设备事件上报请求对象 | |
| 180 | + IotDeviceEventReportReqDTO reportReqDTO = buildEventReportDTO(jsonObject, topicParts); | |
| 181 | + | |
| 182 | + // 调用上游 API 处理设备上报数据 | |
| 183 | + deviceUpstreamApi.reportDeviceEvent(reportReqDTO); | |
| 184 | + log.info("[handleEventPost][处理设备上行消息成功][topic: {}][reportReqDTO: {}]", | |
| 185 | + topic, JSONUtil.toJsonStr(reportReqDTO)); | |
| 186 | + } | |
| 187 | + | |
| 188 | + /** | |
| 142 | 189 | * 构建设备属性上报请求对象 |
| 143 | 190 | */ |
| 144 | 191 | private IotDevicePropertyReportReqDTO buildPropertyReportDTO(JSONObject jsonObject, |
| 145 | - String productKey, | |
| 146 | - String deviceName) { | |
| 192 | + String[] topicParts) { | |
| 147 | 193 | return ((IotDevicePropertyReportReqDTO) new IotDevicePropertyReportReqDTO() |
| 148 | 194 | .setRequestId(jsonObject.getStr("id")) |
| 149 | 195 | .setProcessId(IotPluginCommonUtils.getProcessId()) |
| 150 | 196 | .setReportTime(LocalDateTime.now()) |
| 151 | - .setProductKey(productKey) | |
| 152 | - .setDeviceName(deviceName)) | |
| 197 | + .setProductKey(topicParts[2]) | |
| 198 | + .setDeviceName(topicParts[3])) | |
| 153 | 199 | .setProperties(jsonObject.getJSONObject("params")); |
| 154 | 200 | } |
| 155 | 201 | |
| 156 | 202 | /** |
| 203 | + * 构建设备事件上报请求对象 | |
| 204 | + */ | |
| 205 | + private IotDeviceEventReportReqDTO buildEventReportDTO(JSONObject jsonObject, String[] topicParts) { | |
| 206 | + return ((IotDeviceEventReportReqDTO) new IotDeviceEventReportReqDTO() | |
| 207 | + .setRequestId(jsonObject.getStr("id")) | |
| 208 | + .setProcessId(IotPluginCommonUtils.getProcessId()) | |
| 209 | + .setReportTime(LocalDateTime.now()) | |
| 210 | + .setProductKey(topicParts[2]) | |
| 211 | + .setDeviceName(topicParts[3])) | |
| 212 | + .setIdentifier(topicParts[4]) | |
| 213 | + .setParams(jsonObject.getJSONObject("params")); | |
| 214 | + } | |
| 215 | + | |
| 216 | + /** | |
| 157 | 217 | * 重连 MQTT 客户端 |
| 158 | 218 | */ |
| 159 | 219 | private void reconnectWithDelay() { | ... | ... |
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/resources/application.yml