From 00bd4293f02e1f6104a21bc336ad05657b27d833 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 4 Aug 2025 22:13:07 +0800 Subject: [PATCH] =?UTF-8?q?review=EF=BC=9A=E3=80=90iot=20=E7=89=A9?= =?UTF-8?q?=E8=81=94=E7=BD=91=E3=80=91=E5=9C=BA=E6=99=AF=E8=81=94=E5=8A=A8?= =?UTF-8?q?=E7=9A=84=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dal/dataobject/rule/IotRuleSceneDO.java | 1 + .../dal/dataobject/rule/IotSceneRuleDO.java | 240 ------------------ .../rule/scene/IotRuleSceneServiceImpl.java | 50 +--- .../IotDeviceControlRuleSceneAction.java | 1 + 4 files changed, 7 insertions(+), 285 deletions(-) delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/rule/IotSceneRuleDO.java diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/rule/IotRuleSceneDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/rule/IotRuleSceneDO.java index 2b9cdc5cc5..5996baf52b 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/rule/IotRuleSceneDO.java +++ b/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 * diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/rule/IotSceneRuleDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/rule/IotSceneRuleDO.java deleted file mode 100644 index a65e0f3cf2..0000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/rule/IotSceneRuleDO.java +++ /dev/null @@ -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 triggers; - - /** - * 场景动作配置 - */ - @TableField(typeHandler = JacksonTypeHandler.class) - private List 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> 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; - - } - -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/IotRuleSceneServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/IotRuleSceneServiceImpl.java index dbf13ba9ab..7b30c80b82 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/IotRuleSceneServiceImpl.java +++ b/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 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 list = ruleSceneMapper.selectList(); @@ -471,13 +431,13 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService { return false; } - // 2. 构建 Spring 表达式的变量 + // 2.1 构建 Spring 表达式的变量 Map springExpressionVariables = MapUtil.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: {}", diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/action/IotDeviceControlRuleSceneAction.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/action/IotDeviceControlRuleSceneAction.java index b755307344..8899f5450b 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/action/IotDeviceControlRuleSceneAction.java +++ b/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) {