Commit 0bdd000226e83ee7b01794030248522b84375616

Authored by YunaiV
1 parent 86e4379e

【代码评审】IoT:mqtt 协议的接入

Showing 13 changed files with 61 additions and 100 deletions
yudao-module-iot/yudao-module-iot-biz/pom.xml
... ... @@ -43,6 +43,11 @@
43 43  
44 44 <!-- DB 相关 -->
45 45 <dependency>
  46 + <groupId>com.taosdata.jdbc</groupId>
  47 + <artifactId>taos-jdbcdriver</artifactId>
  48 + </dependency>
  49 +
  50 + <dependency>
46 51 <groupId>cn.iocoder.boot</groupId>
47 52 <artifactId>yudao-spring-boot-starter-mybatis</artifactId>
48 53 </dependency>
... ... @@ -107,12 +112,6 @@
107 112 <version>24.1.2</version>
108 113 </dependency>
109 114  
110   - <!-- TDengine 相关依赖 -->
111   - <dependency>
112   - <groupId>com.taosdata.jdbc</groupId>
113   - <artifactId>taos-jdbcdriver</artifactId>
114   - </dependency>
115   -
116 115 </dependencies>
117 116  
118 117 </project>
... ...
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/downstream/router/IotDeviceConfigSetVertxHandler.java
... ... @@ -46,7 +46,6 @@ public class IotDeviceConfigSetVertxHandler implements Handler&lt;RoutingContext&gt; {
46 46 .setConfig(config);
47 47 } catch (Exception e) {
48 48 log.error("[handle][路径参数({}) 解析参数失败]", routingContext.pathParams(), e);
49   - // 使用IotStandardResponse实体类返回错误
50 49 IotStandardResponse errorResponse = IotStandardResponse.error(
51 50 null, METHOD, BAD_REQUEST.getCode(), BAD_REQUEST.getMsg());
52 51 IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse);
... ... @@ -57,18 +56,16 @@ public class IotDeviceConfigSetVertxHandler implements Handler&lt;RoutingContext&gt; {
57 56 try {
58 57 CommonResult<Boolean> result = deviceDownstreamHandler.setDeviceConfig(reqDTO);
59 58  
60   - // 使用IotStandardResponse实体类返回结果
  59 + // 3. 响应结果
61 60 IotStandardResponse response;
62 61 if (result.isSuccess()) {
63 62 response = IotStandardResponse.success(reqDTO.getRequestId(), METHOD, result.getData());
64 63 } else {
65   - response = IotStandardResponse.error(
66   - reqDTO.getRequestId(), METHOD, result.getCode(), result.getMsg());
  64 + response = IotStandardResponse.error(reqDTO.getRequestId(), METHOD, result.getCode(), result.getMsg());
67 65 }
68 66 IotPluginCommonUtils.writeJsonResponse(routingContext, response);
69 67 } catch (Exception e) {
70 68 log.error("[handle][请求参数({}) 配置设置异常]", reqDTO, e);
71   - // 使用IotStandardResponse实体类返回错误
72 69 IotStandardResponse errorResponse = IotStandardResponse.error(
73 70 reqDTO.getRequestId(), METHOD, INTERNAL_SERVER_ERROR.getCode(), INTERNAL_SERVER_ERROR.getMsg());
74 71 IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse);
... ...
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/downstream/router/IotDeviceOtaUpgradeVertxHandler.java
... ... @@ -51,7 +51,6 @@ public class IotDeviceOtaUpgradeVertxHandler implements Handler&lt;RoutingContext&gt;
51 51 .setInformation(information);
52 52 } catch (Exception e) {
53 53 log.error("[handle][路径参数({}) 解析参数失败]", routingContext.pathParams(), e);
54   - // 使用IotStandardResponse实体类返回错误
55 54 IotStandardResponse errorResponse = IotStandardResponse.error(
56 55 null, METHOD, BAD_REQUEST.getCode(), BAD_REQUEST.getMsg());
57 56 IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse);
... ... @@ -62,18 +61,16 @@ public class IotDeviceOtaUpgradeVertxHandler implements Handler&lt;RoutingContext&gt;
62 61 try {
63 62 CommonResult<Boolean> result = deviceDownstreamHandler.upgradeDeviceOta(reqDTO);
64 63  
65   - // 使用IotStandardResponse实体类返回结果
  64 + // 3. 响应结果
66 65 IotStandardResponse response;
67 66 if (result.isSuccess()) {
68 67 response = IotStandardResponse.success(reqDTO.getRequestId(), METHOD, result.getData());
69 68 } else {
70   - response = IotStandardResponse.error(
71   - reqDTO.getRequestId(), METHOD, result.getCode(), result.getMsg());
  69 + response = IotStandardResponse.error(reqDTO.getRequestId(), METHOD, result.getCode(), result.getMsg());
72 70 }
73 71 IotPluginCommonUtils.writeJsonResponse(routingContext, response);
74 72 } catch (Exception e) {
75 73 log.error("[handle][请求参数({}) OTA 升级异常]", reqDTO, e);
76   - // 使用IotStandardResponse实体类返回错误
77 74 IotStandardResponse errorResponse = IotStandardResponse.error(
78 75 reqDTO.getRequestId(), METHOD, INTERNAL_SERVER_ERROR.getCode(), INTERNAL_SERVER_ERROR.getMsg());
79 76 IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse);
... ...
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/downstream/router/IotDevicePropertyGetVertxHandler.java
... ... @@ -46,7 +46,6 @@ public class IotDevicePropertyGetVertxHandler implements Handler&lt;RoutingContext&gt;
46 46 .setIdentifiers(identifiers);
47 47 } catch (Exception e) {
48 48 log.error("[handle][路径参数({}) 解析参数失败]", routingContext.pathParams(), e);
49   - // 使用IotStandardResponse实体类返回错误
50 49 IotStandardResponse errorResponse = IotStandardResponse.error(
51 50 null, METHOD, BAD_REQUEST.getCode(), BAD_REQUEST.getMsg());
52 51 IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse);
... ... @@ -57,18 +56,16 @@ public class IotDevicePropertyGetVertxHandler implements Handler&lt;RoutingContext&gt;
57 56 try {
58 57 CommonResult<Boolean> result = deviceDownstreamHandler.getDeviceProperty(reqDTO);
59 58  
60   - // 使用IotStandardResponse实体类返回结果
  59 + // 3. 响应结果
61 60 IotStandardResponse response;
62 61 if (result.isSuccess()) {
63 62 response = IotStandardResponse.success(reqDTO.getRequestId(), METHOD, result.getData());
64 63 } else {
65   - response = IotStandardResponse.error(
66   - reqDTO.getRequestId(), METHOD, result.getCode(), result.getMsg());
  64 + response = IotStandardResponse.error(reqDTO.getRequestId(), METHOD, result.getCode(), result.getMsg());
67 65 }
68 66 IotPluginCommonUtils.writeJsonResponse(routingContext, response);
69 67 } catch (Exception e) {
70 68 log.error("[handle][请求参数({}) 属性获取异常]", reqDTO, e);
71   - // 使用IotStandardResponse实体类返回错误
72 69 IotStandardResponse errorResponse = IotStandardResponse.error(
73 70 reqDTO.getRequestId(), METHOD, INTERNAL_SERVER_ERROR.getCode(), INTERNAL_SERVER_ERROR.getMsg());
74 71 IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse);
... ...
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/downstream/router/IotDevicePropertySetVertxHandler.java
... ... @@ -46,7 +46,6 @@ public class IotDevicePropertySetVertxHandler implements Handler&lt;RoutingContext&gt;
46 46 .setProperties(properties);
47 47 } catch (Exception e) {
48 48 log.error("[handle][路径参数({}) 解析参数失败]", routingContext.pathParams(), e);
49   - // 使用IotStandardResponse实体类返回错误
50 49 IotStandardResponse errorResponse = IotStandardResponse.error(
51 50 null, METHOD, BAD_REQUEST.getCode(), BAD_REQUEST.getMsg());
52 51 IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse);
... ... @@ -57,18 +56,16 @@ public class IotDevicePropertySetVertxHandler implements Handler&lt;RoutingContext&gt;
57 56 try {
58 57 CommonResult<Boolean> result = deviceDownstreamHandler.setDeviceProperty(reqDTO);
59 58  
60   - // 使用IotStandardResponse实体类返回结果
  59 + // 3. 响应结果
61 60 IotStandardResponse response;
62 61 if (result.isSuccess()) {
63 62 response = IotStandardResponse.success(reqDTO.getRequestId(), METHOD, result.getData());
64 63 } else {
65   - response = IotStandardResponse.error(
66   - reqDTO.getRequestId(), METHOD, result.getCode(), result.getMsg());
  64 + response = IotStandardResponse.error(reqDTO.getRequestId(), METHOD, result.getCode(), result.getMsg());
67 65 }
68 66 IotPluginCommonUtils.writeJsonResponse(routingContext, response);
69 67 } catch (Exception e) {
70 68 log.error("[handle][请求参数({}) 属性设置异常]", reqDTO, e);
71   - // 使用IotStandardResponse实体类返回错误
72 69 IotStandardResponse errorResponse = IotStandardResponse.error(
73 70 reqDTO.getRequestId(), METHOD, INTERNAL_SERVER_ERROR.getCode(), INTERNAL_SERVER_ERROR.getMsg());
74 71 IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse);
... ...
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/downstream/router/IotDeviceServiceInvokeVertxHandler.java
... ... @@ -48,7 +48,6 @@ public class IotDeviceServiceInvokeVertxHandler implements Handler&lt;RoutingContex
48 48 .setIdentifier(identifier).setParams(params);
49 49 } catch (Exception e) {
50 50 log.error("[handle][路径参数({}) 解析参数失败]", routingContext.pathParams(), e);
51   - // 使用IotStandardResponse实体类返回错误
52 51 String method = METHOD_PREFIX + routingContext.pathParam("identifier") + METHOD_SUFFIX;
53 52 IotStandardResponse errorResponse = IotStandardResponse.error(
54 53 null, method, BAD_REQUEST.getCode(), BAD_REQUEST.getMsg());
... ... @@ -60,19 +59,17 @@ public class IotDeviceServiceInvokeVertxHandler implements Handler&lt;RoutingContex
60 59 try {
61 60 CommonResult<Boolean> result = deviceDownstreamHandler.invokeDeviceService(reqDTO);
62 61  
63   - // 使用IotStandardResponse实体类返回结果
  62 + // 3. 响应结果
64 63 String method = METHOD_PREFIX + reqDTO.getIdentifier() + METHOD_SUFFIX;
65 64 IotStandardResponse response;
66 65 if (result.isSuccess()) {
67 66 response = IotStandardResponse.success(reqDTO.getRequestId(), method, result.getData());
68 67 } else {
69   - response = IotStandardResponse.error(
70   - reqDTO.getRequestId(), method, result.getCode(), result.getMsg());
  68 + response = IotStandardResponse.error(reqDTO.getRequestId(), method, result.getCode(), result.getMsg());
71 69 }
72 70 IotPluginCommonUtils.writeJsonResponse(routingContext, response);
73 71 } catch (Exception e) {
74 72 log.error("[handle][请求参数({}) 服务调用异常]", reqDTO, e);
75   - // 使用IotStandardResponse实体类返回错误
76 73 String method = METHOD_PREFIX + reqDTO.getIdentifier() + METHOD_SUFFIX;
77 74 IotStandardResponse errorResponse = IotStandardResponse.error(
78 75 reqDTO.getRequestId(), method, INTERNAL_SERVER_ERROR.getCode(), INTERNAL_SERVER_ERROR.getMsg());
... ...
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/pojo/IotStandardResponse.java
... ... @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.iot.plugin.common.pojo;
3 3 import lombok.Data;
4 4 import lombok.experimental.Accessors;
5 5  
  6 +// TODO @芋艿:1)后续考虑,要不要叫 Iot 网关之类的 Response;2)包名 pojo
6 7 /**
7 8 * IoT 标准协议响应实体类
8 9 * <p>
... ...
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/emqx/config/IotEmqxPlugin.java
... ... @@ -10,10 +10,9 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext
10 10 /**
11 11 * EMQX 插件实现类
12 12 *
13   - * 基于 PF4J 插件框架,实现 EMQX 消息中间件的集成
14   - * 负责插件的生命周期管理,包括启动、停止和应用上下文的创建
  13 + * 基于 PF4J 插件框架,实现 EMQX 消息中间件的集成:负责插件的生命周期管理,包括启动、停止和应用上下文的创建
15 14 *
16   - * @author 芋道源码
  15 + * @author haohao
17 16 */
18 17 @Slf4j
19 18 public class IotEmqxPlugin extends SpringPlugin {
... ... @@ -26,7 +25,6 @@ public class IotEmqxPlugin extends SpringPlugin {
26 25 public void start() {
27 26 log.info("[EmqxPlugin][EmqxPlugin 插件启动开始...]");
28 27 try {
29   -
30 28 log.info("[EmqxPlugin][EmqxPlugin 插件启动成功...]");
31 29 } catch (Exception e) {
32 30 log.error("[EmqxPlugin][EmqxPlugin 插件开启动异常...]", e);
... ... @@ -52,6 +50,7 @@ public class IotEmqxPlugin extends SpringPlugin {
52 50 // 继续使用插件自己的 ClassLoader 以加载插件内部的类
53 51 pluginContext.setClassLoader(getWrapper().getPluginClassLoader());
54 52 // 扫描当前插件的自动配置包
  53 + // TODO @芋艿:是不是要配置下包
55 54 pluginContext.scan("cn.iocoder.yudao.module.iot.plugin.emqx.config");
56 55 pluginContext.refresh();
57 56 return pluginContext;
... ...
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/emqx/downstream/IotDeviceDownstreamHandlerImpl.java
... ... @@ -17,7 +17,6 @@ import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.MQTT_TOPIC_IL
17 17  
18 18 /**
19 19 * EMQX 插件的 {@link IotDeviceDownstreamHandler} 实现类
20   - * <p>
21 20 *
22 21 * @author 芋道源码
23 22 */
... ... @@ -26,8 +25,7 @@ public class IotDeviceDownstreamHandlerImpl implements IotDeviceDownstreamHandle
26 25  
27 26 private static final String SYS_TOPIC_PREFIX = "/sys/";
28 27  
29   - // TODO @haohao:讨论,感觉 mqtt 和 http,可以做个相对统一的格式哈。
30   - // 回复 都使用 Alink 格式,方便后续扩展。
  28 + // TODO @haohao:讨论,感觉 mqtt 和 http,可以做个相对统一的格式哈。;回复 都使用 Alink 格式,方便后续扩展。
31 29 // 设备服务调用 标准 JSON
32 30 // 请求Topic:/sys/${productKey}/${deviceName}/thing/service/${tsl.service.identifier}
33 31 // 响应Topic:/sys/${productKey}/${deviceName}/thing/service/${tsl.service.identifier}_reply
... ... @@ -62,11 +60,8 @@ public class IotDeviceDownstreamHandlerImpl implements IotDeviceDownstreamHandle
62 60 try {
63 61 // 构建请求主题
64 62 String topic = buildServiceTopic(reqDTO.getProductKey(), reqDTO.getDeviceName(), reqDTO.getIdentifier());
65   -
66   - // 生成请求ID(如果没有提供)
67   - String requestId = reqDTO.getRequestId() != null ? reqDTO.getRequestId() : generateRequestId();
68   -
69 63 // 构建请求消息
  64 + String requestId = reqDTO.getRequestId() != null ? reqDTO.getRequestId() : generateRequestId();
70 65 JSONObject request = buildServiceRequest(requestId, reqDTO.getIdentifier(), reqDTO.getParams());
71 66  
72 67 // 发送消息
... ... @@ -98,11 +93,8 @@ public class IotDeviceDownstreamHandlerImpl implements IotDeviceDownstreamHandle
98 93 try {
99 94 // 构建请求主题
100 95 String topic = buildPropertySetTopic(reqDTO.getProductKey(), reqDTO.getDeviceName());
101   -
102   - // 生成请求ID(如果没有提供)
103   - String requestId = reqDTO.getRequestId() != null ? reqDTO.getRequestId() : generateRequestId();
104   -
105 96 // 构建请求消息
  97 + String requestId = reqDTO.getRequestId() != null ? reqDTO.getRequestId() : generateRequestId();
106 98 JSONObject request = buildPropertySetRequest(requestId, reqDTO.getProperties());
107 99  
108 100 // 发送消息
... ... @@ -163,7 +155,7 @@ public class IotDeviceDownstreamHandlerImpl implements IotDeviceDownstreamHandle
163 155 }
164 156  
165 157 /**
166   - * 发布MQTT消息
  158 + * 发布 MQTT 消息
167 159 */
168 160 private void publishMessage(String topic, JSONObject payload) {
169 161 mqttClient.publish(
... ...
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/emqx/upstream/router/IotDeviceAuthVertxHandler.java
... ... @@ -13,13 +13,12 @@ import lombok.extern.slf4j.Slf4j;
13 13 import java.util.Collections;
14 14  
15 15 /**
16   - * IoT Emqx 连接认证的 Vert.x Handler
17   - * <a href=
18   - * "https://docs.emqx.com/zh/emqx/latest/access-control/authn/http.html">MQTT
19   - * HTTP</a>
  16 + * IoT EMQX 连接认证的 Vert.x Handler
  17 + *
  18 + * <a href="https://docs.emqx.com/zh/emqx/latest/access-control/authn/http.html">EMQX HTTP</a>
20 19 *
21 20 * 注意:该处理器需要返回特定格式:{"result": "allow"} 或 {"result": "deny"},
22   - * 以符合 EMQX 认证插件的要求,因此不使用 IotStandardResponse 实体类。
  21 + * 以符合 EMQX 认证插件的要求,因此不使用 IotStandardResponse 实体类
23 22 *
24 23 * @author haohao
25 24 */
... ...
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/emqx/upstream/router/IotDeviceMqttMessageHandler.java
1 1 package cn.iocoder.yudao.module.iot.plugin.emqx.upstream.router;
2 2  
  3 +import cn.hutool.core.util.StrUtil;
3 4 import cn.hutool.json.JSONObject;
4 5 import cn.hutool.json.JSONUtil;
5 6 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
... ... @@ -21,26 +22,20 @@ import java.util.Map;
21 22  
22 23 /**
23 24 * IoT 设备 MQTT 消息处理器
24   - * <p>
25   - * 参考:
26   - * <p>
27   - * "<a href=
28   - * "https://help.aliyun.com/zh/iot/user-guide/device-properties-events-and-services?spm=a2c4g.11186623.0.0.97a72915vRck44#section-g4j-5zg-12b">...</a>">
  25 + *
  26 + * 参考:"<a href="https://help.aliyun.com/zh/iot/user-guide/device-properties-events-and-services">设备属性、事件、服务</a>">
29 27 */
30 28 @Slf4j
31 29 public class IotDeviceMqttMessageHandler {
32 30  
33   - // TODO @haohao:讨论,感觉 mqtt 和 http,可以做个相对统一的格式哈。
34   - // 回复 都使用 Alink 格式,方便后续扩展。
  31 + // TODO @haohao:讨论,感觉 mqtt 和 http,可以做个相对统一的格式哈;回复 都使用 Alink 格式,方便后续扩展。
35 32 // 设备上报属性 标准 JSON
36 33 // 请求 Topic:/sys/${productKey}/${deviceName}/thing/event/property/post
37 34 // 响应 Topic:/sys/${productKey}/${deviceName}/thing/event/property/post_reply
38 35  
39 36 // 设备上报事件 标准 JSON
40   - // 请求
41   - // Topic:/sys/${productKey}/${deviceName}/thing/event/${tsl.event.identifier}/post
42   - // 响应
43   - // Topic:/sys/${productKey}/${deviceName}/thing/event/${tsl.event.identifier}/post_reply
  37 + // 请求 Topic:/sys/${productKey}/${deviceName}/thing/event/${tsl.event.identifier}/post
  38 + // 响应 Topic:/sys/${productKey}/${deviceName}/thing/event/${tsl.event.identifier}/post_reply
44 39  
45 40 private static final String SYS_TOPIC_PREFIX = "/sys/";
46 41 private static final String PROPERTY_POST_TOPIC = "/thing/event/property/post";
... ... @@ -70,7 +65,7 @@ public class IotDeviceMqttMessageHandler {
70 65 log.info("[messageHandler][接收到消息][topic: {}][payload: {}]", topic, payload);
71 66  
72 67 try {
73   - if (payload == null || payload.isEmpty()) {
  68 + if (StrUtil.isEmpty(payload)) {
74 69 log.warn("[messageHandler][消息内容为空][topic: {}]", topic);
75 70 return;
76 71 }
... ... @@ -214,27 +209,20 @@ public class IotDeviceMqttMessageHandler {
214 209 * @param topic 原始主题
215 210 * @param jsonObject 原始消息JSON对象
216 211 * @param method 响应方法
217   - * @param customData 自定义数据,可为null
  212 + * @param customData 自定义数据,可为 null
218 213 */
219 214 private void sendResponse(String topic, JSONObject jsonObject, String method, Object customData) {
220 215 String replyTopic = topic + REPLY_SUFFIX;
221 216  
222   - // 使用IotStandardResponse实体类构建响应
  217 + // 响应结果
223 218 IotStandardResponse response = IotStandardResponse.success(
224   - jsonObject.getStr("id"),
225   - method,
226   - customData);
227   -
  219 + jsonObject.getStr("id"), method, customData);
228 220 try {
229   - mqttClient.publish(replyTopic,
230   - Buffer.buffer(JsonUtils.toJsonString(response)),
231   - MqttQoS.AT_LEAST_ONCE,
232   - false,
233   - false);
  221 + mqttClient.publish(replyTopic, Buffer.buffer(JsonUtils.toJsonString(response)),
  222 + MqttQoS.AT_LEAST_ONCE, false, false);
234 223 log.info("[sendResponse][发送响应消息成功][topic: {}]", replyTopic);
235 224 } catch (Exception e) {
236   - log.error("[sendResponse][发送响应消息失败][topic: {}][response: {}]",
237   - replyTopic, response, e);
  225 + log.error("[sendResponse][发送响应消息失败][topic: {}][response: {}]", replyTopic, response, e);
238 226 }
239 227 }
240 228  
... ... @@ -304,4 +292,5 @@ public class IotDeviceMqttMessageHandler {
304 292  
305 293 return reportReqDTO;
306 294 }
  295 +
307 296 }
308 297 \ No newline at end of file
... ...
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/emqx/upstream/router/IotDeviceWebhookVertxHandler.java
... ... @@ -16,13 +16,12 @@ import java.time.LocalDateTime;
16 16 import java.util.Collections;
17 17  
18 18 /**
19   - * IoT Emqx Webhook 事件处理的 Vert.x Handler
  19 + * IoT EMQX Webhook 事件处理的 Vert.x Handler
20 20 *
21   - * <a href=
22   - * "https://docs.emqx.com/zh/emqx/latest/data-integration/webhook.html">EMQXWebhook</a>
  21 + * <a href="https://docs.emqx.com/zh/emqx/latest/data-integration/webhook.html">EMQX Webhook</a>
23 22 *
24 23 * 注意:该处理器需要返回特定格式:{"result": "success"} 或 {"result": "error"},
25   - * 以符合 EMQX Webhook 插件的要求,因此不使用 IotStandardResponse 实体类。
  24 + * 以符合 EMQX Webhook 插件的要求,因此不使用 IotStandardResponse 实体类。
26 25 *
27 26 * @author haohao
28 27 */
... ... @@ -137,7 +136,7 @@ public class IotDeviceWebhookVertxHandler implements Handler&lt;RoutingContext&gt; {
137 136 * 解析用户名,格式为 deviceName&productKey
138 137 *
139 138 * @param username 用户名
140   - * @return 解析结果,[0] 为 deviceName,[1] 为productKey,解析失败返回 null
  139 + * @return 解析结果,[0] 为 deviceName,[1] 为 productKey,解析失败返回 null
141 140 */
142 141 private String[] parseUsername(String username) {
143 142 if (StrUtil.isEmpty(username)) {
... ...
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/upstream/router/IotDeviceUpstreamVertxHandler.java
... ... @@ -34,9 +34,13 @@ import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeC
34 34 @Slf4j
35 35 public class IotDeviceUpstreamVertxHandler implements Handler<RoutingContext> {
36 36  
37   - // 属性上报路径
  37 + /**
  38 + * 属性上报路径
  39 + */
38 40 public static final String PROPERTY_PATH = "/sys/:productKey/:deviceName/thing/event/property/post";
39   - // 事件上报路径
  41 + /**
  42 + * 事件上报路径
  43 + */
40 44 public static final String EVENT_PATH = "/sys/:productKey/:deviceName/thing/event/:identifier/post";
41 45  
42 46 private static final String PROPERTY_METHOD = "thing.event.property.post";
... ... @@ -60,7 +64,6 @@ public class IotDeviceUpstreamVertxHandler implements Handler&lt;RoutingContext&gt; {
60 64 // 2. 根据路径模式处理不同类型的请求
61 65 CommonResult<Boolean> result;
62 66 String method;
63   -
64 67 if (path.matches(".*/thing/event/property/post")) {
65 68 // 处理属性上报
66 69 IotDevicePropertyReportReqDTO reportReqDTO = parsePropertyReportRequest(productKey, deviceName, requestId, body);
... ... @@ -97,13 +100,13 @@ public class IotDeviceUpstreamVertxHandler implements Handler&lt;RoutingContext&gt; {
97 100 response = IotStandardResponse.error(requestId, method, result.getCode(), result.getMsg());
98 101 }
99 102 IotPluginCommonUtils.writeJsonResponse(routingContext, response);
100   -
101 103 } catch (Exception e) {
102 104 log.error("[handle][处理上行请求异常] path={}", path, e);
103   -
104 105 // 构建错误响应
105   - String method = path.contains("/property/") ? PROPERTY_METHOD : EVENT_METHOD_PREFIX + (routingContext.pathParams().containsKey("identifier") ? routingContext.pathParam("identifier") : "unknown") + EVENT_METHOD_SUFFIX;
106   -
  106 + String method = path.contains("/property/") ? PROPERTY_METHOD
  107 + : EVENT_METHOD_PREFIX + (routingContext.pathParams().containsKey("identifier")
  108 + ? routingContext.pathParam("identifier")
  109 + : "unknown") + EVENT_METHOD_SUFFIX;
107 110 IotStandardResponse errorResponse = IotStandardResponse.error(requestId, method, INTERNAL_SERVER_ERROR.getCode(), INTERNAL_SERVER_ERROR.getMsg());
108 111 IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse);
109 112 }
... ... @@ -130,20 +133,16 @@ public class IotDeviceUpstreamVertxHandler implements Handler&lt;RoutingContext&gt; {
130 133 */
131 134 @SuppressWarnings("unchecked")
132 135 private IotDevicePropertyReportReqDTO parsePropertyReportRequest(String productKey, String deviceName, String requestId, JsonObject body) {
133   -
134   - // 按照标准JSON格式处理属性数据
  136 + // 按照标准 JSON 格式处理属性数据
135 137 Map<String, Object> properties = new HashMap<>();
136   -
137   - // 优先使用params字段,符合标准
  138 + // 优先使用 params 字段,符合标准
138 139 Map<String, Object> params = body.getJsonObject("params") != null ? body.getJsonObject("params").getMap() : null;
139   -
140 140 if (params != null) {
141   - // 将标准格式的params转换为平台需要的properties格式
  141 + // 将标准格式的 params 转换为平台需要的 properties 格式
142 142 for (Map.Entry<String, Object> entry : params.entrySet()) {
143 143 String key = entry.getKey();
144 144 Object valueObj = entry.getValue();
145   -
146   - // 如果是复杂结构(包含value和time)
  145 + // 如果是复杂结构(包含 value 和 time)
147 146 if (valueObj instanceof Map) {
148 147 Map<String, Object> valueMap = (Map<String, Object>) valueObj;
149 148 properties.put(key, valueMap.getOrDefault("value", valueObj));
... ... @@ -153,6 +152,7 @@ public class IotDeviceUpstreamVertxHandler implements Handler&lt;RoutingContext&gt; {
153 152 }
154 153 }
155 154  
  155 + // 构建属性上报请求 DTO
156 156 return ((IotDevicePropertyReportReqDTO) new IotDevicePropertyReportReqDTO().setRequestId(requestId).setProcessId(IotPluginCommonUtils.getProcessId()).setReportTime(LocalDateTime.now()).setProductKey(productKey).setDeviceName(deviceName)).setProperties(properties);
157 157 }
158 158  
... ... @@ -166,12 +166,9 @@ public class IotDeviceUpstreamVertxHandler implements Handler&lt;RoutingContext&gt; {
166 166 * @param body 请求体
167 167 * @return 事件上报请求DTO
168 168 */
169   - @SuppressWarnings("unchecked")
170 169 private IotDeviceEventReportReqDTO parseEventReportRequest(String productKey, String deviceName, String identifier, String requestId, JsonObject body) {
171   -
172 170 // 按照标准JSON格式处理事件参数
173 171 Map<String, Object> params;
174   -
175 172 // 优先使用params字段,符合标准
176 173 if (body.getJsonObject("params") != null) {
177 174 params = body.getJsonObject("params").getMap();
... ... @@ -180,6 +177,7 @@ public class IotDeviceUpstreamVertxHandler implements Handler&lt;RoutingContext&gt; {
180 177 params = new HashMap<>();
181 178 }
182 179  
  180 + // 构建事件上报请求 DTO
183 181 return ((IotDeviceEventReportReqDTO) new IotDeviceEventReportReqDTO().setRequestId(requestId).setProcessId(IotPluginCommonUtils.getProcessId()).setReportTime(LocalDateTime.now()).setProductKey(productKey).setDeviceName(deviceName)).setIdentifier(identifier).setParams(params);
184 182 }
185 183 }
186 184 \ No newline at end of file
... ...