Commit d83af87f9f9bb7795eb030aef45ca502ce59d039
1 parent
44b835bd
【代码修复】IoT:网络组件相关
Showing
24 changed files
with
54 additions
and
25 deletions
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/IotProductScriptController.java
| @@ -107,6 +107,7 @@ public class IotProductScriptController { | @@ -107,6 +107,7 @@ public class IotProductScriptController { | ||
| 107 | @PreAuthorize("@ss.hasPermission('iot:product-script:query')") | 107 | @PreAuthorize("@ss.hasPermission('iot:product-script:query')") |
| 108 | public CommonResult<String> getSampleScript(@RequestParam("type") Integer type) { | 108 | public CommonResult<String> getSampleScript(@RequestParam("type") Integer type) { |
| 109 | String sample; | 109 | String sample; |
| 110 | + // TODO @haohao:要不枚举下? | ||
| 110 | switch (type) { | 111 | switch (type) { |
| 111 | case 1: | 112 | case 1: |
| 112 | sample = scriptSamples.getPropertyParserSample(); | 113 | sample = scriptSamples.getPropertyParserSample(); |
| @@ -118,6 +119,7 @@ public class IotProductScriptController { | @@ -118,6 +119,7 @@ public class IotProductScriptController { | ||
| 118 | sample = scriptSamples.getCommandEncoderSample(); | 119 | sample = scriptSamples.getCommandEncoderSample(); |
| 119 | break; | 120 | break; |
| 120 | default: | 121 | default: |
| 122 | + // TODO @haohao:不支持,返回 error 会不会好点哈?例如说,参数不正确; | ||
| 121 | sample = "// 不支持的脚本类型"; | 123 | sample = "// 不支持的脚本类型"; |
| 122 | } | 124 | } |
| 123 | return success(sample); | 125 | return success(sample); |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/plugin/IotPluginConfigServiceImpl.java
| @@ -17,6 +17,7 @@ import java.util.List; | @@ -17,6 +17,7 @@ import java.util.List; | ||
| 17 | 17 | ||
| 18 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 18 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 19 | import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.*; | 19 | import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.*; |
| 20 | + | ||
| 20 | /** | 21 | /** |
| 21 | * IoT 插件配置 Service 实现类 | 22 | * IoT 插件配置 Service 实现类 |
| 22 | * | 23 | * |
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-core/src/main/java/cn/iocoder/yudao/module/iot/net/component/core/config/IotNetComponentCommonAutoConfiguration.java
| @@ -13,6 +13,7 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties | @@ -13,6 +13,7 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties | ||
| 13 | import org.springframework.context.annotation.Bean; | 13 | import org.springframework.context.annotation.Bean; |
| 14 | import org.springframework.scheduling.annotation.EnableScheduling; | 14 | import org.springframework.scheduling.annotation.EnableScheduling; |
| 15 | 15 | ||
| 16 | +// TODO @haohao:应该不用写 spring.factories 拉,因为被 imports 替代啦 | ||
| 16 | /** | 17 | /** |
| 17 | * IoT 网络组件的通用自动配置类 | 18 | * IoT 网络组件的通用自动配置类 |
| 18 | * | 19 | * |
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-core/src/main/java/cn/iocoder/yudao/module/iot/net/component/core/constants/IotDeviceTopicEnum.java
| @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.iot.net.component.core.constants; | @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.iot.net.component.core.constants; | ||
| 2 | 2 | ||
| 3 | import lombok.Getter; | 3 | import lombok.Getter; |
| 4 | 4 | ||
| 5 | +// TODO @haohao:要不放到 enums 包下; | ||
| 5 | /** | 6 | /** |
| 6 | * IoT 设备主题枚举 | 7 | * IoT 设备主题枚举 |
| 7 | * <p> | 8 | * <p> |
| @@ -12,6 +13,7 @@ import lombok.Getter; | @@ -12,6 +13,7 @@ import lombok.Getter; | ||
| 12 | @Getter | 13 | @Getter |
| 13 | public enum IotDeviceTopicEnum { | 14 | public enum IotDeviceTopicEnum { |
| 14 | 15 | ||
| 16 | + // TODO @haohao:SYS_TOPIC_PREFIX、SERVICE_TOPIC_PREFIX、REPLY_SUFFIX 类似这种,要不搞成这个里面的静态变量?不是枚举值 | ||
| 15 | /** | 17 | /** |
| 16 | * 系统主题前缀 | 18 | * 系统主题前缀 |
| 17 | */ | 19 | */ |
| @@ -22,6 +24,7 @@ public enum IotDeviceTopicEnum { | @@ -22,6 +24,7 @@ public enum IotDeviceTopicEnum { | ||
| 22 | */ | 24 | */ |
| 23 | SERVICE_TOPIC_PREFIX("/thing/service/", "服务调用主题前缀"), | 25 | SERVICE_TOPIC_PREFIX("/thing/service/", "服务调用主题前缀"), |
| 24 | 26 | ||
| 27 | + // TODO @haohao:注释时,中英文之间,有个空格; | ||
| 25 | /** | 28 | /** |
| 26 | * 设备属性设置主题 | 29 | * 设备属性设置主题 |
| 27 | * 请求Topic:/sys/${productKey}/${deviceName}/thing/service/property/set | 30 | * 请求Topic:/sys/${productKey}/${deviceName}/thing/service/property/set |
| @@ -75,6 +78,7 @@ public enum IotDeviceTopicEnum { | @@ -75,6 +78,7 @@ public enum IotDeviceTopicEnum { | ||
| 75 | private final String topic; | 78 | private final String topic; |
| 76 | private final String description; | 79 | private final String description; |
| 77 | 80 | ||
| 81 | + // TODO @haohao:使用 lombok 去除 | ||
| 78 | IotDeviceTopicEnum(String topic, String description) { | 82 | IotDeviceTopicEnum(String topic, String description) { |
| 79 | this.topic = topic; | 83 | this.topic = topic; |
| 80 | this.description = description; | 84 | this.description = description; |
| @@ -89,6 +93,7 @@ public enum IotDeviceTopicEnum { | @@ -89,6 +93,7 @@ public enum IotDeviceTopicEnum { | ||
| 89 | * @return 完整的主题路径 | 93 | * @return 完整的主题路径 |
| 90 | */ | 94 | */ |
| 91 | public static String buildServiceTopic(String productKey, String deviceName, String serviceIdentifier) { | 95 | public static String buildServiceTopic(String productKey, String deviceName, String serviceIdentifier) { |
| 96 | + // TODO @haohao:貌似 SYS_TOPIC_PREFIX.getTopic() + productKey + "/" + deviceName 是统一的; | ||
| 92 | return SYS_TOPIC_PREFIX.getTopic() + productKey + "/" + deviceName + | 97 | return SYS_TOPIC_PREFIX.getTopic() + productKey + "/" + deviceName + |
| 93 | SERVICE_TOPIC_PREFIX.getTopic() + serviceIdentifier; | 98 | SERVICE_TOPIC_PREFIX.getTopic() + serviceIdentifier; |
| 94 | } | 99 | } |
| @@ -127,7 +132,7 @@ public enum IotDeviceTopicEnum { | @@ -127,7 +132,7 @@ public enum IotDeviceTopicEnum { | ||
| 127 | } | 132 | } |
| 128 | 133 | ||
| 129 | /** | 134 | /** |
| 130 | - * 构建设备OTA升级主题 | 135 | + * 构建设备 OTA 升级主题 |
| 131 | * | 136 | * |
| 132 | * @param productKey 产品Key | 137 | * @param productKey 产品Key |
| 133 | * @param deviceName 设备名称 | 138 | * @param deviceName 设备名称 |
| @@ -170,4 +175,5 @@ public enum IotDeviceTopicEnum { | @@ -170,4 +175,5 @@ public enum IotDeviceTopicEnum { | ||
| 170 | public static String getReplyTopic(String requestTopic) { | 175 | public static String getReplyTopic(String requestTopic) { |
| 171 | return requestTopic + REPLY_SUFFIX.getTopic(); | 176 | return requestTopic + REPLY_SUFFIX.getTopic(); |
| 172 | } | 177 | } |
| 178 | + | ||
| 173 | } | 179 | } |
| 174 | \ No newline at end of file | 180 | \ No newline at end of file |
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-core/src/main/java/cn/iocoder/yudao/module/iot/net/component/core/message/IotAlinkMessage.java
| @@ -11,6 +11,7 @@ import java.util.Map; | @@ -11,6 +11,7 @@ import java.util.Map; | ||
| 11 | * IoT Alink 消息模型 | 11 | * IoT Alink 消息模型 |
| 12 | * <p> | 12 | * <p> |
| 13 | * 基于阿里云 Alink 协议规范实现的标准消息格式 | 13 | * 基于阿里云 Alink 协议规范实现的标准消息格式 |
| 14 | + * @see <a href="https://help.aliyun.com/zh/iot/user-guide/alink-protocol-1">阿里云物联网 —— Alink 协议</a> | ||
| 14 | * | 15 | * |
| 15 | * @author haohao | 16 | * @author haohao |
| 16 | */ | 17 | */ |
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-core/src/main/java/cn/iocoder/yudao/module/iot/net/component/core/pojo/IotStandardResponse.java
| @@ -12,7 +12,7 @@ import lombok.experimental.Accessors; | @@ -12,7 +12,7 @@ import lombok.experimental.Accessors; | ||
| 12 | * @author haohao | 12 | * @author haohao |
| 13 | */ | 13 | */ |
| 14 | @Data | 14 | @Data |
| 15 | -@Accessors(chain = true) | 15 | +@Accessors(chain = true) // TODO @haohao:貌似不用写 @Accessors(chain = true),我全局加啦,可见 lombok.config |
| 16 | public class IotStandardResponse { | 16 | public class IotStandardResponse { |
| 17 | 17 | ||
| 18 | /** | 18 | /** |
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-emqx/src/main/java/cn/iocoder/yudao/module/iot/net/component/emqx/config/IotNetComponentEmqxAutoConfiguration.java
| @@ -28,13 +28,13 @@ import org.springframework.context.event.EventListener; | @@ -28,13 +28,13 @@ import org.springframework.context.event.EventListener; | ||
| 28 | * | 28 | * |
| 29 | * @author haohao | 29 | * @author haohao |
| 30 | */ | 30 | */ |
| 31 | -@Slf4j | ||
| 32 | @AutoConfiguration | 31 | @AutoConfiguration |
| 33 | @EnableConfigurationProperties(IotNetComponentEmqxProperties.class) | 32 | @EnableConfigurationProperties(IotNetComponentEmqxProperties.class) |
| 34 | -@ConditionalOnProperty(prefix = "yudao.iot.component.emqx", name = "enabled", havingValue = "true", matchIfMissing = false) | 33 | +@ConditionalOnProperty(prefix = "yudao.iot.component.emqx", name = "enabled", havingValue = "true") |
| 35 | @ComponentScan(basePackages = { | 34 | @ComponentScan(basePackages = { |
| 36 | "cn.iocoder.yudao.module.iot.net.component.emqx" // 只扫描 EMQX 组件包 | 35 | "cn.iocoder.yudao.module.iot.net.component.emqx" // 只扫描 EMQX 组件包 |
| 37 | -}) | 36 | +}) // TODO @haohao:自动配置后,不需要这个哈。 |
| 37 | +@Slf4j | ||
| 38 | public class IotNetComponentEmqxAutoConfiguration { | 38 | public class IotNetComponentEmqxAutoConfiguration { |
| 39 | 39 | ||
| 40 | /** | 40 | /** |
| @@ -42,6 +42,7 @@ public class IotNetComponentEmqxAutoConfiguration { | @@ -42,6 +42,7 @@ public class IotNetComponentEmqxAutoConfiguration { | ||
| 42 | */ | 42 | */ |
| 43 | private static final String PLUGIN_KEY = "emqx"; | 43 | private static final String PLUGIN_KEY = "emqx"; |
| 44 | 44 | ||
| 45 | + // TODO @haohao:这个是不是要去掉哈。 | ||
| 45 | public IotNetComponentEmqxAutoConfiguration() { | 46 | public IotNetComponentEmqxAutoConfiguration() { |
| 46 | // 构造函数中不输出日志,移到 initialize 方法中 | 47 | // 构造函数中不输出日志,移到 initialize 方法中 |
| 47 | } | 48 | } |
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-emqx/src/main/java/cn/iocoder/yudao/module/iot/net/component/emqx/config/IotNetComponentEmqxProperties.java
| @@ -64,6 +64,7 @@ public class IotNetComponentEmqxProperties { | @@ -64,6 +64,7 @@ public class IotNetComponentEmqxProperties { | ||
| 64 | @NotNull(message = "认证端口不能为空") | 64 | @NotNull(message = "认证端口不能为空") |
| 65 | private Integer authPort; | 65 | private Integer authPort; |
| 66 | 66 | ||
| 67 | + // TODO @haohao:可以使用 Duration 类型,可读性更好 | ||
| 67 | /** | 68 | /** |
| 68 | * 重连延迟时间(毫秒) | 69 | * 重连延迟时间(毫秒) |
| 69 | * <p> | 70 | * <p> |
| @@ -77,4 +78,5 @@ public class IotNetComponentEmqxProperties { | @@ -77,4 +78,5 @@ public class IotNetComponentEmqxProperties { | ||
| 77 | * 默认值:10000 毫秒 | 78 | * 默认值:10000 毫秒 |
| 78 | */ | 79 | */ |
| 79 | private Integer connectionTimeoutMs = 10000; | 80 | private Integer connectionTimeoutMs = 10000; |
| 81 | + | ||
| 80 | } | 82 | } |
| 81 | \ No newline at end of file | 83 | \ No newline at end of file |
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-emqx/src/main/java/cn/iocoder/yudao/module/iot/net/component/emqx/upstream/IotDeviceUpstreamServer.java
| @@ -82,6 +82,7 @@ public class IotDeviceUpstreamServer { | @@ -82,6 +82,7 @@ public class IotDeviceUpstreamServer { | ||
| 82 | log.info("[start][开始启动服务]"); | 82 | log.info("[start][开始启动服务]"); |
| 83 | 83 | ||
| 84 | // 检查 authPort 是否为 null | 84 | // 检查 authPort 是否为 null |
| 85 | + // TODO @haohao:authPort 里面搞默认值?包括下面,这个类不搞任何默认值,都交给 emqxProperties | ||
| 85 | Integer authPort = emqxProperties.getAuthPort(); | 86 | Integer authPort = emqxProperties.getAuthPort(); |
| 86 | if (authPort == null) { | 87 | if (authPort == null) { |
| 87 | log.warn("[start][authPort 为 null,使用默认端口 8080]"); | 88 | log.warn("[start][authPort 为 null,使用默认端口 8080]"); |
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-emqx/src/main/java/cn/iocoder/yudao/module/iot/net/component/emqx/upstream/router/IotDeviceMqttMessageHandler.java
| @@ -30,6 +30,7 @@ import java.util.Map; | @@ -30,6 +30,7 @@ import java.util.Map; | ||
| 30 | @Slf4j | 30 | @Slf4j |
| 31 | public class IotDeviceMqttMessageHandler { | 31 | public class IotDeviceMqttMessageHandler { |
| 32 | 32 | ||
| 33 | + // TODO @haohao:下面的,有办法也抽到 IotDeviceTopicEnum 么?想的是,尽量把这些 method、topic、url 统一化; | ||
| 33 | private static final String PROPERTY_METHOD = "thing.event.property.post"; | 34 | private static final String PROPERTY_METHOD = "thing.event.property.post"; |
| 34 | private static final String EVENT_METHOD_PREFIX = "thing.event."; | 35 | private static final String EVENT_METHOD_PREFIX = "thing.event."; |
| 35 | private static final String EVENT_METHOD_SUFFIX = ".post"; | 36 | private static final String EVENT_METHOD_SUFFIX = ".post"; |
| @@ -223,6 +224,7 @@ public class IotDeviceMqttMessageHandler { | @@ -223,6 +224,7 @@ public class IotDeviceMqttMessageHandler { | ||
| 223 | * @return 设备属性上报请求对象 | 224 | * @return 设备属性上报请求对象 |
| 224 | */ | 225 | */ |
| 225 | private IotDevicePropertyReportReqDTO buildPropertyReportDTO(JSONObject jsonObject, String[] topicParts) { | 226 | private IotDevicePropertyReportReqDTO buildPropertyReportDTO(JSONObject jsonObject, String[] topicParts) { |
| 227 | + // TODO @haohao:IotDevicePropertyReportReqDTO 可以考虑链式哈。其它也是,尽量让同类参数在一行;这样,阅读起来更聚焦; | ||
| 226 | IotDevicePropertyReportReqDTO reportReqDTO = new IotDevicePropertyReportReqDTO(); | 228 | IotDevicePropertyReportReqDTO reportReqDTO = new IotDevicePropertyReportReqDTO(); |
| 227 | reportReqDTO.setRequestId(jsonObject.getStr("id")); | 229 | reportReqDTO.setRequestId(jsonObject.getStr("id")); |
| 228 | reportReqDTO.setProcessId(IotNetComponentCommonUtils.getProcessId()); | 230 | reportReqDTO.setProcessId(IotNetComponentCommonUtils.getProcessId()); |
| @@ -230,7 +232,7 @@ public class IotDeviceMqttMessageHandler { | @@ -230,7 +232,7 @@ public class IotDeviceMqttMessageHandler { | ||
| 230 | reportReqDTO.setProductKey(topicParts[2]); | 232 | reportReqDTO.setProductKey(topicParts[2]); |
| 231 | reportReqDTO.setDeviceName(topicParts[3]); | 233 | reportReqDTO.setDeviceName(topicParts[3]); |
| 232 | 234 | ||
| 233 | - // 只使用标准JSON格式处理属性数据 | 235 | + // 只使用标准 JSON格式处理属性数据 |
| 234 | JSONObject params = jsonObject.getJSONObject("params"); | 236 | JSONObject params = jsonObject.getJSONObject("params"); |
| 235 | if (params == null) { | 237 | if (params == null) { |
| 236 | log.warn("[buildPropertyReportDTO][消息格式不正确,缺少params字段][jsonObject: {}]", jsonObject); | 238 | log.warn("[buildPropertyReportDTO][消息格式不正确,缺少params字段][jsonObject: {}]", jsonObject); |
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-http/src/main/java/cn/iocoder/yudao/module/iot/net/component/http/config/IotNetComponentHttpAutoConfiguration.java
| @@ -61,13 +61,14 @@ public class IotNetComponentHttpAutoConfiguration { | @@ -61,13 +61,14 @@ public class IotNetComponentHttpAutoConfiguration { | ||
| 61 | 61 | ||
| 62 | // 设置当前组件的核心标识 | 62 | // 设置当前组件的核心标识 |
| 63 | // 注意:这里只为当前 HTTP 组件设置 pluginKey,不影响其他组件 | 63 | // 注意:这里只为当前 HTTP 组件设置 pluginKey,不影响其他组件 |
| 64 | + // TODO @haohao:多个会存在冲突的问题哇? | ||
| 64 | commonProperties.setPluginKey(PLUGIN_KEY); | 65 | commonProperties.setPluginKey(PLUGIN_KEY); |
| 65 | 66 | ||
| 66 | // 将 HTTP 组件注册到组件注册表 | 67 | // 将 HTTP 组件注册到组件注册表 |
| 67 | componentRegistry.registerComponent( | 68 | componentRegistry.registerComponent( |
| 68 | PLUGIN_KEY, | 69 | PLUGIN_KEY, |
| 69 | SystemUtil.getHostInfo().getAddress(), | 70 | SystemUtil.getHostInfo().getAddress(), |
| 70 | - 0, // 内嵌模式固定为 0 | 71 | + 0, // 内嵌模式固定为 0:自动生成对应的 port 端口号 |
| 71 | IotNetComponentCommonUtils.getProcessId()); | 72 | IotNetComponentCommonUtils.getProcessId()); |
| 72 | 73 | ||
| 73 | log.info("[initialize][IoT HTTP 组件初始化完成]"); | 74 | log.info("[initialize][IoT HTTP 组件初始化完成]"); |
| @@ -115,4 +116,5 @@ public class IotNetComponentHttpAutoConfiguration { | @@ -115,4 +116,5 @@ public class IotNetComponentHttpAutoConfiguration { | ||
| 115 | public IotDeviceDownstreamHandler deviceDownstreamHandler() { | 116 | public IotDeviceDownstreamHandler deviceDownstreamHandler() { |
| 116 | return new IotDeviceDownstreamHandlerImpl(); | 117 | return new IotDeviceDownstreamHandlerImpl(); |
| 117 | } | 118 | } |
| 119 | + | ||
| 118 | } | 120 | } |
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-http/src/main/java/cn/iocoder/yudao/module/iot/net/component/http/upstream/auth/IotDeviceAuthProvider.java
| @@ -5,12 +5,13 @@ import io.vertx.ext.web.RoutingContext; | @@ -5,12 +5,13 @@ import io.vertx.ext.web.RoutingContext; | ||
| 5 | import lombok.extern.slf4j.Slf4j; | 5 | import lombok.extern.slf4j.Slf4j; |
| 6 | import org.springframework.context.ApplicationContext; | 6 | import org.springframework.context.ApplicationContext; |
| 7 | 7 | ||
| 8 | +// TODO @haohao:待实现,或者不需要? | ||
| 8 | /** | 9 | /** |
| 9 | * IoT 设备认证提供者 | 10 | * IoT 设备认证提供者 |
| 10 | * <p> | 11 | * <p> |
| 11 | * 用于 HTTP 设备接入时的身份认证 | 12 | * 用于 HTTP 设备接入时的身份认证 |
| 12 | * | 13 | * |
| 13 | - * @author 芋道源码 | 14 | + * @author haohao |
| 14 | */ | 15 | */ |
| 15 | @Slf4j | 16 | @Slf4j |
| 16 | public class IotDeviceAuthProvider { | 17 | public class IotDeviceAuthProvider { |
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-http/src/main/java/cn/iocoder/yudao/module/iot/net/component/http/upstream/router/IotDeviceUpstreamVertxHandler.java
| 1 | package cn.iocoder.yudao.module.iot.net.component.http.upstream.router; | 1 | package cn.iocoder.yudao.module.iot.net.component.http.upstream.router; |
| 2 | 2 | ||
| 3 | +import cn.hutool.core.collection.CollUtil; | ||
| 3 | import cn.hutool.core.map.MapUtil; | 4 | import cn.hutool.core.map.MapUtil; |
| 4 | import cn.hutool.core.util.IdUtil; | 5 | import cn.hutool.core.util.IdUtil; |
| 5 | import cn.hutool.core.util.ObjUtil; | 6 | import cn.hutool.core.util.ObjUtil; |
| @@ -35,6 +36,8 @@ import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeC | @@ -35,6 +36,8 @@ import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeC | ||
| 35 | @Slf4j | 36 | @Slf4j |
| 36 | public class IotDeviceUpstreamVertxHandler implements Handler<RoutingContext> { | 37 | public class IotDeviceUpstreamVertxHandler implements Handler<RoutingContext> { |
| 37 | 38 | ||
| 39 | + // TODO @haohao:你说,咱要不要把 "/sys/:productKey/:deviceName" | ||
| 40 | + // + IotDeviceTopicEnum.PROPERTY_POST_TOPIC.getTopic(),也抽到 IotDeviceTopicEnum 的 build 这种?尽量都收敛掉? | ||
| 38 | /** | 41 | /** |
| 39 | * 属性上报路径 | 42 | * 属性上报路径 |
| 40 | */ | 43 | */ |
| @@ -254,8 +257,8 @@ public class IotDeviceUpstreamVertxHandler implements Handler<RoutingContext> { | @@ -254,8 +257,8 @@ public class IotDeviceUpstreamVertxHandler implements Handler<RoutingContext> { | ||
| 254 | return PROPERTY_METHOD; | 257 | return PROPERTY_METHOD; |
| 255 | } | 258 | } |
| 256 | 259 | ||
| 257 | - return EVENT_METHOD_PREFIX + | ||
| 258 | - (routingContext.pathParams().containsKey("identifier") | 260 | + return EVENT_METHOD_PREFIX |
| 261 | + + (routingContext.pathParams().containsKey("identifier") | ||
| 259 | ? routingContext.pathParam("identifier") | 262 | ? routingContext.pathParam("identifier") |
| 260 | : "unknown") | 263 | : "unknown") |
| 261 | + | 264 | + |
| @@ -275,7 +278,6 @@ public class IotDeviceUpstreamVertxHandler implements Handler<RoutingContext> { | @@ -275,7 +278,6 @@ public class IotDeviceUpstreamVertxHandler implements Handler<RoutingContext> { | ||
| 275 | .setReportTime(LocalDateTime.now()) | 278 | .setReportTime(LocalDateTime.now()) |
| 276 | .setProductKey(productKey) | 279 | .setProductKey(productKey) |
| 277 | .setDeviceName(deviceName)).setState(IotDeviceStateEnum.ONLINE.getState()); | 280 | .setDeviceName(deviceName)).setState(IotDeviceStateEnum.ONLINE.getState()); |
| 278 | - | ||
| 279 | deviceUpstreamApi.updateDeviceState(reqDTO); | 281 | deviceUpstreamApi.updateDeviceState(reqDTO); |
| 280 | } | 282 | } |
| 281 | 283 | ||
| @@ -311,8 +313,7 @@ public class IotDeviceUpstreamVertxHandler implements Handler<RoutingContext> { | @@ -311,8 +313,7 @@ public class IotDeviceUpstreamVertxHandler implements Handler<RoutingContext> { | ||
| 311 | private Map<String, Object> parsePropertiesFromBody(JsonObject body) { | 313 | private Map<String, Object> parsePropertiesFromBody(JsonObject body) { |
| 312 | Map<String, Object> properties = MapUtil.newHashMap(); | 314 | Map<String, Object> properties = MapUtil.newHashMap(); |
| 313 | JsonObject params = body.getJsonObject("params"); | 315 | JsonObject params = body.getJsonObject("params"); |
| 314 | - | ||
| 315 | - if (params == null) { | 316 | + if (CollUtil.isEmpty(params)) { |
| 316 | return properties; | 317 | return properties; |
| 317 | } | 318 | } |
| 318 | 319 | ||
| @@ -327,7 +328,6 @@ public class IotDeviceUpstreamVertxHandler implements Handler<RoutingContext> { | @@ -327,7 +328,6 @@ public class IotDeviceUpstreamVertxHandler implements Handler<RoutingContext> { | ||
| 327 | properties.put(key, valueObj); | 328 | properties.put(key, valueObj); |
| 328 | } | 329 | } |
| 329 | } | 330 | } |
| 330 | - | ||
| 331 | return properties; | 331 | return properties; |
| 332 | } | 332 | } |
| 333 | 333 | ||
| @@ -364,15 +364,13 @@ public class IotDeviceUpstreamVertxHandler implements Handler<RoutingContext> { | @@ -364,15 +364,13 @@ public class IotDeviceUpstreamVertxHandler implements Handler<RoutingContext> { | ||
| 364 | private Map<String, Object> parseParamsFromBody(JsonObject body) { | 364 | private Map<String, Object> parseParamsFromBody(JsonObject body) { |
| 365 | Map<String, Object> params = MapUtil.newHashMap(); | 365 | Map<String, Object> params = MapUtil.newHashMap(); |
| 366 | JsonObject paramsJson = body.getJsonObject("params"); | 366 | JsonObject paramsJson = body.getJsonObject("params"); |
| 367 | - | ||
| 368 | - if (paramsJson == null) { | 367 | + if (CollUtil.isEmpty(paramsJson)) { |
| 369 | return params; | 368 | return params; |
| 370 | } | 369 | } |
| 371 | 370 | ||
| 372 | for (String key : paramsJson.fieldNames()) { | 371 | for (String key : paramsJson.fieldNames()) { |
| 373 | params.put(key, paramsJson.getValue(key)); | 372 | params.put(key, paramsJson.getValue(key)); |
| 374 | } | 373 | } |
| 375 | - | ||
| 376 | return params; | 374 | return params; |
| 377 | } | 375 | } |
| 378 | } | 376 | } |
| 379 | \ No newline at end of file | 377 | \ No newline at end of file |
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-server/src/main/java/cn/iocoder/yudao/module/iot/net/component/server/config/IotNetComponentServerConfiguration.java
| @@ -32,6 +32,7 @@ public class IotNetComponentServerConfiguration { | @@ -32,6 +32,7 @@ public class IotNetComponentServerConfiguration { | ||
| 32 | * @return RestTemplate | 32 | * @return RestTemplate |
| 33 | */ | 33 | */ |
| 34 | @Bean | 34 | @Bean |
| 35 | + // TODO @haohao:貌似要独立一个 restTemplate 的名字?不然容易冲突; | ||
| 35 | public RestTemplate restTemplate(IotNetComponentServerProperties properties) { | 36 | public RestTemplate restTemplate(IotNetComponentServerProperties properties) { |
| 36 | return new RestTemplateBuilder() | 37 | return new RestTemplateBuilder() |
| 37 | .connectTimeout(properties.getUpstreamConnectTimeout()) | 38 | .connectTimeout(properties.getUpstreamConnectTimeout()) |
| @@ -104,6 +105,7 @@ public class IotNetComponentServerConfiguration { | @@ -104,6 +105,7 @@ public class IotNetComponentServerConfiguration { | ||
| 104 | return new Object(); | 105 | return new Object(); |
| 105 | } | 106 | } |
| 106 | 107 | ||
| 108 | + // TODO @haohao:这个是不是木有用呀? | ||
| 107 | /** | 109 | /** |
| 108 | * 配置默认的组件实例注册客户端 | 110 | * 配置默认的组件实例注册客户端 |
| 109 | * | 111 | * |
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-server/src/main/java/cn/iocoder/yudao/module/iot/net/component/server/controller/HealthController.java
| @@ -7,6 +7,7 @@ import org.springframework.web.bind.annotation.RestController; | @@ -7,6 +7,7 @@ import org.springframework.web.bind.annotation.RestController; | ||
| 7 | import java.util.HashMap; | 7 | import java.util.HashMap; |
| 8 | import java.util.Map; | 8 | import java.util.Map; |
| 9 | 9 | ||
| 10 | +// TODO @haohao:这个是必须的哇?可以考虑基于 spring boot actuator; | ||
| 10 | /** | 11 | /** |
| 11 | * 健康检查接口 | 12 | * 健康检查接口 |
| 12 | * | 13 | * |
| @@ -29,4 +30,4 @@ public class HealthController { | @@ -29,4 +30,4 @@ public class HealthController { | ||
| 29 | result.put("timestamp", System.currentTimeMillis()); | 30 | result.put("timestamp", System.currentTimeMillis()); |
| 30 | return result; | 31 | return result; |
| 31 | } | 32 | } |
| 32 | -} | ||
| 33 | \ No newline at end of file | 33 | \ No newline at end of file |
| 34 | +} | ||
| 34 | \ No newline at end of file | 35 | \ No newline at end of file |
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-server/src/main/java/cn/iocoder/yudao/module/iot/net/component/server/heartbeat/IotComponentHeartbeatJob.java
| @@ -7,14 +7,12 @@ import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.IotPluginInst | @@ -7,14 +7,12 @@ import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.IotPluginInst | ||
| 7 | import cn.iocoder.yudao.module.iot.net.component.server.config.IotNetComponentServerProperties; | 7 | import cn.iocoder.yudao.module.iot.net.component.server.config.IotNetComponentServerProperties; |
| 8 | import cn.iocoder.yudao.module.iot.net.component.server.downstream.IotComponentDownstreamServer; | 8 | import cn.iocoder.yudao.module.iot.net.component.server.downstream.IotComponentDownstreamServer; |
| 9 | import lombok.extern.slf4j.Slf4j; | 9 | import lombok.extern.slf4j.Slf4j; |
| 10 | -import org.springframework.scheduling.annotation.Scheduled; | ||
| 11 | 10 | ||
| 12 | -import java.time.LocalDateTime; | ||
| 13 | import java.util.concurrent.ScheduledExecutorService; | 11 | import java.util.concurrent.ScheduledExecutorService; |
| 14 | import java.util.concurrent.ScheduledThreadPoolExecutor; | 12 | import java.util.concurrent.ScheduledThreadPoolExecutor; |
| 15 | import java.util.concurrent.TimeUnit; | 13 | import java.util.concurrent.TimeUnit; |
| 16 | -import java.lang.ProcessHandle; | ||
| 17 | 14 | ||
| 15 | +// TODO @haohao:有办法服用 yudao-module-iot-net-component-core 的么?就是 server,只是一个启动器,没什么特殊的功能; | ||
| 18 | /** | 16 | /** |
| 19 | * IoT 组件心跳任务 | 17 | * IoT 组件心跳任务 |
| 20 | * <p> | 18 | * <p> |
yudao-module-iot/yudao-module-iot-script/pom.xml
| @@ -44,6 +44,7 @@ | @@ -44,6 +44,7 @@ | ||
| 44 | </dependency> | 44 | </dependency> |
| 45 | 45 | ||
| 46 | <!-- JavaScript 引擎 - 使用 GraalJS 替代 Nashorn --> | 46 | <!-- JavaScript 引擎 - 使用 GraalJS 替代 Nashorn --> |
| 47 | + <!-- TODO @haohao:得考虑下,jdk8 可能不支持 graalvm,后续哈;【优先级:低】 --> | ||
| 47 | <dependency> | 48 | <dependency> |
| 48 | <groupId>org.graalvm.sdk</groupId> | 49 | <groupId>org.graalvm.sdk</groupId> |
| 49 | <artifactId>graal-sdk</artifactId> | 50 | <artifactId>graal-sdk</artifactId> |
yudao-module-iot/yudao-module-iot-script/src/main/java/cn/iocoder/yudao/module/iot/script/ScriptExample.java
yudao-module-iot/yudao-module-iot-script/src/main/java/cn/iocoder/yudao/module/iot/script/engine/JsScriptEngine.java
| @@ -63,6 +63,7 @@ public class JsScriptEngine extends AbstractScriptEngine implements AutoCloseabl | @@ -63,6 +63,7 @@ public class JsScriptEngine extends AbstractScriptEngine implements AutoCloseabl | ||
| 63 | .build(); | 63 | .build(); |
| 64 | 64 | ||
| 65 | // 创建隔离的临时目录路径 | 65 | // 创建隔离的临时目录路径 |
| 66 | + // TODO @haohao:貌似没用到? | ||
| 66 | Path tempDirectory = Path.of(System.getProperty("java.io.tmpdir"), "graaljs-" + IdUtil.fastSimpleUUID()); | 67 | Path tempDirectory = Path.of(System.getProperty("java.io.tmpdir"), "graaljs-" + IdUtil.fastSimpleUUID()); |
| 67 | 68 | ||
| 68 | // 初始化 GraalJS 上下文 | 69 | // 初始化 GraalJS 上下文 |
| @@ -94,6 +95,7 @@ public class JsScriptEngine extends AbstractScriptEngine implements AutoCloseabl | @@ -94,6 +95,7 @@ public class JsScriptEngine extends AbstractScriptEngine implements AutoCloseabl | ||
| 94 | Source source = getOrCreateSource(script); | 95 | Source source = getOrCreateSource(script); |
| 95 | 96 | ||
| 96 | // 执行脚本并捕获结果,添加超时控制 | 97 | // 执行脚本并捕获结果,添加超时控制 |
| 98 | + // TODO @haohao:通过线程池 + future 会好点? | ||
| 97 | Value result; | 99 | Value result; |
| 98 | Thread executionThread = Thread.currentThread(); | 100 | Thread executionThread = Thread.currentThread(); |
| 99 | Thread watchdogThread = new Thread(() -> { | 101 | Thread watchdogThread = new Thread(() -> { |
| @@ -236,11 +238,14 @@ public class JsScriptEngine extends AbstractScriptEngine implements AutoCloseabl | @@ -236,11 +238,14 @@ public class JsScriptEngine extends AbstractScriptEngine implements AutoCloseabl | ||
| 236 | if (result.isNumber()) { | 238 | if (result.isNumber()) { |
| 237 | if (result.fitsInInt()) { | 239 | if (result.fitsInInt()) { |
| 238 | return result.asInt(); | 240 | return result.asInt(); |
| 239 | - } else if (result.fitsInLong()) { | 241 | + } |
| 242 | + if (result.fitsInLong()) { | ||
| 240 | return result.asLong(); | 243 | return result.asLong(); |
| 241 | - } else if (result.fitsInFloat()) { | 244 | + } |
| 245 | + if (result.fitsInFloat()) { | ||
| 242 | return result.asFloat(); | 246 | return result.asFloat(); |
| 243 | - } else if (result.fitsInDouble()) { | 247 | + } |
| 248 | + if (result.fitsInDouble()) { | ||
| 244 | return result.asDouble(); | 249 | return result.asDouble(); |
| 245 | } | 250 | } |
| 246 | } | 251 | } |
yudao-module-iot/yudao-module-iot-script/src/main/java/cn/iocoder/yudao/module/iot/script/engine/ScriptEngineFactory.java
| @@ -79,7 +79,6 @@ public class ScriptEngineFactory implements DisposableBean { | @@ -79,7 +79,6 @@ public class ScriptEngineFactory implements DisposableBean { | ||
| 79 | 79 | ||
| 80 | @Override | 80 | @Override |
| 81 | public void destroy() { | 81 | public void destroy() { |
| 82 | - // 应用关闭时,释放所有引擎资源 | ||
| 83 | log.info("应用关闭,释放所有脚本引擎资源..."); | 82 | log.info("应用关闭,释放所有脚本引擎资源..."); |
| 84 | releaseAllEngines(); | 83 | releaseAllEngines(); |
| 85 | } | 84 | } |
yudao-module-iot/yudao-module-iot-script/src/main/java/cn/iocoder/yudao/module/iot/script/example/GraalJsExample.java
| @@ -14,6 +14,7 @@ import java.util.concurrent.ExecutionException; | @@ -14,6 +14,7 @@ import java.util.concurrent.ExecutionException; | ||
| 14 | import java.util.concurrent.TimeUnit; | 14 | import java.util.concurrent.TimeUnit; |
| 15 | import java.util.concurrent.TimeoutException; | 15 | import java.util.concurrent.TimeoutException; |
| 16 | 16 | ||
| 17 | +// TODO @haohao:搞到 test 里面哈; | ||
| 17 | /** | 18 | /** |
| 18 | * GraalJS 脚本引擎示例 | 19 | * GraalJS 脚本引擎示例 |
| 19 | * <p> | 20 | * <p> |
yudao-module-iot/yudao-module-iot-script/src/main/java/cn/iocoder/yudao/module/iot/script/sandbox/JsSandbox.java
| @@ -56,6 +56,7 @@ public class JsSandbox implements ScriptSandbox { | @@ -56,6 +56,7 @@ public class JsSandbox implements ScriptSandbox { | ||
| 56 | */ | 56 | */ |
| 57 | public JsSandbox() { | 57 | public JsSandbox() { |
| 58 | // 初始化 Java 相关的不安全关键字 | 58 | // 初始化 Java 相关的不安全关键字 |
| 59 | + // TODO @haohao:可以使用 addAll 哈。 | ||
| 59 | Arrays.asList( | 60 | Arrays.asList( |
| 60 | "java.lang.System", | 61 | "java.lang.System", |
| 61 | "java.io", | 62 | "java.io", |
yudao-module-iot/yudao-module-iot-script/src/main/java/cn/iocoder/yudao/module/iot/script/service/ScriptServiceImpl.java
| @@ -40,6 +40,7 @@ public class ScriptServiceImpl implements ScriptService { | @@ -40,6 +40,7 @@ public class ScriptServiceImpl implements ScriptService { | ||
| 40 | try { | 40 | try { |
| 41 | return engine.execute(script, context); | 41 | return engine.execute(script, context); |
| 42 | } catch (Exception e) { | 42 | } catch (Exception e) { |
| 43 | + // TODO @haohao:最好打印一些参数;下面类似的也是 | ||
| 43 | log.error("执行脚本失败: {}", e.getMessage(), e); | 44 | log.error("执行脚本失败: {}", e.getMessage(), e); |
| 44 | throw new RuntimeException("执行脚本失败: " + e.getMessage(), e); | 45 | throw new RuntimeException("执行脚本失败: " + e.getMessage(), e); |
| 45 | } | 46 | } |
yudao-module-iot/yudao-module-iot-script/src/main/java/cn/iocoder/yudao/module/iot/script/util/ScriptUtils.java