Commit 910bb6ca3c06eeae4d97b665ca61991722013bb0

Authored by YunaiV
1 parent a4be3bb8

【代码新增】IoT:完善 IotRuleSceneServiceImpl 的规则匹配计算,isTriggerConditionParameterMatched 函数有点长,= = 捉摸咋优化下

yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/number/NumberUtils.java
1 package cn.iocoder.yudao.framework.common.util.number; 1 package cn.iocoder.yudao.framework.common.util.number;
2 2
  3 +import cn.hutool.core.collection.CollUtil;
3 import cn.hutool.core.util.NumberUtil; 4 import cn.hutool.core.util.NumberUtil;
4 import cn.hutool.core.util.StrUtil; 5 import cn.hutool.core.util.StrUtil;
5 6
6 import java.math.BigDecimal; 7 import java.math.BigDecimal;
  8 +import java.util.List;
7 9
8 /** 10 /**
9 * 数字的工具类,补全 {@link cn.hutool.core.util.NumberUtil} 的功能 11 * 数字的工具类,补全 {@link cn.hutool.core.util.NumberUtil} 的功能
@@ -20,6 +22,18 @@ public class NumberUtils { @@ -20,6 +22,18 @@ public class NumberUtils {
20 return StrUtil.isNotEmpty(str) ? Integer.valueOf(str) : null; 22 return StrUtil.isNotEmpty(str) ? Integer.valueOf(str) : null;
21 } 23 }
22 24
  25 + public static boolean isAllNumber(List<String> values) {
  26 + if (CollUtil.isEmpty(values)) {
  27 + return false;
  28 + }
  29 + for (String value : values) {
  30 + if (!NumberUtil.isNumber(value)) {
  31 + return false;
  32 + }
  33 + }
  34 + return true;
  35 + }
  36 +
23 /** 37 /**
24 * 通过经纬度获取地球上两点之间的距离 38 * 通过经纬度获取地球上两点之间的距离
25 * 39 *
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/spring/SpringExpressionUtils.java
@@ -97,12 +97,26 @@ public class SpringExpressionUtils { @@ -97,12 +97,26 @@ public class SpringExpressionUtils {
97 * @return 执行界面 97 * @return 执行界面
98 */ 98 */
99 public static Object parseExpression(String expressionString) { 99 public static Object parseExpression(String expressionString) {
  100 + return parseExpression(expressionString, null);
  101 + }
  102 +
  103 + /**
  104 + * 从 Bean 工厂,解析 EL 表达式的结果
  105 + *
  106 + * @param expressionString EL 表达式
  107 + * @param variables 变量
  108 + * @return 执行界面
  109 + */
  110 + public static Object parseExpression(String expressionString, Map<String, Object> variables) {
100 if (StrUtil.isBlank(expressionString)) { 111 if (StrUtil.isBlank(expressionString)) {
101 return null; 112 return null;
102 } 113 }
103 Expression expression = EXPRESSION_PARSER.parseExpression(expressionString); 114 Expression expression = EXPRESSION_PARSER.parseExpression(expressionString);
104 StandardEvaluationContext context = new StandardEvaluationContext(); 115 StandardEvaluationContext context = new StandardEvaluationContext();
105 context.setBeanResolver(new BeanFactoryResolver(SpringUtil.getApplicationContext())); 116 context.setBeanResolver(new BeanFactoryResolver(SpringUtil.getApplicationContext()));
  117 + if (MapUtil.isNotEmpty(variables)) {
  118 + context.setVariables(variables);
  119 + }
106 return expression.getValue(context); 120 return expression.getValue(context);
107 } 121 }
108 122
yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/rule/IotRuleSceneTriggerConditionParameterOperatorEnum.java
@@ -16,29 +16,42 @@ import java.util.Arrays; @@ -16,29 +16,42 @@ import java.util.Arrays;
16 @Getter 16 @Getter
17 public enum IotRuleSceneTriggerConditionParameterOperatorEnum implements ArrayValuable<String> { 17 public enum IotRuleSceneTriggerConditionParameterOperatorEnum implements ArrayValuable<String> {
18 18
19 - EQUALS("=", "%s == %s"),  
20 - NOT_EQUALS("!=", "%s != %s"), 19 + EQUALS("=", "#source == #value"),
  20 + NOT_EQUALS("!=", "!(#source == #value)"),
21 21
22 - GREATER_THAN(">", "%s > %s"),  
23 - GREATER_THAN_OR_EQUALS(">=", "%s >= %s"), 22 + GREATER_THAN(">", "#source > #value"),
  23 + GREATER_THAN_OR_EQUALS(">=", "#source >= #value"),
24 24
25 - LESS_THAN("<", "%s < %s"),  
26 - LESS_THAN_OR_EQUALS("<=", "%s <= %s"), 25 + LESS_THAN("<", "#source < #value"),
  26 + LESS_THAN_OR_EQUALS("<=", "#source <= #value"),
27 27
28 - IN("in", "%s in { %s }"),  
29 - NOT_IN("not in", "%s not in { %s }"), 28 + IN("in", "#values.contains(#source)"),
  29 + NOT_IN("not in", "!(#values.contains(#source))"),
30 30
31 - BETWEEN("between", "(%s >= %s) && (%s <= %s)"),  
32 - NOT_BETWEEN("not between", "!(%s between %s and %s)"), 31 + BETWEEN("between", "(#source >= #values.get(0)) && (#source <= #values.get(1))"),
  32 + NOT_BETWEEN("not between", "(#source < #values.get(0)) || (#source > #values.get(1))"),
33 33
34 - LIKE("like", "%s like %s"), // 字符串匹配  
35 - NOT_NULL("not null", ""); // 非空 34 + LIKE("like", "#source.contains(#value)"), // 字符串匹配
  35 + NOT_NULL("not null", "#source != null && #source.length() > 0"); // 非空
36 36
37 private final String operator; 37 private final String operator;
38 private final String springExpression; 38 private final String springExpression;
39 39
40 public static final String[] ARRAYS = Arrays.stream(values()).map(IotRuleSceneTriggerConditionParameterOperatorEnum::getOperator).toArray(String[]::new); 40 public static final String[] ARRAYS = Arrays.stream(values()).map(IotRuleSceneTriggerConditionParameterOperatorEnum::getOperator).toArray(String[]::new);
41 41
  42 + /**
  43 + * Spring 表达式 - 原始值
  44 + */
  45 + public static final String SPRING_EXPRESSION_SOURCE = "source";
  46 + /**
  47 + * Spring 表达式 - 目标值
  48 + */
  49 + public static final String SPRING_EXPRESSION_VALUE = "value";
  50 + /**
  51 + * Spring 表达式 - 目标值数组
  52 + */
  53 + public static final String SPRING_EXPRESSION_VALUE_List = "values";
  54 +
42 public static IotRuleSceneTriggerConditionParameterOperatorEnum operatorOf(String operator) { 55 public static IotRuleSceneTriggerConditionParameterOperatorEnum operatorOf(String operator) {
43 return ArrayUtil.firstMatch(item -> item.getOperator().equals(operator), values()); 56 return ArrayUtil.firstMatch(item -> item.getOperator().equals(operator), values());
44 } 57 }
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/IotRuleSceneServiceImpl.java
@@ -2,9 +2,12 @@ package cn.iocoder.yudao.module.iot.service.rule; @@ -2,9 +2,12 @@ package cn.iocoder.yudao.module.iot.service.rule;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 import cn.hutool.core.collection.ListUtil; 4 import cn.hutool.core.collection.ListUtil;
  5 +import cn.hutool.core.map.MapUtil;
5 import cn.hutool.core.text.CharPool; 6 import cn.hutool.core.text.CharPool;
  7 +import cn.hutool.core.util.NumberUtil;
6 import cn.hutool.core.util.ObjUtil; 8 import cn.hutool.core.util.ObjUtil;
7 import cn.hutool.core.util.StrUtil; 9 import cn.hutool.core.util.StrUtil;
  10 +import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
8 import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; 11 import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
9 import cn.iocoder.yudao.framework.common.util.spring.SpringExpressionUtils; 12 import cn.iocoder.yudao.framework.common.util.spring.SpringExpressionUtils;
10 import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; 13 import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
@@ -20,9 +23,11 @@ import lombok.extern.slf4j.Slf4j; @@ -20,9 +23,11 @@ import lombok.extern.slf4j.Slf4j;
20 import org.springframework.stereotype.Service; 23 import org.springframework.stereotype.Service;
21 import org.springframework.validation.annotation.Validated; 24 import org.springframework.validation.annotation.Validated;
22 25
  26 +import java.util.HashMap;
23 import java.util.List; 27 import java.util.List;
24 import java.util.Map; 28 import java.util.Map;
25 29
  30 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
26 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList; 31 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList;
27 32
28 /** 33 /**
@@ -48,10 +53,16 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService { @@ -48,10 +53,16 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
48 IotRuleSceneDO.Trigger trigger01 = new IotRuleSceneDO.Trigger(); 53 IotRuleSceneDO.Trigger trigger01 = new IotRuleSceneDO.Trigger();
49 trigger01.setType(IotRuleSceneTriggerTypeEnum.DEVICE.getType()); 54 trigger01.setType(IotRuleSceneTriggerTypeEnum.DEVICE.getType());
50 trigger01.setConditions(CollUtil.newArrayList()); 55 trigger01.setConditions(CollUtil.newArrayList());
  56 + // 属性
51 IotRuleSceneDO.TriggerCondition condition01 = new IotRuleSceneDO.TriggerCondition(); 57 IotRuleSceneDO.TriggerCondition condition01 = new IotRuleSceneDO.TriggerCondition();
52 condition01.setType(IotDeviceMessageTypeEnum.PROPERTY.getType()); 58 condition01.setType(IotDeviceMessageTypeEnum.PROPERTY.getType());
53 condition01.setIdentifier(IotDeviceMessageIdentifierEnum.PROPERTY_REPORT.getIdentifier()); 59 condition01.setIdentifier(IotDeviceMessageIdentifierEnum.PROPERTY_REPORT.getIdentifier());
54 condition01.setParameters(CollUtil.newArrayList()); 60 condition01.setParameters(CollUtil.newArrayList());
  61 +// IotRuleSceneDO.TriggerConditionParameter parameter010 = new IotRuleSceneDO.TriggerConditionParameter();
  62 +// parameter010.setIdentifier("width");
  63 +// parameter010.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.EQUALS.getOperator());
  64 +// parameter010.setValue("abc");
  65 +// condition01.getParameters().add(parameter010);
55 IotRuleSceneDO.TriggerConditionParameter parameter011 = new IotRuleSceneDO.TriggerConditionParameter(); 66 IotRuleSceneDO.TriggerConditionParameter parameter011 = new IotRuleSceneDO.TriggerConditionParameter();
56 parameter011.setIdentifier("width"); 67 parameter011.setIdentifier("width");
57 parameter011.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.EQUALS.getOperator()); 68 parameter011.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.EQUALS.getOperator());
@@ -103,8 +114,23 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService { @@ -103,8 +114,23 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
103 parameter020.setValue("2,3"); 114 parameter020.setValue("2,3");
104 condition01.getParameters().add(parameter020); 115 condition01.getParameters().add(parameter020);
105 trigger01.getConditions().add(condition01); 116 trigger01.getConditions().add(condition01);
  117 + // 状态
  118 + IotRuleSceneDO.TriggerCondition condition02 = new IotRuleSceneDO.TriggerCondition();
  119 + condition02.setType(IotDeviceMessageTypeEnum.STATE.getType());
  120 + condition02.setIdentifier(IotDeviceMessageIdentifierEnum.STATE_ONLINE.getIdentifier());
  121 + condition02.setParameters(CollUtil.newArrayList());
  122 + trigger01.getConditions().add(condition02);
  123 + // TODO 芋艿:事件
  124 + IotRuleSceneDO.TriggerCondition condition03 = new IotRuleSceneDO.TriggerCondition();
  125 + condition03.setType(IotDeviceMessageTypeEnum.EVENT.getType());
  126 + condition03.setIdentifier("xxx");
  127 + condition03.setParameters(CollUtil.newArrayList());
  128 + IotRuleSceneDO.TriggerConditionParameter parameter030 = new IotRuleSceneDO.TriggerConditionParameter();
  129 + parameter030.setIdentifier("width");
  130 + parameter030.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.EQUALS.getOperator());
  131 + parameter030.setValue("1");
  132 + trigger01.getConditions().add(condition03);
106 ruleScene01.getTriggers().add(trigger01); 133 ruleScene01.getTriggers().add(trigger01);
107 -  
108 return ListUtil.toList(ruleScene01); 134 return ListUtil.toList(ruleScene01);
109 } 135 }
110 136
@@ -139,7 +165,6 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService { @@ -139,7 +165,6 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
139 * @param message 设备消息 165 * @param message 设备消息
140 * @return 规则场景列表 166 * @return 规则场景列表
141 */ 167 */
142 - @SuppressWarnings("unchecked")  
143 private List<IotRuleSceneDO> getMatchedRuleSceneList(IotDeviceMessage message) { 168 private List<IotRuleSceneDO> getMatchedRuleSceneList(IotDeviceMessage message) {
144 // 1. 匹配设备 169 // 1. 匹配设备
145 // TODO @芋艿:可能需要 getSelf(); 缓存 170 // TODO @芋艿:可能需要 getSelf(); 缓存
@@ -152,54 +177,27 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService { @@ -152,54 +177,27 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
152 // 2. 匹配 trigger 触发器的条件 177 // 2. 匹配 trigger 触发器的条件
153 return filterList(ruleScenes, ruleScene -> { 178 return filterList(ruleScenes, ruleScene -> {
154 for (IotRuleSceneDO.Trigger trigger : ruleScene.getTriggers()) { 179 for (IotRuleSceneDO.Trigger trigger : ruleScene.getTriggers()) {
155 - // 非设备触发,不匹配 180 + // 2.1 非设备触发,不匹配
156 if (ObjUtil.notEqual(trigger.getType(), IotRuleSceneTriggerTypeEnum.DEVICE.getType())) { 181 if (ObjUtil.notEqual(trigger.getType(), IotRuleSceneTriggerTypeEnum.DEVICE.getType())) {
157 return false; 182 return false;
158 } 183 }
159 // TODO 芋艿:产品、设备的匹配,要不要这里在做一次???貌似和 1. 部分重复了 184 // TODO 芋艿:产品、设备的匹配,要不要这里在做一次???貌似和 1. 部分重复了
160 - // 条件为空,说明没有匹配的条件,因此不匹配 185 + // 2.2 条件为空,说明没有匹配的条件,因此不匹配
161 if (CollUtil.isEmpty(trigger.getConditions())) { 186 if (CollUtil.isEmpty(trigger.getConditions())) {
162 return false; 187 return false;
163 } 188 }
164 - IotRuleSceneDO.TriggerCondition found = CollUtil.findOne(trigger.getConditions(), condition -> { 189 + // 2.3 多个条件,只需要满足一个即可
  190 + IotRuleSceneDO.TriggerCondition matchedCondition = CollUtil.findOne(trigger.getConditions(), condition -> {
165 if (ObjUtil.notEqual(message.getType(), condition.getType()) 191 if (ObjUtil.notEqual(message.getType(), condition.getType())
166 || ObjUtil.notEqual(message.getIdentifier(), condition.getIdentifier())) { 192 || ObjUtil.notEqual(message.getIdentifier(), condition.getIdentifier())) {
167 return false; 193 return false;
168 } 194 }
169 - // TODO @芋艿:设备上线,需要测试下。  
170 - for (IotRuleSceneDO.TriggerConditionParameter parameter : condition.getParameters()) {  
171 - // 计算是否匹配  
172 - IotRuleSceneTriggerConditionParameterOperatorEnum operator =  
173 - IotRuleSceneTriggerConditionParameterOperatorEnum.operatorOf(parameter.getOperator());  
174 - if (operator == null) {  
175 - log.error("[getMatchedRuleSceneList][规则场景编号({}) 的触发器({}) 存在错误的操作符({})]",  
176 - ruleScene.getId(), trigger, parameter.getOperator());  
177 - return false;  
178 - }  
179 - Object messageValue = ((Map<String, Object>) message.getData()).get(parameter.getIdentifier());  
180 - if (messageValue == null) {  
181 - return false;  
182 - }  
183 - String springExpression;  
184 - if (ObjectUtils.equalsAny(operator, IotRuleSceneTriggerConditionParameterOperatorEnum.BETWEEN,  
185 - IotRuleSceneTriggerConditionParameterOperatorEnum.NOT_BETWEEN)) {  
186 - String[] parameterValues = StrUtil.splitToArray(parameter.getValue(), CharPool.COMMA);  
187 - springExpression = String.format(operator.getSpringExpression(), messageValue, parameterValues[0],  
188 - messageValue, parameterValues[1]);  
189 - } else {  
190 - springExpression = String.format(operator.getSpringExpression(), messageValue, parameter.getValue());  
191 - }  
192 - // TODO @芋艿:【需优化】需要考虑 struct、时间等参数的比较  
193 - try {  
194 - System.out.println(SpringExpressionUtils.parseExpression(springExpression));  
195 - } catch (Exception e) {  
196 - log.error("[getMatchedRuleSceneList][消息({}) 规则场景编号({}) 的触发器({}) 的匹配表达式({}) 计算异常]",  
197 - message, ruleScene.getId(), trigger, springExpression, e);  
198 - }  
199 - }  
200 - return true; 195 + // 多个条件参数,必须全部满足。所以,下面的逻辑就是找到一个不满足的条件参数
  196 + IotRuleSceneDO.TriggerConditionParameter notMatchedParameter = CollUtil.findOne(condition.getParameters(),
  197 + parameter -> !isTriggerConditionParameterMatched(message, parameter, ruleScene, trigger));
  198 + return notMatchedParameter == null;
201 }); 199 });
202 - if (found == null) { 200 + if (matchedCondition == null) {
203 return false; 201 return false;
204 } 202 }
205 log.info("[getMatchedRuleSceneList][消息({}) 匹配到规则场景编号({}) 的触发器({})]", message, ruleScene.getId(), trigger); 203 log.info("[getMatchedRuleSceneList][消息({}) 匹配到规则场景编号({}) 的触发器({})]", message, ruleScene.getId(), trigger);
@@ -209,4 +207,68 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService { @@ -209,4 +207,68 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
209 }); 207 });
210 } 208 }
211 209
  210 + // TODO @芋艿:【可优化】可以考虑增加下单测,边界太多了。
  211 + /**
  212 + * 判断触发器的条件参数是否匹配
  213 + *
  214 + * @param message 设备消息
  215 + * @param parameter 触发器条件参数
  216 + * @param ruleScene 规则场景(用于日志,无其它作用)
  217 + * @param trigger 触发器(用于日志,无其它作用)
  218 + * @return 是否匹配
  219 + */
  220 + @SuppressWarnings({"unchecked", "DataFlowIssue"})
  221 + private boolean isTriggerConditionParameterMatched(IotDeviceMessage message, IotRuleSceneDO.TriggerConditionParameter parameter,
  222 + IotRuleSceneDO ruleScene, IotRuleSceneDO.Trigger trigger) {
  223 + // 计算是否匹配
  224 + IotRuleSceneTriggerConditionParameterOperatorEnum operator =
  225 + IotRuleSceneTriggerConditionParameterOperatorEnum.operatorOf(parameter.getOperator());
  226 + if (operator == null) {
  227 + log.error("[isTriggerConditionParameterMatched][规则场景编号({}) 的触发器({}) 存在错误的操作符({})]",
  228 + ruleScene.getId(), trigger, parameter.getOperator());
  229 + return false;
  230 + }
  231 + // TODO @芋艿:目前只支持方便转换成 string 的类型,如果是 struct、list 这种,需要考虑下
  232 + String messageValue = MapUtil.getStr((Map<String, Object>) message.getData(), parameter.getIdentifier());
  233 + if (messageValue == null) {
  234 + return false;
  235 + }
  236 + Map<String, Object> springExpressionVariables = new HashMap<>();
  237 + try {
  238 + springExpressionVariables.put(IotRuleSceneTriggerConditionParameterOperatorEnum.SPRING_EXPRESSION_SOURCE, messageValue);
  239 + springExpressionVariables.put(IotRuleSceneTriggerConditionParameterOperatorEnum.SPRING_EXPRESSION_VALUE, parameter.getValue());
  240 + if (ObjectUtils.equalsAny(operator, IotRuleSceneTriggerConditionParameterOperatorEnum.IN,
  241 + IotRuleSceneTriggerConditionParameterOperatorEnum.NOT_IN)) {
  242 + springExpressionVariables.put(IotRuleSceneTriggerConditionParameterOperatorEnum.SPRING_EXPRESSION_VALUE_List,
  243 + StrUtil.split(parameter.getValue(), CharPool.COMMA));
  244 + } else if (ObjectUtils.equalsAny(operator, IotRuleSceneTriggerConditionParameterOperatorEnum.BETWEEN,
  245 + IotRuleSceneTriggerConditionParameterOperatorEnum.NOT_BETWEEN)) {
  246 + List<String> parameterValues = StrUtil.splitTrim(parameter.getValue(), CharPool.COMMA);
  247 + if (NumberUtil.isNumber(messageValue) && NumberUtils.isAllNumber(parameterValues)) { // 特殊:解决数字的比较
  248 + springExpressionVariables.put(IotRuleSceneTriggerConditionParameterOperatorEnum.SPRING_EXPRESSION_SOURCE,
  249 + NumberUtil.parseDouble(messageValue));
  250 + springExpressionVariables.put(IotRuleSceneTriggerConditionParameterOperatorEnum.SPRING_EXPRESSION_VALUE_List,
  251 + convertList(parameterValues, NumberUtil::parseDouble));
  252 + } else {
  253 + springExpressionVariables.put(IotRuleSceneTriggerConditionParameterOperatorEnum.SPRING_EXPRESSION_VALUE_List, parameterValues);
  254 + }
  255 + } else if (ObjectUtils.equalsAny(operator, IotRuleSceneTriggerConditionParameterOperatorEnum.GREATER_THAN,
  256 + IotRuleSceneTriggerConditionParameterOperatorEnum.GREATER_THAN_OR_EQUALS,
  257 + IotRuleSceneTriggerConditionParameterOperatorEnum.LESS_THAN,
  258 + IotRuleSceneTriggerConditionParameterOperatorEnum.LESS_THAN_OR_EQUALS)) {
  259 + if (NumberUtil.isNumber(messageValue) && NumberUtil.isNumber(parameter.getValue())) { // 特殊:解决数字的比较
  260 + springExpressionVariables.put(IotRuleSceneTriggerConditionParameterOperatorEnum.SPRING_EXPRESSION_SOURCE,
  261 + NumberUtil.parseDouble(messageValue));
  262 + springExpressionVariables.put(IotRuleSceneTriggerConditionParameterOperatorEnum.SPRING_EXPRESSION_VALUE,
  263 + NumberUtil.parseDouble(parameter.getValue()));
  264 + }
  265 + }
  266 + return (Boolean) SpringExpressionUtils.parseExpression(operator.getSpringExpression(), springExpressionVariables);
  267 + } catch (Exception e) {
  268 + log.error("[isTriggerConditionParameterMatched][消息({}) 规则场景编号({}) 的触发器({}) 的匹配表达式({}/{}) 计算异常]",
  269 + message, ruleScene.getId(), trigger, operator, springExpressionVariables, e);
  270 + return false;
  271 + }
  272 + }
  273 +
212 } 274 }