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 23  
24 24 import java.util.List;
25 25  
  26 +// TODO @puhui999:名字改成 IotSceneRuleDO
26 27 /**
27 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 77  
78 78 @Override
79 79 public Long createRuleScene(IotRuleSceneSaveReqVO createReqVO) {
80   - // 插入
81 80 IotRuleSceneDO ruleScene = BeanUtils.toBean(createReqVO, IotRuleSceneDO.class);
82 81 ruleSceneMapper.insert(ruleScene);
83   - // 返回
84 82 return ruleScene.getId();
85 83 }
86 84  
... ... @@ -147,45 +145,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
147 145 @Override
148 146 @TenantIgnore // 忽略租户隔离:因为 IotRuleSceneMessageHandler 调用时,一般未传递租户,所以需要忽略
149 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 151 List<IotRuleSceneDO> list = ruleSceneMapper.selectList();
... ... @@ -471,13 +431,13 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
471 431 return false;
472 432 }
473 433  
474   - // 2. 构建 Spring 表达式的变量
  434 + // 2.1 构建 Spring 表达式的变量
475 435 Map<String, Object> springExpressionVariables = MapUtil.<String, Object>builder()
476 436 .put(IotRuleSceneConditionOperatorEnum.SPRING_EXPRESSION_SOURCE, sourceValue)
477 437 .build();
478   -
479   - // 3. 根据操作符类型处理参数值
  438 + // 2.2 根据操作符类型处理参数值
480 439 if (StrUtil.isNotBlank(paramValue)) {
  440 + // TODO @puhui999:这里是不是在 IotRuleSceneConditionOperatorEnum 加个属性;
481 441 if (operatorEnum == IotRuleSceneConditionOperatorEnum.IN
482 442 || operatorEnum == IotRuleSceneConditionOperatorEnum.NOT_IN
483 443 || operatorEnum == IotRuleSceneConditionOperatorEnum.BETWEEN
... ... @@ -493,7 +453,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
493 453 }
494 454 }
495 455  
496   - // 4. 计算 Spring 表达式
  456 + // 3. 计算 Spring 表达式
497 457 return (Boolean) SpringExpressionUtils.parseExpression(operatorEnum.getSpringExpression(), springExpressionVariables);
498 458 } catch (Exception e) {
499 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 23 @Resource
24 24 private IotDeviceMessageService deviceMessageService;
25 25  
  26 + // TODO @puhui999:这里
26 27 @Override
27 28 public void execute(IotDeviceMessage message,
28 29 IotRuleSceneDO rule, IotRuleSceneDO.Action actionConfig) {
... ...