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