Commit 72d8511d6b9628106e899348200f66f7de386865

Authored by YunaiV
1 parent b5ce269f

【代码评审】IoT:网络组件的 review

Showing 15 changed files with 94 additions and 96 deletions
yudao-module-iot/yudao-module-iot-biz/pom.xml
@@ -24,16 +24,6 @@ @@ -24,16 +24,6 @@
24 <artifactId>yudao-module-iot-api</artifactId> 24 <artifactId>yudao-module-iot-api</artifactId>
25 <version>${revision}</version> 25 <version>${revision}</version>
26 </dependency> 26 </dependency>
27 - <dependency>  
28 - <groupId>cn.iocoder.boot</groupId>  
29 - <artifactId>yudao-module-iot-component-http</artifactId>  
30 - <version>${revision}</version>  
31 - </dependency>  
32 - <dependency>  
33 - <groupId>cn.iocoder.boot</groupId>  
34 - <artifactId>yudao-module-iot-component-emqx</artifactId>  
35 - <version>${revision}</version>  
36 - </dependency>  
37 27
38 <dependency> 28 <dependency>
39 <groupId>cn.iocoder.boot</groupId> 29 <groupId>cn.iocoder.boot</groupId>
@@ -144,6 +134,17 @@ @@ -144,6 +134,17 @@
144 <!-- <artifactId>spring-boot-starter-amqp</artifactId>--> 134 <!-- <artifactId>spring-boot-starter-amqp</artifactId>-->
145 <!-- </dependency>--> 135 <!-- </dependency>-->
146 136
  137 + <!-- IoT 网络组件:接收来自设备的上行数据 -->
  138 + <dependency>
  139 + <groupId>cn.iocoder.boot</groupId>
  140 + <artifactId>yudao-module-iot-component-http</artifactId>
  141 + <version>${revision}</version>
  142 + </dependency>
  143 + <dependency>
  144 + <groupId>cn.iocoder.boot</groupId>
  145 + <artifactId>yudao-module-iot-component-emqx</artifactId>
  146 + <version>${revision}</version>
  147 + </dependency>
