Commit 6791c628589b66b7419bf46a3e476d29d0d77470
1 parent
f88d30f1
review:【iot 物联网】场景联动相关实现
Showing
13 changed files
with
65 additions
and
62 deletions
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/enums/rule/IotSceneRuleTriggerTypeEnum.java
| @@ -60,7 +60,7 @@ public enum IotSceneRuleTriggerTypeEnum implements ArrayValuable<Integer> { | @@ -60,7 +60,7 @@ public enum IotSceneRuleTriggerTypeEnum implements ArrayValuable<Integer> { | ||
| 60 | return ARRAYS; | 60 | return ARRAYS; |
| 61 | } | 61 | } |
| 62 | 62 | ||
| 63 | - | 63 | + // TODO @puhui999:可以参考下别的枚举哈,方法名,和实现都可以更简洁;of(String type) { firstMatch |
| 64 | /** | 64 | /** |
| 65 | * 根据类型值查找触发器类型枚举 | 65 | * 根据类型值查找触发器类型枚举 |
| 66 | * | 66 | * |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/data/action/IotRedisRuleAction.java
| @@ -45,7 +45,6 @@ public class IotRedisRuleAction extends | @@ -45,7 +45,6 @@ public class IotRedisRuleAction extends | ||
| 45 | // 2. 根据数据结构类型执行不同的操作 | 45 | // 2. 根据数据结构类型执行不同的操作 |
| 46 | String messageJson = JsonUtils.toJsonString(message); | 46 | String messageJson = JsonUtils.toJsonString(message); |
| 47 | IotRedisDataStructureEnum dataStructure = getDataStructureByType(config.getDataStructure()); | 47 | IotRedisDataStructureEnum dataStructure = getDataStructureByType(config.getDataStructure()); |
| 48 | - | ||
| 49 | switch (dataStructure) { | 48 | switch (dataStructure) { |
| 50 | case STREAM: | 49 | case STREAM: |
| 51 | executeStream(redisTemplate, config, messageJson); | 50 | executeStream(redisTemplate, config, messageJson); |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/IotSceneRuleServiceImpl.java
| @@ -58,12 +58,15 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService { | @@ -58,12 +58,15 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService { | ||
| 58 | @Resource | 58 | @Resource |
| 59 | private IotSceneRuleMapper sceneRuleMapper; | 59 | private IotSceneRuleMapper sceneRuleMapper; |
| 60 | 60 | ||
| 61 | + // TODO @puhui999:定时任务,基于它调度; | ||
| 61 | @Resource(name = "iotSchedulerManager") | 62 | @Resource(name = "iotSchedulerManager") |
| 62 | private IotSchedulerManager schedulerManager; | 63 | private IotSchedulerManager schedulerManager; |
| 63 | @Resource | 64 | @Resource |
| 64 | private IotProductService productService; | 65 | private IotProductService productService; |
| 65 | @Resource | 66 | @Resource |
| 66 | private IotDeviceService deviceService; | 67 | private IotDeviceService deviceService; |
| 68 | + | ||
| 69 | + // TODO @puhui999:sceneRuleMatcherManager 变量名 | ||
| 67 | @Resource | 70 | @Resource |
| 68 | private IotSceneRuleMatcherManager matcherManager; | 71 | private IotSceneRuleMatcherManager matcherManager; |
| 69 | @Resource | 72 | @Resource |
| @@ -135,7 +138,7 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService { | @@ -135,7 +138,7 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService { | ||
| 135 | return sceneRuleMapper.selectListByStatus(status); | 138 | return sceneRuleMapper.selectListByStatus(status); |
| 136 | } | 139 | } |
| 137 | 140 | ||
| 138 | - // TODO 芋艿,缓存待实现 | 141 | + // TODO 芋艿,缓存待实现 @puhui999 |
| 139 | @Override | 142 | @Override |
| 140 | @TenantIgnore // 忽略租户隔离:因为 IotSceneRuleMessageHandler 调用时,一般未传递租户,所以需要忽略 | 143 | @TenantIgnore // 忽略租户隔离:因为 IotSceneRuleMessageHandler 调用时,一般未传递租户,所以需要忽略 |
| 141 | public List<IotSceneRuleDO> getSceneRuleListByProductIdAndDeviceIdFromCache(Long productId, Long deviceId) { | 144 | public List<IotSceneRuleDO> getSceneRuleListByProductIdAndDeviceIdFromCache(Long productId, Long deviceId) { |
| @@ -177,7 +180,7 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService { | @@ -177,7 +180,7 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService { | ||
| 177 | 180 | ||
| 178 | @Override | 181 | @Override |
| 179 | public void executeSceneRuleByDevice(IotDeviceMessage message) { | 182 | public void executeSceneRuleByDevice(IotDeviceMessage message) { |
| 180 | - // TODO @芋艿:这里的 tenantId,通过设备获取; | 183 | + // TODO @芋艿:这里的 tenantId,通过设备获取;@puhui999: |
| 181 | TenantUtils.execute(message.getTenantId(), () -> { | 184 | TenantUtils.execute(message.getTenantId(), () -> { |
| 182 | // 1. 获得设备匹配的规则场景 | 185 | // 1. 获得设备匹配的规则场景 |
| 183 | List<IotSceneRuleDO> sceneRules = getMatchedSceneRuleListByMessage(message); | 186 | List<IotSceneRuleDO> sceneRules = getMatchedSceneRuleListByMessage(message); |
| @@ -223,7 +226,7 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService { | @@ -223,7 +226,7 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService { | ||
| 223 | */ | 226 | */ |
| 224 | private List<IotSceneRuleDO> getMatchedSceneRuleListByMessage(IotDeviceMessage message) { | 227 | private List<IotSceneRuleDO> getMatchedSceneRuleListByMessage(IotDeviceMessage message) { |
| 225 | // 1. 匹配设备 | 228 | // 1. 匹配设备 |
| 226 | - // TODO @芋艿:可能需要 getSelf(); 缓存 | 229 | + // TODO @芋艿:可能需要 getSelf(); 缓存 @puhui999; |
| 227 | // 1.1 通过 deviceId 获取设备信息 | 230 | // 1.1 通过 deviceId 获取设备信息 |
| 228 | IotDeviceDO device = deviceService.getDeviceFromCache(message.getDeviceId()); | 231 | IotDeviceDO device = deviceService.getDeviceFromCache(message.getDeviceId()); |
| 229 | if (device == null) { | 232 | if (device == null) { |
| @@ -342,7 +345,6 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService { | @@ -342,7 +345,6 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService { | ||
| 342 | private boolean isTriggerConditionMatched(IotDeviceMessage message, IotSceneRuleDO.TriggerCondition condition, | 345 | private boolean isTriggerConditionMatched(IotDeviceMessage message, IotSceneRuleDO.TriggerCondition condition, |
| 343 | IotSceneRuleDO sceneRule, IotSceneRuleDO.Trigger trigger) { | 346 | IotSceneRuleDO sceneRule, IotSceneRuleDO.Trigger trigger) { |
| 344 | try { | 347 | try { |
| 345 | - // 使用重构后的条件匹配管理器进行匹配 | ||
| 346 | return matcherManager.isConditionMatched(message, condition); | 348 | return matcherManager.isConditionMatched(message, condition); |
| 347 | } catch (Exception e) { | 349 | } catch (Exception e) { |
| 348 | log.error("[isTriggerConditionMatched][规则场景编号({}) 的触发器({}) 条件匹配异常]", | 350 | log.error("[isTriggerConditionMatched][规则场景编号({}) 的触发器({}) 条件匹配异常]", |
| @@ -351,8 +353,7 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService { | @@ -351,8 +353,7 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService { | ||
| 351 | } | 353 | } |
| 352 | } | 354 | } |
| 353 | 355 | ||
| 354 | - // TODO @芋艿:【可优化】可以考虑增加下单测,边界太多了。 | ||
| 355 | - | 356 | + // TODO @puhui999:下面还需要么? |
| 356 | /** | 357 | /** |
| 357 | * 判断触发器的条件参数是否匹配 | 358 | * 判断触发器的条件参数是否匹配 |
| 358 | * | 359 | * |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/AbstractIotSceneRuleMatcher.java
| @@ -24,6 +24,8 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils. | @@ -24,6 +24,8 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils. | ||
| 24 | @Slf4j | 24 | @Slf4j |
| 25 | public abstract class AbstractIotSceneRuleMatcher implements IotSceneRuleMatcher { | 25 | public abstract class AbstractIotSceneRuleMatcher implements IotSceneRuleMatcher { |
| 26 | 26 | ||
| 27 | + // TODO @puhui999:这个是不是也是【通用】条件哈? | ||
| 28 | + | ||
| 27 | /** | 29 | /** |
| 28 | * 评估条件是否匹配 | 30 | * 评估条件是否匹配 |
| 29 | * | 31 | * |
| @@ -32,6 +34,7 @@ public abstract class AbstractIotSceneRuleMatcher implements IotSceneRuleMatcher | @@ -32,6 +34,7 @@ public abstract class AbstractIotSceneRuleMatcher implements IotSceneRuleMatcher | ||
| 32 | * @param paramValue 参数值(来自条件配置) | 34 | * @param paramValue 参数值(来自条件配置) |
| 33 | * @return 是否匹配 | 35 | * @return 是否匹配 |
| 34 | */ | 36 | */ |
| 37 | + @SuppressWarnings("DataFlowIssue") | ||
| 35 | protected boolean evaluateCondition(Object sourceValue, String operator, String paramValue) { | 38 | protected boolean evaluateCondition(Object sourceValue, String operator, String paramValue) { |
| 36 | try { | 39 | try { |
| 37 | // 1. 校验操作符是否合法 | 40 | // 1. 校验操作符是否合法 |
| @@ -48,6 +51,7 @@ public abstract class AbstractIotSceneRuleMatcher implements IotSceneRuleMatcher | @@ -48,6 +51,7 @@ public abstract class AbstractIotSceneRuleMatcher implements IotSceneRuleMatcher | ||
| 48 | // 处理参数值 | 51 | // 处理参数值 |
| 49 | if (StrUtil.isNotBlank(paramValue)) { | 52 | if (StrUtil.isNotBlank(paramValue)) { |
| 50 | // 处理多值情况(如 IN、BETWEEN 操作符) | 53 | // 处理多值情况(如 IN、BETWEEN 操作符) |
| 54 | + // TODO @puhui999:使用这个,会不会有问题?例如说:string 恰好有 , 分隔? | ||
| 51 | if (paramValue.contains(",")) { | 55 | if (paramValue.contains(",")) { |
| 52 | List<String> paramValues = StrUtil.split(paramValue, ','); | 56 | List<String> paramValues = StrUtil.split(paramValue, ','); |
| 53 | springExpressionVariables.put(IotSceneRuleConditionOperatorEnum.SPRING_EXPRESSION_VALUE_LIST, | 57 | springExpressionVariables.put(IotSceneRuleConditionOperatorEnum.SPRING_EXPRESSION_VALUE_LIST, |
| @@ -68,7 +72,7 @@ public abstract class AbstractIotSceneRuleMatcher implements IotSceneRuleMatcher | @@ -68,7 +72,7 @@ public abstract class AbstractIotSceneRuleMatcher implements IotSceneRuleMatcher | ||
| 68 | } | 72 | } |
| 69 | } | 73 | } |
| 70 | 74 | ||
| 71 | - // ========== 触发器相关工具方法 ========== | 75 | + // ========== 【触发器】相关工具方法 ========== |
| 72 | 76 | ||
| 73 | /** | 77 | /** |
| 74 | * 检查基础触发器参数是否有效 | 78 | * 检查基础触发器参数是否有效 |
| @@ -111,7 +115,7 @@ public abstract class AbstractIotSceneRuleMatcher implements IotSceneRuleMatcher | @@ -111,7 +115,7 @@ public abstract class AbstractIotSceneRuleMatcher implements IotSceneRuleMatcher | ||
| 111 | log.debug("[{}][消息({}) 匹配触发器({}) 失败: {}]", getMatcherName(), message.getRequestId(), trigger.getType(), reason); | 115 | log.debug("[{}][消息({}) 匹配触发器({}) 失败: {}]", getMatcherName(), message.getRequestId(), trigger.getType(), reason); |
| 112 | } | 116 | } |
| 113 | 117 | ||
| 114 | - // ========== 条件相关工具方法 ========== | 118 | + // ========== 【条件】相关工具方法 ========== |
| 115 | 119 | ||
| 116 | /** | 120 | /** |
| 117 | * 检查基础条件参数是否有效 | 121 | * 检查基础条件参数是否有效 |
| @@ -154,7 +158,7 @@ public abstract class AbstractIotSceneRuleMatcher implements IotSceneRuleMatcher | @@ -154,7 +158,7 @@ public abstract class AbstractIotSceneRuleMatcher implements IotSceneRuleMatcher | ||
| 154 | log.debug("[{}][消息({}) 匹配条件({}) 失败: {}]", getMatcherName(), message.getRequestId(), condition.getType(), reason); | 158 | log.debug("[{}][消息({}) 匹配条件({}) 失败: {}]", getMatcherName(), message.getRequestId(), condition.getType(), reason); |
| 155 | } | 159 | } |
| 156 | 160 | ||
| 157 | - // ========== 通用工具方法 ========== | 161 | + // ========== 【通用】工具方法 ========== |
| 158 | 162 | ||
| 159 | /** | 163 | /** |
| 160 | * 检查标识符是否匹配 | 164 | * 检查标识符是否匹配 |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/CurrentTimeConditionMatcher.java
| @@ -56,15 +56,11 @@ public class CurrentTimeConditionMatcher extends AbstractIotSceneRuleMatcher { | @@ -56,15 +56,11 @@ public class CurrentTimeConditionMatcher extends AbstractIotSceneRuleMatcher { | ||
| 56 | return false; | 56 | return false; |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | - // 3. 获取当前时间 | 59 | + // 3. 根据操作符类型进行不同的时间匹配 |
| 60 | LocalDateTime now = LocalDateTime.now(); | 60 | LocalDateTime now = LocalDateTime.now(); |
| 61 | - | ||
| 62 | - // 4. 根据操作符类型进行不同的时间匹配 | ||
| 63 | String operator = condition.getOperator(); | 61 | String operator = condition.getOperator(); |
| 64 | String param = condition.getParam(); | 62 | String param = condition.getParam(); |
| 65 | - | ||
| 66 | - boolean matched = false; | ||
| 67 | - | 63 | + boolean matched; |
| 68 | try { | 64 | try { |
| 69 | if (operator.startsWith("date_time_")) { | 65 | if (operator.startsWith("date_time_")) { |
| 70 | // 日期时间匹配(时间戳) | 66 | // 日期时间匹配(时间戳) |
| @@ -82,13 +78,11 @@ public class CurrentTimeConditionMatcher extends AbstractIotSceneRuleMatcher { | @@ -82,13 +78,11 @@ public class CurrentTimeConditionMatcher extends AbstractIotSceneRuleMatcher { | ||
| 82 | } else { | 78 | } else { |
| 83 | logConditionMatchFailure(message, condition, "时间条件不匹配"); | 79 | logConditionMatchFailure(message, condition, "时间条件不匹配"); |
| 84 | } | 80 | } |
| 85 | - | ||
| 86 | } catch (Exception e) { | 81 | } catch (Exception e) { |
| 87 | log.error("[CurrentTimeConditionMatcher][时间条件匹配异常] operator: {}, param: {}", operator, param, e); | 82 | log.error("[CurrentTimeConditionMatcher][时间条件匹配异常] operator: {}, param: {}", operator, param, e); |
| 88 | logConditionMatchFailure(message, condition, "时间条件匹配异常: " + e.getMessage()); | 83 | logConditionMatchFailure(message, condition, "时间条件匹配异常: " + e.getMessage()); |
| 89 | matched = false; | 84 | matched = false; |
| 90 | } | 85 | } |
| 91 | - | ||
| 92 | return matched; | 86 | return matched; |
| 93 | } | 87 | } |
| 94 | 88 | ||
| @@ -107,21 +101,20 @@ public class CurrentTimeConditionMatcher extends AbstractIotSceneRuleMatcher { | @@ -107,21 +101,20 @@ public class CurrentTimeConditionMatcher extends AbstractIotSceneRuleMatcher { | ||
| 107 | try { | 101 | try { |
| 108 | String actualOperator = operator.substring("time_".length()); | 102 | String actualOperator = operator.substring("time_".length()); |
| 109 | 103 | ||
| 104 | + // TODO @puhui999:if return 简化; | ||
| 110 | if ("between".equals(actualOperator)) { | 105 | if ("between".equals(actualOperator)) { |
| 111 | // 时间区间匹配 | 106 | // 时间区间匹配 |
| 112 | String[] timeRange = param.split(","); | 107 | String[] timeRange = param.split(","); |
| 113 | if (timeRange.length != 2) { | 108 | if (timeRange.length != 2) { |
| 114 | return false; | 109 | return false; |
| 115 | } | 110 | } |
| 116 | - | ||
| 117 | LocalTime startTime = parseTime(timeRange[0].trim()); | 111 | LocalTime startTime = parseTime(timeRange[0].trim()); |
| 118 | LocalTime endTime = parseTime(timeRange[1].trim()); | 112 | LocalTime endTime = parseTime(timeRange[1].trim()); |
| 119 | - | ||
| 120 | return !currentTime.isBefore(startTime) && !currentTime.isAfter(endTime); | 113 | return !currentTime.isBefore(startTime) && !currentTime.isAfter(endTime); |
| 121 | } else { | 114 | } else { |
| 122 | // 单个时间比较 | 115 | // 单个时间比较 |
| 123 | LocalTime targetTime = parseTime(param); | 116 | LocalTime targetTime = parseTime(param); |
| 124 | - | 117 | + // TODO @puhui999:枚举类; |
| 125 | switch (actualOperator) { | 118 | switch (actualOperator) { |
| 126 | case ">": | 119 | case ">": |
| 127 | return currentTime.isAfter(targetTime); | 120 | return currentTime.isAfter(targetTime); |
| @@ -138,6 +131,7 @@ public class CurrentTimeConditionMatcher extends AbstractIotSceneRuleMatcher { | @@ -138,6 +131,7 @@ public class CurrentTimeConditionMatcher extends AbstractIotSceneRuleMatcher { | ||
| 138 | } | 131 | } |
| 139 | } | 132 | } |
| 140 | } catch (Exception e) { | 133 | } catch (Exception e) { |
| 134 | + // TODO @puhui999:1)日志格式 [][];2)方法名不对哈; | ||
| 141 | log.error("[CurrentTimeConditionMatcher][时间解析异常] param: {}", param, e); | 135 | log.error("[CurrentTimeConditionMatcher][时间解析异常] param: {}", param, e); |
| 142 | return false; | 136 | return false; |
| 143 | } | 137 | } |
| @@ -147,10 +141,10 @@ public class CurrentTimeConditionMatcher extends AbstractIotSceneRuleMatcher { | @@ -147,10 +141,10 @@ public class CurrentTimeConditionMatcher extends AbstractIotSceneRuleMatcher { | ||
| 147 | * 解析时间字符串 | 141 | * 解析时间字符串 |
| 148 | */ | 142 | */ |
| 149 | private LocalTime parseTime(String timeStr) { | 143 | private LocalTime parseTime(String timeStr) { |
| 144 | + // TODO @puhui999:可以用 hutool Assert 类简化 | ||
| 150 | if (StrUtil.isBlank(timeStr)) { | 145 | if (StrUtil.isBlank(timeStr)) { |
| 151 | throw new IllegalArgumentException("时间字符串不能为空"); | 146 | throw new IllegalArgumentException("时间字符串不能为空"); |
| 152 | } | 147 | } |
| 153 | - | ||
| 154 | // 尝试不同的时间格式 | 148 | // 尝试不同的时间格式 |
| 155 | try { | 149 | try { |
| 156 | if (timeStr.length() == 5) { // HH:mm | 150 | if (timeStr.length() == 5) { // HH:mm |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/DevicePropertyConditionMatcher.java
| @@ -26,6 +26,7 @@ public class DevicePropertyConditionMatcher extends AbstractIotSceneRuleMatcher | @@ -26,6 +26,7 @@ public class DevicePropertyConditionMatcher extends AbstractIotSceneRuleMatcher | ||
| 26 | return IotSceneRuleConditionTypeEnum.DEVICE_PROPERTY; | 26 | return IotSceneRuleConditionTypeEnum.DEVICE_PROPERTY; |
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | + // TODO @puhui999:参数校验的,要不要 1.1 1.2 1.3 1.4 ?这样最终看到 2. 3. 就是核心逻辑列; | ||
| 29 | @Override | 30 | @Override |
| 30 | public boolean isMatched(IotDeviceMessage message, IotSceneRuleDO.TriggerCondition condition) { | 31 | public boolean isMatched(IotDeviceMessage message, IotSceneRuleDO.TriggerCondition condition) { |
| 31 | // 1. 基础参数校验 | 32 | // 1. 基础参数校验 |
| @@ -56,13 +57,11 @@ public class DevicePropertyConditionMatcher extends AbstractIotSceneRuleMatcher | @@ -56,13 +57,11 @@ public class DevicePropertyConditionMatcher extends AbstractIotSceneRuleMatcher | ||
| 56 | 57 | ||
| 57 | // 5. 使用条件评估器进行匹配 | 58 | // 5. 使用条件评估器进行匹配 |
| 58 | boolean matched = evaluateCondition(propertyValue, condition.getOperator(), condition.getParam()); | 59 | boolean matched = evaluateCondition(propertyValue, condition.getOperator(), condition.getParam()); |
| 59 | - | ||
| 60 | if (matched) { | 60 | if (matched) { |
| 61 | logConditionMatchSuccess(message, condition); | 61 | logConditionMatchSuccess(message, condition); |
| 62 | } else { | 62 | } else { |
| 63 | logConditionMatchFailure(message, condition, "设备属性条件不匹配"); | 63 | logConditionMatchFailure(message, condition, "设备属性条件不匹配"); |
| 64 | } | 64 | } |
| 65 | - | ||
| 66 | return matched; | 65 | return matched; |
| 67 | } | 66 | } |
| 68 | 67 |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/DevicePropertyPostTriggerMatcher.java
| @@ -20,6 +20,7 @@ public class DevicePropertyPostTriggerMatcher extends AbstractIotSceneRuleMatche | @@ -20,6 +20,7 @@ public class DevicePropertyPostTriggerMatcher extends AbstractIotSceneRuleMatche | ||
| 20 | /** | 20 | /** |
| 21 | * 设备属性上报消息方法 | 21 | * 设备属性上报消息方法 |
| 22 | */ | 22 | */ |
| 23 | + // TODO @puhui999:是不是不用枚举哈?直接使用 IotDeviceMessageMethodEnum.PROPERTY_POST.getMethod() | ||
| 23 | private static final String DEVICE_PROPERTY_POST_METHOD = IotDeviceMessageMethodEnum.PROPERTY_POST.getMethod(); | 24 | private static final String DEVICE_PROPERTY_POST_METHOD = IotDeviceMessageMethodEnum.PROPERTY_POST.getMethod(); |
| 24 | 25 | ||
| 25 | @Override | 26 | @Override |
| @@ -68,13 +69,11 @@ public class DevicePropertyPostTriggerMatcher extends AbstractIotSceneRuleMatche | @@ -68,13 +69,11 @@ public class DevicePropertyPostTriggerMatcher extends AbstractIotSceneRuleMatche | ||
| 68 | 69 | ||
| 69 | // 6. 使用条件评估器进行匹配 | 70 | // 6. 使用条件评估器进行匹配 |
| 70 | boolean matched = evaluateCondition(propertyValue, trigger.getOperator(), trigger.getValue()); | 71 | boolean matched = evaluateCondition(propertyValue, trigger.getOperator(), trigger.getValue()); |
| 71 | - | ||
| 72 | if (matched) { | 72 | if (matched) { |
| 73 | logTriggerMatchSuccess(message, trigger); | 73 | logTriggerMatchSuccess(message, trigger); |
| 74 | } else { | 74 | } else { |
| 75 | logTriggerMatchFailure(message, trigger, "属性值条件不匹配"); | 75 | logTriggerMatchFailure(message, trigger, "属性值条件不匹配"); |
| 76 | } | 76 | } |
| 77 | - | ||
| 78 | return matched; | 77 | return matched; |
| 79 | } | 78 | } |
| 80 | 79 |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/DeviceStateConditionMatcher.java
| @@ -49,13 +49,11 @@ public class DeviceStateConditionMatcher extends AbstractIotSceneRuleMatcher { | @@ -49,13 +49,11 @@ public class DeviceStateConditionMatcher extends AbstractIotSceneRuleMatcher { | ||
| 49 | 49 | ||
| 50 | // 4. 使用条件评估器进行匹配 | 50 | // 4. 使用条件评估器进行匹配 |
| 51 | boolean matched = evaluateCondition(stateValue, condition.getOperator(), condition.getParam()); | 51 | boolean matched = evaluateCondition(stateValue, condition.getOperator(), condition.getParam()); |
| 52 | - | ||
| 53 | if (matched) { | 52 | if (matched) { |
| 54 | logConditionMatchSuccess(message, condition); | 53 | logConditionMatchSuccess(message, condition); |
| 55 | } else { | 54 | } else { |
| 56 | logConditionMatchFailure(message, condition, "设备状态条件不匹配"); | 55 | logConditionMatchFailure(message, condition, "设备状态条件不匹配"); |
| 57 | } | 56 | } |
| 58 | - | ||
| 59 | return matched; | 57 | return matched; |
| 60 | } | 58 | } |
| 61 | 59 |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/DeviceStateUpdateTriggerMatcher.java
| @@ -16,6 +16,7 @@ import org.springframework.stereotype.Component; | @@ -16,6 +16,7 @@ import org.springframework.stereotype.Component; | ||
| 16 | @Component | 16 | @Component |
| 17 | public class DeviceStateUpdateTriggerMatcher extends AbstractIotSceneRuleMatcher { | 17 | public class DeviceStateUpdateTriggerMatcher extends AbstractIotSceneRuleMatcher { |
| 18 | 18 | ||
| 19 | + // TODO @puhui999:是不是不用枚举哈; | ||
| 19 | /** | 20 | /** |
| 20 | * 设备状态更新消息方法 | 21 | * 设备状态更新消息方法 |
| 21 | */ | 22 | */ |
| @@ -60,13 +61,11 @@ public class DeviceStateUpdateTriggerMatcher extends AbstractIotSceneRuleMatcher | @@ -60,13 +61,11 @@ public class DeviceStateUpdateTriggerMatcher extends AbstractIotSceneRuleMatcher | ||
| 60 | 61 | ||
| 61 | // 5. 使用条件评估器进行匹配 | 62 | // 5. 使用条件评估器进行匹配 |
| 62 | boolean matched = evaluateCondition(stateValue, trigger.getOperator(), trigger.getValue()); | 63 | boolean matched = evaluateCondition(stateValue, trigger.getOperator(), trigger.getValue()); |
| 63 | - | ||
| 64 | if (matched) { | 64 | if (matched) { |
| 65 | logTriggerMatchSuccess(message, trigger); | 65 | logTriggerMatchSuccess(message, trigger); |
| 66 | } else { | 66 | } else { |
| 67 | logTriggerMatchFailure(message, trigger, "状态值条件不匹配"); | 67 | logTriggerMatchFailure(message, trigger, "状态值条件不匹配"); |
| 68 | } | 68 | } |
| 69 | - | ||
| 70 | return matched; | 69 | return matched; |
| 71 | } | 70 | } |
| 72 | 71 |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/IotSceneRuleMatcher.java
| @@ -18,18 +18,23 @@ import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum; | @@ -18,18 +18,23 @@ import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum; | ||
| 18 | */ | 18 | */ |
| 19 | public interface IotSceneRuleMatcher { | 19 | public interface IotSceneRuleMatcher { |
| 20 | 20 | ||
| 21 | + // TODO @puhui999:MatcherTypeEnum; | ||
| 22 | + // TODO @puhui999:可以考虑根据类型,新建 trigger、condition 包,然后把对应的实现类放进去哈; | ||
| 21 | /** | 23 | /** |
| 22 | * 匹配器类型枚举 | 24 | * 匹配器类型枚举 |
| 23 | */ | 25 | */ |
| 24 | enum MatcherType { | 26 | enum MatcherType { |
| 27 | + | ||
| 25 | /** | 28 | /** |
| 26 | * 触发器匹配器 - 用于匹配主触发条件 | 29 | * 触发器匹配器 - 用于匹配主触发条件 |
| 27 | */ | 30 | */ |
| 28 | TRIGGER, | 31 | TRIGGER, |
| 32 | + | ||
| 29 | /** | 33 | /** |
| 30 | * 条件匹配器 - 用于匹配子条件 | 34 | * 条件匹配器 - 用于匹配子条件 |
| 31 | */ | 35 | */ |
| 32 | CONDITION | 36 | CONDITION |
| 37 | + | ||
| 33 | } | 38 | } |
| 34 | 39 | ||
| 35 | /** | 40 | /** |
| @@ -39,6 +44,10 @@ public interface IotSceneRuleMatcher { | @@ -39,6 +44,10 @@ public interface IotSceneRuleMatcher { | ||
| 39 | */ | 44 | */ |
| 40 | MatcherType getMatcherType(); | 45 | MatcherType getMatcherType(); |
| 41 | 46 | ||
| 47 | + // TODO @puhui999:【重要】有个思路,IotSceneRuleMatcher 拆分成 2 种 mather 接口;然后 AbstractIotSceneRuleMatcher 是个 Helper 工具类; | ||
| 48 | + | ||
| 49 | + // TODO @puhui999:是不是和 AbstractSceneRuleMatcher 一样,分下块; | ||
| 50 | + | ||
| 42 | /** | 51 | /** |
| 43 | * 获取支持的触发器类型(仅触发器匹配器需要实现) | 52 | * 获取支持的触发器类型(仅触发器匹配器需要实现) |
| 44 | * | 53 | * |
| @@ -90,6 +99,7 @@ public interface IotSceneRuleMatcher { | @@ -90,6 +99,7 @@ public interface IotSceneRuleMatcher { | ||
| 90 | return 100; | 99 | return 100; |
| 91 | } | 100 | } |
| 92 | 101 | ||
| 102 | + // TODO @puhui999:如果目前没自定义,体感可以删除哈; | ||
| 93 | /** | 103 | /** |
| 94 | * 获取匹配器名称,用于日志和调试 | 104 | * 获取匹配器名称,用于日志和调试 |
| 95 | * | 105 | * |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/IotSceneRuleMatcherManager.java
| @@ -30,14 +30,14 @@ public class IotSceneRuleMatcherManager { | @@ -30,14 +30,14 @@ public class IotSceneRuleMatcherManager { | ||
| 30 | * Key: 触发器类型枚举 | 30 | * Key: 触发器类型枚举 |
| 31 | * Value: 对应的匹配器实例 | 31 | * Value: 对应的匹配器实例 |
| 32 | */ | 32 | */ |
| 33 | - private final Map<IotSceneRuleTriggerTypeEnum, IotSceneRuleMatcher> triggerMatcherMap; | 33 | + private final Map<IotSceneRuleTriggerTypeEnum, IotSceneRuleMatcher> triggerMatchers; |
| 34 | 34 | ||
| 35 | /** | 35 | /** |
| 36 | * 条件匹配器映射表 | 36 | * 条件匹配器映射表 |
| 37 | * Key: 条件类型枚举 | 37 | * Key: 条件类型枚举 |
| 38 | * Value: 对应的匹配器实例 | 38 | * Value: 对应的匹配器实例 |
| 39 | */ | 39 | */ |
| 40 | - private final Map<IotSceneRuleConditionTypeEnum, IotSceneRuleMatcher> conditionMatcherMap; | 40 | + private final Map<IotSceneRuleConditionTypeEnum, IotSceneRuleMatcher> conditionMatchers; |
| 41 | 41 | ||
| 42 | /** | 42 | /** |
| 43 | * 所有匹配器列表(按优先级排序) | 43 | * 所有匹配器列表(按优先级排序) |
| @@ -47,8 +47,8 @@ public class IotSceneRuleMatcherManager { | @@ -47,8 +47,8 @@ public class IotSceneRuleMatcherManager { | ||
| 47 | public IotSceneRuleMatcherManager(List<IotSceneRuleMatcher> matchers) { | 47 | public IotSceneRuleMatcherManager(List<IotSceneRuleMatcher> matchers) { |
| 48 | if (CollUtil.isEmpty(matchers)) { | 48 | if (CollUtil.isEmpty(matchers)) { |
| 49 | log.warn("[IotSceneRuleMatcherManager][没有找到任何匹配器]"); | 49 | log.warn("[IotSceneRuleMatcherManager][没有找到任何匹配器]"); |
| 50 | - this.triggerMatcherMap = new HashMap<>(); | ||
| 51 | - this.conditionMatcherMap = new HashMap<>(); | 50 | + this.triggerMatchers = new HashMap<>(); |
| 51 | + this.conditionMatchers = new HashMap<>(); | ||
| 52 | this.allMatchers = new ArrayList<>(); | 52 | this.allMatchers = new ArrayList<>(); |
| 53 | return; | 53 | return; |
| 54 | } | 54 | } |
| @@ -63,13 +63,13 @@ public class IotSceneRuleMatcherManager { | @@ -63,13 +63,13 @@ public class IotSceneRuleMatcherManager { | ||
| 63 | List<IotSceneRuleMatcher> triggerMatchers = this.allMatchers.stream() | 63 | List<IotSceneRuleMatcher> triggerMatchers = this.allMatchers.stream() |
| 64 | .filter(matcher -> matcher.getMatcherType() == IotSceneRuleMatcher.MatcherType.TRIGGER) | 64 | .filter(matcher -> matcher.getMatcherType() == IotSceneRuleMatcher.MatcherType.TRIGGER) |
| 65 | .toList(); | 65 | .toList(); |
| 66 | - | ||
| 67 | List<IotSceneRuleMatcher> conditionMatchers = this.allMatchers.stream() | 66 | List<IotSceneRuleMatcher> conditionMatchers = this.allMatchers.stream() |
| 68 | .filter(matcher -> matcher.getMatcherType() == IotSceneRuleMatcher.MatcherType.CONDITION) | 67 | .filter(matcher -> matcher.getMatcherType() == IotSceneRuleMatcher.MatcherType.CONDITION) |
| 69 | .toList(); | 68 | .toList(); |
| 70 | 69 | ||
| 71 | // 构建触发器匹配器映射表 | 70 | // 构建触发器匹配器映射表 |
| 72 | - this.triggerMatcherMap = triggerMatchers.stream() | 71 | + // TODO @puhui999:convertMap() |
| 72 | + this.triggerMatchers = triggerMatchers.stream() | ||
| 73 | .collect(Collectors.toMap( | 73 | .collect(Collectors.toMap( |
| 74 | IotSceneRuleMatcher::getSupportedTriggerType, | 74 | IotSceneRuleMatcher::getSupportedTriggerType, |
| 75 | Function.identity(), | 75 | Function.identity(), |
| @@ -81,9 +81,8 @@ public class IotSceneRuleMatcherManager { | @@ -81,9 +81,8 @@ public class IotSceneRuleMatcherManager { | ||
| 81 | }, | 81 | }, |
| 82 | LinkedHashMap::new | 82 | LinkedHashMap::new |
| 83 | )); | 83 | )); |
| 84 | - | ||
| 85 | // 构建条件匹配器映射表 | 84 | // 构建条件匹配器映射表 |
| 86 | - this.conditionMatcherMap = conditionMatchers.stream() | 85 | + this.conditionMatchers = conditionMatchers.stream() |
| 87 | .collect(Collectors.toMap( | 86 | .collect(Collectors.toMap( |
| 88 | IotSceneRuleMatcher::getSupportedConditionType, | 87 | IotSceneRuleMatcher::getSupportedConditionType, |
| 89 | Function.identity(), | 88 | Function.identity(), |
| @@ -96,16 +95,13 @@ public class IotSceneRuleMatcherManager { | @@ -96,16 +95,13 @@ public class IotSceneRuleMatcherManager { | ||
| 96 | LinkedHashMap::new | 95 | LinkedHashMap::new |
| 97 | )); | 96 | )); |
| 98 | 97 | ||
| 98 | + // 日志输出初始化信息 | ||
| 99 | log.info("[IotSceneRuleMatcherManager][初始化完成,共加载 {} 个匹配器,其中触发器匹配器 {} 个,条件匹配器 {} 个]", | 99 | log.info("[IotSceneRuleMatcherManager][初始化完成,共加载 {} 个匹配器,其中触发器匹配器 {} 个,条件匹配器 {} 个]", |
| 100 | - this.allMatchers.size(), this.triggerMatcherMap.size(), this.conditionMatcherMap.size()); | ||
| 101 | - | ||
| 102 | - // 记录触发器匹配器详情 | ||
| 103 | - this.triggerMatcherMap.forEach((type, matcher) -> | 100 | + this.allMatchers.size(), this.triggerMatchers.size(), this.conditionMatchers.size()); |
| 101 | + this.triggerMatchers.forEach((type, matcher) -> | ||
| 104 | log.info("[IotSceneRuleMatcherManager][触发器匹配器] 类型: {}, 匹配器: {}, 优先级: {}", | 102 | log.info("[IotSceneRuleMatcherManager][触发器匹配器] 类型: {}, 匹配器: {}, 优先级: {}", |
| 105 | type, matcher.getMatcherName(), matcher.getPriority())); | 103 | type, matcher.getMatcherName(), matcher.getPriority())); |
| 106 | - | ||
| 107 | - // 记录条件匹配器详情 | ||
| 108 | - this.conditionMatcherMap.forEach((type, matcher) -> | 104 | + this.conditionMatchers.forEach((type, matcher) -> |
| 109 | log.info("[IotSceneRuleMatcherManager][条件匹配器] 类型: {}, 匹配器: {}, 优先级: {}", | 105 | log.info("[IotSceneRuleMatcherManager][条件匹配器] 类型: {}, 匹配器: {}, 优先级: {}", |
| 110 | type, matcher.getMatcherName(), matcher.getPriority())); | 106 | type, matcher.getMatcherName(), matcher.getPriority())); |
| 111 | } | 107 | } |
| @@ -118,19 +114,17 @@ public class IotSceneRuleMatcherManager { | @@ -118,19 +114,17 @@ public class IotSceneRuleMatcherManager { | ||
| 118 | * @return 是否匹配 | 114 | * @return 是否匹配 |
| 119 | */ | 115 | */ |
| 120 | public boolean isMatched(IotDeviceMessage message, IotSceneRuleDO.Trigger trigger) { | 116 | public boolean isMatched(IotDeviceMessage message, IotSceneRuleDO.Trigger trigger) { |
| 117 | + // TODO @puhui999:日志优化下;claude 打出来的日志风格,和项目有点不一样哈; | ||
| 121 | if (message == null || trigger == null || trigger.getType() == null) { | 118 | if (message == null || trigger == null || trigger.getType() == null) { |
| 122 | log.debug("[isMatched][参数无效] message: {}, trigger: {}", message, trigger); | 119 | log.debug("[isMatched][参数无效] message: {}, trigger: {}", message, trigger); |
| 123 | return false; | 120 | return false; |
| 124 | } | 121 | } |
| 125 | - | ||
| 126 | - // 根据触发器类型查找对应的匹配器 | ||
| 127 | IotSceneRuleTriggerTypeEnum triggerType = findTriggerTypeEnum(trigger.getType()); | 122 | IotSceneRuleTriggerTypeEnum triggerType = findTriggerTypeEnum(trigger.getType()); |
| 128 | if (triggerType == null) { | 123 | if (triggerType == null) { |
| 129 | log.warn("[isMatched][未知的触发器类型: {}]", trigger.getType()); | 124 | log.warn("[isMatched][未知的触发器类型: {}]", trigger.getType()); |
| 130 | return false; | 125 | return false; |
| 131 | } | 126 | } |
| 132 | - | ||
| 133 | - IotSceneRuleMatcher matcher = triggerMatcherMap.get(triggerType); | 127 | + IotSceneRuleMatcher matcher = triggerMatchers.get(triggerType); |
| 134 | if (matcher == null) { | 128 | if (matcher == null) { |
| 135 | log.warn("[isMatched][触发器类型({})没有对应的匹配器]", triggerType); | 129 | log.warn("[isMatched][触发器类型({})没有对应的匹配器]", triggerType); |
| 136 | return false; | 130 | return false; |
| @@ -165,7 +159,7 @@ public class IotSceneRuleMatcherManager { | @@ -165,7 +159,7 @@ public class IotSceneRuleMatcherManager { | ||
| 165 | return false; | 159 | return false; |
| 166 | } | 160 | } |
| 167 | 161 | ||
| 168 | - IotSceneRuleMatcher matcher = conditionMatcherMap.get(conditionType); | 162 | + IotSceneRuleMatcher matcher = conditionMatchers.get(conditionType); |
| 169 | if (matcher == null) { | 163 | if (matcher == null) { |
| 170 | log.warn("[isConditionMatched][条件类型({})没有对应的匹配器]", conditionType); | 164 | log.warn("[isConditionMatched][条件类型({})没有对应的匹配器]", conditionType); |
| 171 | return false; | 165 | return false; |
| @@ -199,7 +193,7 @@ public class IotSceneRuleMatcherManager { | @@ -199,7 +193,7 @@ public class IotSceneRuleMatcherManager { | ||
| 199 | * @return 支持的触发器类型列表 | 193 | * @return 支持的触发器类型列表 |
| 200 | */ | 194 | */ |
| 201 | public Set<IotSceneRuleTriggerTypeEnum> getSupportedTriggerTypes() { | 195 | public Set<IotSceneRuleTriggerTypeEnum> getSupportedTriggerTypes() { |
| 202 | - return new HashSet<>(triggerMatcherMap.keySet()); | 196 | + return new HashSet<>(triggerMatchers.keySet()); |
| 203 | } | 197 | } |
| 204 | 198 | ||
| 205 | /** | 199 | /** |
| @@ -208,9 +202,11 @@ public class IotSceneRuleMatcherManager { | @@ -208,9 +202,11 @@ public class IotSceneRuleMatcherManager { | ||
| 208 | * @return 支持的条件类型列表 | 202 | * @return 支持的条件类型列表 |
| 209 | */ | 203 | */ |
| 210 | public Set<IotSceneRuleConditionTypeEnum> getSupportedConditionTypes() { | 204 | public Set<IotSceneRuleConditionTypeEnum> getSupportedConditionTypes() { |
| 211 | - return new HashSet<>(conditionMatcherMap.keySet()); | 205 | + return new HashSet<>(conditionMatchers.keySet()); |
| 212 | } | 206 | } |
| 213 | 207 | ||
| 208 | + // TODO @puhui999:用不到的方法,可以去掉先哈; | ||
| 209 | + | ||
| 214 | /** | 210 | /** |
| 215 | * 获取指定触发器类型的匹配器 | 211 | * 获取指定触发器类型的匹配器 |
| 216 | * | 212 | * |
| @@ -218,7 +214,7 @@ public class IotSceneRuleMatcherManager { | @@ -218,7 +214,7 @@ public class IotSceneRuleMatcherManager { | ||
| 218 | * @return 匹配器实例,如果不存在则返回 null | 214 | * @return 匹配器实例,如果不存在则返回 null |
| 219 | */ | 215 | */ |
| 220 | public IotSceneRuleMatcher getTriggerMatcher(IotSceneRuleTriggerTypeEnum triggerType) { | 216 | public IotSceneRuleMatcher getTriggerMatcher(IotSceneRuleTriggerTypeEnum triggerType) { |
| 221 | - return triggerMatcherMap.get(triggerType); | 217 | + return triggerMatchers.get(triggerType); |
| 222 | } | 218 | } |
| 223 | 219 | ||
| 224 | /** | 220 | /** |
| @@ -228,9 +224,10 @@ public class IotSceneRuleMatcherManager { | @@ -228,9 +224,10 @@ public class IotSceneRuleMatcherManager { | ||
| 228 | * @return 匹配器实例,如果不存在则返回 null | 224 | * @return 匹配器实例,如果不存在则返回 null |
| 229 | */ | 225 | */ |
| 230 | public IotSceneRuleMatcher getConditionMatcher(IotSceneRuleConditionTypeEnum conditionType) { | 226 | public IotSceneRuleMatcher getConditionMatcher(IotSceneRuleConditionTypeEnum conditionType) { |
| 231 | - return conditionMatcherMap.get(conditionType); | 227 | + return conditionMatchers.get(conditionType); |
| 232 | } | 228 | } |
| 233 | 229 | ||
| 230 | + // TODO @puhui999:是不是不用这个哈;直接 @Getter,单测直接处理; | ||
| 234 | /** | 231 | /** |
| 235 | * 获取所有匹配器的统计信息 | 232 | * 获取所有匹配器的统计信息 |
| 236 | * | 233 | * |
| @@ -239,14 +236,14 @@ public class IotSceneRuleMatcherManager { | @@ -239,14 +236,14 @@ public class IotSceneRuleMatcherManager { | ||
| 239 | public Map<String, Object> getMatcherStatistics() { | 236 | public Map<String, Object> getMatcherStatistics() { |
| 240 | Map<String, Object> statistics = new HashMap<>(); | 237 | Map<String, Object> statistics = new HashMap<>(); |
| 241 | statistics.put("totalMatchers", allMatchers.size()); | 238 | statistics.put("totalMatchers", allMatchers.size()); |
| 242 | - statistics.put("triggerMatchers", triggerMatcherMap.size()); | ||
| 243 | - statistics.put("conditionMatchers", conditionMatcherMap.size()); | 239 | + statistics.put("triggerMatchers", triggerMatchers.size()); |
| 240 | + statistics.put("conditionMatchers", conditionMatchers.size()); | ||
| 244 | statistics.put("supportedTriggerTypes", getSupportedTriggerTypes()); | 241 | statistics.put("supportedTriggerTypes", getSupportedTriggerTypes()); |
| 245 | statistics.put("supportedConditionTypes", getSupportedConditionTypes()); | 242 | statistics.put("supportedConditionTypes", getSupportedConditionTypes()); |
| 246 | 243 | ||
| 247 | // 触发器匹配器详情 | 244 | // 触发器匹配器详情 |
| 248 | Map<String, Object> triggerMatcherDetails = new HashMap<>(); | 245 | Map<String, Object> triggerMatcherDetails = new HashMap<>(); |
| 249 | - triggerMatcherMap.forEach((type, matcher) -> { | 246 | + triggerMatchers.forEach((type, matcher) -> { |
| 250 | Map<String, Object> detail = new HashMap<>(); | 247 | Map<String, Object> detail = new HashMap<>(); |
| 251 | detail.put("matcherName", matcher.getMatcherName()); | 248 | detail.put("matcherName", matcher.getMatcherName()); |
| 252 | detail.put("priority", matcher.getPriority()); | 249 | detail.put("priority", matcher.getPriority()); |
| @@ -257,7 +254,7 @@ public class IotSceneRuleMatcherManager { | @@ -257,7 +254,7 @@ public class IotSceneRuleMatcherManager { | ||
| 257 | 254 | ||
| 258 | // 条件匹配器详情 | 255 | // 条件匹配器详情 |
| 259 | Map<String, Object> conditionMatcherDetails = new HashMap<>(); | 256 | Map<String, Object> conditionMatcherDetails = new HashMap<>(); |
| 260 | - conditionMatcherMap.forEach((type, matcher) -> { | 257 | + conditionMatchers.forEach((type, matcher) -> { |
| 261 | Map<String, Object> detail = new HashMap<>(); | 258 | Map<String, Object> detail = new HashMap<>(); |
| 262 | detail.put("matcherName", matcher.getMatcherName()); | 259 | detail.put("matcherName", matcher.getMatcherName()); |
| 263 | detail.put("priority", matcher.getPriority()); | 260 | detail.put("priority", matcher.getPriority()); |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/TimerTriggerMatcher.java
| @@ -61,6 +61,7 @@ public class TimerTriggerMatcher extends AbstractIotSceneRuleMatcher { | @@ -61,6 +61,7 @@ public class TimerTriggerMatcher extends AbstractIotSceneRuleMatcher { | ||
| 61 | * @return 是否有效 | 61 | * @return 是否有效 |
| 62 | */ | 62 | */ |
| 63 | private boolean isValidCronExpression(String cronExpression) { | 63 | private boolean isValidCronExpression(String cronExpression) { |
| 64 | + // TODO @puhui999:CronExpression.isValidExpression(cronExpression); | ||
| 64 | try { | 65 | try { |
| 65 | // 简单的 CRON 表达式格式验证 | 66 | // 简单的 CRON 表达式格式验证 |
| 66 | // 标准 CRON 表达式应该有 6 或 7 个字段(秒 分 时 日 月 周 [年]) | 67 | // 标准 CRON 表达式应该有 6 或 7 个字段(秒 分 时 日 月 周 [年]) |
yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/IotSceneRuleTriggerMatcherTest.java
| @@ -20,6 +20,8 @@ import static org.junit.jupiter.api.Assertions.*; | @@ -20,6 +20,8 @@ import static org.junit.jupiter.api.Assertions.*; | ||
| 20 | */ | 20 | */ |
| 21 | public class IotSceneRuleTriggerMatcherTest extends BaseMockitoUnitTest { | 21 | public class IotSceneRuleTriggerMatcherTest extends BaseMockitoUnitTest { |
| 22 | 22 | ||
| 23 | + // TODO @puhui999:public 都加下哈; | ||
| 24 | + | ||
| 23 | private IotSceneRuleMatcherManager matcherManager; | 25 | private IotSceneRuleMatcherManager matcherManager; |
| 24 | 26 | ||
| 25 | @BeforeEach | 27 | @BeforeEach |
| @@ -42,13 +44,13 @@ public class IotSceneRuleTriggerMatcherTest extends BaseMockitoUnitTest { | @@ -42,13 +44,13 @@ public class IotSceneRuleTriggerMatcherTest extends BaseMockitoUnitTest { | ||
| 42 | // 1. 准备测试数据 | 44 | // 1. 准备测试数据 |
| 43 | IotDeviceMessage message = IotDeviceMessage.builder() | 45 | IotDeviceMessage message = IotDeviceMessage.builder() |
| 44 | .requestId("test-001") | 46 | .requestId("test-001") |
| 45 | - .method("thing.state.update") | ||
| 46 | - .data(1) // 在线状态 | 47 | + .method("thing.state.update") // TODO @puhui999:这里的枚举; |
| 48 | + .data(1) // 在线状态 TODO @puhui999:这里的枚举; | ||
| 47 | .build(); | 49 | .build(); |
| 48 | 50 | ||
| 49 | IotSceneRuleDO.Trigger trigger = new IotSceneRuleDO.Trigger(); | 51 | IotSceneRuleDO.Trigger trigger = new IotSceneRuleDO.Trigger(); |
| 50 | trigger.setType(IotSceneRuleTriggerTypeEnum.DEVICE_STATE_UPDATE.getType()); | 52 | trigger.setType(IotSceneRuleTriggerTypeEnum.DEVICE_STATE_UPDATE.getType()); |
| 51 | - trigger.setOperator("="); | 53 | + trigger.setOperator("="); // TODO @puhui999:这里的枚举;下面也是类似; |
| 52 | trigger.setValue("1"); | 54 | trigger.setValue("1"); |
| 53 | 55 | ||
| 54 | // 2. 执行测试 | 56 | // 2. 执行测试 |