diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/IotSceneRuleMatcherHelper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/IotSceneRuleMatcherHelper.java index 5d62bab..1a2b2f3 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/IotSceneRuleMatcherHelper.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/IotSceneRuleMatcherHelper.java @@ -2,13 +2,17 @@ package cn.iocoder.yudao.module.iot.service.rule.scene.matcher; import cn.hutool.core.text.CharPool; import cn.hutool.core.util.NumberUtil; +import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.util.number.NumberUtils; import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import cn.iocoder.yudao.framework.common.util.spring.SpringExpressionUtils; +import cn.iocoder.yudao.framework.common.util.spring.SpringUtils; import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; +import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO; import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleConditionOperatorEnum; +import cn.iocoder.yudao.module.iot.service.device.IotDeviceService; import lombok.extern.slf4j.Slf4j; import java.util.HashMap; @@ -248,4 +252,16 @@ public final class IotSceneRuleMatcherHelper { return StrUtil.isNotBlank(expectedIdentifier) && expectedIdentifier.equals(actualIdentifier); } + /** + * 校验匹配器中的产品和设备是否一致 + * @param message 消息 + * @param productId 产品ID + * @param deviceId 设备id + * @return 校验结果 + */ + public static boolean productAndDeviceNotMatched(IotDeviceMessage message, Long productId, Long deviceId) { + IotDeviceDO device = SpringUtils.getBean(IotDeviceService.class).getDeviceFromCache(message.getDeviceId()); + + return IotDeviceDO.DEVICE_ID_ALL.equals(deviceId) ? ObjectUtil.notEqual(device.getProductId(), productId) : ObjectUtil.notEqual(message.getDeviceId(), deviceId); + } } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/condition/IotCurrentTimeConditionMatcher.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/condition/IotCurrentTimeConditionMatcher.java index a54785a..d2ecb17 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/condition/IotCurrentTimeConditionMatcher.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/condition/IotCurrentTimeConditionMatcher.java @@ -31,7 +31,13 @@ public class IotCurrentTimeConditionMatcher implements IotSceneRuleConditionMatc return false; } - // 1.2 检查操作符和参数是否有效 + // 1.2 修复条件匹配中忽略了产品和设备的一致性验证,2025.05.25 by panda + if (IotSceneRuleMatcherHelper.productAndDeviceNotMatched(message, condition.getProductId(),condition.getDeviceId())){ + IotSceneRuleMatcherHelper.logConditionMatchFailure(message,condition,"条件匹配器中产品或设备不匹配"); + return false; + } + + // 1.3 检查操作符和参数是否有效 if (!IotSceneRuleMatcherHelper.isConditionOperatorAndParamValid(condition)) { IotSceneRuleMatcherHelper.logConditionMatchFailure(message, condition, "操作符或参数无效"); return false; diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/condition/IotDevicePropertyConditionMatcher.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/condition/IotDevicePropertyConditionMatcher.java index 5741b95..951dcc9 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/condition/IotDevicePropertyConditionMatcher.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/condition/IotDevicePropertyConditionMatcher.java @@ -30,7 +30,13 @@ public class IotDevicePropertyConditionMatcher implements IotSceneRuleConditionM return false; } - // 1.2 检查消息中是否包含条件指定的属性标识符 + // 1.2 修复条件匹配中忽略了产品和设备的一致性验证,2025.05.25 by panda + if (IotSceneRuleMatcherHelper.productAndDeviceNotMatched(message, condition.getProductId(),condition.getDeviceId())){ + IotSceneRuleMatcherHelper.logConditionMatchFailure(message,condition,"条件匹配器中产品或设备不匹配"); + return false; + } + + // 1.3 检查消息中是否包含条件指定的属性标识符 // 注意:属性上报可能同时上报多个属性,所以需要判断 condition.getIdentifier() 是否在 message 的 params 中 if (IotDeviceMessageUtils.notContainsIdentifier(message, condition.getIdentifier())) { IotSceneRuleMatcherHelper.logConditionMatchFailure(message, condition, "消息中不包含属性: " + condition.getIdentifier()); diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/condition/IotDeviceStateConditionMatcher.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/condition/IotDeviceStateConditionMatcher.java index 2328122..15dcbbd 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/condition/IotDeviceStateConditionMatcher.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/condition/IotDeviceStateConditionMatcher.java @@ -27,8 +27,13 @@ public class IotDeviceStateConditionMatcher implements IotSceneRuleConditionMatc IotSceneRuleMatcherHelper.logConditionMatchFailure(message, condition, "条件基础参数无效"); return false; } + // 1.2 修复条件匹配中忽略了产品和设备的一致性验证,2025.05.25 by panda + if (IotSceneRuleMatcherHelper.productAndDeviceNotMatched(message, condition.getProductId(),condition.getDeviceId())){ + IotSceneRuleMatcherHelper.logConditionMatchFailure(message,condition,"条件匹配器中产品或设备不匹配"); + return false; + } - // 1.2 检查操作符和参数是否有效 + // 1.3 检查操作符和参数是否有效 if (!IotSceneRuleMatcherHelper.isConditionOperatorAndParamValid(condition)) { IotSceneRuleMatcherHelper.logConditionMatchFailure(message, condition, "操作符或参数无效"); return false; diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/trigger/IotDeviceEventPostTriggerMatcher.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/trigger/IotDeviceEventPostTriggerMatcher.java index d997e46..2d54ff0 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/trigger/IotDeviceEventPostTriggerMatcher.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/trigger/IotDeviceEventPostTriggerMatcher.java @@ -43,7 +43,13 @@ public class IotDeviceEventPostTriggerMatcher implements IotSceneRuleTriggerMatc return false; } - // 1.3 检查标识符是否匹配 + // 1.3 修复触发器中忽略了产品和设备的一致性验证,2025.05.25 by panda + if (IotSceneRuleMatcherHelper.productAndDeviceNotMatched(message, trigger.getProductId(),trigger.getDeviceId())){ + IotSceneRuleMatcherHelper.logTriggerMatchFailure(message,trigger,"触发器中产品或设备不匹配"); + return false; + } + + // 1.4 检查标识符是否匹配 String messageIdentifier = IotDeviceMessageUtils.getIdentifier(message); if (!IotSceneRuleMatcherHelper.isIdentifierMatched(trigger.getIdentifier(), messageIdentifier)) { IotSceneRuleMatcherHelper.logTriggerMatchFailure(message, trigger, "标识符不匹配,期望: " + diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/trigger/IotDevicePropertyPostTriggerMatcher.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/trigger/IotDevicePropertyPostTriggerMatcher.java index 1f019b5..ea89ce3 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/trigger/IotDevicePropertyPostTriggerMatcher.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/trigger/IotDevicePropertyPostTriggerMatcher.java @@ -36,7 +36,13 @@ public class IotDevicePropertyPostTriggerMatcher implements IotSceneRuleTriggerM return false; } - // 1.3 检查消息中是否包含触发器指定的属性标识符 + // 1.3 修复触发器中忽略了产品和设备的一致性验证,2025.05.25 by panda + if (IotSceneRuleMatcherHelper.productAndDeviceNotMatched(message, trigger.getProductId(),trigger.getDeviceId())){ + IotSceneRuleMatcherHelper.logTriggerMatchFailure(message,trigger,"触发器中产品或设备不匹配"); + return false; + } + + // 1.4 检查消息中是否包含触发器指定的属性标识符 // 注意:属性上报可能同时上报多个属性,所以需要判断 trigger.getIdentifier() 是否在 message 的 params 中 if (IotDeviceMessageUtils.notContainsIdentifier(message, trigger.getIdentifier())) { IotSceneRuleMatcherHelper.logTriggerMatchFailure(message, trigger, "消息中不包含属性: " + diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/trigger/IotDeviceServiceInvokeTriggerMatcher.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/trigger/IotDeviceServiceInvokeTriggerMatcher.java index 842d081..5dcde66 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/trigger/IotDeviceServiceInvokeTriggerMatcher.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/trigger/IotDeviceServiceInvokeTriggerMatcher.java @@ -7,7 +7,9 @@ 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.device.IotDeviceService; import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.IotSceneRuleMatcherHelper; +import jakarta.annotation.Resource; import org.springframework.stereotype.Component; import java.util.Map; @@ -20,6 +22,9 @@ import java.util.Map; @Component public class IotDeviceServiceInvokeTriggerMatcher implements IotSceneRuleTriggerMatcher { + @Resource + private IotDeviceService iotDeviceService; + @Override public IotSceneRuleTriggerTypeEnum getSupportedTriggerType() { return IotSceneRuleTriggerTypeEnum.DEVICE_SERVICE_INVOKE; @@ -37,7 +42,12 @@ public class IotDeviceServiceInvokeTriggerMatcher implements IotSceneRuleTrigger IotSceneRuleMatcherHelper.logTriggerMatchFailure(message, trigger, "消息方法不匹配,期望: " + IotDeviceMessageMethodEnum.SERVICE_INVOKE.getMethod() + ", 实际: " + message.getMethod()); return false; } - // 1.3 检查标识符是否匹配 + // 1.3 修复触发器中忽略了产品和设备的一致性验证,2025.05.25 by panda + if (IotSceneRuleMatcherHelper.productAndDeviceNotMatched(message, trigger.getProductId(),trigger.getDeviceId())){ + IotSceneRuleMatcherHelper.logTriggerMatchFailure(message,trigger,"触发器中产品或设备不匹配"); + return false; + } + // 1.4 检查标识符是否匹配 String messageIdentifier = IotDeviceMessageUtils.getIdentifier(message); if (!IotSceneRuleMatcherHelper.isIdentifierMatched(trigger.getIdentifier(), messageIdentifier)) { IotSceneRuleMatcherHelper.logTriggerMatchFailure(message, trigger, "标识符不匹配,期望: " + trigger.getIdentifier() + ", 实际: " + messageIdentifier); diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/trigger/IotDeviceStateUpdateTriggerMatcher.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/trigger/IotDeviceStateUpdateTriggerMatcher.java index 6b8c73a..183442e 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/trigger/IotDeviceStateUpdateTriggerMatcher.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/trigger/IotDeviceStateUpdateTriggerMatcher.java @@ -5,7 +5,9 @@ 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.device.IotDeviceService; import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.IotSceneRuleMatcherHelper; +import jakarta.annotation.Resource; import org.springframework.stereotype.Component; /** @@ -16,6 +18,9 @@ import org.springframework.stereotype.Component; @Component public class IotDeviceStateUpdateTriggerMatcher implements IotSceneRuleTriggerMatcher { + @Resource + private IotDeviceService iotDeviceService; + @Override public IotSceneRuleTriggerTypeEnum getSupportedTriggerType() { return IotSceneRuleTriggerTypeEnum.DEVICE_STATE_UPDATE; @@ -36,7 +41,13 @@ public class IotDeviceStateUpdateTriggerMatcher implements IotSceneRuleTriggerMa return false; } - // 1.3 检查操作符和值是否有效 + // 1.3 修复触发器中忽略了产品和设备的一致性验证,2025.05.25 by panda + if (IotSceneRuleMatcherHelper.productAndDeviceNotMatched(message, trigger.getProductId(),trigger.getDeviceId())){ + IotSceneRuleMatcherHelper.logTriggerMatchFailure(message,trigger,"触发器中产品或设备不匹配"); + return false; + } + + // 1.4 检查操作符和值是否有效 if (!IotSceneRuleMatcherHelper.isTriggerOperatorAndValueValid(trigger)) { IotSceneRuleMatcherHelper.logTriggerMatchFailure(message, trigger, "操作符或值无效"); return false;