Commit 72d8511d6b9628106e899348200f66f7de386865
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
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
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
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 | ... | ... |