Explorar o código

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

YunaiV hai 1 ano
pai
achega
00bd4293f0

+ 1 - 0
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;
 
 import java.util.List;
 
+// TODO @puhui999:名字改成 IotSceneRuleDO
 /**
  * IoT 场景联动规则 DO
  *

+ 0 - 240
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/rule/IotSceneRuleDO.java

@@ -1,240 +0,0 @@
-package cn.iocoder.yudao.module.iot.dal.dataobject.rule;
-
-import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
-import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
-import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
-import cn.iocoder.yudao.module.iot.dal.dataobject.alert.IotAlertConfigDO;
-import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
-import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
-import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO;
-import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum;
-import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneConditionOperatorEnum;
-import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneConditionTypeEnum;
-import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneTriggerTypeEnum;
-import com.baomidou.mybatisplus.annotation.KeySequence;
-import com.baomidou.mybatisplus.annotation.TableField;
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableName;
-import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.util.List;
-
-// TODO @puhui999:还是在 IotRuleSceneDO 里搞,这里主要可以看到变化字段哈。
-/**
- * IoT 场景联动 DO
- *
- * 基于 {@link Trigger} 触发 {@link Action}
- *
- * @author 芋道源码
- */
-@TableName(value = "iot_scene_rule", autoResultMap = true)
-@KeySequence("iot_scene_rule_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
-@Data
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class IotSceneRuleDO extends TenantBaseDO {
-
-    /**
-     * 场景联动编号
-     */
-    @TableId
-    private Long id;
-    /**
-     * 场景联动名称
-     */
-    private String name;
-    /**
-     * 场景联动描述
-     */
-    private String description;
-    /**
-     * 场景联动状态
-     *
-     * 枚举 {@link CommonStatusEnum}
-     */
-    private Integer status;
-
-    /**
-     * 场景定义配置
-     */
-    @TableField(typeHandler = JacksonTypeHandler.class)
-    private List<Trigger> triggers;
-
-    /**
-     * 场景动作配置
-     */
-    @TableField(typeHandler = JacksonTypeHandler.class)
-    private List<Action> actions;
-
-    /**
-     * 场景定义配置
-     */
-    @Data
-    public static class Trigger {
-
-        // ========== 事件部分 ==========
-
-        /**
-         * 场景事件类型
-         *
-         * 枚举 {@link IotRuleSceneTriggerTypeEnum}
-         * 1. {@link IotRuleSceneTriggerTypeEnum#DEVICE_STATE_UPDATE} 时,operator 非空,并且 value 为在线状态
-         * 2. {@link IotRuleSceneTriggerTypeEnum#DEVICE_PROPERTY_POST}
-         *    {@link IotRuleSceneTriggerTypeEnum#DEVICE_EVENT_POST} 时,identifier、operator 非空,并且 value 为属性值
-         * 3. {@link IotRuleSceneTriggerTypeEnum#DEVICE_EVENT_POST}
-         *    {@link IotRuleSceneTriggerTypeEnum#DEVICE_SERVICE_INVOKE} 时,identifier 非空,但是 operator、value 为空
-         * 4. {@link IotRuleSceneTriggerTypeEnum#TIMER} 时,conditions 非空,并且设备无关(无需 productId、deviceId 字段)
-         */
-        private Integer type;
-
-        /**
-         * 产品编号
-         *
-         * 关联 {@link IotProductDO#getId()}
-         */
-        private Long productId;
-        /**
-         * 设备编号
-         *
-         * 关联 {@link IotDeviceDO#getId()}
-         * 特殊:如果为 {@link IotDeviceDO#DEVICE_ID_ALL} 时,则是全部设备
-         */
-        private Long deviceId;
-        /**
-         * 物模型标识符
-         *
-         * 对应:{@link IotThingModelDO#getIdentifier()}
-         */
-        private String identifier;
-        /**
-         * 操作符
-         *
-         * 枚举 {@link IotRuleSceneConditionOperatorEnum}
-         */
-        private String operator;
-        /**
-         * 参数(属性值、在线状态)
-         *
-         * 如果有多个值,则使用 "," 分隔,类似 "1,2,3"。
-         * 例如说,{@link IotRuleSceneConditionOperatorEnum#IN}、{@link IotRuleSceneConditionOperatorEnum#BETWEEN}
-         */
-        private String value;
-
-        /**
-         * CRON 表达式
-         */
-        private String cronExpression;
-
-        // ========== 条件部分 ==========
-
-        /**
-         * 触发条件分组(状态条件分组)的数组
-         *
-         * 第一层 List:分组与分组之间,是“或”的关系
-         * 第二层 List:条件与条件之间,是“且”的关系
-         */
-        private List<List<TriggerCondition>> conditionGroups;
-
-    }
-
-    /**
-     * 触发条件(状态条件)
-     */
-    @Data
-    public static class TriggerCondition {
-
-        /**
-         * 触发条件类型
-         *
-         * 枚举 {@link IotRuleSceneConditionTypeEnum}
-         * 1. {@link IotRuleSceneConditionTypeEnum#DEVICE_STATE} 时,operator 非空,并且 value 为在线状态
-         * 2. {@link IotRuleSceneConditionTypeEnum#DEVICE_PROPERTY} 时,identifier、operator 非空,并且 value 为属性值
-         * 3. {@link IotRuleSceneConditionTypeEnum#CURRENT_TIME} 时,operator 非空(使用 DATE_TIME_ 和 TIME_ 部分),并且 value 非空
-         */
-        private Integer type;
-
-        /**
-         * 产品编号
-         *
-         * 关联 {@link IotProductDO#getId()}
-         */
-        private Long productId;
-        /**
-         * 设备编号
-         *
-         * 关联 {@link IotDeviceDO#getId()}
-         */
-        private Long deviceId;
-        /**
-         * 标识符(属性)
-         *
-         * 关联 {@link IotThingModelDO#getIdentifier()}
-         */
-        private String identifier;
-        /**
-         * 操作符
-         *
-         * 枚举 {@link IotRuleSceneConditionOperatorEnum}
-         */
-        private String operator;
-        /**
-         * 参数
-         *
-         * 如果有多个值,则使用 "," 分隔,类似 "1,2,3"。
-         * 例如说,{@link IotRuleSceneConditionOperatorEnum#IN}、{@link IotRuleSceneConditionOperatorEnum#BETWEEN}
-         */
-        private String param;
-
-    }
-
-    /**
-     * 场景动作配置
-     */
-    @Data
-    public static class Action {
-
-        /**
-         * 执行类型
-         *
-         * 枚举 {@link IotRuleSceneActionTypeEnum}
-         * 1. {@link IotRuleSceneActionTypeEnum#DEVICE_PROPERTY_SET} 时,params 非空
-         *    {@link IotRuleSceneActionTypeEnum#DEVICE_SERVICE_INVOKE} 时,params 非空
-         * 2. {@link IotRuleSceneActionTypeEnum#ALERT_TRIGGER} 时,alertConfigId 为空,因为是 {@link IotAlertConfigDO} 里面关联它
-         * 3. {@link IotRuleSceneActionTypeEnum#ALERT_RECOVER} 时,alertConfigId 非空
-         */
-        private Integer type;
-
-        /**
-         * 产品编号
-         *
-         * 关联 {@link IotProductDO#getId()}
-         */
-        private Long productId;
-        /**
-         * 设备编号
-         *
-         * 关联 {@link IotDeviceDO#getId()}
-         */
-        private Long deviceId;
-        /**
-         * 请求参数
-         *
-         * 一般来说,对应 {@link IotDeviceMessage#getParams()} 请求参数
-         */
-        private Object params;
-
-        /**
-         * 告警配置编号
-         *
-         * 关联 {@link IotAlertConfigDO#getId()}
-         */
-        private Long alertConfigId;
-
-    }
-
-}

+ 5 - 45
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 {
 
     @Override
     public Long createRuleScene(IotRuleSceneSaveReqVO createReqVO) {
-        // 插入
         IotRuleSceneDO ruleScene = BeanUtils.toBean(createReqVO, IotRuleSceneDO.class);
         ruleSceneMapper.insert(ruleScene);
-        // 返回
         return ruleScene.getId();
     }
 
@@ -147,45 +145,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
     @Override
     @TenantIgnore // 忽略租户隔离:因为 IotRuleSceneMessageHandler 调用时,一般未传递租户,所以需要忽略
     public List<IotRuleSceneDO> getRuleSceneListByProductKeyAndDeviceNameFromCache(String productKey, String deviceName) {
-        // TODO @芋艿:测试代码示例(使用新结构),可根据需要启用
-        if (false) {
-            // 创建测试规则场景
-            IotRuleSceneDO ruleScene = new IotRuleSceneDO();
-            ruleScene.setId(1L);
-            ruleScene.setName("测试场景");
-            ruleScene.setStatus(CommonStatusEnum.ENABLE.getStatus());
-
-            // 创建触发器
-            IotRuleSceneDO.Trigger trigger = new IotRuleSceneDO.Trigger();
-            trigger.setType(IotRuleSceneTriggerTypeEnum.DEVICE_PROPERTY_POST.getType());
-            trigger.setProductId(1L); // 假设产品ID为1
-            trigger.setDeviceId(1L);  // 假设设备ID为1
-            trigger.setIdentifier("temperature"); // 温度属性
-            trigger.setOperator(IotRuleSceneConditionOperatorEnum.GREATER_THAN.getOperator());
-            trigger.setValue("25"); // 温度大于25度
-
-            // 创建条件分组
-            IotRuleSceneDO.TriggerCondition condition = new IotRuleSceneDO.TriggerCondition();
-            condition.setType(IotRuleSceneConditionTypeEnum.DEVICE_PROPERTY.getType());
-            condition.setIdentifier("temperature");
-            condition.setOperator(IotRuleSceneConditionOperatorEnum.GREATER_THAN.getOperator());
-            condition.setParam("25");
-
-            trigger.setConditionGroups(ListUtil.toList(Collections.singleton(ListUtil.toList(condition))));
-            ruleScene.setTriggers(ListUtil.toList(trigger));
-
-            // 创建动作
-            IotRuleSceneDO.Action action = new IotRuleSceneDO.Action();
-            action.setType(IotRuleSceneActionTypeEnum.DEVICE_PROPERTY_SET.getType());
-            action.setProductId(1L);
-            action.setDeviceId(1L);
-            action.setParams(MapUtil.of("fan", "on")); // 打开风扇
-
-            ruleScene.setActions(ListUtil.toList(action));
-
-            return ListUtil.toList(ruleScene);
-        }
-
+        // TODO @puhui999:一些注释,看看要不要优化下;
         // 注意:旧的测试代码已删除,因为使用了废弃的数据结构
         // 如需测试,请使用上面的新结构测试代码示例
         List<IotRuleSceneDO> list = ruleSceneMapper.selectList();
@@ -471,13 +431,13 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
                 return false;
             }
 
-            // 2. 构建 Spring 表达式的变量
+            // 2.1 构建 Spring 表达式的变量
             Map<String, Object> springExpressionVariables = MapUtil.<String, Object>builder()
                     .put(IotRuleSceneConditionOperatorEnum.SPRING_EXPRESSION_SOURCE, sourceValue)
                     .build();
-
-            // 3. 根据操作符类型处理参数值
+            // 2.2 根据操作符类型处理参数值
             if (StrUtil.isNotBlank(paramValue)) {
+                // TODO @puhui999:这里是不是在 IotRuleSceneConditionOperatorEnum 加个属性;
                 if (operatorEnum == IotRuleSceneConditionOperatorEnum.IN
                         || operatorEnum == IotRuleSceneConditionOperatorEnum.NOT_IN
                         || operatorEnum == IotRuleSceneConditionOperatorEnum.BETWEEN
@@ -493,7 +453,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
                 }
             }
 
-            // 4. 计算 Spring 表达式
+            // 3. 计算 Spring 表达式
             return (Boolean) SpringExpressionUtils.parseExpression(operatorEnum.getSpringExpression(), springExpressionVariables);
         } catch (Exception e) {
             log.error("[evaluateCondition][条件评估异常] sourceValue: {}, operator: {}, paramValue: {}",

+ 1 - 0
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 {
     @Resource
     private IotDeviceMessageService deviceMessageService;
 
+    // TODO @puhui999:这里
     @Override
     public void execute(IotDeviceMessage message,
                         IotRuleSceneDO rule, IotRuleSceneDO.Action actionConfig) {