Commit 34f1a2ed71d5d09f48061a56a208eeaa0b5d7edf
1 parent
1e17e357
perf:【IoT 物联网】场景联动规则匹配接口拆分使职责更清晰
Showing
13 changed files
with
217 additions
and
299 deletions
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/IotSceneRuleMatcher.java
| 1 | package cn.iocoder.yudao.module.iot.service.rule.scene.matcher; | 1 | package cn.iocoder.yudao.module.iot.service.rule.scene.matcher; |
| 2 | 2 | ||
| 3 | -import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; | ||
| 4 | -import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO; | ||
| 5 | -import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleConditionTypeEnum; | ||
| 6 | -import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum; | 3 | +import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.condition.IotSceneRuleConditionMatcher; |
| 4 | +import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.trigger.IotSceneRuleTriggerMatcher; | ||
| 7 | 5 | ||
| 8 | /** | 6 | /** |
| 9 | - * IoT 场景规则匹配器统一接口 | 7 | + * IoT 场景规则匹配器基础接口 |
| 10 | * <p> | 8 | * <p> |
| 11 | - * 支持触发器匹配和条件匹配两种类型,遵循策略模式设计 | 9 | + * 定义所有匹配器的通用行为,包括优先级、名称和启用状态 |
| 12 | * <p> | 10 | * <p> |
| 13 | - * 匹配器类型说明: | ||
| 14 | - * - 触发器匹配器:用于匹配主触发条件(如设备消息类型、定时器等) | ||
| 15 | - * - 条件匹配器:用于匹配子条件(如设备状态、属性值、时间条件等) | 11 | + * - {@link IotSceneRuleTriggerMatcher} 触发器匹配器 |
| 12 | + * - {@link IotSceneRuleConditionMatcher} 条件匹配器 | ||
| 16 | * | 13 | * |
| 17 | * @author HUIHUI | 14 | * @author HUIHUI |
| 18 | */ | 15 | */ |
| 19 | public interface IotSceneRuleMatcher { | 16 | public interface IotSceneRuleMatcher { |
| 20 | 17 | ||
| 21 | /** | 18 | /** |
| 22 | - * 匹配器类型枚举 | ||
| 23 | - */ | ||
| 24 | - enum MatcherTypeEnum { | ||
| 25 | - | ||
| 26 | - /** | ||
| 27 | - * 触发器匹配器 - 用于匹配主触发条件 | ||
| 28 | - */ | ||
| 29 | - TRIGGER, | ||
| 30 | - | ||
| 31 | - /** | ||
| 32 | - * 条件匹配器 - 用于匹配子条件 | ||
| 33 | - */ | ||
| 34 | - CONDITION | ||
| 35 | - | ||
| 36 | - } | ||
| 37 | - | ||
| 38 | - /** | ||
| 39 | - * 获取匹配器类型 | ||
| 40 | - * | ||
| 41 | - * @return 匹配器类型 | ||
| 42 | - */ | ||
| 43 | - MatcherTypeEnum getMatcherType(); | ||
| 44 | - | ||
| 45 | - // TODO @puhui999:【重要】有个思路,IotSceneRuleMatcher 拆分成 2 种 mather 接口;然后 AbstractIotSceneRuleMatcher 是个 Helper 工具类; | ||
| 46 | - | ||
| 47 | - // TODO @puhui999:是不是和 AbstractSceneRuleMatcher 一样,分下块; | ||
| 48 | - | ||
| 49 | - /** | ||
| 50 | - * 获取支持的触发器类型(仅触发器匹配器需要实现) | ||
| 51 | - * | ||
| 52 | - * @return 触发器类型枚举,条件匹配器返回 null | ||
| 53 | - */ | ||
| 54 | - default IotSceneRuleTriggerTypeEnum getSupportedTriggerType() { | ||
| 55 | - return null; | ||
| 56 | - } | ||
| 57 | - | ||
| 58 | - /** | ||
| 59 | - * 获取支持的条件类型(仅条件匹配器需要实现) | ||
| 60 | - * | ||
| 61 | - * @return 条件类型枚举,触发器匹配器返回 null | ||
| 62 | - */ | ||
| 63 | - default IotSceneRuleConditionTypeEnum getSupportedConditionType() { | ||
| 64 | - return null; | ||
| 65 | - } | ||
| 66 | - | ||
| 67 | - /** | ||
| 68 | - * 检查触发器是否匹配消息(仅触发器匹配器需要实现) | ||
| 69 | - * | ||
| 70 | - * @param message 设备消息 | ||
| 71 | - * @param trigger 触发器配置 | ||
| 72 | - * @return 是否匹配 | ||
| 73 | - */ | ||
| 74 | - default boolean isMatched(IotDeviceMessage message, IotSceneRuleDO.Trigger trigger) { | ||
| 75 | - throw new UnsupportedOperationException("触发器匹配方法仅支持触发器匹配器"); | ||
| 76 | - } | ||
| 77 | - | ||
| 78 | - /** | ||
| 79 | - * 检查条件是否匹配消息(仅条件匹配器需要实现) | ||
| 80 | - * | ||
| 81 | - * @param message 设备消息 | ||
| 82 | - * @param condition 触发条件 | ||
| 83 | - * @return 是否匹配 | ||
| 84 | - */ | ||
| 85 | - default boolean isMatched(IotDeviceMessage message, IotSceneRuleDO.TriggerCondition condition) { | ||
| 86 | - throw new UnsupportedOperationException("条件匹配方法仅支持条件匹配器"); | ||
| 87 | - } | ||
| 88 | - | ||
| 89 | - /** | ||
| 90 | * 获取匹配优先级(数值越小优先级越高) | 19 | * 获取匹配优先级(数值越小优先级越高) |
| 91 | * <p> | 20 | * <p> |
| 92 | * 用于在多个匹配器支持同一类型时确定优先级 | 21 | * 用于在多个匹配器支持同一类型时确定优先级 |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/AbstractIotSceneRuleMatcher.java renamed to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/IotSceneRuleMatcherHelper.java
| @@ -15,16 +15,22 @@ import java.util.Map; | @@ -15,16 +15,22 @@ import java.util.Map; | ||
| 15 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | 15 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; |
| 16 | 16 | ||
| 17 | /** | 17 | /** |
| 18 | - * IoT 场景规则匹配器抽象基类 | 18 | + * IoT 场景规则匹配器工具类 |
| 19 | * <p> | 19 | * <p> |
| 20 | - * 提供通用的条件评估逻辑和工具方法,支持触发器和条件两种匹配类型 | 20 | + * 提供通用的条件评估逻辑和工具方法,供触发器和条件匹配器使用 |
| 21 | + * <p> | ||
| 22 | + * 该类包含了匹配器实现中常用的工具方法,如条件评估、参数校验、日志记录等 | ||
| 21 | * | 23 | * |
| 22 | * @author HUIHUI | 24 | * @author HUIHUI |
| 23 | */ | 25 | */ |
| 24 | @Slf4j | 26 | @Slf4j |
| 25 | -public abstract class AbstractIotSceneRuleMatcher implements IotSceneRuleMatcher { | 27 | +public final class IotSceneRuleMatcherHelper { |
| 26 | 28 | ||
| 27 | - // TODO @puhui999:这个是不是也是【通用】条件哈? | 29 | + /** |
| 30 | + * 私有构造函数,防止实例化 | ||
| 31 | + */ | ||
| 32 | + private IotSceneRuleMatcherHelper() { | ||
| 33 | + } | ||
| 28 | 34 | ||
| 29 | /** | 35 | /** |
| 30 | * 评估条件是否匹配 | 36 | * 评估条件是否匹配 |
| @@ -35,7 +41,7 @@ public abstract class AbstractIotSceneRuleMatcher implements IotSceneRuleMatcher | @@ -35,7 +41,7 @@ public abstract class AbstractIotSceneRuleMatcher implements IotSceneRuleMatcher | ||
| 35 | * @return 是否匹配 | 41 | * @return 是否匹配 |
| 36 | */ | 42 | */ |
| 37 | @SuppressWarnings("DataFlowIssue") | 43 | @SuppressWarnings("DataFlowIssue") |
| 38 | - protected boolean evaluateCondition(Object sourceValue, String operator, String paramValue) { | 44 | + public static boolean evaluateCondition(Object sourceValue, String operator, String paramValue) { |
| 39 | try { | 45 | try { |
| 40 | // 1. 校验操作符是否合法 | 46 | // 1. 校验操作符是否合法 |
| 41 | IotSceneRuleConditionOperatorEnum operatorEnum = IotSceneRuleConditionOperatorEnum.operatorOf(operator); | 47 | IotSceneRuleConditionOperatorEnum operatorEnum = IotSceneRuleConditionOperatorEnum.operatorOf(operator); |
| @@ -80,7 +86,7 @@ public abstract class AbstractIotSceneRuleMatcher implements IotSceneRuleMatcher | @@ -80,7 +86,7 @@ public abstract class AbstractIotSceneRuleMatcher implements IotSceneRuleMatcher | ||
| 80 | * @param trigger 触发器配置 | 86 | * @param trigger 触发器配置 |
| 81 | * @return 是否有效 | 87 | * @return 是否有效 |
| 82 | */ | 88 | */ |
| 83 | - protected boolean isBasicTriggerValid(IotSceneRuleDO.Trigger trigger) { | 89 | + public static boolean isBasicTriggerValid(IotSceneRuleDO.Trigger trigger) { |
| 84 | return trigger != null && trigger.getType() != null; | 90 | return trigger != null && trigger.getType() != null; |
| 85 | } | 91 | } |
| 86 | 92 | ||
| @@ -90,29 +96,31 @@ public abstract class AbstractIotSceneRuleMatcher implements IotSceneRuleMatcher | @@ -90,29 +96,31 @@ public abstract class AbstractIotSceneRuleMatcher implements IotSceneRuleMatcher | ||
| 90 | * @param trigger 触发器配置 | 96 | * @param trigger 触发器配置 |
| 91 | * @return 是否有效 | 97 | * @return 是否有效 |
| 92 | */ | 98 | */ |
| 93 | - protected boolean isTriggerOperatorAndValueValid(IotSceneRuleDO.Trigger trigger) { | 99 | + public static boolean isTriggerOperatorAndValueValid(IotSceneRuleDO.Trigger trigger) { |
| 94 | return StrUtil.isNotBlank(trigger.getOperator()) && StrUtil.isNotBlank(trigger.getValue()); | 100 | return StrUtil.isNotBlank(trigger.getOperator()) && StrUtil.isNotBlank(trigger.getValue()); |
| 95 | } | 101 | } |
| 96 | 102 | ||
| 97 | /** | 103 | /** |
| 98 | * 记录触发器匹配成功日志 | 104 | * 记录触发器匹配成功日志 |
| 99 | * | 105 | * |
| 100 | - * @param message 设备消息 | ||
| 101 | - * @param trigger 触发器配置 | 106 | + * @param matcherName 匹配器名称 |
| 107 | + * @param message 设备消息 | ||
| 108 | + * @param trigger 触发器配置 | ||
| 102 | */ | 109 | */ |
| 103 | - protected void logTriggerMatchSuccess(IotDeviceMessage message, IotSceneRuleDO.Trigger trigger) { | ||
| 104 | - log.debug("[{}][消息({}) 匹配触发器({}) 成功]", getMatcherName(), message.getRequestId(), trigger.getType()); | 110 | + public static void logTriggerMatchSuccess(String matcherName, IotDeviceMessage message, IotSceneRuleDO.Trigger trigger) { |
| 111 | + log.debug("[{}][消息({}) 匹配触发器({}) 成功]", matcherName, message.getRequestId(), trigger.getType()); | ||
| 105 | } | 112 | } |
| 106 | 113 | ||
| 107 | /** | 114 | /** |
| 108 | * 记录触发器匹配失败日志 | 115 | * 记录触发器匹配失败日志 |
| 109 | * | 116 | * |
| 110 | - * @param message 设备消息 | ||
| 111 | - * @param trigger 触发器配置 | ||
| 112 | - * @param reason 失败原因 | 117 | + * @param matcherName 匹配器名称 |
| 118 | + * @param message 设备消息 | ||
| 119 | + * @param trigger 触发器配置 | ||
| 120 | + * @param reason 失败原因 | ||
| 113 | */ | 121 | */ |
| 114 | - protected void logTriggerMatchFailure(IotDeviceMessage message, IotSceneRuleDO.Trigger trigger, String reason) { | ||
| 115 | - log.debug("[{}][消息({}) 匹配触发器({}) 失败: {}]", getMatcherName(), message.getRequestId(), trigger.getType(), reason); | 122 | + public static void logTriggerMatchFailure(String matcherName, IotDeviceMessage message, IotSceneRuleDO.Trigger trigger, String reason) { |
| 123 | + log.debug("[{}][消息({}) 匹配触发器({}) 失败: {}]", matcherName, message.getRequestId(), trigger.getType(), reason); | ||
| 116 | } | 124 | } |
| 117 | 125 | ||
| 118 | // ========== 【条件】相关工具方法 ========== | 126 | // ========== 【条件】相关工具方法 ========== |
| @@ -123,7 +131,7 @@ public abstract class AbstractIotSceneRuleMatcher implements IotSceneRuleMatcher | @@ -123,7 +131,7 @@ public abstract class AbstractIotSceneRuleMatcher implements IotSceneRuleMatcher | ||
| 123 | * @param condition 触发条件 | 131 | * @param condition 触发条件 |
| 124 | * @return 是否有效 | 132 | * @return 是否有效 |
| 125 | */ | 133 | */ |
| 126 | - protected boolean isBasicConditionValid(IotSceneRuleDO.TriggerCondition condition) { | 134 | + public static boolean isBasicConditionValid(IotSceneRuleDO.TriggerCondition condition) { |
| 127 | return condition != null && condition.getType() != null; | 135 | return condition != null && condition.getType() != null; |
| 128 | } | 136 | } |
| 129 | 137 | ||
| @@ -133,29 +141,31 @@ public abstract class AbstractIotSceneRuleMatcher implements IotSceneRuleMatcher | @@ -133,29 +141,31 @@ public abstract class AbstractIotSceneRuleMatcher implements IotSceneRuleMatcher | ||
| 133 | * @param condition 触发条件 | 141 | * @param condition 触发条件 |
| 134 | * @return 是否有效 | 142 | * @return 是否有效 |
| 135 | */ | 143 | */ |
| 136 | - protected boolean isConditionOperatorAndParamValid(IotSceneRuleDO.TriggerCondition condition) { | 144 | + public static boolean isConditionOperatorAndParamValid(IotSceneRuleDO.TriggerCondition condition) { |
| 137 | return StrUtil.isNotBlank(condition.getOperator()) && StrUtil.isNotBlank(condition.getParam()); | 145 | return StrUtil.isNotBlank(condition.getOperator()) && StrUtil.isNotBlank(condition.getParam()); |
| 138 | } | 146 | } |
| 139 | 147 | ||
| 140 | /** | 148 | /** |
| 141 | * 记录条件匹配成功日志 | 149 | * 记录条件匹配成功日志 |
| 142 | * | 150 | * |
| 143 | - * @param message 设备消息 | ||
| 144 | - * @param condition 触发条件 | 151 | + * @param matcherName 匹配器名称 |
| 152 | + * @param message 设备消息 | ||
| 153 | + * @param condition 触发条件 | ||
| 145 | */ | 154 | */ |
| 146 | - protected void logConditionMatchSuccess(IotDeviceMessage message, IotSceneRuleDO.TriggerCondition condition) { | ||
| 147 | - log.debug("[{}][消息({}) 匹配条件({}) 成功]", getMatcherName(), message.getRequestId(), condition.getType()); | 155 | + public static void logConditionMatchSuccess(String matcherName, IotDeviceMessage message, IotSceneRuleDO.TriggerCondition condition) { |
| 156 | + log.debug("[{}][消息({}) 匹配条件({}) 成功]", matcherName, message.getRequestId(), condition.getType()); | ||
| 148 | } | 157 | } |
| 149 | 158 | ||
| 150 | /** | 159 | /** |
| 151 | * 记录条件匹配失败日志 | 160 | * 记录条件匹配失败日志 |
| 152 | * | 161 | * |
| 153 | - * @param message 设备消息 | ||
| 154 | - * @param condition 触发条件 | ||
| 155 | - * @param reason 失败原因 | 162 | + * @param matcherName 匹配器名称 |
| 163 | + * @param message 设备消息 | ||
| 164 | + * @param condition 触发条件 | ||
| 165 | + * @param reason 失败原因 | ||
| 156 | */ | 166 | */ |
| 157 | - protected void logConditionMatchFailure(IotDeviceMessage message, IotSceneRuleDO.TriggerCondition condition, String reason) { | ||
| 158 | - log.debug("[{}][消息({}) 匹配条件({}) 失败: {}]", getMatcherName(), message.getRequestId(), condition.getType(), reason); | 167 | + public static void logConditionMatchFailure(String matcherName, IotDeviceMessage message, IotSceneRuleDO.TriggerCondition condition, String reason) { |
| 168 | + log.debug("[{}][消息({}) 匹配条件({}) 失败: {}]", matcherName, message.getRequestId(), condition.getType(), reason); | ||
| 159 | } | 169 | } |
| 160 | 170 | ||
| 161 | // ========== 【通用】工具方法 ========== | 171 | // ========== 【通用】工具方法 ========== |
| @@ -167,7 +177,7 @@ public abstract class AbstractIotSceneRuleMatcher implements IotSceneRuleMatcher | @@ -167,7 +177,7 @@ public abstract class AbstractIotSceneRuleMatcher implements IotSceneRuleMatcher | ||
| 167 | * @param actualIdentifier 实际的标识符 | 177 | * @param actualIdentifier 实际的标识符 |
| 168 | * @return 是否匹配 | 178 | * @return 是否匹配 |
| 169 | */ | 179 | */ |
| 170 | - protected boolean isIdentifierMatched(String expectedIdentifier, String actualIdentifier) { | 180 | + public static boolean isIdentifierMatched(String expectedIdentifier, String actualIdentifier) { |
| 171 | return StrUtil.isNotBlank(expectedIdentifier) && expectedIdentifier.equals(actualIdentifier); | 181 | return StrUtil.isNotBlank(expectedIdentifier) && expectedIdentifier.equals(actualIdentifier); |
| 172 | } | 182 | } |
| 173 | 183 |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/IotSceneRuleMatcherManager.java
| @@ -5,6 +5,8 @@ import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; | @@ -5,6 +5,8 @@ import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; | ||
| 5 | import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO; | 5 | import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO; |
| 6 | import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleConditionTypeEnum; | 6 | import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleConditionTypeEnum; |
| 7 | import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum; | 7 | import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum; |
| 8 | +import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.condition.IotSceneRuleConditionMatcher; | ||
| 9 | +import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.trigger.IotSceneRuleTriggerMatcher; | ||
| 8 | import lombok.extern.slf4j.Slf4j; | 10 | import lombok.extern.slf4j.Slf4j; |
| 9 | import org.springframework.stereotype.Component; | 11 | import org.springframework.stereotype.Component; |
| 10 | 12 | ||
| @@ -30,14 +32,14 @@ public class IotSceneRuleMatcherManager { | @@ -30,14 +32,14 @@ public class IotSceneRuleMatcherManager { | ||
| 30 | * Key: 触发器类型枚举 | 32 | * Key: 触发器类型枚举 |
| 31 | * Value: 对应的匹配器实例 | 33 | * Value: 对应的匹配器实例 |
| 32 | */ | 34 | */ |
| 33 | - private final Map<IotSceneRuleTriggerTypeEnum, IotSceneRuleMatcher> triggerMatchers; | 35 | + private final Map<IotSceneRuleTriggerTypeEnum, IotSceneRuleTriggerMatcher> triggerMatchers; |
| 34 | 36 | ||
| 35 | /** | 37 | /** |
| 36 | * 条件匹配器映射表 | 38 | * 条件匹配器映射表 |
| 37 | * Key: 条件类型枚举 | 39 | * Key: 条件类型枚举 |
| 38 | * Value: 对应的匹配器实例 | 40 | * Value: 对应的匹配器实例 |
| 39 | */ | 41 | */ |
| 40 | - private final Map<IotSceneRuleConditionTypeEnum, IotSceneRuleMatcher> conditionMatchers; | 42 | + private final Map<IotSceneRuleConditionTypeEnum, IotSceneRuleConditionMatcher> conditionMatchers; |
| 41 | 43 | ||
| 42 | /** | 44 | /** |
| 43 | * 所有匹配器列表(按优先级排序) | 45 | * 所有匹配器列表(按优先级排序) |
| @@ -60,18 +62,20 @@ public class IotSceneRuleMatcherManager { | @@ -60,18 +62,20 @@ public class IotSceneRuleMatcherManager { | ||
| 60 | .collect(Collectors.toList()); | 62 | .collect(Collectors.toList()); |
| 61 | 63 | ||
| 62 | // 分离触发器匹配器和条件匹配器 | 64 | // 分离触发器匹配器和条件匹配器 |
| 63 | - List<IotSceneRuleMatcher> triggerMatchers = this.allMatchers.stream() | ||
| 64 | - .filter(matcher -> matcher.getMatcherType() == IotSceneRuleMatcher.MatcherTypeEnum.TRIGGER) | 65 | + List<IotSceneRuleTriggerMatcher> triggerMatchers = this.allMatchers.stream() |
| 66 | + .filter(matcher -> matcher instanceof IotSceneRuleTriggerMatcher) | ||
| 67 | + .map(matcher -> (IotSceneRuleTriggerMatcher) matcher) | ||
| 65 | .toList(); | 68 | .toList(); |
| 66 | - List<IotSceneRuleMatcher> conditionMatchers = this.allMatchers.stream() | ||
| 67 | - .filter(matcher -> matcher.getMatcherType() == IotSceneRuleMatcher.MatcherTypeEnum.CONDITION) | 69 | + List<IotSceneRuleConditionMatcher> conditionMatchers = this.allMatchers.stream() |
| 70 | + .filter(matcher -> matcher instanceof IotSceneRuleConditionMatcher) | ||
| 71 | + .map(matcher -> (IotSceneRuleConditionMatcher) matcher) | ||
| 68 | .toList(); | 72 | .toList(); |
| 69 | 73 | ||
| 70 | // 构建触发器匹配器映射表 | 74 | // 构建触发器匹配器映射表 |
| 71 | // TODO @puhui999:convertMap() | 75 | // TODO @puhui999:convertMap() |
| 72 | this.triggerMatchers = triggerMatchers.stream() | 76 | this.triggerMatchers = triggerMatchers.stream() |
| 73 | .collect(Collectors.toMap( | 77 | .collect(Collectors.toMap( |
| 74 | - IotSceneRuleMatcher::getSupportedTriggerType, | 78 | + IotSceneRuleTriggerMatcher::getSupportedTriggerType, |
| 75 | Function.identity(), | 79 | Function.identity(), |
| 76 | (existing, replacement) -> { | 80 | (existing, replacement) -> { |
| 77 | log.warn("[IotSceneRuleMatcherManager][触发器类型({})存在多个匹配器,使用优先级更高的: {}]", | 81 | log.warn("[IotSceneRuleMatcherManager][触发器类型({})存在多个匹配器,使用优先级更高的: {}]", |
| @@ -84,7 +88,7 @@ public class IotSceneRuleMatcherManager { | @@ -84,7 +88,7 @@ public class IotSceneRuleMatcherManager { | ||
| 84 | // 构建条件匹配器映射表 | 88 | // 构建条件匹配器映射表 |
| 85 | this.conditionMatchers = conditionMatchers.stream() | 89 | this.conditionMatchers = conditionMatchers.stream() |
| 86 | .collect(Collectors.toMap( | 90 | .collect(Collectors.toMap( |
| 87 | - IotSceneRuleMatcher::getSupportedConditionType, | 91 | + IotSceneRuleConditionMatcher::getSupportedConditionType, |
| 88 | Function.identity(), | 92 | Function.identity(), |
| 89 | (existing, replacement) -> { | 93 | (existing, replacement) -> { |
| 90 | log.warn("[IotSceneRuleMatcherManager][条件类型({})存在多个匹配器,使用优先级更高的: {}]", | 94 | log.warn("[IotSceneRuleMatcherManager][条件类型({})存在多个匹配器,使用优先级更高的: {}]", |
| @@ -124,7 +128,7 @@ public class IotSceneRuleMatcherManager { | @@ -124,7 +128,7 @@ public class IotSceneRuleMatcherManager { | ||
| 124 | log.warn("[isMatched][未知的触发器类型: {}]", trigger.getType()); | 128 | log.warn("[isMatched][未知的触发器类型: {}]", trigger.getType()); |
| 125 | return false; | 129 | return false; |
| 126 | } | 130 | } |
| 127 | - IotSceneRuleMatcher matcher = triggerMatchers.get(triggerType); | 131 | + IotSceneRuleTriggerMatcher matcher = triggerMatchers.get(triggerType); |
| 128 | if (matcher == null) { | 132 | if (matcher == null) { |
| 129 | log.warn("[isMatched][触发器类型({})没有对应的匹配器]", triggerType); | 133 | log.warn("[isMatched][触发器类型({})没有对应的匹配器]", triggerType); |
| 130 | return false; | 134 | return false; |
| @@ -159,7 +163,7 @@ public class IotSceneRuleMatcherManager { | @@ -159,7 +163,7 @@ public class IotSceneRuleMatcherManager { | ||
| 159 | return false; | 163 | return false; |
| 160 | } | 164 | } |
| 161 | 165 | ||
| 162 | - IotSceneRuleMatcher matcher = conditionMatchers.get(conditionType); | 166 | + IotSceneRuleConditionMatcher matcher = conditionMatchers.get(conditionType); |
| 163 | if (matcher == null) { | 167 | if (matcher == null) { |
| 164 | log.warn("[isConditionMatched][条件类型({})没有对应的匹配器]", conditionType); | 168 | log.warn("[isConditionMatched][条件类型({})没有对应的匹配器]", conditionType); |
| 165 | return false; | 169 | return false; |
| @@ -205,65 +209,4 @@ public class IotSceneRuleMatcherManager { | @@ -205,65 +209,4 @@ public class IotSceneRuleMatcherManager { | ||
| 205 | return new HashSet<>(conditionMatchers.keySet()); | 209 | return new HashSet<>(conditionMatchers.keySet()); |
| 206 | } | 210 | } |
| 207 | 211 | ||
| 208 | - // TODO @puhui999:用不到的方法,可以去掉先哈; | ||
| 209 | - | ||
| 210 | - /** | ||
| 211 | - * 获取指定触发器类型的匹配器 | ||
| 212 | - * | ||
| 213 | - * @param triggerType 触发器类型 | ||
| 214 | - * @return 匹配器实例,如果不存在则返回 null | ||
| 215 | - */ | ||
| 216 | - public IotSceneRuleMatcher getTriggerMatcher(IotSceneRuleTriggerTypeEnum triggerType) { | ||
| 217 | - return triggerMatchers.get(triggerType); | ||
| 218 | - } | ||
| 219 | - | ||
| 220 | - /** | ||
| 221 | - * 获取指定条件类型的匹配器 | ||
| 222 | - * | ||
| 223 | - * @param conditionType 条件类型 | ||
| 224 | - * @return 匹配器实例,如果不存在则返回 null | ||
| 225 | - */ | ||
| 226 | - public IotSceneRuleMatcher getConditionMatcher(IotSceneRuleConditionTypeEnum conditionType) { | ||
| 227 | - return conditionMatchers.get(conditionType); | ||
| 228 | - } | ||
| 229 | - | ||
| 230 | - // TODO @puhui999:是不是不用这个哈;直接 @Getter,单测直接处理; | ||
| 231 | - /** | ||
| 232 | - * 获取所有匹配器的统计信息 | ||
| 233 | - * | ||
| 234 | - * @return 统计信息映射表 | ||
| 235 | - */ | ||
| 236 | - public Map<String, Object> getMatcherStatistics() { | ||
| 237 | - Map<String, Object> statistics = new HashMap<>(); | ||
| 238 | - statistics.put("totalMatchers", allMatchers.size()); | ||
| 239 | - statistics.put("triggerMatchers", triggerMatchers.size()); | ||
| 240 | - statistics.put("conditionMatchers", conditionMatchers.size()); | ||
| 241 | - statistics.put("supportedTriggerTypes", getSupportedTriggerTypes()); | ||
| 242 | - statistics.put("supportedConditionTypes", getSupportedConditionTypes()); | ||
| 243 | - | ||
| 244 | - // 触发器匹配器详情 | ||
| 245 | - Map<String, Object> triggerMatcherDetails = new HashMap<>(); | ||
| 246 | - triggerMatchers.forEach((type, matcher) -> { | ||
| 247 | - Map<String, Object> detail = new HashMap<>(); | ||
| 248 | - detail.put("matcherName", matcher.getMatcherName()); | ||
| 249 | - detail.put("priority", matcher.getPriority()); | ||
| 250 | - detail.put("enabled", matcher.isEnabled()); | ||
| 251 | - triggerMatcherDetails.put(type.name(), detail); | ||
| 252 | - }); | ||
| 253 | - statistics.put("triggerMatcherDetails", triggerMatcherDetails); | ||
| 254 | - | ||
| 255 | - // 条件匹配器详情 | ||
| 256 | - Map<String, Object> conditionMatcherDetails = new HashMap<>(); | ||
| 257 | - conditionMatchers.forEach((type, matcher) -> { | ||
| 258 | - Map<String, Object> detail = new HashMap<>(); | ||
| 259 | - detail.put("matcherName", matcher.getMatcherName()); | ||
| 260 | - detail.put("priority", matcher.getPriority()); | ||
| 261 | - detail.put("enabled", matcher.isEnabled()); | ||
| 262 | - conditionMatcherDetails.put(type.name(), detail); | ||
| 263 | - }); | ||
| 264 | - statistics.put("conditionMatcherDetails", conditionMatcherDetails); | ||
| 265 | - | ||
| 266 | - return statistics; | ||
| 267 | - } | ||
| 268 | - | ||
| 269 | } | 212 | } |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/condition/CurrentTimeConditionMatcher.java
| @@ -4,7 +4,7 @@ import cn.hutool.core.util.StrUtil; | @@ -4,7 +4,7 @@ import cn.hutool.core.util.StrUtil; | ||
| 4 | import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; | 4 | import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; |
| 5 | import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO; | 5 | import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO; |
| 6 | import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleConditionTypeEnum; | 6 | import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleConditionTypeEnum; |
| 7 | -import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.AbstractIotSceneRuleMatcher; | 7 | +import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.IotSceneRuleMatcherHelper; |
| 8 | import lombok.extern.slf4j.Slf4j; | 8 | import lombok.extern.slf4j.Slf4j; |
| 9 | import org.springframework.stereotype.Component; | 9 | import org.springframework.stereotype.Component; |
| 10 | 10 | ||
| @@ -21,7 +21,7 @@ import java.time.format.DateTimeFormatter; | @@ -21,7 +21,7 @@ import java.time.format.DateTimeFormatter; | ||
| 21 | */ | 21 | */ |
| 22 | @Component | 22 | @Component |
| 23 | @Slf4j | 23 | @Slf4j |
| 24 | -public class CurrentTimeConditionMatcher extends AbstractIotSceneRuleMatcher { | 24 | +public class CurrentTimeConditionMatcher implements IotSceneRuleConditionMatcher { |
| 25 | 25 | ||
| 26 | /** | 26 | /** |
| 27 | * 时间格式化器 - HH:mm:ss | 27 | * 时间格式化器 - HH:mm:ss |
| @@ -34,11 +34,6 @@ public class CurrentTimeConditionMatcher extends AbstractIotSceneRuleMatcher { | @@ -34,11 +34,6 @@ public class CurrentTimeConditionMatcher extends AbstractIotSceneRuleMatcher { | ||
| 34 | private static final DateTimeFormatter TIME_FORMATTER_SHORT = DateTimeFormatter.ofPattern("HH:mm"); | 34 | private static final DateTimeFormatter TIME_FORMATTER_SHORT = DateTimeFormatter.ofPattern("HH:mm"); |
| 35 | 35 | ||
| 36 | @Override | 36 | @Override |
| 37 | - public MatcherTypeEnum getMatcherType() { | ||
| 38 | - return MatcherTypeEnum.CONDITION; | ||
| 39 | - } | ||
| 40 | - | ||
| 41 | - @Override | ||
| 42 | public IotSceneRuleConditionTypeEnum getSupportedConditionType() { | 37 | public IotSceneRuleConditionTypeEnum getSupportedConditionType() { |
| 43 | return IotSceneRuleConditionTypeEnum.CURRENT_TIME; | 38 | return IotSceneRuleConditionTypeEnum.CURRENT_TIME; |
| 44 | } | 39 | } |
| @@ -46,14 +41,14 @@ public class CurrentTimeConditionMatcher extends AbstractIotSceneRuleMatcher { | @@ -46,14 +41,14 @@ public class CurrentTimeConditionMatcher extends AbstractIotSceneRuleMatcher { | ||
| 46 | @Override | 41 | @Override |
| 47 | public boolean isMatched(IotDeviceMessage message, IotSceneRuleDO.TriggerCondition condition) { | 42 | public boolean isMatched(IotDeviceMessage message, IotSceneRuleDO.TriggerCondition condition) { |
| 48 | // 1. 基础参数校验 | 43 | // 1. 基础参数校验 |
| 49 | - if (!isBasicConditionValid(condition)) { | ||
| 50 | - logConditionMatchFailure(message, condition, "条件基础参数无效"); | 44 | + if (!IotSceneRuleMatcherHelper.isBasicConditionValid(condition)) { |
| 45 | + IotSceneRuleMatcherHelper.logConditionMatchFailure(getMatcherName(), message, condition, "条件基础参数无效"); | ||
| 51 | return false; | 46 | return false; |
| 52 | } | 47 | } |
| 53 | 48 | ||
| 54 | // 2. 检查操作符和参数是否有效 | 49 | // 2. 检查操作符和参数是否有效 |
| 55 | - if (!isConditionOperatorAndParamValid(condition)) { | ||
| 56 | - logConditionMatchFailure(message, condition, "操作符或参数无效"); | 50 | + if (!IotSceneRuleMatcherHelper.isConditionOperatorAndParamValid(condition)) { |
| 51 | + IotSceneRuleMatcherHelper.logConditionMatchFailure(getMatcherName(), message, condition, "操作符或参数无效"); | ||
| 57 | return false; | 52 | return false; |
| 58 | } | 53 | } |
| 59 | 54 | ||
| @@ -71,17 +66,17 @@ public class CurrentTimeConditionMatcher extends AbstractIotSceneRuleMatcher { | @@ -71,17 +66,17 @@ public class CurrentTimeConditionMatcher extends AbstractIotSceneRuleMatcher { | ||
| 71 | matched = matchTime(now.toLocalTime(), operator, param); | 66 | matched = matchTime(now.toLocalTime(), operator, param); |
| 72 | } else { | 67 | } else { |
| 73 | // 其他操作符,使用通用条件评估器 | 68 | // 其他操作符,使用通用条件评估器 |
| 74 | - matched = evaluateCondition(now.toEpochSecond(java.time.ZoneOffset.of("+8")), operator, param); | 69 | + matched = IotSceneRuleMatcherHelper.evaluateCondition(now.toEpochSecond(java.time.ZoneOffset.of("+8")), operator, param); |
| 75 | } | 70 | } |
| 76 | 71 | ||
| 77 | if (matched) { | 72 | if (matched) { |
| 78 | - logConditionMatchSuccess(message, condition); | 73 | + IotSceneRuleMatcherHelper.logConditionMatchSuccess(getMatcherName(), message, condition); |
| 79 | } else { | 74 | } else { |
| 80 | - logConditionMatchFailure(message, condition, "时间条件不匹配"); | 75 | + IotSceneRuleMatcherHelper.logConditionMatchFailure(getMatcherName(), message, condition, "时间条件不匹配"); |
| 81 | } | 76 | } |
| 82 | } catch (Exception e) { | 77 | } catch (Exception e) { |
| 83 | log.error("[CurrentTimeConditionMatcher][时间条件匹配异常] operator: {}, param: {}", operator, param, e); | 78 | log.error("[CurrentTimeConditionMatcher][时间条件匹配异常] operator: {}, param: {}", operator, param, e); |
| 84 | - logConditionMatchFailure(message, condition, "时间条件匹配异常: " + e.getMessage()); | 79 | + IotSceneRuleMatcherHelper.logConditionMatchFailure(getMatcherName(), message, condition, "时间条件匹配异常: " + e.getMessage()); |
| 85 | matched = false; | 80 | matched = false; |
| 86 | } | 81 | } |
| 87 | return matched; | 82 | return matched; |
| @@ -92,7 +87,7 @@ public class CurrentTimeConditionMatcher extends AbstractIotSceneRuleMatcher { | @@ -92,7 +87,7 @@ public class CurrentTimeConditionMatcher extends AbstractIotSceneRuleMatcher { | ||
| 92 | */ | 87 | */ |
| 93 | private boolean matchDateTime(LocalDateTime now, String operator, String param) { | 88 | private boolean matchDateTime(LocalDateTime now, String operator, String param) { |
| 94 | long currentTimestamp = now.toEpochSecond(java.time.ZoneOffset.of("+8")); | 89 | long currentTimestamp = now.toEpochSecond(java.time.ZoneOffset.of("+8")); |
| 95 | - return evaluateCondition(currentTimestamp, operator.substring("date_time_".length()), param); | 90 | + return IotSceneRuleMatcherHelper.evaluateCondition(currentTimestamp, operator.substring("date_time_".length()), param); |
| 96 | } | 91 | } |
| 97 | 92 | ||
| 98 | /** | 93 | /** |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/condition/DevicePropertyConditionMatcher.java
| @@ -4,7 +4,7 @@ import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; | @@ -4,7 +4,7 @@ import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; | ||
| 4 | import cn.iocoder.yudao.module.iot.core.util.IotDeviceMessageUtils; | 4 | import cn.iocoder.yudao.module.iot.core.util.IotDeviceMessageUtils; |
| 5 | import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO; | 5 | import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO; |
| 6 | import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleConditionTypeEnum; | 6 | import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleConditionTypeEnum; |
| 7 | -import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.AbstractIotSceneRuleMatcher; | 7 | +import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.IotSceneRuleMatcherHelper; |
| 8 | import org.springframework.stereotype.Component; | 8 | import org.springframework.stereotype.Component; |
| 9 | 9 | ||
| 10 | /** | 10 | /** |
| @@ -15,12 +15,7 @@ import org.springframework.stereotype.Component; | @@ -15,12 +15,7 @@ import org.springframework.stereotype.Component; | ||
| 15 | * @author HUIHUI | 15 | * @author HUIHUI |
| 16 | */ | 16 | */ |
| 17 | @Component | 17 | @Component |
| 18 | -public class DevicePropertyConditionMatcher extends AbstractIotSceneRuleMatcher { | ||
| 19 | - | ||
| 20 | - @Override | ||
| 21 | - public MatcherTypeEnum getMatcherType() { | ||
| 22 | - return MatcherTypeEnum.CONDITION; | ||
| 23 | - } | 18 | +public class DevicePropertyConditionMatcher implements IotSceneRuleConditionMatcher { |
| 24 | 19 | ||
| 25 | @Override | 20 | @Override |
| 26 | public IotSceneRuleConditionTypeEnum getSupportedConditionType() { | 21 | public IotSceneRuleConditionTypeEnum getSupportedConditionType() { |
| @@ -31,37 +26,37 @@ public class DevicePropertyConditionMatcher extends AbstractIotSceneRuleMatcher | @@ -31,37 +26,37 @@ public class DevicePropertyConditionMatcher extends AbstractIotSceneRuleMatcher | ||
| 31 | @Override | 26 | @Override |
| 32 | public boolean isMatched(IotDeviceMessage message, IotSceneRuleDO.TriggerCondition condition) { | 27 | public boolean isMatched(IotDeviceMessage message, IotSceneRuleDO.TriggerCondition condition) { |
| 33 | // 1. 基础参数校验 | 28 | // 1. 基础参数校验 |
| 34 | - if (!isBasicConditionValid(condition)) { | ||
| 35 | - logConditionMatchFailure(message, condition, "条件基础参数无效"); | 29 | + if (!IotSceneRuleMatcherHelper.isBasicConditionValid(condition)) { |
| 30 | + IotSceneRuleMatcherHelper.logConditionMatchFailure(getMatcherName(), message, condition, "条件基础参数无效"); | ||
| 36 | return false; | 31 | return false; |
| 37 | } | 32 | } |
| 38 | 33 | ||
| 39 | // 2. 检查标识符是否匹配 | 34 | // 2. 检查标识符是否匹配 |
| 40 | String messageIdentifier = IotDeviceMessageUtils.getIdentifier(message); | 35 | String messageIdentifier = IotDeviceMessageUtils.getIdentifier(message); |
| 41 | - if (!isIdentifierMatched(condition.getIdentifier(), messageIdentifier)) { | ||
| 42 | - logConditionMatchFailure(message, condition, "标识符不匹配,期望: " + condition.getIdentifier() + ", 实际: " + messageIdentifier); | 36 | + if (!IotSceneRuleMatcherHelper.isIdentifierMatched(condition.getIdentifier(), messageIdentifier)) { |
| 37 | + IotSceneRuleMatcherHelper.logConditionMatchFailure(getMatcherName(), message, condition, "标识符不匹配,期望: " + condition.getIdentifier() + ", 实际: " + messageIdentifier); | ||
| 43 | return false; | 38 | return false; |
| 44 | } | 39 | } |
| 45 | 40 | ||
| 46 | // 3. 检查操作符和参数是否有效 | 41 | // 3. 检查操作符和参数是否有效 |
| 47 | - if (!isConditionOperatorAndParamValid(condition)) { | ||
| 48 | - logConditionMatchFailure(message, condition, "操作符或参数无效"); | 42 | + if (!IotSceneRuleMatcherHelper.isConditionOperatorAndParamValid(condition)) { |
| 43 | + IotSceneRuleMatcherHelper.logConditionMatchFailure(getMatcherName(), message, condition, "操作符或参数无效"); | ||
| 49 | return false; | 44 | return false; |
| 50 | } | 45 | } |
| 51 | 46 | ||
| 52 | // 4. 获取属性值 | 47 | // 4. 获取属性值 |
| 53 | Object propertyValue = message.getData(); | 48 | Object propertyValue = message.getData(); |
| 54 | if (propertyValue == null) { | 49 | if (propertyValue == null) { |
| 55 | - logConditionMatchFailure(message, condition, "消息中属性值为空"); | 50 | + IotSceneRuleMatcherHelper.logConditionMatchFailure(getMatcherName(), message, condition, "消息中属性值为空"); |
| 56 | return false; | 51 | return false; |
| 57 | } | 52 | } |
| 58 | 53 | ||
| 59 | // 5. 使用条件评估器进行匹配 | 54 | // 5. 使用条件评估器进行匹配 |
| 60 | - boolean matched = evaluateCondition(propertyValue, condition.getOperator(), condition.getParam()); | 55 | + boolean matched = IotSceneRuleMatcherHelper.evaluateCondition(propertyValue, condition.getOperator(), condition.getParam()); |
| 61 | if (matched) { | 56 | if (matched) { |
| 62 | - logConditionMatchSuccess(message, condition); | 57 | + IotSceneRuleMatcherHelper.logConditionMatchSuccess(getMatcherName(), message, condition); |
| 63 | } else { | 58 | } else { |
| 64 | - logConditionMatchFailure(message, condition, "设备属性条件不匹配"); | 59 | + IotSceneRuleMatcherHelper.logConditionMatchFailure(getMatcherName(), message, condition, "设备属性条件不匹配"); |
| 65 | } | 60 | } |
| 66 | return matched; | 61 | return matched; |
| 67 | } | 62 | } |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/condition/DeviceStateConditionMatcher.java
| @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.iot.service.rule.scene.matcher.condition; | @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.iot.service.rule.scene.matcher.condition; | ||
| 3 | import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; | 3 | import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; |
| 4 | import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO; | 4 | import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO; |
| 5 | import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleConditionTypeEnum; | 5 | import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleConditionTypeEnum; |
| 6 | -import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.AbstractIotSceneRuleMatcher; | 6 | +import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.IotSceneRuleMatcherHelper; |
| 7 | import org.springframework.stereotype.Component; | 7 | import org.springframework.stereotype.Component; |
| 8 | 8 | ||
| 9 | /** | 9 | /** |
| @@ -14,12 +14,7 @@ import org.springframework.stereotype.Component; | @@ -14,12 +14,7 @@ import org.springframework.stereotype.Component; | ||
| 14 | * @author HUIHUI | 14 | * @author HUIHUI |
| 15 | */ | 15 | */ |
| 16 | @Component | 16 | @Component |
| 17 | -public class DeviceStateConditionMatcher extends AbstractIotSceneRuleMatcher { | ||
| 18 | - | ||
| 19 | - @Override | ||
| 20 | - public MatcherTypeEnum getMatcherType() { | ||
| 21 | - return MatcherTypeEnum.CONDITION; | ||
| 22 | - } | 17 | +public class DeviceStateConditionMatcher implements IotSceneRuleConditionMatcher { |
| 23 | 18 | ||
| 24 | @Override | 19 | @Override |
| 25 | public IotSceneRuleConditionTypeEnum getSupportedConditionType() { | 20 | public IotSceneRuleConditionTypeEnum getSupportedConditionType() { |
| @@ -29,14 +24,14 @@ public class DeviceStateConditionMatcher extends AbstractIotSceneRuleMatcher { | @@ -29,14 +24,14 @@ public class DeviceStateConditionMatcher extends AbstractIotSceneRuleMatcher { | ||
| 29 | @Override | 24 | @Override |
| 30 | public boolean isMatched(IotDeviceMessage message, IotSceneRuleDO.TriggerCondition condition) { | 25 | public boolean isMatched(IotDeviceMessage message, IotSceneRuleDO.TriggerCondition condition) { |
| 31 | // 1. 基础参数校验 | 26 | // 1. 基础参数校验 |
| 32 | - if (!isBasicConditionValid(condition)) { | ||
| 33 | - logConditionMatchFailure(message, condition, "条件基础参数无效"); | 27 | + if (!IotSceneRuleMatcherHelper.isBasicConditionValid(condition)) { |
| 28 | + IotSceneRuleMatcherHelper.logConditionMatchFailure(getMatcherName(), message, condition, "条件基础参数无效"); | ||
| 34 | return false; | 29 | return false; |
| 35 | } | 30 | } |
| 36 | 31 | ||
| 37 | // 2. 检查操作符和参数是否有效 | 32 | // 2. 检查操作符和参数是否有效 |
| 38 | - if (!isConditionOperatorAndParamValid(condition)) { | ||
| 39 | - logConditionMatchFailure(message, condition, "操作符或参数无效"); | 33 | + if (!IotSceneRuleMatcherHelper.isConditionOperatorAndParamValid(condition)) { |
| 34 | + IotSceneRuleMatcherHelper.logConditionMatchFailure(getMatcherName(), message, condition, "操作符或参数无效"); | ||
| 40 | return false; | 35 | return false; |
| 41 | } | 36 | } |
| 42 | 37 | ||
| @@ -44,16 +39,16 @@ public class DeviceStateConditionMatcher extends AbstractIotSceneRuleMatcher { | @@ -44,16 +39,16 @@ public class DeviceStateConditionMatcher extends AbstractIotSceneRuleMatcher { | ||
| 44 | // 设备状态通常在消息的 data 字段中 | 39 | // 设备状态通常在消息的 data 字段中 |
| 45 | Object stateValue = message.getData(); | 40 | Object stateValue = message.getData(); |
| 46 | if (stateValue == null) { | 41 | if (stateValue == null) { |
| 47 | - logConditionMatchFailure(message, condition, "消息中设备状态值为空"); | 42 | + IotSceneRuleMatcherHelper.logConditionMatchFailure(getMatcherName(), message, condition, "消息中设备状态值为空"); |
| 48 | return false; | 43 | return false; |
| 49 | } | 44 | } |
| 50 | 45 | ||
| 51 | // 4. 使用条件评估器进行匹配 | 46 | // 4. 使用条件评估器进行匹配 |
| 52 | - boolean matched = evaluateCondition(stateValue, condition.getOperator(), condition.getParam()); | 47 | + boolean matched = IotSceneRuleMatcherHelper.evaluateCondition(stateValue, condition.getOperator(), condition.getParam()); |
| 53 | if (matched) { | 48 | if (matched) { |
| 54 | - logConditionMatchSuccess(message, condition); | 49 | + IotSceneRuleMatcherHelper.logConditionMatchSuccess(getMatcherName(), message, condition); |
| 55 | } else { | 50 | } else { |
| 56 | - logConditionMatchFailure(message, condition, "设备状态条件不匹配"); | 51 | + IotSceneRuleMatcherHelper.logConditionMatchFailure(getMatcherName(), message, condition, "设备状态条件不匹配"); |
| 57 | } | 52 | } |
| 58 | return matched; | 53 | return matched; |
| 59 | } | 54 | } |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/condition/IotSceneRuleConditionMatcher.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.iot.service.rule.scene.matcher.condition; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; | ||
| 4 | +import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO; | ||
| 5 | +import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleConditionTypeEnum; | ||
| 6 | +import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.IotSceneRuleMatcher; | ||
| 7 | + | ||
| 8 | +/** | ||
| 9 | + * IoT 场景规则条件匹配器接口 | ||
| 10 | + * <p> | ||
| 11 | + * 专门处理子条件的匹配逻辑,如设备状态、属性值、时间条件等 | ||
| 12 | + * <p> | ||
| 13 | + * 条件匹配器负责判断设备消息是否满足场景规则的附加条件, | ||
| 14 | + * 在触发器匹配成功后进行进一步的条件筛选 | ||
| 15 | + * | ||
| 16 | + * @author HUIHUI | ||
| 17 | + */ | ||
| 18 | +public interface IotSceneRuleConditionMatcher extends IotSceneRuleMatcher { | ||
| 19 | + | ||
| 20 | + /** | ||
| 21 | + * 获取支持的条件类型 | ||
| 22 | + * | ||
| 23 | + * @return 条件类型枚举 | ||
| 24 | + */ | ||
| 25 | + IotSceneRuleConditionTypeEnum getSupportedConditionType(); | ||
| 26 | + | ||
| 27 | + /** | ||
| 28 | + * 检查条件是否匹配消息 | ||
| 29 | + * <p> | ||
| 30 | + * 判断设备消息是否满足指定的触发条件 | ||
| 31 | + * | ||
| 32 | + * @param message 设备消息 | ||
| 33 | + * @param condition 触发条件 | ||
| 34 | + * @return 是否匹配 | ||
| 35 | + */ | ||
| 36 | + boolean isMatched(IotDeviceMessage message, IotSceneRuleDO.TriggerCondition condition); | ||
| 37 | + | ||
| 38 | +} |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/trigger/DeviceEventPostTriggerMatcher.java
| @@ -6,7 +6,7 @@ import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; | @@ -6,7 +6,7 @@ import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; | ||
| 6 | import cn.iocoder.yudao.module.iot.core.util.IotDeviceMessageUtils; | 6 | import cn.iocoder.yudao.module.iot.core.util.IotDeviceMessageUtils; |
| 7 | import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO; | 7 | import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO; |
| 8 | import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum; | 8 | import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum; |
| 9 | -import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.AbstractIotSceneRuleMatcher; | 9 | +import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.IotSceneRuleMatcherHelper; |
| 10 | import org.springframework.stereotype.Component; | 10 | import org.springframework.stereotype.Component; |
| 11 | 11 | ||
| 12 | /** | 12 | /** |
| @@ -17,7 +17,7 @@ import org.springframework.stereotype.Component; | @@ -17,7 +17,7 @@ import org.springframework.stereotype.Component; | ||
| 17 | * @author HUIHUI | 17 | * @author HUIHUI |
| 18 | */ | 18 | */ |
| 19 | @Component | 19 | @Component |
| 20 | -public class DeviceEventPostTriggerMatcher extends AbstractIotSceneRuleMatcher { | 20 | +public class DeviceEventPostTriggerMatcher implements IotSceneRuleTriggerMatcher { |
| 21 | 21 | ||
| 22 | /** | 22 | /** |
| 23 | * 设备事件上报消息方法 | 23 | * 设备事件上报消息方法 |
| @@ -25,11 +25,6 @@ public class DeviceEventPostTriggerMatcher extends AbstractIotSceneRuleMatcher { | @@ -25,11 +25,6 @@ public class DeviceEventPostTriggerMatcher extends AbstractIotSceneRuleMatcher { | ||
| 25 | private static final String DEVICE_EVENT_POST_METHOD = IotDeviceMessageMethodEnum.EVENT_POST.getMethod(); | 25 | private static final String DEVICE_EVENT_POST_METHOD = IotDeviceMessageMethodEnum.EVENT_POST.getMethod(); |
| 26 | 26 | ||
| 27 | @Override | 27 | @Override |
| 28 | - public MatcherTypeEnum getMatcherType() { | ||
| 29 | - return MatcherTypeEnum.TRIGGER; | ||
| 30 | - } | ||
| 31 | - | ||
| 32 | - @Override | ||
| 33 | public IotSceneRuleTriggerTypeEnum getSupportedTriggerType() { | 28 | public IotSceneRuleTriggerTypeEnum getSupportedTriggerType() { |
| 34 | return IotSceneRuleTriggerTypeEnum.DEVICE_EVENT_POST; | 29 | return IotSceneRuleTriggerTypeEnum.DEVICE_EVENT_POST; |
| 35 | } | 30 | } |
| @@ -37,21 +32,21 @@ public class DeviceEventPostTriggerMatcher extends AbstractIotSceneRuleMatcher { | @@ -37,21 +32,21 @@ public class DeviceEventPostTriggerMatcher extends AbstractIotSceneRuleMatcher { | ||
| 37 | @Override | 32 | @Override |
| 38 | public boolean isMatched(IotDeviceMessage message, IotSceneRuleDO.Trigger trigger) { | 33 | public boolean isMatched(IotDeviceMessage message, IotSceneRuleDO.Trigger trigger) { |
| 39 | // 1. 基础参数校验 | 34 | // 1. 基础参数校验 |
| 40 | - if (!isBasicTriggerValid(trigger)) { | ||
| 41 | - logTriggerMatchFailure(message, trigger, "触发器基础参数无效"); | 35 | + if (!IotSceneRuleMatcherHelper.isBasicTriggerValid(trigger)) { |
| 36 | + IotSceneRuleMatcherHelper.logTriggerMatchFailure(getMatcherName(), message, trigger, "触发器基础参数无效"); | ||
| 42 | return false; | 37 | return false; |
| 43 | } | 38 | } |
| 44 | 39 | ||
| 45 | // 2. 检查消息方法是否匹配 | 40 | // 2. 检查消息方法是否匹配 |
| 46 | if (!DEVICE_EVENT_POST_METHOD.equals(message.getMethod())) { | 41 | if (!DEVICE_EVENT_POST_METHOD.equals(message.getMethod())) { |
| 47 | - logTriggerMatchFailure(message, trigger, "消息方法不匹配,期望: " + DEVICE_EVENT_POST_METHOD + ", 实际: " + message.getMethod()); | 42 | + IotSceneRuleMatcherHelper.logTriggerMatchFailure(getMatcherName(), message, trigger, "消息方法不匹配,期望: " + DEVICE_EVENT_POST_METHOD + ", 实际: " + message.getMethod()); |
| 48 | return false; | 43 | return false; |
| 49 | } | 44 | } |
| 50 | 45 | ||
| 51 | // 3. 检查标识符是否匹配 | 46 | // 3. 检查标识符是否匹配 |
| 52 | String messageIdentifier = IotDeviceMessageUtils.getIdentifier(message); | 47 | String messageIdentifier = IotDeviceMessageUtils.getIdentifier(message); |
| 53 | - if (!isIdentifierMatched(trigger.getIdentifier(), messageIdentifier)) { | ||
| 54 | - logTriggerMatchFailure(message, trigger, "标识符不匹配,期望: " + trigger.getIdentifier() + ", 实际: " + messageIdentifier); | 48 | + if (!IotSceneRuleMatcherHelper.isIdentifierMatched(trigger.getIdentifier(), messageIdentifier)) { |
| 49 | + IotSceneRuleMatcherHelper.logTriggerMatchFailure(getMatcherName(), message, trigger, "标识符不匹配,期望: " + trigger.getIdentifier() + ", 实际: " + messageIdentifier); | ||
| 55 | return false; | 50 | return false; |
| 56 | } | 51 | } |
| 57 | 52 | ||
| @@ -60,18 +55,18 @@ public class DeviceEventPostTriggerMatcher extends AbstractIotSceneRuleMatcher { | @@ -60,18 +55,18 @@ public class DeviceEventPostTriggerMatcher extends AbstractIotSceneRuleMatcher { | ||
| 60 | if (StrUtil.isNotBlank(trigger.getOperator()) && StrUtil.isNotBlank(trigger.getValue())) { | 55 | if (StrUtil.isNotBlank(trigger.getOperator()) && StrUtil.isNotBlank(trigger.getValue())) { |
| 61 | Object eventData = message.getData(); | 56 | Object eventData = message.getData(); |
| 62 | if (eventData == null) { | 57 | if (eventData == null) { |
| 63 | - logTriggerMatchFailure(message, trigger, "消息中事件数据为空"); | 58 | + IotSceneRuleMatcherHelper.logTriggerMatchFailure(getMatcherName(), message, trigger, "消息中事件数据为空"); |
| 64 | return false; | 59 | return false; |
| 65 | } | 60 | } |
| 66 | 61 | ||
| 67 | - boolean matched = evaluateCondition(eventData, trigger.getOperator(), trigger.getValue()); | 62 | + boolean matched = IotSceneRuleMatcherHelper.evaluateCondition(eventData, trigger.getOperator(), trigger.getValue()); |
| 68 | if (!matched) { | 63 | if (!matched) { |
| 69 | - logTriggerMatchFailure(message, trigger, "事件数据条件不匹配"); | 64 | + IotSceneRuleMatcherHelper.logTriggerMatchFailure(getMatcherName(), message, trigger, "事件数据条件不匹配"); |
| 70 | return false; | 65 | return false; |
| 71 | } | 66 | } |
| 72 | } | 67 | } |
| 73 | 68 | ||
| 74 | - logTriggerMatchSuccess(message, trigger); | 69 | + IotSceneRuleMatcherHelper.logTriggerMatchSuccess(getMatcherName(), message, trigger); |
| 75 | return true; | 70 | return true; |
| 76 | } | 71 | } |
| 77 | 72 |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/trigger/DevicePropertyPostTriggerMatcher.java
| @@ -5,7 +5,7 @@ import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; | @@ -5,7 +5,7 @@ import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; | ||
| 5 | import cn.iocoder.yudao.module.iot.core.util.IotDeviceMessageUtils; | 5 | import cn.iocoder.yudao.module.iot.core.util.IotDeviceMessageUtils; |
| 6 | import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO; | 6 | import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO; |
| 7 | import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum; | 7 | import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum; |
| 8 | -import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.AbstractIotSceneRuleMatcher; | 8 | +import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.IotSceneRuleMatcherHelper; |
| 9 | import org.springframework.stereotype.Component; | 9 | import org.springframework.stereotype.Component; |
| 10 | 10 | ||
| 11 | /** | 11 | /** |
| @@ -16,7 +16,7 @@ import org.springframework.stereotype.Component; | @@ -16,7 +16,7 @@ import org.springframework.stereotype.Component; | ||
| 16 | * @author HUIHUI | 16 | * @author HUIHUI |
| 17 | */ | 17 | */ |
| 18 | @Component | 18 | @Component |
| 19 | -public class DevicePropertyPostTriggerMatcher extends AbstractIotSceneRuleMatcher { | 19 | +public class DevicePropertyPostTriggerMatcher implements IotSceneRuleTriggerMatcher { |
| 20 | 20 | ||
| 21 | /** | 21 | /** |
| 22 | * 设备属性上报消息方法 | 22 | * 设备属性上报消息方法 |
| @@ -25,11 +25,6 @@ public class DevicePropertyPostTriggerMatcher extends AbstractIotSceneRuleMatche | @@ -25,11 +25,6 @@ public class DevicePropertyPostTriggerMatcher extends AbstractIotSceneRuleMatche | ||
| 25 | private static final String DEVICE_PROPERTY_POST_METHOD = IotDeviceMessageMethodEnum.PROPERTY_POST.getMethod(); | 25 | private static final String DEVICE_PROPERTY_POST_METHOD = IotDeviceMessageMethodEnum.PROPERTY_POST.getMethod(); |
| 26 | 26 | ||
| 27 | @Override | 27 | @Override |
| 28 | - public MatcherTypeEnum getMatcherType() { | ||
| 29 | - return MatcherTypeEnum.TRIGGER; | ||
| 30 | - } | ||
| 31 | - | ||
| 32 | - @Override | ||
| 33 | public IotSceneRuleTriggerTypeEnum getSupportedTriggerType() { | 28 | public IotSceneRuleTriggerTypeEnum getSupportedTriggerType() { |
| 34 | return IotSceneRuleTriggerTypeEnum.DEVICE_PROPERTY_POST; | 29 | return IotSceneRuleTriggerTypeEnum.DEVICE_PROPERTY_POST; |
| 35 | } | 30 | } |
| @@ -37,43 +32,43 @@ public class DevicePropertyPostTriggerMatcher extends AbstractIotSceneRuleMatche | @@ -37,43 +32,43 @@ public class DevicePropertyPostTriggerMatcher extends AbstractIotSceneRuleMatche | ||
| 37 | @Override | 32 | @Override |
| 38 | public boolean isMatched(IotDeviceMessage message, IotSceneRuleDO.Trigger trigger) { | 33 | public boolean isMatched(IotDeviceMessage message, IotSceneRuleDO.Trigger trigger) { |
| 39 | // 1. 基础参数校验 | 34 | // 1. 基础参数校验 |
| 40 | - if (!isBasicTriggerValid(trigger)) { | ||
| 41 | - logTriggerMatchFailure(message, trigger, "触发器基础参数无效"); | 35 | + if (!IotSceneRuleMatcherHelper.isBasicTriggerValid(trigger)) { |
| 36 | + IotSceneRuleMatcherHelper.logTriggerMatchFailure(getMatcherName(), message, trigger, "触发器基础参数无效"); | ||
| 42 | return false; | 37 | return false; |
| 43 | } | 38 | } |
| 44 | 39 | ||
| 45 | // 2. 检查消息方法是否匹配 | 40 | // 2. 检查消息方法是否匹配 |
| 46 | if (!DEVICE_PROPERTY_POST_METHOD.equals(message.getMethod())) { | 41 | if (!DEVICE_PROPERTY_POST_METHOD.equals(message.getMethod())) { |
| 47 | - logTriggerMatchFailure(message, trigger, "消息方法不匹配,期望: " + DEVICE_PROPERTY_POST_METHOD + ", 实际: " + message.getMethod()); | 42 | + IotSceneRuleMatcherHelper.logTriggerMatchFailure(getMatcherName(), message, trigger, "消息方法不匹配,期望: " + DEVICE_PROPERTY_POST_METHOD + ", 实际: " + message.getMethod()); |
| 48 | return false; | 43 | return false; |
| 49 | } | 44 | } |
| 50 | 45 | ||
| 51 | // 3. 检查标识符是否匹配 | 46 | // 3. 检查标识符是否匹配 |
| 52 | String messageIdentifier = IotDeviceMessageUtils.getIdentifier(message); | 47 | String messageIdentifier = IotDeviceMessageUtils.getIdentifier(message); |
| 53 | - if (!isIdentifierMatched(trigger.getIdentifier(), messageIdentifier)) { | ||
| 54 | - logTriggerMatchFailure(message, trigger, "标识符不匹配,期望: " + trigger.getIdentifier() + ", 实际: " + messageIdentifier); | 48 | + if (!IotSceneRuleMatcherHelper.isIdentifierMatched(trigger.getIdentifier(), messageIdentifier)) { |
| 49 | + IotSceneRuleMatcherHelper.logTriggerMatchFailure(getMatcherName(), message, trigger, "标识符不匹配,期望: " + trigger.getIdentifier() + ", 实际: " + messageIdentifier); | ||
| 55 | return false; | 50 | return false; |
| 56 | } | 51 | } |
| 57 | 52 | ||
| 58 | // 4. 检查操作符和值是否有效 | 53 | // 4. 检查操作符和值是否有效 |
| 59 | - if (!isTriggerOperatorAndValueValid(trigger)) { | ||
| 60 | - logTriggerMatchFailure(message, trigger, "操作符或值无效"); | 54 | + if (!IotSceneRuleMatcherHelper.isTriggerOperatorAndValueValid(trigger)) { |
| 55 | + IotSceneRuleMatcherHelper.logTriggerMatchFailure(getMatcherName(), message, trigger, "操作符或值无效"); | ||
| 61 | return false; | 56 | return false; |
| 62 | } | 57 | } |
| 63 | 58 | ||
| 64 | // 5. 获取属性值 | 59 | // 5. 获取属性值 |
| 65 | Object propertyValue = message.getData(); | 60 | Object propertyValue = message.getData(); |
| 66 | if (propertyValue == null) { | 61 | if (propertyValue == null) { |
| 67 | - logTriggerMatchFailure(message, trigger, "消息中属性值为空"); | 62 | + IotSceneRuleMatcherHelper.logTriggerMatchFailure(getMatcherName(), message, trigger, "消息中属性值为空"); |
| 68 | return false; | 63 | return false; |
| 69 | } | 64 | } |
| 70 | 65 | ||
| 71 | // 6. 使用条件评估器进行匹配 | 66 | // 6. 使用条件评估器进行匹配 |
| 72 | - boolean matched = evaluateCondition(propertyValue, trigger.getOperator(), trigger.getValue()); | 67 | + boolean matched = IotSceneRuleMatcherHelper.evaluateCondition(propertyValue, trigger.getOperator(), trigger.getValue()); |
| 73 | if (matched) { | 68 | if (matched) { |
| 74 | - logTriggerMatchSuccess(message, trigger); | 69 | + IotSceneRuleMatcherHelper.logTriggerMatchSuccess(getMatcherName(), message, trigger); |
| 75 | } else { | 70 | } else { |
| 76 | - logTriggerMatchFailure(message, trigger, "属性值条件不匹配"); | 71 | + IotSceneRuleMatcherHelper.logTriggerMatchFailure(getMatcherName(), message, trigger, "属性值条件不匹配"); |
| 77 | } | 72 | } |
| 78 | return matched; | 73 | return matched; |
| 79 | } | 74 | } |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/trigger/DeviceServiceInvokeTriggerMatcher.java
| @@ -5,7 +5,7 @@ import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; | @@ -5,7 +5,7 @@ import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; | ||
| 5 | import cn.iocoder.yudao.module.iot.core.util.IotDeviceMessageUtils; | 5 | import cn.iocoder.yudao.module.iot.core.util.IotDeviceMessageUtils; |
| 6 | import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO; | 6 | import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO; |
| 7 | import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum; | 7 | import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum; |
| 8 | -import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.AbstractIotSceneRuleMatcher; | 8 | +import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.IotSceneRuleMatcherHelper; |
| 9 | import org.springframework.stereotype.Component; | 9 | import org.springframework.stereotype.Component; |
| 10 | 10 | ||
| 11 | /** | 11 | /** |
| @@ -16,7 +16,7 @@ import org.springframework.stereotype.Component; | @@ -16,7 +16,7 @@ import org.springframework.stereotype.Component; | ||
| 16 | * @author HUIHUI | 16 | * @author HUIHUI |
| 17 | */ | 17 | */ |
| 18 | @Component | 18 | @Component |
| 19 | -public class DeviceServiceInvokeTriggerMatcher extends AbstractIotSceneRuleMatcher { | 19 | +public class DeviceServiceInvokeTriggerMatcher implements IotSceneRuleTriggerMatcher { |
| 20 | 20 | ||
| 21 | /** | 21 | /** |
| 22 | * 设备服务调用消息方法 | 22 | * 设备服务调用消息方法 |
| @@ -24,11 +24,6 @@ public class DeviceServiceInvokeTriggerMatcher extends AbstractIotSceneRuleMatch | @@ -24,11 +24,6 @@ public class DeviceServiceInvokeTriggerMatcher extends AbstractIotSceneRuleMatch | ||
| 24 | private static final String DEVICE_SERVICE_INVOKE_METHOD = IotDeviceMessageMethodEnum.SERVICE_INVOKE.getMethod(); | 24 | private static final String DEVICE_SERVICE_INVOKE_METHOD = IotDeviceMessageMethodEnum.SERVICE_INVOKE.getMethod(); |
| 25 | 25 | ||
| 26 | @Override | 26 | @Override |
| 27 | - public MatcherTypeEnum getMatcherType() { | ||
| 28 | - return MatcherTypeEnum.TRIGGER; | ||
| 29 | - } | ||
| 30 | - | ||
| 31 | - @Override | ||
| 32 | public IotSceneRuleTriggerTypeEnum getSupportedTriggerType() { | 27 | public IotSceneRuleTriggerTypeEnum getSupportedTriggerType() { |
| 33 | return IotSceneRuleTriggerTypeEnum.DEVICE_SERVICE_INVOKE; | 28 | return IotSceneRuleTriggerTypeEnum.DEVICE_SERVICE_INVOKE; |
| 34 | } | 29 | } |
| @@ -36,28 +31,28 @@ public class DeviceServiceInvokeTriggerMatcher extends AbstractIotSceneRuleMatch | @@ -36,28 +31,28 @@ public class DeviceServiceInvokeTriggerMatcher extends AbstractIotSceneRuleMatch | ||
| 36 | @Override | 31 | @Override |
| 37 | public boolean isMatched(IotDeviceMessage message, IotSceneRuleDO.Trigger trigger) { | 32 | public boolean isMatched(IotDeviceMessage message, IotSceneRuleDO.Trigger trigger) { |
| 38 | // 1. 基础参数校验 | 33 | // 1. 基础参数校验 |
| 39 | - if (!isBasicTriggerValid(trigger)) { | ||
| 40 | - logTriggerMatchFailure(message, trigger, "触发器基础参数无效"); | 34 | + if (!IotSceneRuleMatcherHelper.isBasicTriggerValid(trigger)) { |
| 35 | + IotSceneRuleMatcherHelper.logTriggerMatchFailure(getMatcherName(), message, trigger, "触发器基础参数无效"); | ||
| 41 | return false; | 36 | return false; |
| 42 | } | 37 | } |
| 43 | 38 | ||
| 44 | // 2. 检查消息方法是否匹配 | 39 | // 2. 检查消息方法是否匹配 |
| 45 | if (!DEVICE_SERVICE_INVOKE_METHOD.equals(message.getMethod())) { | 40 | if (!DEVICE_SERVICE_INVOKE_METHOD.equals(message.getMethod())) { |
| 46 | - logTriggerMatchFailure(message, trigger, "消息方法不匹配,期望: " + DEVICE_SERVICE_INVOKE_METHOD + ", 实际: " + message.getMethod()); | 41 | + IotSceneRuleMatcherHelper.logTriggerMatchFailure(getMatcherName(), message, trigger, "消息方法不匹配,期望: " + DEVICE_SERVICE_INVOKE_METHOD + ", 实际: " + message.getMethod()); |
| 47 | return false; | 42 | return false; |
| 48 | } | 43 | } |
| 49 | 44 | ||
| 50 | // 3. 检查标识符是否匹配 | 45 | // 3. 检查标识符是否匹配 |
| 51 | String messageIdentifier = IotDeviceMessageUtils.getIdentifier(message); | 46 | String messageIdentifier = IotDeviceMessageUtils.getIdentifier(message); |
| 52 | - if (!isIdentifierMatched(trigger.getIdentifier(), messageIdentifier)) { | ||
| 53 | - logTriggerMatchFailure(message, trigger, "标识符不匹配,期望: " + trigger.getIdentifier() + ", 实际: " + messageIdentifier); | 47 | + if (!IotSceneRuleMatcherHelper.isIdentifierMatched(trigger.getIdentifier(), messageIdentifier)) { |
| 48 | + IotSceneRuleMatcherHelper.logTriggerMatchFailure(getMatcherName(), message, trigger, "标识符不匹配,期望: " + trigger.getIdentifier() + ", 实际: " + messageIdentifier); | ||
| 54 | return false; | 49 | return false; |
| 55 | } | 50 | } |
| 56 | 51 | ||
| 57 | // 4. 对于服务调用触发器,通常只需要匹配服务标识符即可 | 52 | // 4. 对于服务调用触发器,通常只需要匹配服务标识符即可 |
| 58 | // 不需要检查操作符和值,因为服务调用本身就是触发条件 | 53 | // 不需要检查操作符和值,因为服务调用本身就是触发条件 |
| 59 | 54 | ||
| 60 | - logTriggerMatchSuccess(message, trigger); | 55 | + IotSceneRuleMatcherHelper.logTriggerMatchSuccess(getMatcherName(), message, trigger); |
| 61 | return true; | 56 | return true; |
| 62 | } | 57 | } |
| 63 | 58 |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/trigger/DeviceStateUpdateTriggerMatcher.java
| @@ -4,7 +4,7 @@ import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageMethodEnum; | @@ -4,7 +4,7 @@ import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageMethodEnum; | ||
| 4 | import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; | 4 | import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; |
| 5 | import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO; | 5 | import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO; |
| 6 | import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum; | 6 | import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum; |
| 7 | -import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.AbstractIotSceneRuleMatcher; | 7 | +import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.IotSceneRuleMatcherHelper; |
| 8 | import org.springframework.stereotype.Component; | 8 | import org.springframework.stereotype.Component; |
| 9 | 9 | ||
| 10 | /** | 10 | /** |
| @@ -15,7 +15,7 @@ import org.springframework.stereotype.Component; | @@ -15,7 +15,7 @@ import org.springframework.stereotype.Component; | ||
| 15 | * @author HUIHUI | 15 | * @author HUIHUI |
| 16 | */ | 16 | */ |
| 17 | @Component | 17 | @Component |
| 18 | -public class DeviceStateUpdateTriggerMatcher extends AbstractIotSceneRuleMatcher { | 18 | +public class DeviceStateUpdateTriggerMatcher implements IotSceneRuleTriggerMatcher { |
| 19 | 19 | ||
| 20 | // TODO @puhui999:是不是不用枚举哈; | 20 | // TODO @puhui999:是不是不用枚举哈; |
| 21 | /** | 21 | /** |
| @@ -24,11 +24,6 @@ public class DeviceStateUpdateTriggerMatcher extends AbstractIotSceneRuleMatcher | @@ -24,11 +24,6 @@ public class DeviceStateUpdateTriggerMatcher extends AbstractIotSceneRuleMatcher | ||
| 24 | private static final String DEVICE_STATE_UPDATE_METHOD = IotDeviceMessageMethodEnum.STATE_UPDATE.getMethod(); | 24 | private static final String DEVICE_STATE_UPDATE_METHOD = IotDeviceMessageMethodEnum.STATE_UPDATE.getMethod(); |
| 25 | 25 | ||
| 26 | @Override | 26 | @Override |
| 27 | - public MatcherTypeEnum getMatcherType() { | ||
| 28 | - return MatcherTypeEnum.TRIGGER; | ||
| 29 | - } | ||
| 30 | - | ||
| 31 | - @Override | ||
| 32 | public IotSceneRuleTriggerTypeEnum getSupportedTriggerType() { | 27 | public IotSceneRuleTriggerTypeEnum getSupportedTriggerType() { |
| 33 | return IotSceneRuleTriggerTypeEnum.DEVICE_STATE_UPDATE; | 28 | return IotSceneRuleTriggerTypeEnum.DEVICE_STATE_UPDATE; |
| 34 | } | 29 | } |
| @@ -36,36 +31,36 @@ public class DeviceStateUpdateTriggerMatcher extends AbstractIotSceneRuleMatcher | @@ -36,36 +31,36 @@ public class DeviceStateUpdateTriggerMatcher extends AbstractIotSceneRuleMatcher | ||
| 36 | @Override | 31 | @Override |
| 37 | public boolean isMatched(IotDeviceMessage message, IotSceneRuleDO.Trigger trigger) { | 32 | public boolean isMatched(IotDeviceMessage message, IotSceneRuleDO.Trigger trigger) { |
| 38 | // 1. 基础参数校验 | 33 | // 1. 基础参数校验 |
| 39 | - if (!isBasicTriggerValid(trigger)) { | ||
| 40 | - logTriggerMatchFailure(message, trigger, "触发器基础参数无效"); | 34 | + if (!IotSceneRuleMatcherHelper.isBasicTriggerValid(trigger)) { |
| 35 | + IotSceneRuleMatcherHelper.logTriggerMatchFailure(getMatcherName(), message, trigger, "触发器基础参数无效"); | ||
| 41 | return false; | 36 | return false; |
| 42 | } | 37 | } |
| 43 | 38 | ||
| 44 | // 2. 检查消息方法是否匹配 | 39 | // 2. 检查消息方法是否匹配 |
| 45 | if (!DEVICE_STATE_UPDATE_METHOD.equals(message.getMethod())) { | 40 | if (!DEVICE_STATE_UPDATE_METHOD.equals(message.getMethod())) { |
| 46 | - logTriggerMatchFailure(message, trigger, "消息方法不匹配,期望: " + DEVICE_STATE_UPDATE_METHOD + ", 实际: " + message.getMethod()); | 41 | + IotSceneRuleMatcherHelper.logTriggerMatchFailure(getMatcherName(), message, trigger, "消息方法不匹配,期望: " + DEVICE_STATE_UPDATE_METHOD + ", 实际: " + message.getMethod()); |
| 47 | return false; | 42 | return false; |
| 48 | } | 43 | } |
| 49 | 44 | ||
| 50 | // 3. 检查操作符和值是否有效 | 45 | // 3. 检查操作符和值是否有效 |
| 51 | - if (!isTriggerOperatorAndValueValid(trigger)) { | ||
| 52 | - logTriggerMatchFailure(message, trigger, "操作符或值无效"); | 46 | + if (!IotSceneRuleMatcherHelper.isTriggerOperatorAndValueValid(trigger)) { |
| 47 | + IotSceneRuleMatcherHelper.logTriggerMatchFailure(getMatcherName(), message, trigger, "操作符或值无效"); | ||
| 53 | return false; | 48 | return false; |
| 54 | } | 49 | } |
| 55 | 50 | ||
| 56 | // 4. 获取设备状态值 | 51 | // 4. 获取设备状态值 |
| 57 | Object stateValue = message.getData(); | 52 | Object stateValue = message.getData(); |
| 58 | if (stateValue == null) { | 53 | if (stateValue == null) { |
| 59 | - logTriggerMatchFailure(message, trigger, "消息中设备状态值为空"); | 54 | + IotSceneRuleMatcherHelper.logTriggerMatchFailure(getMatcherName(), message, trigger, "消息中设备状态值为空"); |
| 60 | return false; | 55 | return false; |
| 61 | } | 56 | } |
| 62 | 57 | ||
| 63 | // 5. 使用条件评估器进行匹配 | 58 | // 5. 使用条件评估器进行匹配 |
| 64 | - boolean matched = evaluateCondition(stateValue, trigger.getOperator(), trigger.getValue()); | 59 | + boolean matched = IotSceneRuleMatcherHelper.evaluateCondition(stateValue, trigger.getOperator(), trigger.getValue()); |
| 65 | if (matched) { | 60 | if (matched) { |
| 66 | - logTriggerMatchSuccess(message, trigger); | 61 | + IotSceneRuleMatcherHelper.logTriggerMatchSuccess(getMatcherName(), message, trigger); |
| 67 | } else { | 62 | } else { |
| 68 | - logTriggerMatchFailure(message, trigger, "状态值条件不匹配"); | 63 | + IotSceneRuleMatcherHelper.logTriggerMatchFailure(getMatcherName(), message, trigger, "状态值条件不匹配"); |
| 69 | } | 64 | } |
| 70 | return matched; | 65 | return matched; |
| 71 | } | 66 | } |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/trigger/IotSceneRuleTriggerMatcher.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.iot.service.rule.scene.matcher.trigger; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; | ||
| 4 | +import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO; | ||
| 5 | +import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum; | ||
| 6 | +import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.IotSceneRuleMatcher; | ||
| 7 | + | ||
| 8 | +/** | ||
| 9 | + * IoT 场景规则触发器匹配器接口 | ||
| 10 | + * <p> | ||
| 11 | + * 专门处理主触发条件的匹配逻辑,如设备消息类型、定时器等 | ||
| 12 | + * <p> | ||
| 13 | + * 触发器匹配器负责判断设备消息是否满足场景规则的主触发条件, | ||
| 14 | + * 是场景规则执行的第一道门槛 | ||
| 15 | + * | ||
| 16 | + * @author HUIHUI | ||
| 17 | + */ | ||
| 18 | +public interface IotSceneRuleTriggerMatcher extends IotSceneRuleMatcher { | ||
| 19 | + | ||
| 20 | + /** | ||
| 21 | + * 获取支持的触发器类型 | ||
| 22 | + * | ||
| 23 | + * @return 触发器类型枚举 | ||
| 24 | + */ | ||
| 25 | + IotSceneRuleTriggerTypeEnum getSupportedTriggerType(); | ||
| 26 | + | ||
| 27 | + /** | ||
| 28 | + * 检查触发器是否匹配消息 | ||
| 29 | + * <p> | ||
| 30 | + * 判断设备消息是否满足指定的触发器条件 | ||
| 31 | + * | ||
| 32 | + * @param message 设备消息 | ||
| 33 | + * @param trigger 触发器配置 | ||
| 34 | + * @return 是否匹配 | ||
| 35 | + */ | ||
| 36 | + boolean isMatched(IotDeviceMessage message, IotSceneRuleDO.Trigger trigger); | ||
| 37 | + | ||
| 38 | +} |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/trigger/TimerTriggerMatcher.java
| @@ -4,7 +4,7 @@ import cn.hutool.core.util.StrUtil; | @@ -4,7 +4,7 @@ import cn.hutool.core.util.StrUtil; | ||
| 4 | import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; | 4 | import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; |
| 5 | import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO; | 5 | import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO; |
| 6 | import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum; | 6 | import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum; |
| 7 | -import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.AbstractIotSceneRuleMatcher; | 7 | +import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.IotSceneRuleMatcherHelper; |
| 8 | import org.springframework.stereotype.Component; | 8 | import org.springframework.stereotype.Component; |
| 9 | 9 | ||
| 10 | /** | 10 | /** |
| @@ -16,12 +16,7 @@ import org.springframework.stereotype.Component; | @@ -16,12 +16,7 @@ import org.springframework.stereotype.Component; | ||
| 16 | * @author HUIHUI | 16 | * @author HUIHUI |
| 17 | */ | 17 | */ |
| 18 | @Component | 18 | @Component |
| 19 | -public class TimerTriggerMatcher extends AbstractIotSceneRuleMatcher { | ||
| 20 | - | ||
| 21 | - @Override | ||
| 22 | - public MatcherTypeEnum getMatcherType() { | ||
| 23 | - return MatcherTypeEnum.TRIGGER; | ||
| 24 | - } | 19 | +public class TimerTriggerMatcher implements IotSceneRuleTriggerMatcher { |
| 25 | 20 | ||
| 26 | @Override | 21 | @Override |
| 27 | public IotSceneRuleTriggerTypeEnum getSupportedTriggerType() { | 22 | public IotSceneRuleTriggerTypeEnum getSupportedTriggerType() { |
| @@ -31,14 +26,14 @@ public class TimerTriggerMatcher extends AbstractIotSceneRuleMatcher { | @@ -31,14 +26,14 @@ public class TimerTriggerMatcher extends AbstractIotSceneRuleMatcher { | ||
| 31 | @Override | 26 | @Override |
| 32 | public boolean isMatched(IotDeviceMessage message, IotSceneRuleDO.Trigger trigger) { | 27 | public boolean isMatched(IotDeviceMessage message, IotSceneRuleDO.Trigger trigger) { |
| 33 | // 1. 基础参数校验 | 28 | // 1. 基础参数校验 |
| 34 | - if (!isBasicTriggerValid(trigger)) { | ||
| 35 | - logTriggerMatchFailure(message, trigger, "触发器基础参数无效"); | 29 | + if (!IotSceneRuleMatcherHelper.isBasicTriggerValid(trigger)) { |
| 30 | + IotSceneRuleMatcherHelper.logTriggerMatchFailure(getMatcherName(), message, trigger, "触发器基础参数无效"); | ||
| 36 | return false; | 31 | return false; |
| 37 | } | 32 | } |
| 38 | 33 | ||
| 39 | // 2. 检查 CRON 表达式是否存在 | 34 | // 2. 检查 CRON 表达式是否存在 |
| 40 | if (StrUtil.isBlank(trigger.getCronExpression())) { | 35 | if (StrUtil.isBlank(trigger.getCronExpression())) { |
| 41 | - logTriggerMatchFailure(message, trigger, "定时触发器缺少 CRON 表达式"); | 36 | + IotSceneRuleMatcherHelper.logTriggerMatchFailure(getMatcherName(), message, trigger, "定时触发器缺少 CRON 表达式"); |
| 42 | return false; | 37 | return false; |
| 43 | } | 38 | } |
| 44 | 39 | ||
| @@ -47,11 +42,11 @@ public class TimerTriggerMatcher extends AbstractIotSceneRuleMatcher { | @@ -47,11 +42,11 @@ public class TimerTriggerMatcher extends AbstractIotSceneRuleMatcher { | ||
| 47 | 42 | ||
| 48 | // 4. 可以添加 CRON 表达式格式验证 | 43 | // 4. 可以添加 CRON 表达式格式验证 |
| 49 | if (!isValidCronExpression(trigger.getCronExpression())) { | 44 | if (!isValidCronExpression(trigger.getCronExpression())) { |
| 50 | - logTriggerMatchFailure(message, trigger, "CRON 表达式格式无效: " + trigger.getCronExpression()); | 45 | + IotSceneRuleMatcherHelper.logTriggerMatchFailure(getMatcherName(), message, trigger, "CRON 表达式格式无效: " + trigger.getCronExpression()); |
| 51 | return false; | 46 | return false; |
| 52 | } | 47 | } |
| 53 | 48 | ||
| 54 | - logTriggerMatchSuccess(message, trigger); | 49 | + IotSceneRuleMatcherHelper.logTriggerMatchSuccess(getMatcherName(), message, trigger); |
| 55 | return true; | 50 | return true; |
| 56 | } | 51 | } |
| 57 | 52 |