Commit 07f26a7e02291c71565207317b49012475d68ca0

Authored by panda
1 parent a08526d8

fix: 修复触发器和条件匹配器中缺少对产品和设备一致性的验证

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; @@ -2,13 +2,17 @@ package cn.iocoder.yudao.module.iot.service.rule.scene.matcher;
2 2
3 import cn.hutool.core.text.CharPool; 3 import cn.hutool.core.text.CharPool;
4 import cn.hutool.core.util.NumberUtil; 4 import cn.hutool.core.util.NumberUtil;
  5 +import cn.hutool.core.util.ObjectUtil;
5 import cn.hutool.core.util.StrUtil; 6 import cn.hutool.core.util.StrUtil;
6 import cn.iocoder.yudao.framework.common.util.number.NumberUtils; 7 import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
7 import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; 8 import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
8 import cn.iocoder.yudao.framework.common.util.spring.SpringExpressionUtils; 9 import cn.iocoder.yudao.framework.common.util.spring.SpringExpressionUtils;
  10 +import cn.iocoder.yudao.framework.common.util.spring.SpringUtils;
9 import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; 11 import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
  12 +import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
10 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO; 13 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
11 import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleConditionOperatorEnum; 14 import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleConditionOperatorEnum;
  15 +import cn.iocoder.yudao.module.iot.service.device.IotDeviceService;
12 import lombok.extern.slf4j.Slf4j; 16 import lombok.extern.slf4j.Slf4j;
13 17
14 import java.util.HashMap; 18 import java.util.HashMap;
@@ -248,4 +252,16 @@ public final class IotSceneRuleMatcherHelper { @@ -248,4 +252,16 @@ public final class IotSceneRuleMatcherHelper {
248 return StrUtil.isNotBlank(expectedIdentifier) && expectedIdentifier.equals(actualIdentifier); 252 return StrUtil.isNotBlank(expectedIdentifier) && expectedIdentifier.equals(actualIdentifier);
249 } 253 }
250 254
  255 + /**
  256 + * 校验匹配器中的产品和设备是否一致
  257 + * @param message 消息
  258 + * @param productId 产品ID
  259 + * @param deviceId 设备id
  260 + * @return 校验结果
  261 + */
  262 + public static boolean productAndDeviceNotMatched(IotDeviceMessage message, Long productId, Long deviceId) {
  263 + IotDeviceDO device = SpringUtils.getBean(IotDeviceService.class).getDeviceFromCache(message.getDeviceId());
  264 +
  265 + return IotDeviceDO.DEVICE_ID_ALL.equals(deviceId) ? ObjectUtil.notEqual(device.getProductId(), productId) : ObjectUtil.notEqual(message.getDeviceId(), deviceId);
  266 + }
251 } 267 }
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 @@ -31,7 +31,13 @@ public class IotCurrentTimeConditionMatcher implements IotSceneRuleConditionMatc
31 return false; 31 return false;
32 } 32 }
33 33
34 - // 1.2 检查操作符和参数是否有效 34 + // 1.2 修复条件匹配中忽略了产品和设备的一致性验证,2025.05.25 by panda
  35 + if (IotSceneRuleMatcherHelper.productAndDeviceNotMatched(message, condition.getProductId(),condition.getDeviceId())){
  36 + IotSceneRuleMatcherHelper.logConditionMatchFailure(message,condition,"条件匹配器中产品或设备不匹配");
  37 + return false;
  38 + }
  39 +
  40 + // 1.3 检查操作符和参数是否有效