147 </dependencies> 148 </dependencies>
148 149
149 </project> 150 </project>
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/api/device/IoTDeviceUpstreamApiImpl.java
@@ -16,7 +16,7 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; @@ -16,7 +16,7 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
16 */ 16 */
17 @RestController 17 @RestController
18 @Validated 18 @Validated
19 -@Primary 19 +@Primary // 保证优先匹配,因为 yudao-module-iot-component-core 也有 IotDeviceUpstreamApi 的实现,并且也可能会被 biz 引入
20 public class IoTDeviceUpstreamApiImpl implements IotDeviceUpstreamApi { 20 public class IoTDeviceUpstreamApiImpl implements IotDeviceUpstreamApi {
21 21
22 @Resource 22 @Resource
yudao-module-iot/yudao-module-iot-components/README.md
@@ -133,3 +133,5 @@ Parameter 1 of method deviceDownstreamServer in IotPluginCommonAutoConfiguration @@ -133,3 +133,5 @@ Parameter 1 of method deviceDownstreamServer in IotPluginCommonAutoConfiguration
133 ### 5. 使用默认配置 133 ### 5. 使用默认配置
134 134
135 组件现已加入完善的默认配置和空值处理机制,使配置更加灵活。但需要注意的是,这些默认配置值必须通过在主应用配置文件中设置相应的属性才能生效。 135 组件现已加入完善的默认配置和空值处理机制,使配置更加灵活。但需要注意的是,这些默认配置值必须通过在主应用配置文件中设置相应的属性才能生效。
  136 +
  137 +// TODO 芋艿:后续继续完善 README.md
136 \ No newline at end of file 138 \ No newline at end of file
yudao-module-iot/yudao-module-iot-components/yudao-module-iot-component-core/pom.xml
@@ -13,6 +13,7 @@ @@ -13,6 +13,7 @@
13 <packaging>jar</packaging> 13 <packaging>jar</packaging>
14 14
15 <name>${project.artifactId}</name> 15 <name>${project.artifactId}</name>
  16 + <!-- TODO @芋艿:description 后续统一优化一波 -->
16 <description> 17 <description>
17 物联网组件核心模块 18 物联网组件核心模块
18 </description> 19 </description>
@@ -49,4 +50,4 @@ @@ -49,4 +50,4 @@
49 <optional>true</optional> 50 <optional>true</optional>
50 </dependency> 51 </dependency>
51 </dependencies> 52 </dependencies>
52 -</project>  
53 \ No newline at end of file 53 \ No newline at end of file
  54 +</project>
54 \ No newline at end of file 55 \ No newline at end of file
yudao-module-iot/yudao-module-iot-components/yudao-module-iot-component-core/src/main/java/cn/iocoder/yudao/module/iot/component/core/config/IotComponentCommonAutoConfiguration.java
@@ -24,13 +24,15 @@ import org.springframework.scheduling.annotation.EnableScheduling; @@ -24,13 +24,15 @@ import org.springframework.scheduling.annotation.EnableScheduling;
24 public class IotComponentCommonAutoConfiguration { 24 public class IotComponentCommonAutoConfiguration {
25 25
26 /** 26 /**
27 - * 创建EMQX设备下行服务器  
28 - * 当yudao.iot.component.emqx.enabled=true时,使用emqxDeviceDownstreamHandler 27 + * 创建 EMQX 设备下行服务器
  28 + *
  29 + * 当 yudao.iot.component.emqx.enabled = true 时,优先使用 emqxDeviceDownstreamHandler
29 */ 30 */
30 @Bean 31 @Bean
31 @ConditionalOnProperty(prefix = "yudao.iot.component.emqx", name = "enabled", havingValue = "true") 32 @ConditionalOnProperty(prefix = "yudao.iot.component.emqx", name = "enabled", havingValue = "true")
32 - public IotDeviceDownstreamServer emqxDeviceDownstreamServer(IotComponentCommonProperties properties,  
33 - @Qualifier("emqxDeviceDownstreamHandler") IotDeviceDownstreamHandler deviceDownstreamHandler) { 33 + public IotDeviceDownstreamServer emqxDeviceDownstreamServer(
  34 + IotComponentCommonProperties properties,
  35 + @Qualifier("emqxDeviceDownstreamHandler") IotDeviceDownstreamHandler deviceDownstreamHandler) {
34 return new IotDeviceDownstreamServer(properties, deviceDownstreamHandler); 36 return new IotDeviceDownstreamServer(properties, deviceDownstreamHandler);
35 } 37 }
36 38
yudao-module-iot/yudao-module-iot-components/yudao-module-iot-component-core/src/main/java/cn/iocoder/yudao/module/iot/component/core/heartbeat/IotComponentInstanceHeartbeatJob.java
@@ -17,27 +17,24 @@ import java.util.concurrent.TimeUnit; @@ -17,27 +17,24 @@ import java.util.concurrent.TimeUnit;
17 /** 17 /**
18 * IoT 组件实例心跳定时任务 18 * IoT 组件实例心跳定时任务
19 * <p> 19 * <p>
20 - * 将组件的状态定时上报给 server 服务器  
21 - * <p>  
22 - * 用于定时发送心跳给服务端 20 + * 将组件的状态,定时上报给 server 服务器
23 */ 21 */
24 @RequiredArgsConstructor 22 @RequiredArgsConstructor
25 @Slf4j 23 @Slf4j
26 public class IotComponentInstanceHeartbeatJob { 24 public class IotComponentInstanceHeartbeatJob {
27 25
28 /** 26 /**
29 - * 内嵌模式的端口值(固定为0) 27 + * 内嵌模式的端口值(固定为 0)
30 */ 28 */
31 private static final Integer EMBEDDED_PORT = 0; 29 private static final Integer EMBEDDED_PORT = 0;
32 30
33 private final IotDeviceUpstreamApi deviceUpstreamApi; 31 private final IotDeviceUpstreamApi deviceUpstreamApi;
34 - private final IotDeviceDownstreamServer deviceDownstreamServer; 32 + private final IotDeviceDownstreamServer deviceDownstreamServer; // TODO @haohao:这个变量还需要哇?
35 private final IotComponentCommonProperties commonProperties; 33 private final IotComponentCommonProperties commonProperties;
36 private final IotComponentRegistry componentRegistry; 34 private final IotComponentRegistry componentRegistry;
37 35
38 /** 36 /**
39 - * 初始化方法由Spring调用  
40 - * 注册当前组件并发送上线心跳 37 + * 初始化方法,由 Spring调 用:注册当前组件并发送上线心跳
41 */ 38 */
42 public void init() { 39 public void init() {
43 // 将当前组件注册到注册表 40 // 将当前组件注册到注册表
@@ -64,8 +61,7 @@ public class IotComponentInstanceHeartbeatJob { @@ -64,8 +61,7 @@ public class IotComponentInstanceHeartbeatJob {
64 } 61 }
65 62
66 /** 63 /**
67 - * 停止方法由Spring调用  
68 - * 发送下线心跳并注销组件 64 + * 停止方法,由 Spring 调用:发送下线心跳并注销组件
69 */ 65 */
70 public void stop() { 66 public void stop() {
71 // 发送所有组件的下线心跳 67 // 发送所有组件的下线心跳
@@ -101,31 +97,29 @@ public class IotComponentInstanceHeartbeatJob { @@ -101,31 +97,29 @@ public class IotComponentInstanceHeartbeatJob {
101 } 97 }
102 98
103 /** 99 /**
104 - * 构建心跳DTO 100 + * 构建心跳 DTO
105 * 101 *
106 * @param component 组件信息 102 * @param component 组件信息
107 * @param online 是否在线 103 * @param online 是否在线
108 - * @return 心跳DTO 104 + * @return 心跳 DTO
109 */ 105 */
110 private IotPluginInstanceHeartbeatReqDTO buildPluginInstanceHeartbeatReqDTO(IotComponentInfo component, 106 private IotPluginInstanceHeartbeatReqDTO buildPluginInstanceHeartbeatReqDTO(IotComponentInfo component,
111 Boolean online) { 107 Boolean online) {
112 return new IotPluginInstanceHeartbeatReqDTO() 108 return new IotPluginInstanceHeartbeatReqDTO()
113 - .setPluginKey(component.getPluginKey())  
114 - .setProcessId(component.getProcessId())  
115 - .setHostIp(component.getHostIp())  
116 - .setDownstreamPort(component.getDownstreamPort()) 109 + .setPluginKey(component.getPluginKey()).setProcessId(component.getProcessId())
  110 + .setHostIp(component.getHostIp()).setDownstreamPort(component.getDownstreamPort())
117 .setOnline(online); 111 .setOnline(online);
118 } 112 }
119 113
  114 + // TODO @haohao:要和 IotPluginCommonUtils 保持一致么?
120 /** 115 /**
121 - * 获取当前进程ID 116 + * 获取当前进程 ID
122 * 117 *
123 - * @return 进程ID 118 + * @return 进程 ID
124 */ 119 */
125 private String getProcessId() { 120 private String getProcessId() {
126 - // 获取进程的 name  
127 String name = ManagementFactory.getRuntimeMXBean().getName(); 121 String name = ManagementFactory.getRuntimeMXBean().getName();
128 - // 分割名称,格式为 pid@hostname 122 + // TODO @haohao:是不是 SystemUtil.getCurrentPID(); 直接获取 pid 哈?
129 return name.split("@")[0]; 123 return name.split("@")[0];
130 } 124 }
131 } 125 }
yudao-module-iot/yudao-module-iot-components/yudao-module-iot-component-core/src/main/java/cn/iocoder/yudao/module/iot/component/core/heartbeat/IotComponentRegistry.java
1 package cn.iocoder.yudao.module.iot.component.core.heartbeat; 1 package cn.iocoder.yudao.module.iot.component.core.heartbeat;
2 2
3 import lombok.Data; 3 import lombok.Data;
4 -import lombok.ToString;  
5 import lombok.extern.slf4j.Slf4j; 4 import lombok.extern.slf4j.Slf4j;
6 import org.springframework.stereotype.Component; 5 import org.springframework.stereotype.Component;
7 6
@@ -9,6 +8,8 @@ import java.util.Collection; @@ -9,6 +8,8 @@ import java.util.Collection;
9 import java.util.Map; 8 import java.util.Map;
10 import java.util.concurrent.ConcurrentHashMap; 9 import java.util.concurrent.ConcurrentHashMap;
11 10
  11 +// TODO @haohao:组件相关的注释,要不把 组件 => 网络组件?可能更容易理解?
  12 +// TODO @haohao:yudao-module-iot-components => yudao-module-iot-net-components 增加一个 net 如何?虽然会长一点,但是意思更精准?
12 /** 13 /**
13 * IoT 组件注册表 14 * IoT 组件注册表
14 * <p> 15 * <p>
@@ -22,14 +23,14 @@ public class IotComponentRegistry { @@ -22,14 +23,14 @@ public class IotComponentRegistry {
22 * 组件信息 23 * 组件信息
23 */ 24 */
24 @Data 25 @Data
25 - @ToString  
26 public static class IotComponentInfo { 26 public static class IotComponentInfo {
  27 +
27 /** 28 /**
28 - * 组件Key 29 + * 组件 Key
29 */ 30 */
30 private final String pluginKey; 31 private final String pluginKey;
31 /** 32 /**
32 - * 主机IP 33 + * 主机 IP
33 */ 34 */
34 private final String hostIp; 35 private final String hostIp;
35 /** 36 /**
@@ -37,23 +38,24 @@ public class IotComponentRegistry { @@ -37,23 +38,24 @@ public class IotComponentRegistry {
37 */ 38 */
38 private final Integer downstreamPort; 39 private final Integer downstreamPort;
39 /** 40 /**
40 - * 进程ID 41 + * 进程 ID
41 */ 42 */
42 private final String processId; 43 private final String processId;
  44 +
43 } 45 }
44 46
45 /** 47 /**
46 - * 组件映射表,key为组件Key 48 + * 组件映射表:key 为组件 Key
47 */ 49 */
48 private final Map<String, IotComponentInfo> components = new ConcurrentHashMap<>(); 50 private final Map<String, IotComponentInfo> components = new ConcurrentHashMap<>();
49 51
50 /** 52 /**
51 * 注册组件 53 * 注册组件
52 * 54 *
53 - * @param pluginKey 组件Key  
54 - * @param hostIp 主机IP 55 + * @param pluginKey 组件 Key
  56 + * @param hostIp 主机 IP
55 * @param downstreamPort 下游端口 57 * @param downstreamPort 下游端口
56 - * @param processId 进程ID 58 + * @param processId 进程 ID
57 */ 59 */
58 public void registerComponent(String pluginKey, String hostIp, Integer downstreamPort, String processId) { 60 public void registerComponent(String pluginKey, String hostIp, Integer downstreamPort, String processId) {
59 log.info("[registerComponent][注册组件, pluginKey={}, hostIp={}, downstreamPort={}, processId={}]", 61 log.info("[registerComponent][注册组件, pluginKey={}, hostIp={}, downstreamPort={}, processId={}]",
@@ -64,7 +66,7 @@ public class IotComponentRegistry { @@ -64,7 +66,7 @@ public class IotComponentRegistry {
64 /** 66 /**
65 * 注销组件 67 * 注销组件
66 * 68 *
67 - * @param pluginKey 组件Key 69 + * @param pluginKey 组件 Key
68 */ 70 */
69 public void unregisterComponent(String pluginKey) { 71 public void unregisterComponent(String pluginKey) {
70 log.info("[unregisterComponent][注销组件, pluginKey={}]", pluginKey); 72 log.info("[unregisterComponent][注销组件, pluginKey={}]", pluginKey);
@@ -83,10 +85,11 @@ public class IotComponentRegistry { @@ -83,10 +85,11 @@ public class IotComponentRegistry {
83 /** 85 /**
84 * 获取指定组件 86 * 获取指定组件
85 * 87 *
86 - * @param pluginKey 组件Key 88 + * @param pluginKey 组件 Key
87 * @return 组件信息 89 * @return 组件信息
88 */ 90 */
89 public IotComponentInfo getComponent(String pluginKey) { 91 public IotComponentInfo getComponent(String pluginKey) {
90 return components.get(pluginKey); 92 return components.get(pluginKey);
91 } 93 }
  94 +
92 } 95 }
93 \ No newline at end of file 96 \ No newline at end of file
yudao-module-iot/yudao-module-iot-components/yudao-module-iot-component-core/src/main/java/cn/iocoder/yudao/module/iot/component/core/pojo/IotStandardResponse.java
@@ -62,13 +62,8 @@ public class IotStandardResponse { @@ -62,13 +62,8 @@ public class IotStandardResponse {
62 * @return 成功响应 62 * @return 成功响应
63 */ 63 */
64 public static IotStandardResponse success(String id, String method, Object data) { 64 public static IotStandardResponse success(String id, String method, Object data) {
65 - return new IotStandardResponse()  
66 - .setId(id)  
67 - .setCode(200)  
68 - .setData(data)  
69 - .setMessage("success")  
70 - .setMethod(method)  
71 - .setVersion("1.0"); 65 + return new IotStandardResponse().setId(id).setCode(200).setData(data).setMessage("success")
  66 + .setMethod(method).setVersion("1.0");
72 } 67 }
73 68
74 /** 69 /**
@@ -81,13 +76,8 @@ public class IotStandardResponse { @@ -81,13 +76,8 @@ public class IotStandardResponse {
81 * @return 错误响应 76 * @return 错误响应
82 */ 77 */
83 public static IotStandardResponse error(String id, String method, Integer code, String message) { 78 public static IotStandardResponse error(String id, String method, Integer code, String message) {
84 - return new IotStandardResponse()  
85 - .setId(id)  
86 - .setCode(code)  
87 - .setData(null)  
88 - .setMessage(message)  
89 - .setMethod(method)  
90 - .setVersion("1.0"); 79 + return new IotStandardResponse().setId(id).setCode(code).setData(null).setMessage(message)
  80 + .setMethod(method).setVersion("1.0");
91 } 81 }
92 82
93 } 83 }
94 \ No newline at end of file 84 \ No newline at end of file
yudao-module-iot/yudao-module-iot-components/yudao-module-iot-component-core/src/main/java/cn/iocoder/yudao/module/iot/component/core/util/IotPluginCommonUtils.java
@@ -9,6 +9,7 @@ import io.vertx.core.http.HttpHeaders; @@ -9,6 +9,7 @@ import io.vertx.core.http.HttpHeaders;
9 import io.vertx.ext.web.RoutingContext; 9 import io.vertx.ext.web.RoutingContext;
10 import org.springframework.http.MediaType; 10 import org.springframework.http.MediaType;
11 11
  12 +// TODO @haohao:名字要改下哈。
12 /** 13 /**
13 * IoT 插件的通用工具类 14 * IoT 插件的通用工具类
14 * 15 *
yudao-module-iot/yudao-module-iot-components/yudao-module-iot-component-emqx/src/main/java/cn/iocoder/yudao/module/iot/component/emqx/config/IotComponentEmqxAutoConfiguration.java
@@ -31,41 +31,45 @@ import java.lang.management.ManagementFactory; @@ -31,41 +31,45 @@ import java.lang.management.ManagementFactory;
31 @AutoConfiguration 31 @AutoConfiguration
32 @EnableConfigurationProperties(IotComponentEmqxProperties.class) 32 @EnableConfigurationProperties(IotComponentEmqxProperties.class)
33 @ConditionalOnProperty(prefix = "yudao.iot.component.emqx", name = "enabled", havingValue = "true", matchIfMissing = false) 33 @ConditionalOnProperty(prefix = "yudao.iot.component.emqx", name = "enabled", havingValue = "true", matchIfMissing = false)
  34 +// TODO @haohao:是不是不用扫 cn.iocoder.yudao.module.iot.component.core 拉,它尽量靠自动配置
34 @ComponentScan(basePackages = { 35 @ComponentScan(basePackages = {
35 "cn.iocoder.yudao.module.iot.component.core", // 核心包 36 "cn.iocoder.yudao.module.iot.component.core", // 核心包
36 - "cn.iocoder.yudao.module.iot.component.emqx" // EMQX组件包 37 + "cn.iocoder.yudao.module.iot.component.emqx" // EMQX 组件包
37 }) 38 })
38 public class IotComponentEmqxAutoConfiguration { 39 public class IotComponentEmqxAutoConfiguration {
39 40
40 /** 41 /**
41 - * 组件key 42 + * 组件 key
42 */ 43 */
43 private static final String PLUGIN_KEY = "emqx"; 44 private static final String PLUGIN_KEY = "emqx";
44 45
45 public IotComponentEmqxAutoConfiguration() { 46 public IotComponentEmqxAutoConfiguration() {
  47 + // TODO @haohao:这个日志,融合到 initialize ?
46 log.info("[IotComponentEmqxAutoConfiguration][已启动]"); 48 log.info("[IotComponentEmqxAutoConfiguration][已启动]");
47 } 49 }
48 50
49 @EventListener(ApplicationStartedEvent.class) 51 @EventListener(ApplicationStartedEvent.class)
50 public void initialize(ApplicationStartedEvent event) { 52 public void initialize(ApplicationStartedEvent event) {
51 - // 从应用上下文中获取需要的Bean 53 + // 从应用上下文中获取需要的 Bean
52 IotComponentRegistry componentRegistry = event.getApplicationContext().getBean(IotComponentRegistry.class); 54 IotComponentRegistry componentRegistry = event.getApplicationContext().getBean(IotComponentRegistry.class);
53 IotComponentCommonProperties commonProperties = event.getApplicationContext().getBean(IotComponentCommonProperties.class); 55 IotComponentCommonProperties commonProperties = event.getApplicationContext().getBean(IotComponentCommonProperties.class);
54 56
55 // 设置当前组件的核心标识 57 // 设置当前组件的核心标识
  58 + // TODO @haohao:如果多个组件,都去设置,会不会冲突哈?
56 commonProperties.setPluginKey(PLUGIN_KEY); 59 commonProperties.setPluginKey(PLUGIN_KEY);
57 60
58 - // 将EMQX组件注册到组件注册表 61 + // 将 EMQX 组件注册到组件注册表
59 componentRegistry.registerComponent( 62 componentRegistry.registerComponent(
60 PLUGIN_KEY, 63 PLUGIN_KEY,
61 SystemUtil.getHostInfo().getAddress(), 64 SystemUtil.getHostInfo().getAddress(),
62 - 0, // 内嵌模式固定为0 65 + 0, // 内嵌模式固定为 0
63 getProcessId() 66 getProcessId()
64 ); 67 );
65 68
66 log.info("[initialize][IoT EMQX 组件初始化完成]"); 69 log.info("[initialize][IoT EMQX 组件初始化完成]");
67 } 70 }
68 71
  72 + // TODO @haohao:这个可能要注意,可能会有多个?冲突?
69 @Bean 73 @Bean
70 public Vertx vertx() { 74 public Vertx vertx() {
71 return Vertx.vertx(); 75 return Vertx.vertx();
@@ -73,6 +77,7 @@ public class IotComponentEmqxAutoConfiguration { @@ -73,6 +77,7 @@ public class IotComponentEmqxAutoConfiguration {
73 77
74 @Bean 78 @Bean
75 public MqttClient mqttClient(Vertx vertx, IotComponentEmqxProperties emqxProperties) { 79 public MqttClient mqttClient(Vertx vertx, IotComponentEmqxProperties emqxProperties) {
  80 + // TODO @haohao:这个日志,要不要去掉,避免过多哈
76 log.info("MQTT配置: host={}, port={}, username={}, ssl={}", 81 log.info("MQTT配置: host={}, port={}, username={}, ssl={}",
77 emqxProperties.getMqttHost(), emqxProperties.getMqttPort(), 82 emqxProperties.getMqttHost(), emqxProperties.getMqttPort(),
78 emqxProperties.getMqttUsername(), emqxProperties.getMqttSsl()); 83 emqxProperties.getMqttUsername(), emqxProperties.getMqttSsl());
@@ -81,14 +86,12 @@ public class IotComponentEmqxAutoConfiguration { @@ -81,14 +86,12 @@ public class IotComponentEmqxAutoConfiguration {
81 .setClientId("yudao-iot-downstream-" + IdUtil.fastSimpleUUID()) 86 .setClientId("yudao-iot-downstream-" + IdUtil.fastSimpleUUID())
82 .setUsername(emqxProperties.getMqttUsername()) 87 .setUsername(emqxProperties.getMqttUsername())
83 .setPassword(emqxProperties.getMqttPassword()); 88 .setPassword(emqxProperties.getMqttPassword());
84 - 89 + // TODO @haohao:可以用 ObjUtil.default
85 if (emqxProperties.getMqttSsl() != null) { 90 if (emqxProperties.getMqttSsl() != null) {
86 options.setSsl(emqxProperties.getMqttSsl()); 91 options.setSsl(emqxProperties.getMqttSsl());
87 } else { 92 } else {
88 options.setSsl(false); 93 options.setSsl(false);
89 - log.warn("MQTT SSL配置为null,默认设置为false");  
90 } 94 }
91 -  
92 return MqttClient.create(vertx, options); 95 return MqttClient.create(vertx, options);
93 } 96 }
94 97
@@ -106,6 +109,7 @@ public class IotComponentEmqxAutoConfiguration { @@ -106,6 +109,7 @@ public class IotComponentEmqxAutoConfiguration {
106 return new IotDeviceDownstreamHandlerImpl(mqttClient); 109 return new IotDeviceDownstreamHandlerImpl(mqttClient);
107 } 110 }
108 111
  112 + // TODO @haohao:这个通用下一下哈。
109 /** 113 /**
110 * 获取当前进程ID 114 * 获取当前进程ID
111 * 115 *
@@ -118,4 +122,5 @@ public class IotComponentEmqxAutoConfiguration { @@ -118,4 +122,5 @@ public class IotComponentEmqxAutoConfiguration {
118 String pid = name.split("@")[0]; 122 String pid = name.split("@")[0];
119 return pid; 123 return pid;
120 } 124 }
  125 +
121 } 126 }
122 \ No newline at end of file 127 \ No newline at end of file
yudao-module-iot/yudao-module-iot-components/yudao-module-iot-component-emqx/src/main/java/cn/iocoder/yudao/module/iot/component/emqx/config/IotComponentEmqxProperties.java
@@ -7,47 +7,48 @@ import lombok.Data; @@ -7,47 +7,48 @@ import lombok.Data;
7 import org.springframework.boot.context.properties.ConfigurationProperties; 7 import org.springframework.boot.context.properties.ConfigurationProperties;
8 8
9 /** 9 /**
10 - * IoT EMQX组件配置属性 10 + * IoT EMQX 组件配置属性
11 */ 11 */
12 @ConfigurationProperties(prefix = "yudao.iot.component.emqx") 12 @ConfigurationProperties(prefix = "yudao.iot.component.emqx")
13 @Data 13 @Data
14 public class IotComponentEmqxProperties { 14 public class IotComponentEmqxProperties {
15 15
16 /** 16 /**
17 - * 是否启用EMQX组件 17 + * 是否启用 EMQX 组件
18 */ 18 */
19 private Boolean enabled; 19 private Boolean enabled;
20 20
  21 + // TODO @haohao:一般中英文之间,加个空格哈,写作(注释)习惯。类似 MQTT 密码;
21 /** 22 /**
22 * 服务主机 23 * 服务主机
23 */ 24 */
24 - @NotBlank(message = "MQTT服务器主机不能为空") 25 + @NotBlank(message = "MQTT 服务器主机不能为空")
25 private String mqttHost; 26 private String mqttHost;
26 /** 27 /**
27 * 服务端口 28 * 服务端口
28 */ 29 */
29 - @NotNull(message = "MQTT服务器端口不能为空") 30 + @NotNull(message = "MQTT 服务器端口不能为空")
30 private Integer mqttPort; 31 private Integer mqttPort;
31 /** 32 /**
32 * 服务用户名 33 * 服务用户名
33 */ 34 */
34 - @NotBlank(message = "MQTT服务器用户名不能为空") 35 + @NotBlank(message = "MQTT 服务器用户名不能为空")
35 private String mqttUsername; 36 private String mqttUsername;
36 /** 37 /**
37 * 服务密码 38 * 服务密码
38 */ 39 */
39 - @NotBlank(message = "MQTT服务器密码不能为空") 40 + @NotBlank(message = "MQTT 服务器密码不能为空")
40 private String mqttPassword; 41 private String mqttPassword;
41 /** 42 /**
42 * 是否启用 SSL 43 * 是否启用 SSL
43 */ 44 */
44 - @NotNull(message = "MQTT SSL配置不能为空") 45 + @NotNull(message = "MQTT SSL 配置不能为空")
45 private Boolean mqttSsl; 46 private Boolean mqttSsl;
46 47
47 /** 48 /**
48 * 订阅的主题列表 49 * 订阅的主题列表
49 */ 50 */
50 - @NotEmpty(message = "MQTT订阅主题不能为空") 51 + @NotEmpty(message = "MQTT 订阅主题不能为空")
51 private String[] mqttTopics; 52 private String[] mqttTopics;
52 53
53 /** 54 /**
@@ -56,4 +57,4 @@ public class IotComponentEmqxProperties { @@ -56,4 +57,4 @@ public class IotComponentEmqxProperties {
56 @NotNull(message = "认证端口不能为空") 57 @NotNull(message = "认证端口不能为空")
57 private Integer authPort; 58 private Integer authPort;
58 59
59 -}  
60 \ No newline at end of file 60 \ No newline at end of file
  61 +}
61 \ No newline at end of file 62 \ No newline at end of file
yudao-module-iot/yudao-module-iot-components/yudao-module-iot-component-emqx/src/main/java/cn/iocoder/yudao/module/iot/component/emqx/downstream/IotDeviceDownstreamHandlerImpl.java
@@ -167,6 +167,7 @@ public class IotDeviceDownstreamHandlerImpl implements IotDeviceDownstreamHandle @@ -167,6 +167,7 @@ public class IotDeviceDownstreamHandlerImpl implements IotDeviceDownstreamHandle
167 log.info("[publishMessage][发送消息成功][topic: {}][payload: {}]", topic, payload); 167 log.info("[publishMessage][发送消息成功][topic: {}][payload: {}]", topic, payload);
168 } 168 }
169 169
  170 + // TODO @haohao:这个要不抽到 IotPluginCommonUtils 里?
170 /** 171 /**
171 * 生成请求 ID 172 * 生成请求 ID
172 */ 173 */
yudao-module-iot/yudao-module-iot-components/yudao-module-iot-component-emqx/src/main/java/cn/iocoder/yudao/module/iot/component/emqx/upstream/IotDeviceUpstreamServer.java
1 package cn.iocoder.yudao.module.iot.component.emqx.upstream; 1 package cn.iocoder.yudao.module.iot.component.emqx.upstream;
2 2
3 import cn.hutool.core.util.ArrayUtil; 3 import cn.hutool.core.util.ArrayUtil;
  4 +import cn.hutool.core.util.StrUtil;
4 import cn.iocoder.yudao.module.iot.api.device.IotDeviceUpstreamApi; 5 import cn.iocoder.yudao.module.iot.api.device.IotDeviceUpstreamApi;
5 import cn.iocoder.yudao.module.iot.component.core.heartbeat.IotComponentRegistry; 6 import cn.iocoder.yudao.module.iot.component.core.heartbeat.IotComponentRegistry;
6 import cn.iocoder.yudao.module.iot.component.emqx.config.IotComponentEmqxProperties; 7 import cn.iocoder.yudao.module.iot.component.emqx.config.IotComponentEmqxProperties;
@@ -29,6 +30,7 @@ import java.util.concurrent.TimeUnit; @@ -29,6 +30,7 @@ import java.util.concurrent.TimeUnit;
29 @Slf4j 30 @Slf4j
30 public class IotDeviceUpstreamServer { 31 public class IotDeviceUpstreamServer {
31 32
  33 + // TODO @haohao:抽到 IotComponentEmqxProperties 里?
32 /** 34 /**
33 * 重连延迟时间(毫秒) 35 * 重连延迟时间(毫秒)
34 */ 36 */
@@ -101,7 +103,7 @@ public class IotDeviceUpstreamServer { @@ -101,7 +103,7 @@ public class IotDeviceUpstreamServer {
101 CompletableFuture<Void> httpFuture = server.listen(finalAuthPort) 103 CompletableFuture<Void> httpFuture = server.listen(finalAuthPort)
102 .toCompletionStage() 104 .toCompletionStage()
103 .toCompletableFuture() 105 .toCompletableFuture()
104 - .thenAccept(v -> log.info("[start][HTTP服务器启动完成,端口: {}]", server.actualPort())); 106 + .thenAccept(v -> log.info("[start][HTTP 服务器启动完成,端口: {}]", server.actualPort()));
105 107
106 // 2. 连接 MQTT Broker 108 // 2. 连接 MQTT Broker
107 CompletableFuture<Void> mqttFuture = connectMqtt() 109 CompletableFuture<Void> mqttFuture = connectMqtt()
@@ -110,7 +112,7 @@ public class IotDeviceUpstreamServer { @@ -110,7 +112,7 @@ public class IotDeviceUpstreamServer {
110 .thenAccept(v -> { 112 .thenAccept(v -> {
111 // 2.1 添加 MQTT 断开重连监听器 113 // 2.1 添加 MQTT 断开重连监听器
112 client.closeHandler(closeEvent -> { 114 client.closeHandler(closeEvent -> {
113 - log.warn("[closeHandler][MQTT连接已断开,准备重连]"); 115 + log.warn("[closeHandler][MQTT 连接已断开,准备重连]");
114 reconnectWithDelay(); 116 reconnectWithDelay();
115 }); 117 });
116 // 2. 设置 MQTT 消息处理器 118 // 2. 设置 MQTT 消息处理器
@@ -135,7 +137,7 @@ public class IotDeviceUpstreamServer { @@ -135,7 +137,7 @@ public class IotDeviceUpstreamServer {
135 */ 137 */
136 private void setupMessageHandler() { 138 private void setupMessageHandler() {
137 client.publishHandler(mqttMessageHandler::handle); 139 client.publishHandler(mqttMessageHandler::handle);
138 - log.debug("[setupMessageHandler][MQTT消息处理器设置完成]"); 140 + log.debug("[setupMessageHandler][MQTT 消息处理器设置完成]");
139 } 141 }
140 142
141 /** 143 /**
@@ -159,22 +161,20 @@ public class IotDeviceUpstreamServer { @@ -159,22 +161,20 @@ public class IotDeviceUpstreamServer {
159 * @return 连接结果的Future 161 * @return 连接结果的Future
160 */ 162 */
161 private Future<Void> connectMqtt() { 163 private Future<Void> connectMqtt() {
162 - // 检查必要的MQTT配置 164 + // 检查必要的 MQTT 配置
163 String host = emqxProperties.getMqttHost(); 165 String host = emqxProperties.getMqttHost();
164 Integer port = emqxProperties.getMqttPort(); 166 Integer port = emqxProperties.getMqttPort();
165 -  
166 if (host == null) { 167 if (host == null) {
167 - String msg = "[connectMqtt][MQTT Host为null,无法连接]"; 168 + String msg = "[connectMqtt][MQTT Host 为 null,无法连接]";
168 log.error(msg); 169 log.error(msg);
169 return Future.failedFuture(new IllegalStateException(msg)); 170 return Future.failedFuture(new IllegalStateException(msg));
170 } 171 }
171 -  
172 if (port == null) { 172 if (port == null) {
173 - log.warn("[connectMqtt][MQTT Port为null,使用默认端口1883]");  
174 - port = 1883; // 默认MQTT端口 173 + log.warn("[connectMqtt][MQTT Port 为 null,使用默认端口 1883]");
  174 + port = 1883; // 默认 MQTT 端口
175 } 175 }
176 176
177 - final Integer finalPort = port; // 为lambda表达式创建final变量 177 + final Integer finalPort = port;
178 return client.connect(finalPort, host) 178 return client.connect(finalPort, host)
179 .compose(connAck -> { 179 .compose(connAck -> {
180 log.info("[connectMqtt][MQTT客户端连接成功]"); 180 log.info("[connectMqtt][MQTT客户端连接成功]");
@@ -195,19 +195,15 @@ public class IotDeviceUpstreamServer { @@ -195,19 +195,15 @@ public class IotDeviceUpstreamServer {
195 private Future<Void> subscribeToTopics() { 195 private Future<Void> subscribeToTopics() {
196 String[] topics = emqxProperties.getMqttTopics(); 196 String[] topics = emqxProperties.getMqttTopics();
197 if (ArrayUtil.isEmpty(topics)) { 197 if (ArrayUtil.isEmpty(topics)) {
198 - log.warn("[subscribeToTopics][未配置MQTT主题或为null,使用默认主题]");  
199 - // 默认订阅所有设备上下行主题  
200 - topics = new String[]{"/device/#"}; 198 + log.warn("[subscribeToTopics][未配置 MQTT 主题或为 null,使用默认主题]");
  199 + topics = new String[]{"/device/#"}; // 默认订阅所有设备上下行主题
201 } 200 }
202 log.info("[subscribeToTopics][开始订阅设备上行消息主题]"); 201 log.info("[subscribeToTopics][开始订阅设备上行消息主题]");
203 202
204 Future<Void> compositeFuture = Future.succeededFuture(); 203 Future<Void> compositeFuture = Future.succeededFuture();
205 for (String topic : topics) { 204 for (String topic : topics) {
206 - if (topic == null) {  
207 - continue; // 跳过null主题  
208 - }  
209 - String trimmedTopic = topic.trim();  
210 - if (trimmedTopic.isEmpty()) { 205 + String trimmedTopic = StrUtil.trim(topic);
  206 + if (StrUtil.isBlank(trimmedTopic)) {
211 continue; 207 continue;
212 } 208 }
213 compositeFuture = compositeFuture.compose(v -> client.subscribe(trimmedTopic, DEFAULT_QOS.value()) 209 compositeFuture = compositeFuture.compose(v -> client.subscribe(trimmedTopic, DEFAULT_QOS.value())
yudao-module-iot/yudao-module-iot-components/yudao-module-iot-component-http/src/main/java/cn/iocoder/yudao/module/iot/component/http/config/IotComponentHttpAutoConfiguration.java
@@ -19,6 +19,7 @@ import org.springframework.context.event.EventListener; @@ -19,6 +19,7 @@ import org.springframework.context.event.EventListener;
19 19
20 import java.lang.management.ManagementFactory; 20 import java.lang.management.ManagementFactory;
21 21
  22 +// TODO @haohao:类似 IotComponentEmqxAutoConfiguration 的建议
22 /** 23 /**
23 * IoT 组件 HTTP 的自动配置类 24 * IoT 组件 HTTP 的自动配置类
24 * 25 *
yudao-module-iot/yudao-module-iot-components/yudao-module-iot-component-http/src/main/java/cn/iocoder/yudao/module/iot/component/http/config/IotComponentHttpProperties.java
@@ -5,7 +5,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties; @@ -5,7 +5,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
5 import org.springframework.validation.annotation.Validated; 5 import org.springframework.validation.annotation.Validated;
6 6
7 /** 7 /**
8 - * IoT HTTP组件配置属性 8 + * IoT HTTP 组件配置属性
9 */ 9 */
10 @ConfigurationProperties(prefix = "yudao.iot.component.http") 10 @ConfigurationProperties(prefix = "yudao.iot.component.http")
11 @Validated 11 @Validated