mirror of
https://gitee.com/yudaocode/yudao-boot-mini.git
synced 2026-03-22 05:27:15 +08:00
perf:【IoT 物联网】场景联动规则匹配接口拆分使职责更清晰
This commit is contained in:
@@ -1,91 +1,20 @@
|
||||
package cn.iocoder.yudao.module.iot.service.rule.scene.matcher;
|
||||
|
||||
import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
|
||||
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleConditionTypeEnum;
|
||||
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum;
|
||||
import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.condition.IotSceneRuleConditionMatcher;
|
||||
import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.trigger.IotSceneRuleTriggerMatcher;
|
||||
|
||||
/**
|
||||
* IoT 场景规则匹配器统一接口
|
||||
* IoT 场景规则匹配器基础接口
|
||||
* <p>
|
||||
* 支持触发器匹配和条件匹配两种类型,遵循策略模式设计
|
||||
* 定义所有匹配器的通用行为,包括优先级、名称和启用状态
|
||||
* <p>
|
||||
* 匹配器类型说明:
|
||||
* - 触发器匹配器:用于匹配主触发条件(如设备消息类型、定时器等)
|
||||
* - 条件匹配器:用于匹配子条件(如设备状态、属性值、时间条件等)
|
||||
* - {@link IotSceneRuleTriggerMatcher} 触发器匹配器
|
||||
* - {@link IotSceneRuleConditionMatcher} 条件匹配器
|
||||
*
|
||||
* @author HUIHUI
|
||||
*/
|
||||
public interface IotSceneRuleMatcher {
|
||||
|
||||
/**
|
||||
* 匹配器类型枚举
|
||||
*/
|
||||
enum MatcherTypeEnum {
|
||||
|
||||
/**
|
||||
* 触发器匹配器 - 用于匹配主触发条件
|
||||
*/
|
||||
TRIGGER,
|
||||
|
||||
/**
|
||||
* 条件匹配器 - 用于匹配子条件
|
||||
*/
|
||||
CONDITION
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取匹配器类型
|
||||
*
|
||||
* @return 匹配器类型
|
||||
*/
|
||||
MatcherTypeEnum getMatcherType();
|
||||
|
||||
// TODO @puhui999:【重要】有个思路,IotSceneRuleMatcher 拆分成 2 种 mather 接口;然后 AbstractIotSceneRuleMatcher 是个 Helper 工具类;
|
||||
|
||||
// TODO @puhui999:是不是和 AbstractSceneRuleMatcher 一样,分下块;
|
||||
|
||||
/**
|
||||
* 获取支持的触发器类型(仅触发器匹配器需要实现)
|
||||
*
|
||||
* @return 触发器类型枚举,条件匹配器返回 null
|
||||
*/
|
||||
default IotSceneRuleTriggerTypeEnum getSupportedTriggerType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取支持的条件类型(仅条件匹配器需要实现)
|
||||
*
|
||||
* @return 条件类型枚举,触发器匹配器返回 null
|
||||
*/
|
||||
default IotSceneRuleConditionTypeEnum getSupportedConditionType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查触发器是否匹配消息(仅触发器匹配器需要实现)
|
||||
*
|
||||
* @param message 设备消息
|
||||
* @param trigger 触发器配置
|
||||
* @return 是否匹配
|
||||
*/
|
||||
default boolean isMatched(IotDeviceMessage message, IotSceneRuleDO.Trigger trigger) {
|
||||
throw new UnsupportedOperationException("触发器匹配方法仅支持触发器匹配器");
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查条件是否匹配消息(仅条件匹配器需要实现)
|
||||
*
|
||||
* @param message 设备消息
|
||||
* @param condition 触发条件
|
||||
* @return 是否匹配
|
||||
*/
|
||||
default boolean isMatched(IotDeviceMessage message, IotSceneRuleDO.TriggerCondition condition) {
|
||||
throw new UnsupportedOperationException("条件匹配方法仅支持条件匹配器");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取匹配优先级(数值越小优先级越高)
|
||||
* <p>
|
||||
|
||||
@@ -15,16 +15,22 @@ import java.util.Map;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
|
||||
|
||||
/**
|
||||
* IoT 场景规则匹配器抽象基类
|
||||
* IoT 场景规则匹配器工具类
|
||||
* <p>
|
||||
* 提供通用的条件评估逻辑和工具方法,支持触发器和条件两种匹配类型
|
||||
* 提供通用的条件评估逻辑和工具方法,供触发器和条件匹配器使用
|
||||
* <p>
|
||||
* 该类包含了匹配器实现中常用的工具方法,如条件评估、参数校验、日志记录等
|
||||
*
|
||||
* @author HUIHUI
|
||||
*/
|
||||
@Slf4j
|
||||
public abstract class AbstractIotSceneRuleMatcher implements IotSceneRuleMatcher {
|
||||
public final class IotSceneRuleMatcherHelper {
|
||||
|
||||
// TODO @puhui999:这个是不是也是【通用】条件哈?
|
||||
/**
|
||||
* 私有构造函数,防止实例化
|
||||
*/
|
||||
private IotSceneRuleMatcherHelper() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 评估条件是否匹配
|
||||
@@ -35,7 +41,7 @@ public abstract class AbstractIotSceneRuleMatcher implements IotSceneRuleMatcher
|
||||
* @return 是否匹配
|
||||
*/
|
||||
@SuppressWarnings("DataFlowIssue")
|
||||
protected boolean evaluateCondition(Object sourceValue, String operator, String paramValue) {
|
||||
public static boolean evaluateCondition(Object sourceValue, String operator, String paramValue) {
|
||||
try {
|
||||
// 1. 校验操作符是否合法
|
||||
IotSceneRuleConditionOperatorEnum operatorEnum = IotSceneRuleConditionOperatorEnum.operatorOf(operator);
|
||||
@@ -80,7 +86,7 @@ public abstract class AbstractIotSceneRuleMatcher implements IotSceneRuleMatcher
|
||||
* @param trigger 触发器配置
|
||||
* @return 是否有效
|
||||
*/
|
||||
protected boolean isBasicTriggerValid(IotSceneRuleDO.Trigger trigger) {
|
||||
public static boolean isBasicTriggerValid(IotSceneRuleDO.Trigger trigger) {
|
||||
return trigger != null && trigger.getType() != null;
|
||||
}
|
||||
|
||||
@@ -90,29 +96,31 @@ public abstract class AbstractIotSceneRuleMatcher implements IotSceneRuleMatcher
|
||||
* @param trigger 触发器配置
|
||||
* @return 是否有效
|
||||
*/
|
||||
protected boolean isTriggerOperatorAndValueValid(IotSceneRuleDO.Trigger trigger) {
|
||||
public static boolean isTriggerOperatorAndValueValid(IotSceneRuleDO.Trigger trigger) {
|
||||
return StrUtil.isNotBlank(trigger.getOperator()) && StrUtil.isNotBlank(trigger.getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录触发器匹配成功日志
|
||||
*
|
||||
* @param message 设备消息
|
||||
* @param trigger 触发器配置
|
||||
* @param matcherName 匹配器名称
|
||||
* @param message 设备消息
|
||||
* @param trigger 触发器配置
|
||||
*/
|
||||
protected void logTriggerMatchSuccess(IotDeviceMessage message, IotSceneRuleDO.Trigger trigger) {
|
||||
log.debug("[{}][消息({}) 匹配触发器({}) 成功]", getMatcherName(), message.getRequestId(), trigger.getType());
|
||||
public static void logTriggerMatchSuccess(String matcherName, IotDeviceMessage message, IotSceneRuleDO.Trigger trigger) {
|
||||
log.debug("[{}][消息({}) 匹配触发器({}) 成功]", matcherName, message.getRequestId(), trigger.getType());
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录触发器匹配失败日志
|
||||
*
|
||||
* @param message 设备消息
|
||||
* @param trigger 触发器配置
|
||||
* @param reason 失败原因
|
||||
* @param matcherName 匹配器名称
|
||||
* @param message 设备消息
|
||||
* @param trigger 触发器配置
|
||||
* @param reason 失败原因
|
||||
*/
|
||||
protected void logTriggerMatchFailure(IotDeviceMessage message, IotSceneRuleDO.Trigger trigger, String reason) {
|
||||
log.debug("[{}][消息({}) 匹配触发器({}) 失败: {}]", getMatcherName(), message.getRequestId(), trigger.getType(), reason);
|
||||
public static void logTriggerMatchFailure(String matcherName, IotDeviceMessage message, IotSceneRuleDO.Trigger trigger, String reason) {
|
||||
log.debug("[{}][消息({}) 匹配触发器({}) 失败: {}]", matcherName, message.getRequestId(), trigger.getType(), reason);
|
||||
}
|
||||
|
||||
// ========== 【条件】相关工具方法 ==========
|
||||
@@ -123,7 +131,7 @@ public abstract class AbstractIotSceneRuleMatcher implements IotSceneRuleMatcher
|
||||
* @param condition 触发条件
|
||||
* @return 是否有效
|
||||
*/
|
||||
protected boolean isBasicConditionValid(IotSceneRuleDO.TriggerCondition condition) {
|
||||
public static boolean isBasicConditionValid(IotSceneRuleDO.TriggerCondition condition) {
|
||||
return condition != null && condition.getType() != null;
|
||||
}
|
||||
|
||||
@@ -133,29 +141,31 @@ public abstract class AbstractIotSceneRuleMatcher implements IotSceneRuleMatcher
|
||||
* @param condition 触发条件
|
||||
* @return 是否有效
|
||||
*/
|
||||
protected boolean isConditionOperatorAndParamValid(IotSceneRuleDO.TriggerCondition condition) {
|
||||
public static boolean isConditionOperatorAndParamValid(IotSceneRuleDO.TriggerCondition condition) {
|
||||
return StrUtil.isNotBlank(condition.getOperator()) && StrUtil.isNotBlank(condition.getParam());
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录条件匹配成功日志
|
||||
*
|
||||
* @param message 设备消息
|
||||
* @param condition 触发条件
|
||||
* @param matcherName 匹配器名称
|
||||
* @param message 设备消息
|
||||
* @param condition 触发条件
|
||||
*/
|
||||
protected void logConditionMatchSuccess(IotDeviceMessage message, IotSceneRuleDO.TriggerCondition condition) {
|
||||
log.debug("[{}][消息({}) 匹配条件({}) 成功]", getMatcherName(), message.getRequestId(), condition.getType());
|
||||
public static void logConditionMatchSuccess(String matcherName, IotDeviceMessage message, IotSceneRuleDO.TriggerCondition condition) {
|
||||
log.debug("[{}][消息({}) 匹配条件({}) 成功]", matcherName, message.getRequestId(), condition.getType());
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录条件匹配失败日志
|
||||
*
|
||||
* @param message 设备消息
|
||||
* @param condition 触发条件
|
||||
* @param reason 失败原因
|
||||
* @param matcherName 匹配器名称
|
||||
* @param message 设备消息
|
||||
* @param condition 触发条件
|
||||
* @param reason 失败原因
|
||||
*/
|
||||
protected void logConditionMatchFailure(IotDeviceMessage message, IotSceneRuleDO.TriggerCondition condition, String reason) {
|
||||
log.debug("[{}][消息({}) 匹配条件({}) 失败: {}]", getMatcherName(), message.getRequestId(), condition.getType(), reason);
|
||||
public static void logConditionMatchFailure(String matcherName, IotDeviceMessage message, IotSceneRuleDO.TriggerCondition condition, String reason) {
|
||||
log.debug("[{}][消息({}) 匹配条件({}) 失败: {}]", matcherName, message.getRequestId(), condition.getType(), reason);
|
||||
}
|
||||
|
||||
// ========== 【通用】工具方法 ==========
|
||||
@@ -167,7 +177,7 @@ public abstract class AbstractIotSceneRuleMatcher implements IotSceneRuleMatcher
|
||||
* @param actualIdentifier 实际的标识符
|
||||
* @return 是否匹配
|
||||
*/
|
||||
protected boolean isIdentifierMatched(String expectedIdentifier, String actualIdentifier) {
|
||||
public static boolean isIdentifierMatched(String expectedIdentifier, String actualIdentifier) {
|
||||
return StrUtil.isNotBlank(expectedIdentifier) && expectedIdentifier.equals(actualIdentifier);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
|
||||
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleConditionTypeEnum;
|
||||
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum;
|
||||
import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.condition.IotSceneRuleConditionMatcher;
|
||||
import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.trigger.IotSceneRuleTriggerMatcher;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -30,14 +32,14 @@ public class IotSceneRuleMatcherManager {
|
||||
* Key: 触发器类型枚举
|
||||
* Value: 对应的匹配器实例
|
||||
*/
|
||||
private final Map<IotSceneRuleTriggerTypeEnum, IotSceneRuleMatcher> triggerMatchers;
|
||||
private final Map<IotSceneRuleTriggerTypeEnum, IotSceneRuleTriggerMatcher> triggerMatchers;
|
||||
|
||||
/**
|
||||
* 条件匹配器映射表
|
||||
* Key: 条件类型枚举
|
||||
* Value: 对应的匹配器实例
|
||||
*/
|
||||
private final Map<IotSceneRuleConditionTypeEnum, IotSceneRuleMatcher> conditionMatchers;
|
||||
private final Map<IotSceneRuleConditionTypeEnum, IotSceneRuleConditionMatcher> conditionMatchers;
|
||||
|
||||
/**
|
||||
* 所有匹配器列表(按优先级排序)
|
||||
@@ -60,18 +62,20 @@ public class IotSceneRuleMatcherManager {
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 分离触发器匹配器和条件匹配器
|
||||
List<IotSceneRuleMatcher> triggerMatchers = this.allMatchers.stream()
|
||||
.filter(matcher -> matcher.getMatcherType() == IotSceneRuleMatcher.MatcherTypeEnum.TRIGGER)
|
||||
List<IotSceneRuleTriggerMatcher> triggerMatchers = this.allMatchers.stream()
|
||||
.filter(matcher -> matcher instanceof IotSceneRuleTriggerMatcher)
|
||||
.map(matcher -> (IotSceneRuleTriggerMatcher) matcher)
|
||||
.toList();
|
||||
List<IotSceneRuleMatcher> conditionMatchers = this.allMatchers.stream()
|
||||
.filter(matcher -> matcher.getMatcherType() == IotSceneRuleMatcher.MatcherTypeEnum.CONDITION)
|
||||
List<IotSceneRuleConditionMatcher> conditionMatchers = this.allMatchers.stream()
|
||||
.filter(matcher -> matcher instanceof IotSceneRuleConditionMatcher)
|
||||
.map(matcher -> (IotSceneRuleConditionMatcher) matcher)
|
||||
.toList();
|
||||
|
||||
// 构建触发器匹配器映射表
|
||||
// TODO @puhui999:convertMap()
|
||||
this.triggerMatchers = triggerMatchers.stream()
|
||||
.collect(Collectors.toMap(
|
||||
IotSceneRuleMatcher::getSupportedTriggerType,
|
||||
IotSceneRuleTriggerMatcher::getSupportedTriggerType,
|
||||
Function.identity(),
|
||||
(existing, replacement) -> {
|
||||
log.warn("[IotSceneRuleMatcherManager][触发器类型({})存在多个匹配器,使用优先级更高的: {}]",
|
||||
@@ -84,7 +88,7 @@ public class IotSceneRuleMatcherManager {
|
||||
// 构建条件匹配器映射表
|
||||
this.conditionMatchers = conditionMatchers.stream()
|
||||
.collect(Collectors.toMap(
|
||||
IotSceneRuleMatcher::getSupportedConditionType,
|
||||
IotSceneRuleConditionMatcher::getSupportedConditionType,
|
||||
Function.identity(),
|
||||
(existing, replacement) -> {
|
||||
log.warn("[IotSceneRuleMatcherManager][条件类型({})存在多个匹配器,使用优先级更高的: {}]",
|
||||
@@ -124,7 +128,7 @@ public class IotSceneRuleMatcherManager {
|
||||
log.warn("[isMatched][未知的触发器类型: {}]", trigger.getType());
|
||||
return false;
|
||||
}
|
||||
IotSceneRuleMatcher matcher = triggerMatchers.get(triggerType);
|
||||
IotSceneRuleTriggerMatcher matcher = triggerMatchers.get(triggerType);
|
||||
if (matcher == null) {
|
||||
log.warn("[isMatched][触发器类型({})没有对应的匹配器]", triggerType);
|
||||
return false;
|
||||
@@ -159,7 +163,7 @@ public class IotSceneRuleMatcherManager {
|
||||
return false;
|
||||
}
|
||||
|
||||
IotSceneRuleMatcher matcher = conditionMatchers.get(conditionType);
|
||||
IotSceneRuleConditionMatcher matcher = conditionMatchers.get(conditionType);
|
||||
if (matcher == null) {
|
||||
log.warn("[isConditionMatched][条件类型({})没有对应的匹配器]", conditionType);
|
||||
return false;
|
||||
@@ -205,65 +209,4 @@ public class IotSceneRuleMatcherManager {
|
||||
return new HashSet<>(conditionMatchers.keySet());
|
||||
}
|
||||
|
||||
// TODO @puhui999:用不到的方法,可以去掉先哈;
|
||||
|
||||
/**
|
||||
* 获取指定触发器类型的匹配器
|
||||
*
|
||||
* @param triggerType 触发器类型
|
||||
* @return 匹配器实例,如果不存在则返回 null
|
||||
*/
|
||||
public IotSceneRuleMatcher getTriggerMatcher(IotSceneRuleTriggerTypeEnum triggerType) {
|
||||
return triggerMatchers.get(triggerType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定条件类型的匹配器
|
||||
*
|
||||
* @param conditionType 条件类型
|
||||
* @return 匹配器实例,如果不存在则返回 null
|
||||
*/
|
||||
public IotSceneRuleMatcher getConditionMatcher(IotSceneRuleConditionTypeEnum conditionType) {
|
||||
return conditionMatchers.get(conditionType);
|
||||
}
|
||||
|
||||
// TODO @puhui999:是不是不用这个哈;直接 @Getter,单测直接处理;
|
||||
/**
|
||||
* 获取所有匹配器的统计信息
|
||||
*
|
||||
* @return 统计信息映射表
|
||||
*/
|
||||
public Map<String, Object> getMatcherStatistics() {
|
||||
Map<String, Object> statistics = new HashMap<>();
|
||||
statistics.put("totalMatchers", allMatchers.size());
|
||||
statistics.put("triggerMatchers", triggerMatchers.size());
|
||||
statistics.put("conditionMatchers", conditionMatchers.size());
|
||||
statistics.put("supportedTriggerTypes", getSupportedTriggerTypes());
|
||||
statistics.put("supportedConditionTypes", getSupportedConditionTypes());
|
||||
|
||||
// 触发器匹配器详情
|
||||
Map<String, Object> triggerMatcherDetails = new HashMap<>();
|
||||
triggerMatchers.forEach((type, matcher) -> {
|
||||
Map<String, Object> detail = new HashMap<>();
|
||||
detail.put("matcherName", matcher.getMatcherName());
|
||||
detail.put("priority", matcher.getPriority());
|
||||
detail.put("enabled", matcher.isEnabled());
|
||||
triggerMatcherDetails.put(type.name(), detail);
|
||||
});
|
||||
statistics.put("triggerMatcherDetails", triggerMatcherDetails);
|
||||
|
||||
// 条件匹配器详情
|
||||
Map<String, Object> conditionMatcherDetails = new HashMap<>();
|
||||
conditionMatchers.forEach((type, matcher) -> {
|
||||
Map<String, Object> detail = new HashMap<>();
|
||||
detail.put("matcherName", matcher.getMatcherName());
|
||||
detail.put("priority", matcher.getPriority());
|
||||
detail.put("enabled", matcher.isEnabled());
|
||||
conditionMatcherDetails.put(type.name(), detail);
|
||||
});
|
||||
statistics.put("conditionMatcherDetails", conditionMatcherDetails);
|
||||
|
||||
return statistics;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
|
||||
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleConditionTypeEnum;
|
||||
import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.AbstractIotSceneRuleMatcher;
|
||||
import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.IotSceneRuleMatcherHelper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -21,7 +21,7 @@ import java.time.format.DateTimeFormatter;
|
||||
*/
|
||||
@Component
|
||||
@Slf4j
|
||||
public class CurrentTimeConditionMatcher extends AbstractIotSceneRuleMatcher {
|
||||
public class CurrentTimeConditionMatcher implements IotSceneRuleConditionMatcher {
|
||||
|
||||
/**
|
||||
* 时间格式化器 - HH:mm:ss
|
||||
@@ -33,11 +33,6 @@ public class CurrentTimeConditionMatcher extends AbstractIotSceneRuleMatcher {
|
||||
*/
|
||||
private static final DateTimeFormatter TIME_FORMATTER_SHORT = DateTimeFormatter.ofPattern("HH:mm");
|
||||
|
||||
@Override
|
||||
public MatcherTypeEnum getMatcherType() {
|
||||
return MatcherTypeEnum.CONDITION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IotSceneRuleConditionTypeEnum getSupportedConditionType() {
|
||||
return IotSceneRuleConditionTypeEnum.CURRENT_TIME;
|
||||
@@ -46,14 +41,14 @@ public class CurrentTimeConditionMatcher extends AbstractIotSceneRuleMatcher {
|
||||
@Override
|
||||
public boolean isMatched(IotDeviceMessage message, IotSceneRuleDO.TriggerCondition condition) {
|
||||
// 1. 基础参数校验
|
||||
if (!isBasicConditionValid(condition)) {
|
||||
logConditionMatchFailure(message, condition, "条件基础参数无效");
|
||||
if (!IotSceneRuleMatcherHelper.isBasicConditionValid(condition)) {
|
||||
IotSceneRuleMatcherHelper.logConditionMatchFailure(getMatcherName(), message, condition, "条件基础参数无效");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2. 检查操作符和参数是否有效
|
||||
if (!isConditionOperatorAndParamValid(condition)) {
|
||||
logConditionMatchFailure(message, condition, "操作符或参数无效");
|
||||
if (!IotSceneRuleMatcherHelper.isConditionOperatorAndParamValid(condition)) {
|
||||
IotSceneRuleMatcherHelper.logConditionMatchFailure(getMatcherName(), message, condition, "操作符或参数无效");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -71,17 +66,17 @@ public class CurrentTimeConditionMatcher extends AbstractIotSceneRuleMatcher {
|
||||
matched = matchTime(now.toLocalTime(), operator, param);
|
||||
} else {
|
||||
// 其他操作符,使用通用条件评估器
|
||||
matched = evaluateCondition(now.toEpochSecond(java.time.ZoneOffset.of("+8")), operator, param);
|
||||
matched = IotSceneRuleMatcherHelper.evaluateCondition(now.toEpochSecond(java.time.ZoneOffset.of("+8")), operator, param);
|
||||
}
|
||||
|
||||
if (matched) {
|
||||
logConditionMatchSuccess(message, condition);
|
||||
IotSceneRuleMatcherHelper.logConditionMatchSuccess(getMatcherName(), message, condition);
|
||||
} else {
|
||||
logConditionMatchFailure(message, condition, "时间条件不匹配");
|
||||
IotSceneRuleMatcherHelper.logConditionMatchFailure(getMatcherName(), message, condition, "时间条件不匹配");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("[CurrentTimeConditionMatcher][时间条件匹配异常] operator: {}, param: {}", operator, param, e);
|
||||
logConditionMatchFailure(message, condition, "时间条件匹配异常: " + e.getMessage());
|
||||
IotSceneRuleMatcherHelper.logConditionMatchFailure(getMatcherName(), message, condition, "时间条件匹配异常: " + e.getMessage());
|
||||
matched = false;
|
||||
}
|
||||
return matched;
|
||||
@@ -92,7 +87,7 @@ public class CurrentTimeConditionMatcher extends AbstractIotSceneRuleMatcher {
|
||||
*/
|
||||
private boolean matchDateTime(LocalDateTime now, String operator, String param) {
|
||||
long currentTimestamp = now.toEpochSecond(java.time.ZoneOffset.of("+8"));
|
||||
return evaluateCondition(currentTimestamp, operator.substring("date_time_".length()), param);
|
||||
return IotSceneRuleMatcherHelper.evaluateCondition(currentTimestamp, operator.substring("date_time_".length()), param);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,7 +4,7 @@ import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
|
||||
import cn.iocoder.yudao.module.iot.core.util.IotDeviceMessageUtils;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
|
||||
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleConditionTypeEnum;
|
||||
import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.AbstractIotSceneRuleMatcher;
|
||||
import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.IotSceneRuleMatcherHelper;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
@@ -15,12 +15,7 @@ import org.springframework.stereotype.Component;
|
||||
* @author HUIHUI
|
||||
*/
|
||||
@Component
|
||||
public class DevicePropertyConditionMatcher extends AbstractIotSceneRuleMatcher {
|
||||
|
||||
@Override
|
||||
public MatcherTypeEnum getMatcherType() {
|
||||
return MatcherTypeEnum.CONDITION;
|
||||
}
|
||||
public class DevicePropertyConditionMatcher implements IotSceneRuleConditionMatcher {
|
||||
|
||||
@Override
|
||||
public IotSceneRuleConditionTypeEnum getSupportedConditionType() {
|
||||
@@ -31,37 +26,37 @@ public class DevicePropertyConditionMatcher extends AbstractIotSceneRuleMatcher
|
||||
@Override
|
||||
public boolean isMatched(IotDeviceMessage message, IotSceneRuleDO.TriggerCondition condition) {
|
||||
// 1. 基础参数校验
|
||||
if (!isBasicConditionValid(condition)) {
|
||||
logConditionMatchFailure(message, condition, "条件基础参数无效");
|
||||
if (!IotSceneRuleMatcherHelper.isBasicConditionValid(condition)) {
|
||||
IotSceneRuleMatcherHelper.logConditionMatchFailure(getMatcherName(), message, condition, "条件基础参数无效");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2. 检查标识符是否匹配
|
||||
String messageIdentifier = IotDeviceMessageUtils.getIdentifier(message);
|
||||
if (!isIdentifierMatched(condition.getIdentifier(), messageIdentifier)) {
|
||||
logConditionMatchFailure(message, condition, "标识符不匹配,期望: " + condition.getIdentifier() + ", 实际: " + messageIdentifier);
|
||||
if (!IotSceneRuleMatcherHelper.isIdentifierMatched(condition.getIdentifier(), messageIdentifier)) {
|
||||
IotSceneRuleMatcherHelper.logConditionMatchFailure(getMatcherName(), message, condition, "标识符不匹配,期望: " + condition.getIdentifier() + ", 实际: " + messageIdentifier);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 3. 检查操作符和参数是否有效
|
||||
if (!isConditionOperatorAndParamValid(condition)) {
|
||||
logConditionMatchFailure(message, condition, "操作符或参数无效");
|
||||
if (!IotSceneRuleMatcherHelper.isConditionOperatorAndParamValid(condition)) {
|
||||
IotSceneRuleMatcherHelper.logConditionMatchFailure(getMatcherName(), message, condition, "操作符或参数无效");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 4. 获取属性值
|
||||
Object propertyValue = message.getData();
|
||||
if (propertyValue == null) {
|
||||
logConditionMatchFailure(message, condition, "消息中属性值为空");
|
||||
IotSceneRuleMatcherHelper.logConditionMatchFailure(getMatcherName(), message, condition, "消息中属性值为空");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 5. 使用条件评估器进行匹配
|
||||
boolean matched = evaluateCondition(propertyValue, condition.getOperator(), condition.getParam());
|
||||
boolean matched = IotSceneRuleMatcherHelper.evaluateCondition(propertyValue, condition.getOperator(), condition.getParam());
|
||||
if (matched) {
|
||||
logConditionMatchSuccess(message, condition);
|
||||
IotSceneRuleMatcherHelper.logConditionMatchSuccess(getMatcherName(), message, condition);
|
||||
} else {
|
||||
logConditionMatchFailure(message, condition, "设备属性条件不匹配");
|
||||
IotSceneRuleMatcherHelper.logConditionMatchFailure(getMatcherName(), message, condition, "设备属性条件不匹配");
|
||||
}
|
||||
return matched;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.iot.service.rule.scene.matcher.condition;
|
||||
import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
|
||||
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleConditionTypeEnum;
|
||||
import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.AbstractIotSceneRuleMatcher;
|
||||
import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.IotSceneRuleMatcherHelper;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
@@ -14,12 +14,7 @@ import org.springframework.stereotype.Component;
|
||||
* @author HUIHUI
|
||||
*/
|
||||
@Component
|
||||
public class DeviceStateConditionMatcher extends AbstractIotSceneRuleMatcher {
|
||||
|
||||
@Override
|
||||
public MatcherTypeEnum getMatcherType() {
|
||||
return MatcherTypeEnum.CONDITION;
|
||||
}
|
||||
public class DeviceStateConditionMatcher implements IotSceneRuleConditionMatcher {
|
||||
|
||||
@Override
|
||||
public IotSceneRuleConditionTypeEnum getSupportedConditionType() {
|
||||
@@ -29,14 +24,14 @@ public class DeviceStateConditionMatcher extends AbstractIotSceneRuleMatcher {
|
||||
@Override
|
||||
public boolean isMatched(IotDeviceMessage message, IotSceneRuleDO.TriggerCondition condition) {
|
||||
// 1. 基础参数校验
|
||||
if (!isBasicConditionValid(condition)) {
|
||||
logConditionMatchFailure(message, condition, "条件基础参数无效");
|
||||
if (!IotSceneRuleMatcherHelper.isBasicConditionValid(condition)) {
|
||||
IotSceneRuleMatcherHelper.logConditionMatchFailure(getMatcherName(), message, condition, "条件基础参数无效");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2. 检查操作符和参数是否有效
|
||||
if (!isConditionOperatorAndParamValid(condition)) {
|
||||
logConditionMatchFailure(message, condition, "操作符或参数无效");
|
||||
if (!IotSceneRuleMatcherHelper.isConditionOperatorAndParamValid(condition)) {
|
||||
IotSceneRuleMatcherHelper.logConditionMatchFailure(getMatcherName(), message, condition, "操作符或参数无效");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -44,16 +39,16 @@ public class DeviceStateConditionMatcher extends AbstractIotSceneRuleMatcher {
|
||||
// 设备状态通常在消息的 data 字段中
|
||||
Object stateValue = message.getData();
|
||||
if (stateValue == null) {
|
||||
logConditionMatchFailure(message, condition, "消息中设备状态值为空");
|
||||
IotSceneRuleMatcherHelper.logConditionMatchFailure(getMatcherName(), message, condition, "消息中设备状态值为空");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 4. 使用条件评估器进行匹配
|
||||
boolean matched = evaluateCondition(stateValue, condition.getOperator(), condition.getParam());
|
||||
boolean matched = IotSceneRuleMatcherHelper.evaluateCondition(stateValue, condition.getOperator(), condition.getParam());
|
||||
if (matched) {
|
||||
logConditionMatchSuccess(message, condition);
|
||||
IotSceneRuleMatcherHelper.logConditionMatchSuccess(getMatcherName(), message, condition);
|
||||
} else {
|
||||
logConditionMatchFailure(message, condition, "设备状态条件不匹配");
|
||||
IotSceneRuleMatcherHelper.logConditionMatchFailure(getMatcherName(), message, condition, "设备状态条件不匹配");
|
||||
}
|
||||
return matched;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package cn.iocoder.yudao.module.iot.service.rule.scene.matcher.condition;
|
||||
|
||||
import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
|
||||
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleConditionTypeEnum;
|
||||
import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.IotSceneRuleMatcher;
|
||||
|
||||
/**
|
||||
* IoT 场景规则条件匹配器接口
|
||||
* <p>
|
||||
* 专门处理子条件的匹配逻辑,如设备状态、属性值、时间条件等
|
||||
* <p>
|
||||
* 条件匹配器负责判断设备消息是否满足场景规则的附加条件,
|
||||
* 在触发器匹配成功后进行进一步的条件筛选
|
||||
*
|
||||
* @author HUIHUI
|
||||
*/
|
||||
public interface IotSceneRuleConditionMatcher extends IotSceneRuleMatcher {
|
||||
|
||||
/**
|
||||
* 获取支持的条件类型
|
||||
*
|
||||
* @return 条件类型枚举
|
||||
*/
|
||||
IotSceneRuleConditionTypeEnum getSupportedConditionType();
|
||||
|
||||
/**
|
||||
* 检查条件是否匹配消息
|
||||
* <p>
|
||||
* 判断设备消息是否满足指定的触发条件
|
||||
*
|
||||
* @param message 设备消息
|
||||
* @param condition 触发条件
|
||||
* @return 是否匹配
|
||||
*/
|
||||
boolean isMatched(IotDeviceMessage message, IotSceneRuleDO.TriggerCondition condition);
|
||||
|
||||
}
|
||||
@@ -6,7 +6,7 @@ import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
|
||||
import cn.iocoder.yudao.module.iot.core.util.IotDeviceMessageUtils;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
|
||||
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum;
|
||||
import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.AbstractIotSceneRuleMatcher;
|
||||
import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.IotSceneRuleMatcherHelper;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
@@ -17,18 +17,13 @@ import org.springframework.stereotype.Component;
|
||||
* @author HUIHUI
|
||||
*/
|
||||
@Component
|
||||
public class DeviceEventPostTriggerMatcher extends AbstractIotSceneRuleMatcher {
|
||||
public class DeviceEventPostTriggerMatcher implements IotSceneRuleTriggerMatcher {
|
||||
|
||||
/**
|
||||
* 设备事件上报消息方法
|
||||
*/
|
||||
private static final String DEVICE_EVENT_POST_METHOD = IotDeviceMessageMethodEnum.EVENT_POST.getMethod();
|
||||
|
||||
@Override
|
||||
public MatcherTypeEnum getMatcherType() {
|
||||
return MatcherTypeEnum.TRIGGER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IotSceneRuleTriggerTypeEnum getSupportedTriggerType() {
|
||||
return IotSceneRuleTriggerTypeEnum.DEVICE_EVENT_POST;
|
||||
@@ -37,21 +32,21 @@ public class DeviceEventPostTriggerMatcher extends AbstractIotSceneRuleMatcher {
|
||||
@Override
|
||||
public boolean isMatched(IotDeviceMessage message, IotSceneRuleDO.Trigger trigger) {
|
||||
// 1. 基础参数校验
|
||||
if (!isBasicTriggerValid(trigger)) {
|
||||
logTriggerMatchFailure(message, trigger, "触发器基础参数无效");
|
||||
if (!IotSceneRuleMatcherHelper.isBasicTriggerValid(trigger)) {
|
||||
IotSceneRuleMatcherHelper.logTriggerMatchFailure(getMatcherName(), message, trigger, "触发器基础参数无效");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2. 检查消息方法是否匹配
|
||||
if (!DEVICE_EVENT_POST_METHOD.equals(message.getMethod())) {
|
||||
logTriggerMatchFailure(message, trigger, "消息方法不匹配,期望: " + DEVICE_EVENT_POST_METHOD + ", 实际: " + message.getMethod());
|
||||
IotSceneRuleMatcherHelper.logTriggerMatchFailure(getMatcherName(), message, trigger, "消息方法不匹配,期望: " + DEVICE_EVENT_POST_METHOD + ", 实际: " + message.getMethod());
|
||||
return false;
|
||||
}
|
||||
|
||||
// 3. 检查标识符是否匹配
|
||||
String messageIdentifier = IotDeviceMessageUtils.getIdentifier(message);
|
||||
if (!isIdentifierMatched(trigger.getIdentifier(), messageIdentifier)) {
|
||||
logTriggerMatchFailure(message, trigger, "标识符不匹配,期望: " + trigger.getIdentifier() + ", 实际: " + messageIdentifier);
|
||||
if (!IotSceneRuleMatcherHelper.isIdentifierMatched(trigger.getIdentifier(), messageIdentifier)) {
|
||||
IotSceneRuleMatcherHelper.logTriggerMatchFailure(getMatcherName(), message, trigger, "标识符不匹配,期望: " + trigger.getIdentifier() + ", 实际: " + messageIdentifier);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -60,18 +55,18 @@ public class DeviceEventPostTriggerMatcher extends AbstractIotSceneRuleMatcher {
|
||||
if (StrUtil.isNotBlank(trigger.getOperator()) && StrUtil.isNotBlank(trigger.getValue())) {
|
||||
Object eventData = message.getData();
|
||||
if (eventData == null) {
|
||||
logTriggerMatchFailure(message, trigger, "消息中事件数据为空");
|
||||
IotSceneRuleMatcherHelper.logTriggerMatchFailure(getMatcherName(), message, trigger, "消息中事件数据为空");
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean matched = evaluateCondition(eventData, trigger.getOperator(), trigger.getValue());
|
||||
boolean matched = IotSceneRuleMatcherHelper.evaluateCondition(eventData, trigger.getOperator(), trigger.getValue());
|
||||
if (!matched) {
|
||||
logTriggerMatchFailure(message, trigger, "事件数据条件不匹配");
|
||||
IotSceneRuleMatcherHelper.logTriggerMatchFailure(getMatcherName(), message, trigger, "事件数据条件不匹配");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
logTriggerMatchSuccess(message, trigger);
|
||||
IotSceneRuleMatcherHelper.logTriggerMatchSuccess(getMatcherName(), message, trigger);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
|
||||
import cn.iocoder.yudao.module.iot.core.util.IotDeviceMessageUtils;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
|
||||
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum;
|
||||
import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.AbstractIotSceneRuleMatcher;
|
||||
import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.IotSceneRuleMatcherHelper;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
@@ -16,7 +16,7 @@ import org.springframework.stereotype.Component;
|
||||
* @author HUIHUI
|
||||
*/
|
||||
@Component
|
||||
public class DevicePropertyPostTriggerMatcher extends AbstractIotSceneRuleMatcher {
|
||||
public class DevicePropertyPostTriggerMatcher implements IotSceneRuleTriggerMatcher {
|
||||
|
||||
/**
|
||||
* 设备属性上报消息方法
|
||||
@@ -24,11 +24,6 @@ public class DevicePropertyPostTriggerMatcher extends AbstractIotSceneRuleMatche
|
||||
// TODO @puhui999:是不是不用枚举哈?直接使用 IotDeviceMessageMethodEnum.PROPERTY_POST.getMethod()
|
||||
private static final String DEVICE_PROPERTY_POST_METHOD = IotDeviceMessageMethodEnum.PROPERTY_POST.getMethod();
|
||||
|
||||
@Override
|
||||
public MatcherTypeEnum getMatcherType() {
|
||||
return MatcherTypeEnum.TRIGGER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IotSceneRuleTriggerTypeEnum getSupportedTriggerType() {
|
||||
return IotSceneRuleTriggerTypeEnum.DEVICE_PROPERTY_POST;
|
||||
@@ -37,43 +32,43 @@ public class DevicePropertyPostTriggerMatcher extends AbstractIotSceneRuleMatche
|
||||
@Override
|
||||
public boolean isMatched(IotDeviceMessage message, IotSceneRuleDO.Trigger trigger) {
|
||||
// 1. 基础参数校验
|
||||
if (!isBasicTriggerValid(trigger)) {
|
||||
logTriggerMatchFailure(message, trigger, "触发器基础参数无效");
|
||||
if (!IotSceneRuleMatcherHelper.isBasicTriggerValid(trigger)) {
|
||||
IotSceneRuleMatcherHelper.logTriggerMatchFailure(getMatcherName(), message, trigger, "触发器基础参数无效");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2. 检查消息方法是否匹配
|
||||
if (!DEVICE_PROPERTY_POST_METHOD.equals(message.getMethod())) {
|
||||
logTriggerMatchFailure(message, trigger, "消息方法不匹配,期望: " + DEVICE_PROPERTY_POST_METHOD + ", 实际: " + message.getMethod());
|
||||
IotSceneRuleMatcherHelper.logTriggerMatchFailure(getMatcherName(), message, trigger, "消息方法不匹配,期望: " + DEVICE_PROPERTY_POST_METHOD + ", 实际: " + message.getMethod());
|
||||
return false;
|
||||
}
|
||||
|
||||
// 3. 检查标识符是否匹配
|
||||
String messageIdentifier = IotDeviceMessageUtils.getIdentifier(message);
|
||||
if (!isIdentifierMatched(trigger.getIdentifier(), messageIdentifier)) {
|
||||
logTriggerMatchFailure(message, trigger, "标识符不匹配,期望: " + trigger.getIdentifier() + ", 实际: " + messageIdentifier);
|
||||
if (!IotSceneRuleMatcherHelper.isIdentifierMatched(trigger.getIdentifier(), messageIdentifier)) {
|
||||
IotSceneRuleMatcherHelper.logTriggerMatchFailure(getMatcherName(), message, trigger, "标识符不匹配,期望: " + trigger.getIdentifier() + ", 实际: " + messageIdentifier);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 4. 检查操作符和值是否有效
|
||||
if (!isTriggerOperatorAndValueValid(trigger)) {
|
||||
logTriggerMatchFailure(message, trigger, "操作符或值无效");
|
||||
if (!IotSceneRuleMatcherHelper.isTriggerOperatorAndValueValid(trigger)) {
|
||||
IotSceneRuleMatcherHelper.logTriggerMatchFailure(getMatcherName(), message, trigger, "操作符或值无效");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 5. 获取属性值
|
||||
Object propertyValue = message.getData();
|
||||
if (propertyValue == null) {
|
||||
logTriggerMatchFailure(message, trigger, "消息中属性值为空");
|
||||
IotSceneRuleMatcherHelper.logTriggerMatchFailure(getMatcherName(), message, trigger, "消息中属性值为空");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 6. 使用条件评估器进行匹配
|
||||
boolean matched = evaluateCondition(propertyValue, trigger.getOperator(), trigger.getValue());
|
||||
boolean matched = IotSceneRuleMatcherHelper.evaluateCondition(propertyValue, trigger.getOperator(), trigger.getValue());
|
||||
if (matched) {
|
||||
logTriggerMatchSuccess(message, trigger);
|
||||
IotSceneRuleMatcherHelper.logTriggerMatchSuccess(getMatcherName(), message, trigger);
|
||||
} else {
|
||||
logTriggerMatchFailure(message, trigger, "属性值条件不匹配");
|
||||
IotSceneRuleMatcherHelper.logTriggerMatchFailure(getMatcherName(), message, trigger, "属性值条件不匹配");
|
||||
}
|
||||
return matched;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
|
||||
import cn.iocoder.yudao.module.iot.core.util.IotDeviceMessageUtils;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
|
||||
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum;
|
||||
import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.AbstractIotSceneRuleMatcher;
|
||||
import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.IotSceneRuleMatcherHelper;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
@@ -16,18 +16,13 @@ import org.springframework.stereotype.Component;
|
||||
* @author HUIHUI
|
||||
*/
|
||||
@Component
|
||||
public class DeviceServiceInvokeTriggerMatcher extends AbstractIotSceneRuleMatcher {
|
||||
public class DeviceServiceInvokeTriggerMatcher implements IotSceneRuleTriggerMatcher {
|
||||
|
||||
/**
|
||||
* 设备服务调用消息方法
|
||||
*/
|
||||
private static final String DEVICE_SERVICE_INVOKE_METHOD = IotDeviceMessageMethodEnum.SERVICE_INVOKE.getMethod();
|
||||
|
||||
@Override
|
||||
public MatcherTypeEnum getMatcherType() {
|
||||
return MatcherTypeEnum.TRIGGER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IotSceneRuleTriggerTypeEnum getSupportedTriggerType() {
|
||||
return IotSceneRuleTriggerTypeEnum.DEVICE_SERVICE_INVOKE;
|
||||
@@ -36,28 +31,28 @@ public class DeviceServiceInvokeTriggerMatcher extends AbstractIotSceneRuleMatch
|
||||
@Override
|
||||
public boolean isMatched(IotDeviceMessage message, IotSceneRuleDO.Trigger trigger) {
|
||||
// 1. 基础参数校验
|
||||
if (!isBasicTriggerValid(trigger)) {
|
||||
logTriggerMatchFailure(message, trigger, "触发器基础参数无效");
|
||||
if (!IotSceneRuleMatcherHelper.isBasicTriggerValid(trigger)) {
|
||||
IotSceneRuleMatcherHelper.logTriggerMatchFailure(getMatcherName(), message, trigger, "触发器基础参数无效");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2. 检查消息方法是否匹配
|
||||
if (!DEVICE_SERVICE_INVOKE_METHOD.equals(message.getMethod())) {
|
||||
logTriggerMatchFailure(message, trigger, "消息方法不匹配,期望: " + DEVICE_SERVICE_INVOKE_METHOD + ", 实际: " + message.getMethod());
|
||||
IotSceneRuleMatcherHelper.logTriggerMatchFailure(getMatcherName(), message, trigger, "消息方法不匹配,期望: " + DEVICE_SERVICE_INVOKE_METHOD + ", 实际: " + message.getMethod());
|
||||
return false;
|
||||
}
|
||||
|
||||
// 3. 检查标识符是否匹配
|
||||
String messageIdentifier = IotDeviceMessageUtils.getIdentifier(message);
|
||||
if (!isIdentifierMatched(trigger.getIdentifier(), messageIdentifier)) {
|
||||
logTriggerMatchFailure(message, trigger, "标识符不匹配,期望: " + trigger.getIdentifier() + ", 实际: " + messageIdentifier);
|
||||
if (!IotSceneRuleMatcherHelper.isIdentifierMatched(trigger.getIdentifier(), messageIdentifier)) {
|
||||
IotSceneRuleMatcherHelper.logTriggerMatchFailure(getMatcherName(), message, trigger, "标识符不匹配,期望: " + trigger.getIdentifier() + ", 实际: " + messageIdentifier);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 4. 对于服务调用触发器,通常只需要匹配服务标识符即可
|
||||
// 不需要检查操作符和值,因为服务调用本身就是触发条件
|
||||
|
||||
logTriggerMatchSuccess(message, trigger);
|
||||
IotSceneRuleMatcherHelper.logTriggerMatchSuccess(getMatcherName(), message, trigger);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageMethodEnum;
|
||||
import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
|
||||
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum;
|
||||
import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.AbstractIotSceneRuleMatcher;
|
||||
import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.IotSceneRuleMatcherHelper;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
@@ -15,7 +15,7 @@ import org.springframework.stereotype.Component;
|
||||
* @author HUIHUI
|
||||
*/
|
||||
@Component
|
||||
public class DeviceStateUpdateTriggerMatcher extends AbstractIotSceneRuleMatcher {
|
||||
public class DeviceStateUpdateTriggerMatcher implements IotSceneRuleTriggerMatcher {
|
||||
|
||||
// TODO @puhui999:是不是不用枚举哈;
|
||||
/**
|
||||
@@ -23,11 +23,6 @@ public class DeviceStateUpdateTriggerMatcher extends AbstractIotSceneRuleMatcher
|
||||
*/
|
||||
private static final String DEVICE_STATE_UPDATE_METHOD = IotDeviceMessageMethodEnum.STATE_UPDATE.getMethod();
|
||||
|
||||
@Override
|
||||
public MatcherTypeEnum getMatcherType() {
|
||||
return MatcherTypeEnum.TRIGGER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IotSceneRuleTriggerTypeEnum getSupportedTriggerType() {
|
||||
return IotSceneRuleTriggerTypeEnum.DEVICE_STATE_UPDATE;
|
||||
@@ -36,36 +31,36 @@ public class DeviceStateUpdateTriggerMatcher extends AbstractIotSceneRuleMatcher
|
||||
@Override
|
||||
public boolean isMatched(IotDeviceMessage message, IotSceneRuleDO.Trigger trigger) {
|
||||
// 1. 基础参数校验
|
||||
if (!isBasicTriggerValid(trigger)) {
|
||||
logTriggerMatchFailure(message, trigger, "触发器基础参数无效");
|
||||
if (!IotSceneRuleMatcherHelper.isBasicTriggerValid(trigger)) {
|
||||
IotSceneRuleMatcherHelper.logTriggerMatchFailure(getMatcherName(), message, trigger, "触发器基础参数无效");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2. 检查消息方法是否匹配
|
||||
if (!DEVICE_STATE_UPDATE_METHOD.equals(message.getMethod())) {
|
||||
logTriggerMatchFailure(message, trigger, "消息方法不匹配,期望: " + DEVICE_STATE_UPDATE_METHOD + ", 实际: " + message.getMethod());
|
||||
IotSceneRuleMatcherHelper.logTriggerMatchFailure(getMatcherName(), message, trigger, "消息方法不匹配,期望: " + DEVICE_STATE_UPDATE_METHOD + ", 实际: " + message.getMethod());
|
||||
return false;
|
||||
}
|
||||
|
||||
// 3. 检查操作符和值是否有效
|
||||
if (!isTriggerOperatorAndValueValid(trigger)) {
|
||||
logTriggerMatchFailure(message, trigger, "操作符或值无效");
|
||||
if (!IotSceneRuleMatcherHelper.isTriggerOperatorAndValueValid(trigger)) {
|
||||
IotSceneRuleMatcherHelper.logTriggerMatchFailure(getMatcherName(), message, trigger, "操作符或值无效");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 4. 获取设备状态值
|
||||
Object stateValue = message.getData();
|
||||
if (stateValue == null) {
|
||||
logTriggerMatchFailure(message, trigger, "消息中设备状态值为空");
|
||||
IotSceneRuleMatcherHelper.logTriggerMatchFailure(getMatcherName(), message, trigger, "消息中设备状态值为空");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 5. 使用条件评估器进行匹配
|
||||
boolean matched = evaluateCondition(stateValue, trigger.getOperator(), trigger.getValue());
|
||||
boolean matched = IotSceneRuleMatcherHelper.evaluateCondition(stateValue, trigger.getOperator(), trigger.getValue());
|
||||
if (matched) {
|
||||
logTriggerMatchSuccess(message, trigger);
|
||||
IotSceneRuleMatcherHelper.logTriggerMatchSuccess(getMatcherName(), message, trigger);
|
||||
} else {
|
||||
logTriggerMatchFailure(message, trigger, "状态值条件不匹配");
|
||||
IotSceneRuleMatcherHelper.logTriggerMatchFailure(getMatcherName(), message, trigger, "状态值条件不匹配");
|
||||
}
|
||||
return matched;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package cn.iocoder.yudao.module.iot.service.rule.scene.matcher.trigger;
|
||||
|
||||
import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
|
||||
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum;
|
||||
import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.IotSceneRuleMatcher;
|
||||
|
||||
/**
|
||||
* IoT 场景规则触发器匹配器接口
|
||||
* <p>
|
||||
* 专门处理主触发条件的匹配逻辑,如设备消息类型、定时器等
|
||||
* <p>
|
||||
* 触发器匹配器负责判断设备消息是否满足场景规则的主触发条件,
|
||||
* 是场景规则执行的第一道门槛
|
||||
*
|
||||
* @author HUIHUI
|
||||
*/
|
||||
public interface IotSceneRuleTriggerMatcher extends IotSceneRuleMatcher {
|
||||
|
||||
/**
|
||||
* 获取支持的触发器类型
|
||||
*
|
||||
* @return 触发器类型枚举
|
||||
*/
|
||||
IotSceneRuleTriggerTypeEnum getSupportedTriggerType();
|
||||
|
||||
/**
|
||||
* 检查触发器是否匹配消息
|
||||
* <p>
|
||||
* 判断设备消息是否满足指定的触发器条件
|
||||
*
|
||||
* @param message 设备消息
|
||||
* @param trigger 触发器配置
|
||||
* @return 是否匹配
|
||||
*/
|
||||
boolean isMatched(IotDeviceMessage message, IotSceneRuleDO.Trigger trigger);
|
||||
|
||||
}
|
||||
@@ -4,7 +4,7 @@ import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
|
||||
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum;
|
||||
import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.AbstractIotSceneRuleMatcher;
|
||||
import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.IotSceneRuleMatcherHelper;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
@@ -16,12 +16,7 @@ import org.springframework.stereotype.Component;
|
||||
* @author HUIHUI
|
||||
*/
|
||||
@Component
|
||||
public class TimerTriggerMatcher extends AbstractIotSceneRuleMatcher {
|
||||
|
||||
@Override
|
||||
public MatcherTypeEnum getMatcherType() {
|
||||
return MatcherTypeEnum.TRIGGER;
|
||||
}
|
||||
public class TimerTriggerMatcher implements IotSceneRuleTriggerMatcher {
|
||||
|
||||
@Override
|
||||
public IotSceneRuleTriggerTypeEnum getSupportedTriggerType() {
|
||||
@@ -31,14 +26,14 @@ public class TimerTriggerMatcher extends AbstractIotSceneRuleMatcher {
|
||||
@Override
|
||||
public boolean isMatched(IotDeviceMessage message, IotSceneRuleDO.Trigger trigger) {
|
||||
// 1. 基础参数校验
|
||||
if (!isBasicTriggerValid(trigger)) {
|
||||
logTriggerMatchFailure(message, trigger, "触发器基础参数无效");
|
||||
if (!IotSceneRuleMatcherHelper.isBasicTriggerValid(trigger)) {
|
||||
IotSceneRuleMatcherHelper.logTriggerMatchFailure(getMatcherName(), message, trigger, "触发器基础参数无效");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2. 检查 CRON 表达式是否存在
|
||||
if (StrUtil.isBlank(trigger.getCronExpression())) {
|
||||
logTriggerMatchFailure(message, trigger, "定时触发器缺少 CRON 表达式");
|
||||
IotSceneRuleMatcherHelper.logTriggerMatchFailure(getMatcherName(), message, trigger, "定时触发器缺少 CRON 表达式");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -47,11 +42,11 @@ public class TimerTriggerMatcher extends AbstractIotSceneRuleMatcher {
|
||||
|
||||
// 4. 可以添加 CRON 表达式格式验证
|
||||
if (!isValidCronExpression(trigger.getCronExpression())) {
|
||||
logTriggerMatchFailure(message, trigger, "CRON 表达式格式无效: " + trigger.getCronExpression());
|
||||
IotSceneRuleMatcherHelper.logTriggerMatchFailure(getMatcherName(), message, trigger, "CRON 表达式格式无效: " + trigger.getCronExpression());
|
||||
return false;
|
||||
}
|
||||
|
||||
logTriggerMatchSuccess(message, trigger);
|
||||
IotSceneRuleMatcherHelper.logTriggerMatchSuccess(getMatcherName(), message, trigger);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user