35 if (!IotSceneRuleMatcherHelper.isConditionOperatorAndParamValid(condition)) { 41 if (!IotSceneRuleMatcherHelper.isConditionOperatorAndParamValid(condition)) {
36 IotSceneRuleMatcherHelper.logConditionMatchFailure(message, condition, "操作符或参数无效"); 42 IotSceneRuleMatcherHelper.logConditionMatchFailure(message, condition, "操作符或参数无效");
37 return false; 43 return false;
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 @@ -30,7 +30,13 @@ public class IotDevicePropertyConditionMatcher implements IotSceneRuleConditionM
30 return false; 30 return false;
31 } 31 }
32 32
33 - // 1.2 检查消息中是否包含条件指定的属性标识符 33 + // 1.2 修复条件匹配中忽略了产品和设备的一致性验证,2025.05.25 by panda
  34 + if (IotSceneRuleMatcherHelper.productAndDeviceNotMatched(message, condition.getProductId(),condition.getDeviceId())){
  35 + IotSceneRuleMatcherHelper.logConditionMatchFailure(message,condition,"条件匹配器中产品或设备不匹配");
  36 + return false;
  37 + }
  38 +
  39 + // 1.3 检查消息中是否包含条件指定的属性标识符
34 // 注意:属性上报可能同时上报多个属性,所以需要判断 condition.getIdentifier() 是否在 message 的 params 中 40 // 注意:属性上报可能同时上报多个属性,所以需要判断 condition.getIdentifier() 是否在 message 的 params 中
35 if (IotDeviceMessageUtils.notContainsIdentifier(message, condition.getIdentifier())) { 41 if (IotDeviceMessageUtils.notContainsIdentifier(message, condition.getIdentifier())) {
36 IotSceneRuleMatcherHelper.logConditionMatchFailure(message, condition, "消息中不包含属性: " + condition.getIdentifier()); 42 IotSceneRuleMatcherHelper.logConditionMatchFailure(message, condition, "消息中不包含属性: " + condition.getIdentifier());
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 @@ -27,8 +27,13 @@ public class IotDeviceStateConditionMatcher implements IotSceneRuleConditionMatc
27 IotSceneRuleMatcherHelper.logConditionMatchFailure(message, condition, "条件基础参数无效"); 27 IotSceneRuleMatcherHelper.logConditionMatchFailure(message, condition, "条件基础参数无效");
28 return false; 28 return false;
29 } 29 }
  30 + // 1.2 修复条件匹配中忽略了产品和设备的一致性验证,2025.05.25 by panda
  31 + if (IotSceneRuleMatcherHelper.productAndDeviceNotMatched(message, condition.getProductId(),condition.getDeviceId())){
  32 + IotSceneRuleMatcherHelper.logConditionMatchFailure(message,condition,"条件匹配器中产品或设备不匹配");
  33 + return false;
  34 + }
30 35
31 - // 1.2 检查操作符和参数是否有效 36 + // 1.3 检查操作符和参数是否有效
32 if (!IotSceneRuleMatcherHelper.isConditionOperatorAndParamValid(condition)) { 37 if (!IotSceneRuleMatcherHelper.isConditionOperatorAndParamValid(condition)) {
33 IotSceneRuleMatcherHelper.logConditionMatchFailure(message, condition, "操作符或参数无效"); 38 IotSceneRuleMatcherHelper.logConditionMatchFailure(message, condition, "操作符或参数无效");
34 return false; 39 return false;
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 @@ -43,7 +43,13 @@ public class IotDeviceEventPostTriggerMatcher implements IotSceneRuleTriggerMatc
43 return false; 43 return false;
44 } 44 }
45 45
46 - // 1.3 检查标识符是否匹配 46 + // 1.3 修复触发器中忽略了产品和设备的一致性验证,2025.05.25 by panda
  47 + if (IotSceneRuleMatcherHelper.productAndDeviceNotMatched(message, trigger.getProductId(),trigger.getDeviceId())){
  48 + IotSceneRuleMatcherHelper.logTriggerMatchFailure(message,trigger,"触发器中产品或设备不匹配");
  49 + return false;
  50 + }
  51 +
  52 + // 1.4 检查标识符是否匹配
