Commit 910bb6ca3c06eeae4d97b665ca61991722013bb0
1 parent
a4be3bb8
【代码新增】IoT:完善 IotRuleSceneServiceImpl 的规则匹配计算,isTriggerConditionParameterMatched 函数有点长,= = 捉摸咋优化下
Showing
4 changed files
with
153 additions
and
50 deletions
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 | } |