Commit 00bd4293f02e1f6104a21bc336ad05657b27d833

Authored by YunaiV
1 parent e7a09de3

review:【iot 物联网】场景联动的逻辑

yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/rule/IotRuleSceneDO.java
@@ -23,6 +23,7 @@ import lombok.NoArgsConstructor; @@ -23,6 +23,7 @@ import lombok.NoArgsConstructor;
23 23
24 import java.util.List; 24 import java.util.List;
25 25
  26 +// TODO @puhui999:名字改成 IotSceneRuleDO
26 /** 27 /**
27 * IoT 场景联动规则 DO 28 * IoT 场景联动规则 DO
28 * 29 *
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/rule/IotSceneRuleDO.java deleted
1 -package cn.iocoder.yudao.module.iot.dal.dataobject.rule;  
2 -  
3 -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;  
4 -import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;  
5 -import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;  
6 -import cn.iocoder.yudao.module.iot.dal.dataobject.alert.IotAlertConfigDO;  
7 -import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;  
8 -import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;  
9 -import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO;  
10 -import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum;  
11 -import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneConditionOperatorEnum;  
12 -import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneConditionTypeEnum;  
13 -import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneTriggerTypeEnum;  
14 -import com.baomidou.mybatisplus.annotation.KeySequence;  
15 -import com.baomidou.mybatisplus.annotation.TableField;  
16 -import com.baomidou.mybatisplus.annotation.TableId;  
17 -import com.baomidou.mybatisplus.annotation.TableName;  
18 -import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;  
19 -import lombok.AllArgsConstructor;  
20 -import lombok.Builder;  
21 -import lombok.Data;  
22 -import lombok.NoArgsConstructor;  
23 -  
24 -import java.util.List;  
25 -  
26 -// TODO @puhui999:还是在 IotRuleSceneDO 里搞,这里主要可以看到变化字段哈。  
27 -/**  
28 - * IoT 场景联动 DO  
29 - *  
30 - * 基于 {@link Trigger} 触发 {@link Action}  
31 - *  
32 - * @author 芋道源码  
33 - */  
34 -@TableName(value = "iot_scene_rule", autoResultMap = true)  
35 -@KeySequence("iot_scene_rule_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。  
36 -@Data  
37 -@Builder  
38 -@NoArgsConstructor  
39 -@AllArgsConstructor  
40 -public class IotSceneRuleDO extends TenantBaseDO {  
41 -  
42 - /**  
43 - * 场景联动编号  
44 - */  
45 - @TableId  
46 - private Long id;  
47 - /**  
48 - * 场景联动名称  
49 - */  
50 - private String name;  
51 - /**  
52 - * 场景联动描述  
53 - */  
54 - private String description;  
55 - /**  
56 - * 场景联动状态  
57 - *  
58 - * 枚举 {@link CommonStatusEnum}  
59 - */  
60 - private Integer status;  
61 -  
62 - /**  
63 - * 场景定义配置  
64 - */  
65 - @TableField(typeHandler = JacksonTypeHandler.class)  
66 - private List<Trigger> triggers;  
67 -  
68 - /**  
69 - * 场景动作配置  
70 - */  
71 - @TableField(typeHandler = JacksonTypeHandler.class)  
72 - private List<Action> actions;  
73 -  
74 - /**  
75 - * 场景定义配置  
76 - */  
77 - @Data  
78 - public static class Trigger {  
79 -  
80 - // ========== 事件部分 ==========  
81 -  
82 - /**  
83 - * 场景事件类型  
84 - *  
85 - * 枚举 {@link IotRuleSceneTriggerTypeEnum}  
86 - * 1. {@link IotRuleSceneTriggerTypeEnum#DEVICE_STATE_UPDATE} 时,operator 非空,并且 value 为在线状态  
87 - * 2. {@link IotRuleSceneTriggerTypeEnum#DEVICE_PROPERTY_POST}  
88 - * {@link IotRuleSceneTriggerTypeEnum#DEVICE_EVENT_POST} 时,identifier、operator 非空,并且 value 为属性值  
89 - * 3. {@link IotRuleSceneTriggerTypeEnum#DEVICE_EVENT_POST}  
90 - * {@link IotRuleSceneTriggerTypeEnum#DEVICE_SERVICE_INVOKE} 时,identifier 非空,但是 operator、value 为空  
91 - * 4. {@link IotRuleSceneTriggerTypeEnum#TIMER} 时,conditions 非空,并且设备无关(无需 productId、deviceId 字段)  
92 - */  
93 - private Integer type;  
94 -  
95 - /**  
96 - * 产品编号  
97 - *  
98 - * 关联 {@link IotProductDO#getId()}  
99 - */  
100 - private Long productId;  
101 - /**  
102 - * 设备编号  
103 - *  
104 - * 关联 {@link IotDeviceDO#getId()}  
105 - * 特殊:如果为 {@link IotDeviceDO#DEVICE_ID_ALL} 时,则是全部设备  
106 - */  
107 - private Long deviceId;  
108 - /**  
109 - * 物模型标识符  
110 - *  
111 - * 对应:{@link IotThingModelDO#getIdentifier()}  
112 - */  
113 - private String identifier;  
114 - /**  
115 - * 操作符  
116 - *  
117 - * 枚举 {@link IotRuleSceneConditionOperatorEnum}  
118 - */  
119 - private String operator;  
120 - /**  
121 - * 参数(属性值、在线状态)  
122 - *  
123 - * 如果有多个值,则使用 "," 分隔,类似 "1,2,3"。  
124 - * 例如说,{@link IotRuleSceneConditionOperatorEnum#IN}、{@link IotRuleSceneConditionOperatorEnum#BETWEEN}  
125 - */  
126 - private String value;  
127 -  
128 - /**  
129 - * CRON 表达式  
130 - */  
131 - private String cronExpression;  
132 -  
133 - // ========== 条件部分 ==========  
134 -  
135 - /**  
136 - * 触发条件分组(状态条件分组)的数组  
137 - *  
138 - * 第一层 List:分组与分组之间,是“或”的关系  
139 - * 第二层 List:条件与条件之间,是“且”的关系  
140 - */  
141 - private List<List<TriggerCondition>> conditionGroups;  
142 -  
143 - }  
144 -  
145 - /**  
146 - * 触发条件(状态条件)  
147 - */  
148 - @Data  
149 - public static class TriggerCondition {  
150 -  
151 - /**  
152 - * 触发条件类型  
153 - *  
154 - * 枚举 {@link IotRuleSceneConditionTypeEnum}  
155 - * 1. {@link IotRuleSceneConditionTypeEnum#DEVICE_STATE} 时,operator 非空,并且 value 为在线状态  
156 - * 2. {@link IotRuleSceneConditionTypeEnum#DEVICE_PROPERTY} 时,identifier、operator 非空,并且 value 为属性值  
157 - * 3. {@link IotRuleSceneConditionTypeEnum#CURRENT_TIME} 时,operator 非空(使用 DATE_TIME_ 和 TIME_ 部分),并且 value 非空  
158 - */  
159 - private Integer type;  
160 -  
161 - /**  
162 - * 产品编号  
163 - *  
164 - * 关联 {@link IotProductDO#getId()}  
165 - */  
166 - private Long productId;  
167 - /**  
168 - * 设备编号  
169 - *  
170 - * 关联 {@link IotDeviceDO#getId()}  
171 - */  
172 - private Long deviceId;  
173 - /**  
174 - * 标识符(属性)  
175 - *  
176 - * 关联 {@link IotThingModelDO#getIdentifier()}  
177 - */  
178 - private String identifier;  
179 - /**  
180 - * 操作符  
181 - *  
182 - * 枚举 {@link IotRuleSceneConditionOperatorEnum}  
183 - */  
184 - private String operator;  
185 - /**  
186 - * 参数  
187 - *  
188 - * 如果有多个值,则使用 "," 分隔,类似 "1,2,3"。  
189 - * 例如说,{@link IotRuleSceneConditionOperatorEnum#IN}、{@link IotRuleSceneConditionOperatorEnum#BETWEEN}  
190 - */  
191 - private String param;  
192 -  
193 - }  
194 -  
195 - /**  
196 - * 场景动作配置  
197 - */  
198 - @Data  
199 - public static class Action {  
200 -  
201 - /**  
202 - * 执行类型  
203 - *  
204 - * 枚举 {@link IotRuleSceneActionTypeEnum}  
205 - * 1. {@link IotRuleSceneActionTypeEnum#DEVICE_PROPERTY_SET} 时,params 非空  
206 - * {@link IotRuleSceneActionTypeEnum#DEVICE_SERVICE_INVOKE} 时,params 非空  
207 - * 2. {@link IotRuleSceneActionTypeEnum#ALERT_TRIGGER} 时,alertConfigId 为空,因为是 {@link IotAlertConfigDO} 里面关联它  
208 - * 3. {@link IotRuleSceneActionTypeEnum#ALERT_RECOVER} 时,alertConfigId 非空  
209 - */  
210 - private Integer type;  
211 -  
212 - /**  
213 - * 产品编号  
214 - *  
215 - * 关联 {@link IotProductDO#getId()}  
216 - */  
217 - private Long productId;  
218 - /**  
219 - * 设备编号  
220 - *  
221 - * 关联 {@link IotDeviceDO#getId()}  
222 - */  
223 - private Long deviceId;  
224 - /**  
225 - * 请求参数  
226 - *  
227 - * 一般来说,对应 {@link IotDeviceMessage#getParams()} 请求参数  
228 - */  
229 - private Object params;  
230 -  
231 - /**  
232 - * 告警配置编号  
233 - *  
234 - * 关联 {@link IotAlertConfigDO#getId()}  
235 - */  
236 - private Long alertConfigId;  
237 -  
238 - }  
239 -  
240 -}  
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/IotRuleSceneServiceImpl.java
@@ -77,10 +77,8 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService { @@ -77,10 +77,8 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
77 77
78 @Override 78 @Override
79 public Long createRuleScene(IotRuleSceneSaveReqVO createReqVO) { 79 public Long createRuleScene(IotRuleSceneSaveReqVO createReqVO) {
80 - // 插入  
81 IotRuleSceneDO ruleScene = BeanUtils.toBean(createReqVO, IotRuleSceneDO.class); 80 IotRuleSceneDO ruleScene = BeanUtils.toBean(createReqVO, IotRuleSceneDO.class);
82 ruleSceneMapper.insert(ruleScene); 81 ruleSceneMapper.insert(ruleScene);
83 - // 返回  
84 return ruleScene.getId(); 82 return ruleScene.getId();
85 } 83 }
86 84
@@ -147,45 +145,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService { @@ -147,45 +145,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
147 @Override 145 @Override
148 @TenantIgnore // 忽略租户隔离:因为 IotRuleSceneMessageHandler 调用时,一般未传递租户,所以需要忽略 146 @TenantIgnore // 忽略租户隔离:因为 IotRuleSceneMessageHandler 调用时,一般未传递租户,所以需要忽略
149 public List<IotRuleSceneDO> getRuleSceneListByProductKeyAndDeviceNameFromCache(String productKey, String deviceName) { 147 public List<IotRuleSceneDO> getRuleSceneListByProductKeyAndDeviceNameFromCache(String productKey, String deviceName) {
150 - // TODO @芋艿:测试代码示例(使用新结构),可根据需要启用  
151 - if (false) {  
152 - // 创建测试规则场景  
153 - IotRuleSceneDO ruleScene = new IotRuleSceneDO();  
154 - ruleScene.setId(1L);  
155 - ruleScene.setName("测试场景");  
156 - ruleScene.setStatus(CommonStatusEnum.ENABLE.getStatus());  
157 -  
158 - // 创建触发器  
159 - IotRuleSceneDO.Trigger trigger = new IotRuleSceneDO.Trigger();  
160 - trigger.setType(IotRuleSceneTriggerTypeEnum.DEVICE_PROPERTY_POST.getType());  
161 - trigger.setProductId(1L); // 假设产品ID为1  
162 - trigger.setDeviceId(1L); // 假设设备ID为1  
163 - trigger.setIdentifier("temperature"); // 温度属性  
164 - trigger.setOperator(IotRuleSceneConditionOperatorEnum.GREATER_THAN.getOperator());  
165 - trigger.setValue("25"); // 温度大于25度  
166 -  
167 - // 创建条件分组  
168 - IotRuleSceneDO.TriggerCondition condition = new IotRuleSceneDO.TriggerCondition();  
169 - condition.setType(IotRuleSceneConditionTypeEnum.DEVICE_PROPERTY.getType());  
170 - condition.setIdentifier("temperature");  
171 - condition.setOperator(IotRuleSceneConditionOperatorEnum.GREATER_THAN.getOperator());  
172 - condition.setParam("25");  
173 -  
174 - trigger.setConditionGroups(ListUtil.toList(Collections.singleton(ListUtil.toList(condition))));  
175 - ruleScene.setTriggers(ListUtil.toList(trigger));  
176 -  
177 - // 创建动作  
178 - IotRuleSceneDO.Action action = new IotRuleSceneDO.Action();  
179 - action.setType(IotRuleSceneActionTypeEnum.DEVICE_PROPERTY_SET.getType());  
180 - action.setProductId(1L);  
181 - action.setDeviceId(1L);  
182 - action.setParams(MapUtil.of("fan", "on")); // 打开风扇  
183 -  
184 - ruleScene.setActions(ListUtil.toList(action));  
185 -  
186 - return ListUtil.toList(ruleScene);  
187 - }  
188 - 148 + // TODO @puhui999:一些注释,看看要不要优化下;
189 // 注意:旧的测试代码已删除,因为使用了废弃的数据结构 149 // 注意:旧的测试代码已删除,因为使用了废弃的数据结构
190 // 如需测试,请使用上面的新结构测试代码示例 150 // 如需测试,请使用上面的新结构测试代码示例
191 List<IotRuleSceneDO> list = ruleSceneMapper.selectList(); 151 List<IotRuleSceneDO> list = ruleSceneMapper.selectList();
@@ -471,13 +431,13 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService { @@ -471,13 +431,13 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
471 return false; 431 return false;
472 } 432 }
473 433
474 - // 2. 构建 Spring 表达式的变量 434 + // 2.1 构建 Spring 表达式的变量
475 Map<String, Object> springExpressionVariables = MapUtil.<String, Object>builder() 435 Map<String, Object> springExpressionVariables = MapUtil.<String, Object>builder()
476 .put(IotRuleSceneConditionOperatorEnum.SPRING_EXPRESSION_SOURCE, sourceValue) 436 .put(IotRuleSceneConditionOperatorEnum.SPRING_EXPRESSION_SOURCE, sourceValue)
477 .build(); 437 .build();
478 -  
479 - // 3. 根据操作符类型处理参数值 438 + // 2.2 根据操作符类型处理参数值
480 if (StrUtil.isNotBlank(paramValue)) { 439 if (StrUtil.isNotBlank(paramValue)) {
  440 + // TODO @puhui999:这里是不是在 IotRuleSceneConditionOperatorEnum 加个属性;
481 if (operatorEnum == IotRuleSceneConditionOperatorEnum.IN 441 if (operatorEnum == IotRuleSceneConditionOperatorEnum.IN
482 || operatorEnum == IotRuleSceneConditionOperatorEnum.NOT_IN 442 || operatorEnum == IotRuleSceneConditionOperatorEnum.NOT_IN
483 || operatorEnum == IotRuleSceneConditionOperatorEnum.BETWEEN 443 || operatorEnum == IotRuleSceneConditionOperatorEnum.BETWEEN
@@ -493,7 +453,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService { @@ -493,7 +453,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
493 } 453 }
494 } 454 }
495 455
496 - // 4. 计算 Spring 表达式 456 + // 3. 计算 Spring 表达式
497 return (Boolean) SpringExpressionUtils.parseExpression(operatorEnum.getSpringExpression(), springExpressionVariables); 457 return (Boolean) SpringExpressionUtils.parseExpression(operatorEnum.getSpringExpression(), springExpressionVariables);
498 } catch (Exception e) { 458 } catch (Exception e) {
499 log.error("[evaluateCondition][条件评估异常] sourceValue: {}, operator: {}, paramValue: {}", 459 log.error("[evaluateCondition][条件评估异常] sourceValue: {}, operator: {}, paramValue: {}",
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/action/IotDeviceControlRuleSceneAction.java
@@ -23,6 +23,7 @@ public class IotDeviceControlRuleSceneAction implements IotSceneRuleAction { @@ -23,6 +23,7 @@ public class IotDeviceControlRuleSceneAction implements IotSceneRuleAction {
23 @Resource 23 @Resource
24 private IotDeviceMessageService deviceMessageService; 24 private IotDeviceMessageService deviceMessageService;
25 25
  26 + // TODO @puhui999:这里
26 @Override 27 @Override
27 public void execute(IotDeviceMessage message, 28 public void execute(IotDeviceMessage message,
28 IotRuleSceneDO rule, IotRuleSceneDO.Action actionConfig) { 29 IotRuleSceneDO rule, IotRuleSceneDO.Action actionConfig) {