47 String messageIdentifier = IotDeviceMessageUtils.getIdentifier(message); 53 String messageIdentifier = IotDeviceMessageUtils.getIdentifier(message);
48 if (!IotSceneRuleMatcherHelper.isIdentifierMatched(trigger.getIdentifier(), messageIdentifier)) { 54 if (!IotSceneRuleMatcherHelper.isIdentifierMatched(trigger.getIdentifier(), messageIdentifier)) {
49 IotSceneRuleMatcherHelper.logTriggerMatchFailure(message, trigger, "标识符不匹配,期望: " + 55 IotSceneRuleMatcherHelper.logTriggerMatchFailure(message, trigger, "标识符不匹配,期望: " +
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 @@ -36,7 +36,13 @@ public class IotDevicePropertyPostTriggerMatcher implements IotSceneRuleTriggerM
36 return false; 36 return false;
37 } 37 }
38 38
39 - // 1.3 检查消息中是否包含触发器指定的属性标识符 39 + // 1.3 修复触发器中忽略了产品和设备的一致性验证,2025.05.25 by panda
  40 + if (IotSceneRuleMatcherHelper.productAndDeviceNotMatched(message, trigger.getProductId(),trigger.getDeviceId())){
  41 + IotSceneRuleMatcherHelper.logTriggerMatchFailure(message,trigger,"触发器中产品或设备不匹配");
  42 + return false;
  43 + }
  44 +
  45 + // 1.4 检查消息中是否包含触发器指定的属性标识符
40 // 注意:属性上报可能同时上报多个属性,所以需要判断 trigger.getIdentifier() 是否在 message 的 params 中 46 // 注意:属性上报可能同时上报多个属性,所以需要判断 trigger.getIdentifier() 是否在 message 的 params 中
41 if (IotDeviceMessageUtils.notContainsIdentifier(message, trigger.getIdentifier())) { 47 if (IotDeviceMessageUtils.notContainsIdentifier(message, trigger.getIdentifier())) {
42 IotSceneRuleMatcherHelper.logTriggerMatchFailure(message, trigger, "消息中不包含属性: " + 48 IotSceneRuleMatcherHelper.logTriggerMatchFailure(message, trigger, "消息中不包含属性: " +
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; @@ -7,7 +7,9 @@ import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
7 import cn.iocoder.yudao.module.iot.core.util.IotDeviceMessageUtils; 7 import cn.iocoder.yudao.module.iot.core.util.IotDeviceMessageUtils;
8 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO; 8 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
9 import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum; 9 import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum;
  10 +import cn.iocoder.yudao.module.iot.service.device.IotDeviceService;
10 import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.IotSceneRuleMatcherHelper; 11 import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.IotSceneRuleMatcherHelper;
  12 +import jakarta.annotation.Resource;
11 import org.springframework.stereotype.Component; 13 import org.springframework.stereotype.Component;
12 14
13 import java.util.Map; 15 import java.util.Map;
@@ -20,6 +22,9 @@ import java.util.Map; @@ -20,6 +22,9 @@ import java.util.Map;
20 @Component 22 @Component
21 public class IotDeviceServiceInvokeTriggerMatcher implements IotSceneRuleTriggerMatcher { 23 public class IotDeviceServiceInvokeTriggerMatcher implements IotSceneRuleTriggerMatcher {
22 24
  25 + @Resource
  26 + private IotDeviceService iotDeviceService;
  27 +
23 @Override 28 @Override
24 public IotSceneRuleTriggerTypeEnum getSupportedTriggerType() { 29 public IotSceneRuleTriggerTypeEnum getSupportedTriggerType() {
25 return IotSceneRuleTriggerTypeEnum.DEVICE_SERVICE_INVOKE; 30 return IotSceneRuleTriggerTypeEnum.DEVICE_SERVICE_INVOKE;
@@ -37,7 +42,12 @@ public class IotDeviceServiceInvokeTriggerMatcher implements IotSceneRuleTrigger @@ -37,7 +42,12 @@ public class IotDeviceServiceInvokeTriggerMatcher implements IotSceneRuleTrigger
37 IotSceneRuleMatcherHelper.logTriggerMatchFailure(message, trigger, "消息方法不匹配,期望: " + IotDeviceMessageMethodEnum.SERVICE_INVOKE.getMethod() + ", 实际: " + message.getMethod()); 42 IotSceneRuleMatcherHelper.logTriggerMatchFailure(message, trigger, "消息方法不匹配,期望: " + IotDeviceMessageMethodEnum.SERVICE_INVOKE.getMethod() + ", 实际: " + message.getMethod());
38 return false; 43 return false;
39 } 44 }
40 - // 1.3 检查标识符是否匹配 45 + // 1.3 修复触发器中忽略了产品和设备的一致性验证,2025.05.25 by panda
  46 + if (IotSceneRuleMatcherHelper.productAndDeviceNotMatched(message, trigger.getProductId(),trigger.getDeviceId())){
  47 + IotSceneRuleMatcherHelper.logTriggerMatchFailure(message,trigger,"触发器中产品或设备不匹配");
  48 + return false;
  49 + }
  50 + // 1.4 检查标识符是否匹配
41 String messageIdentifier = IotDeviceMessageUtils.getIdentifier(message); 51 String messageIdentifier = IotDeviceMessageUtils.getIdentifier(message);
42 if (!IotSceneRuleMatcherHelper.isIdentifierMatched(trigger.getIdentifier(), messageIdentifier)) { 52 if (!IotSceneRuleMatcherHelper.isIdentifierMatched(trigger.getIdentifier(), messageIdentifier)) {
43 IotSceneRuleMatcherHelper.logTriggerMatchFailure(message, trigger, "标识符不匹配,期望: " + trigger.getIdentifier() + ", 实际: " + messageIdentifier); 53 IotSceneRuleMatcherHelper.logTriggerMatchFailure(message, trigger, "标识符不匹配,期望: " + trigger.getIdentifier() + ", 实际: " + messageIdentifier);
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; @@ -5,7 +5,9 @@ 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.device.IotDeviceService;
8 import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.IotSceneRuleMatcherHelper; 9 import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.IotSceneRuleMatcherHelper;
  10 +import jakarta.annotation.Resource;
9 import org.springframework.stereotype.Component; 11 import org.springframework.stereotype.Component;
10 12
11 /** 13 /**
@@ -16,6 +18,9 @@ import org.springframework.stereotype.Component; @@ -16,6 +18,9 @@ import org.springframework.stereotype.Component;
16 @Component 18 @Component
17 public class IotDeviceStateUpdateTriggerMatcher implements IotSceneRuleTriggerMatcher { 19 public class IotDeviceStateUpdateTriggerMatcher implements IotSceneRuleTriggerMatcher {
18 20
  21 + @Resource
  22 + private IotDeviceService iotDeviceService;
  23 +
19 @Override 24 @Override
20 public IotSceneRuleTriggerTypeEnum getSupportedTriggerType() { 25 public IotSceneRuleTriggerTypeEnum getSupportedTriggerType() {
21 return IotSceneRuleTriggerTypeEnum.DEVICE_STATE_UPDATE; 26 return IotSceneRuleTriggerTypeEnum.DEVICE_STATE_UPDATE;
@@ -36,7 +41,13 @@ public class IotDeviceStateUpdateTriggerMatcher implements IotSceneRuleTriggerMa @@ -36,7 +41,13 @@ public class IotDeviceStateUpdateTriggerMatcher implements IotSceneRuleTriggerMa
36 return false; 41 return false;
37 } 42 }
38 43
39 - // 1.3 检查操作符和值是否有效 44 + // 1.3 修复触发器中忽略了产品和设备的一致性验证,2025.05.25 by panda
  45 + if (IotSceneRuleMatcherHelper.productAndDeviceNotMatched(message, trigger.getProductId(),trigger.getDeviceId())){
  46 + IotSceneRuleMatcherHelper.logTriggerMatchFailure(message,trigger,"触发器中产品或设备不匹配");
  47 + return false;
  48 + }
  49 +
  50 + // 1.4 检查操作符和值是否有效
40 if (!IotSceneRuleMatcherHelper.isTriggerOperatorAndValueValid(trigger)) { 51 if (!IotSceneRuleMatcherHelper.isTriggerOperatorAndValueValid(trigger)) {
41 IotSceneRuleMatcherHelper.logTriggerMatchFailure(message, trigger, "操作符或值无效"); 52 IotSceneRuleMatcherHelper.logTriggerMatchFailure(message, trigger, "操作符或值无效");
42 return false; 53 return false;