Commit 4746281df96b59c38d5f33ef940cc1b228414eb1

Authored by 安浩浩
1 parent 4015e790

【功能完善】IoT: 更新 MQTT 主题配置,重构设备属性和事件上报处理逻辑,优化消息处理流程

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
... ... @@ -15,5 +15,5 @@ yudao:
15 15 mqtt-ssl: false
16 16 mqtt-username: yudao
17 17 mqtt-password: 123456
18   - mqtt-topics: "/+/#"
  18 + mqtt-topics: "/sys/#"
19 19 auth-port: 8101
... ...