فهرست منبع

!1296 【功能新增】IoT: 规则场景
Merge pull request !1296 from puhui999/iot

芋道源码 7 ماه پیش
والد
کامیت
35dd91d6c9
28فایلهای تغییر یافته به همراه649 افزوده شده و 388 حذف شده
  1. 3 0
      yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/ErrorCodeConstants.java
  2. 1 1
      yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/rule/IotRuleSceneTriggerConditionParameterOperatorEnum.java
  3. 55 3
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/IotRuleSceneController.java
  4. 33 0
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/scene/IotRuleScenePageReqVO.java
  5. 36 0
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/scene/IotRuleSceneRespVO.java
  6. 41 0
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/scene/IotRuleSceneSaveReqVO.java
  7. 37 0
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/scene/config/IotRuleSceneActionConfig.java
  8. 57 0
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/scene/config/IotRuleSceneActionDeviceControl.java
  9. 37 0
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/scene/config/IotRuleSceneTriggerCondition.java
  10. 37 0
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/scene/config/IotRuleSceneTriggerConditionParameter.java
  11. 53 0
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/scene/config/IotRuleSceneTriggerConfig.java
  12. 2 3
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/IotThingModelController.http
  13. 5 9
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/IotThingModelController.java
  14. 0 6
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/vo/IotThingModelRespVO.java
  15. 30 0
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/vo/IotThingModelTSLRespVO.java
  16. 0 112
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/IotThinkModelFunctionController.http
  17. 8 188
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/rule/IotRuleSceneDO.java
  18. 17 0
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/rule/IotRuleSceneMapper.java
  19. 42 0
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/IotRuleSceneService.java
  20. 97 46
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/IotRuleSceneServiceImpl.java
  21. 4 3
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/IotRuleSceneAction.java
  22. 2 2
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/IotRuleSceneAlertAction.java
  23. 2 2
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/IotRuleSceneDataBridgeAction.java
  24. 4 3
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/IotRuleSceneDeviceControlAction.java
  25. 9 0
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelService.java
  26. 26 0
      yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelServiceImpl.java
  27. 5 5
      yudao-server/pom.xml
  28. 6 5
      yudao-server/src/main/resources/application-local.yaml

+ 3 - 0
yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/ErrorCodeConstants.java

@@ -72,4 +72,7 @@ public interface ErrorCodeConstants {
     // ========== IoT 数据桥梁 1-050-010-000 ==========
     ErrorCode DATA_BRIDGE_NOT_EXISTS = new ErrorCode(1_050_010_000, "IoT 数据桥梁不存在");
 
+    // ========== IoT 规则场景(场景联动) 1-050-011-000 ==========
+    ErrorCode RULE_SCENE_NOT_EXISTS = new ErrorCode(1_050_011_000, "IoT 规则场景(场景联动)不存在");
+
 }

+ 1 - 1
yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/rule/IotRuleSceneTriggerConditionParameterOperatorEnum.java

@@ -50,7 +50,7 @@ public enum IotRuleSceneTriggerConditionParameterOperatorEnum implements ArrayVa
     /**
      * Spring 表达式 - 目标值数组
      */
-    public static final String SPRING_EXPRESSION_VALUE_List = "values";
+    public static final String SPRING_EXPRESSION_VALUE_LIST = "values";
 
     public static IotRuleSceneTriggerConditionParameterOperatorEnum operatorOf(String operator) {
         return ArrayUtil.firstMatch(item -> item.getOperator().equals(operator), values());

+ 55 - 3
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/IotRuleSceneController.java

@@ -1,13 +1,24 @@
 package cn.iocoder.yudao.module.iot.controller.admin.rule;
 
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotRuleScenePageReqVO;
+import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotRuleSceneRespVO;
+import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotRuleSceneSaveReqVO;
+import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO;
 import cn.iocoder.yudao.module.iot.service.rule.IotRuleSceneService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import jakarta.annotation.Resource;
 import jakarta.annotation.security.PermitAll;
+import jakarta.validation.Valid;
+import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 
 @Tag(name = "管理后台 - IoT 规则场景")
 @RestController
@@ -18,6 +29,47 @@ public class IotRuleSceneController {
     @Resource
     private IotRuleSceneService ruleSceneService;
 
+    @PostMapping("/create")
+    @Operation(summary = "创建规则场景(场景联动)")
+    @PreAuthorize("@ss.hasPermission('iot:rule-scene:create')")
+    public CommonResult<Long> createRuleScene(@Valid @RequestBody IotRuleSceneSaveReqVO createReqVO) {
+        return success(ruleSceneService.createRuleScene(createReqVO));
+    }
+
+    @PutMapping("/update")
+    @Operation(summary = "更新规则场景(场景联动)")
+    @PreAuthorize("@ss.hasPermission('iot:rule-scene:update')")
+    public CommonResult<Boolean> updateRuleScene(@Valid @RequestBody IotRuleSceneSaveReqVO updateReqVO) {
+        ruleSceneService.updateRuleScene(updateReqVO);
+        return success(true);
+    }
+
+    @DeleteMapping("/delete")
+    @Operation(summary = "删除规则场景(场景联动)")
+    @Parameter(name = "id", description = "编号", required = true)
+    @PreAuthorize("@ss.hasPermission('iot:rule-scene:delete')")
+    public CommonResult<Boolean> deleteRuleScene(@RequestParam("id") Long id) {
+        ruleSceneService.deleteRuleScene(id);
+        return success(true);
+    }
+
+    @GetMapping("/get")
+    @Operation(summary = "获得规则场景(场景联动)")
+    @Parameter(name = "id", description = "编号", required = true, example = "1024")
+    @PreAuthorize("@ss.hasPermission('iot:rule-scene:query')")
+    public CommonResult<IotRuleSceneRespVO> getRuleScene(@RequestParam("id") Long id) {
+        IotRuleSceneDO ruleScene = ruleSceneService.getRuleScene(id);
+        return success(BeanUtils.toBean(ruleScene, IotRuleSceneRespVO.class));
+    }
+
+    @GetMapping("/page")
+    @Operation(summary = "获得规则场景(场景联动)分页")
+    @PreAuthorize("@ss.hasPermission('iot:rule-scene:query')")
+    public CommonResult<PageResult<IotRuleSceneRespVO>> getRuleScenePage(@Valid IotRuleScenePageReqVO pageReqVO) {
+        PageResult<IotRuleSceneDO> pageResult = ruleSceneService.getRuleScenePage(pageReqVO);
+        return success(BeanUtils.toBean(pageResult, IotRuleSceneRespVO.class));
+    }
+
     @GetMapping("/test")
     @PermitAll
     public void test() {

+ 33 - 0
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/scene/IotRuleScenePageReqVO.java

@@ -0,0 +1,33 @@
+package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - IoT 规则场景(场景联动)分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class IotRuleScenePageReqVO extends PageParam {
+
+    @Schema(description = "场景名称", example = "赵六")
+    private String name;
+
+    @Schema(description = "场景描述", example = "你猜")
+    private String description;
+
+    @Schema(description = "场景状态", example = "1")
+    private Integer status;
+
+    @Schema(description = "创建时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] createTime;
+
+}

+ 36 - 0
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/scene/IotRuleSceneRespVO.java

@@ -0,0 +1,36 @@
+package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene;
+
+import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config.IotRuleSceneActionConfig;
+import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config.IotRuleSceneTriggerConfig;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+@Schema(description = "管理后台 - IoT 规则场景(场景联动) Response VO")
+@Data
+public class IotRuleSceneRespVO {
+
+    @Schema(description = "场景编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15865")
+    private Long id;
+
+    @Schema(description = "场景名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六")
+    private String name;
+
+    @Schema(description = "场景描述", example = "你猜")
+    private String description;
+
+    @Schema(description = "场景状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    private Integer status;
+
+    @Schema(description = "触发器数组", requiredMode = Schema.RequiredMode.REQUIRED)
+    private List<IotRuleSceneTriggerConfig> triggers;
+
+    @Schema(description = "执行器数组", requiredMode = Schema.RequiredMode.REQUIRED)
+    private List<IotRuleSceneActionConfig> actions;
+
+    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+    private LocalDateTime createTime;
+
+}

+ 41 - 0
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/scene/IotRuleSceneSaveReqVO.java

@@ -0,0 +1,41 @@
+package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene;
+
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
+import cn.iocoder.yudao.framework.common.validation.InEnum;
+import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config.IotRuleSceneActionConfig;
+import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config.IotRuleSceneTriggerConfig;
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.util.List;
+
+@Schema(description = "管理后台 - IoT 规则场景(场景联动)新增/修改 Request VO")
+@Data
+public class IotRuleSceneSaveReqVO {
+
+    @Schema(description = "场景编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15865")
+    private Long id;
+
+    @Schema(description = "场景名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六")
+    @NotEmpty(message = "场景名称不能为空")
+    private String name;
+
+    @Schema(description = "场景描述", example = "你猜")
+    private String description;
+
+    @Schema(description = "场景状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
+    @NotNull(message = "场景状态不能为空")
+    @InEnum(CommonStatusEnum.class)
+    private Integer status;
+
+    @Schema(description = "触发器数组", requiredMode = Schema.RequiredMode.REQUIRED)
+    @NotEmpty(message = "触发器数组不能为空")
+    private List<IotRuleSceneTriggerConfig> triggers;
+
+    @Schema(description = "执行器数组", requiredMode = Schema.RequiredMode.REQUIRED)
+    @NotEmpty(message = "执行器数组不能为空")
+    private List<IotRuleSceneActionConfig> actions;
+
+}

+ 37 - 0
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/scene/config/IotRuleSceneActionConfig.java

@@ -0,0 +1,37 @@
+package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config;
+
+import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataBridgeDO;
+import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum;
+import lombok.Data;
+
+/**
+ * 执行器配置
+ *
+ * @author 芋道源码
+ */
+@Data
+public class IotRuleSceneActionConfig {
+
+    /**
+     * 执行类型
+     *
+     * 枚举 {@link IotRuleSceneActionTypeEnum}
+     */
+    private Integer type;
+
+    /**
+     * 设备控制
+     *
+     * 必填:当 {@link #type} 为 {@link IotRuleSceneActionTypeEnum#DEVICE_CONTROL} 时
+     */
+    private IotRuleSceneActionDeviceControl deviceControl;
+
+    /**
+     * 数据桥接编号
+     *
+     * 必填:当 {@link #type} 为 {@link IotRuleSceneActionTypeEnum#DATA_BRIDGE} 时
+     * 关联:{@link IotDataBridgeDO#getId()}
+     */
+    private Long dataBridgeId;
+
+}

+ 57 - 0
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/scene/config/IotRuleSceneActionDeviceControl.java

@@ -0,0 +1,57 @@
+package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config;
+
+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.enums.device.IotDeviceMessageIdentifierEnum;
+import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageTypeEnum;
+import lombok.Data;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 执行设备控制
+ *
+ * @author 芋道源码
+ */
+@Data
+public class IotRuleSceneActionDeviceControl {
+
+    /**
+     * 产品标识
+     *
+     * 关联 {@link IotProductDO#getProductKey()}
+     */
+    private String productKey;
+    /**
+     * 设备名称数组
+     *
+     * 关联 {@link IotDeviceDO#getDeviceName()}
+     */
+    private List<String> deviceNames;
+
+    /**
+     * 消息类型
+     *
+     * 枚举 {@link IotDeviceMessageTypeEnum#PROPERTY}、{@link IotDeviceMessageTypeEnum#SERVICE}
+     */
+    private String type;
+    /**
+     * 消息标识符
+     *
+     * 枚举 {@link IotDeviceMessageIdentifierEnum}
+     *
+     * 1. 属性设置:对应 {@link IotDeviceMessageIdentifierEnum#PROPERTY_SET}
+     * 2. 服务调用:对应 {@link IotDeviceMessageIdentifierEnum#SERVICE_INVOKE}
+     */
+    private String identifier;
+
+    /**
+     * 具体数据
+     *
+     * 1. 属性设置:在 {@link #type} 是 {@link IotDeviceMessageTypeEnum#PROPERTY} 时,对应 properties
+     * 2. 服务调用:在 {@link #type} 是 {@link IotDeviceMessageTypeEnum#SERVICE} 时,对应 params
+     */
+    private Map<String, Object> data;
+
+}

+ 37 - 0
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/scene/config/IotRuleSceneTriggerCondition.java

@@ -0,0 +1,37 @@
+package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config;
+
+import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageIdentifierEnum;
+import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageTypeEnum;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 触发条件
+ *
+ * @author 芋道源码
+ */
+@Data
+public class IotRuleSceneTriggerCondition {
+
+    /**
+     * 消息类型
+     *
+     * 枚举 {@link IotDeviceMessageTypeEnum}
+     */
+    private String type;
+    /**
+     * 消息标识符
+     *
+     * 枚举 {@link IotDeviceMessageIdentifierEnum}
+     */
+    private String identifier;
+
+    /**
+     * 参数数组
+     *
+     * 参数与参数之间,是“或”的关系
+     */
+    private List<IotRuleSceneTriggerConditionParameter> parameters;
+
+}

+ 37 - 0
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/scene/config/IotRuleSceneTriggerConditionParameter.java

@@ -0,0 +1,37 @@
+package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config;
+
+import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO;
+import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneTriggerConditionParameterOperatorEnum;
+import lombok.Data;
+
+/**
+ * 触发条件参数
+ *
+ * @author 芋道源码
+ */
+@Data
+public class IotRuleSceneTriggerConditionParameter {
+
+    /**
+     * 标识符(属性、事件、服务)
+     *
+     * 关联 {@link IotThingModelDO#getIdentifier()}
+     */
+    private String identifier;
+
+    /**
+     * 操作符
+     *
+     * 枚举 {@link IotRuleSceneTriggerConditionParameterOperatorEnum}
+     */
+    private String operator;
+
+    /**
+     * 比较值
+     *
+     * 如果有多个值,则使用 "," 分隔,类似 "1,2,3"。
+     * 例如说,{@link IotRuleSceneTriggerConditionParameterOperatorEnum#IN}、{@link IotRuleSceneTriggerConditionParameterOperatorEnum#BETWEEN}
+     */
+    private String value;
+
+}

+ 53 - 0
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/scene/config/IotRuleSceneTriggerConfig.java

@@ -0,0 +1,53 @@
+package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config;
+
+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.enums.rule.IotRuleSceneTriggerTypeEnum;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 触发器配置
+ *
+ * @author 芋道源码
+ */
+@Data
+public class IotRuleSceneTriggerConfig {
+
+    /**
+     * 触发类型
+     *
+     * 枚举 {@link IotRuleSceneTriggerTypeEnum}
+     */
+    private Integer type;
+
+    /**
+     * 产品标识
+     *
+     * 关联 {@link IotProductDO#getProductKey()}
+     */
+    private String productKey;
+    /**
+     * 设备名称数组
+     *
+     * 关联 {@link IotDeviceDO#getDeviceName()}
+     */
+    private List<String> deviceNames;
+
+    /**
+     * 触发条件数组
+     *
+     * 必填:当 {@link #type} 为 {@link IotRuleSceneTriggerTypeEnum#DEVICE} 时
+     * 条件与条件之间,是“或”的关系
+     */
+    private List<IotRuleSceneTriggerCondition> conditions;
+
+    /**
+     * CRON 表达式
+     *
+     * 必填:当 {@link #type} 为 {@link IotRuleSceneTriggerTypeEnum#TIMER} 时
+     */
+    private String cronExpression;
+
+}

+ 2 - 3
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/IotThingModelController.http

@@ -174,8 +174,7 @@ GET {{baseUrl}}/iot/product-thing-model/get?id=67
 tenant-id: {{adminTenentId}}
 Authorization: Bearer {{token}}
 
-
-### 请求 /iot/product-thing-model/list-by-product-id 接口 => 成功
-GET {{baseUrl}}/iot/product-thing-model/list-by-product-id?productId=1001
+### 请求 /iot/product-thing-model/tsl-by-product-id 接口 => 成功
+GET {{baseUrl}}/iot/product-thing-model/tsl-by-product-id?productId=1001
 tenant-id: {{adminTenentId}}
 Authorization: Bearer {{token}}

+ 5 - 9
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/IotThingModelController.java

@@ -3,10 +3,7 @@ package cn.iocoder.yudao.module.iot.controller.admin.thingmodel;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
-import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelListReqVO;
-import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelPageReqVO;
-import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelRespVO;
-import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelSaveReqVO;
+import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.*;
 import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO;
 import cn.iocoder.yudao.module.iot.service.thingmodel.IotThingModelService;
 import io.swagger.v3.oas.annotations.Operation;
@@ -64,13 +61,12 @@ public class IotThingModelController {
         return success(BeanUtils.toBean(thingModel, IotThingModelRespVO.class));
     }
 
-    @GetMapping("/list-by-product-id")
-    @Operation(summary = "获得产品物模型")
+    @GetMapping("/tsl-by-product-id")
+    @Operation(summary = "获得产品物模型 TSL")
     @Parameter(name = "productId", description = "产品ID", required = true, example = "1024")
     @PreAuthorize("@ss.hasPermission('iot:thing-model:query')")
-    public CommonResult<List<IotThingModelRespVO>> getThingModelListByProductId(@RequestParam("productId") Long productId) {
-        List<IotThingModelDO> list = thingModelService.getThingModelListByProductId(productId);
-        return success(BeanUtils.toBean(list, IotThingModelRespVO.class));
+    public CommonResult<IotThingModelTSLRespVO> getThingModelTslByProductId(@RequestParam("productId") Long productId) {
+        return success(thingModelService.getThingModelTslByProductId(productId));
     }
 
     // TODO @puhui @super:getThingModelListByProductId 和 getThingModelListByProductId 可以融合么?

+ 0 - 6
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/vo/IotThingModelRespVO.java

@@ -3,8 +3,6 @@ package cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo;
 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.ThingModelEvent;
 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.ThingModelProperty;
 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.ThingModelService;
-import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
-import com.alibaba.excel.annotation.ExcelProperty;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
@@ -12,18 +10,15 @@ import java.time.LocalDateTime;
 
 @Schema(description = "管理后台 - IoT 产品物模型 Response VO")
 @Data
-@ExcelIgnoreUnannotated
 public class IotThingModelRespVO {
 
     @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "21816")
-    @ExcelProperty("产品ID")
     private Long id;
 
     @Schema(description = "产品标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
     private Long productId;
 
     @Schema(description = "产品标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "temperature_sensor")
-    @ExcelProperty("产品标识")
     private String productKey;
 
     @Schema(description = "功能标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "temperature")
@@ -48,7 +43,6 @@ public class IotThingModelRespVO {
     private ThingModelService service;
 
     @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
-    @ExcelProperty("创建时间")
     private LocalDateTime createTime;
 
 }

+ 30 - 0
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/vo/IotThingModelTSLRespVO.java

@@ -0,0 +1,30 @@
+package cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo;
+
+import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.ThingModelEvent;
+import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.ThingModelProperty;
+import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.ThingModelService;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.util.List;
+
+@Schema(description = "管理后台 - IoT 产品物模型 TSL Response VO")
+@Data
+public class IotThingModelTSLRespVO {
+
+    @Schema(description = "产品标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+    private Long productId;
+
+    @Schema(description = "产品标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "temperature_sensor")
+    private String productKey;
+
+    @Schema(description = "属性列表", requiredMode = Schema.RequiredMode.REQUIRED)
+    private List<ThingModelProperty> properties;
+
+    @Schema(description = "服务列表", requiredMode = Schema.RequiredMode.REQUIRED)
+    private List<ThingModelEvent> events;
+
+    @Schema(description = "事件列表", requiredMode = Schema.RequiredMode.REQUIRED)
+    private List<ThingModelService> services;
+
+}

+ 0 - 112
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/IotThinkModelFunctionController.http

@@ -1,112 +0,0 @@
-### 请求 /iot/think-model-function/create 接口 => 成功
-POST {{baseUrl}}/iot/think-model-function/create
-Content-Type: application/json
-tenant-id: {{adminTenantId}}
-Authorization: Bearer {{token}}
-
-{
-  "productId": 1001,
-  "productKey": "smart-sensor-001",
-  "identifier": "Temperature",
-  "name": "温度",
-  "description": "当前温度值",
-  "type": 1,
-  "property": {
-    "identifier": "Temperature",
-    "name": "温度",
-    "accessMode": "r",
-    "required": true,
-    "dataType": {
-      "type": "float",
-      "specs": {
-        "min": -10.0,
-        "max": 100.0,
-        "step": 0.1,
-        "unit": "℃"
-      }
-    },
-    "description": "当前温度值"
-  }
-}
-
-### 请求 /iot/think-model-function/create 接口 => 成功
-POST {{baseUrl}}/iot/think-model-function/create
-Content-Type: application/json
-tenant-id: {{adminTenantId}}
-Authorization: Bearer {{token}}
-
-{
-  "productId": 1001,
-  "productKey": "smart-sensor-001",
-  "identifier": "Humidity",
-  "name": "湿度",
-  "description": "当前湿度值",
-  "type": 1,
-  "property": {
-    "identifier": "Humidity",
-    "name": "湿度",
-    "accessMode": "r",
-    "required": true,
-    "dataType": {
-      "type": "float",
-      "specs": {
-        "min": 0.0,
-        "max": 100.0,
-        "step": 0.1,
-        "unit": "%"
-      }
-    },
-    "description": "当前湿度值"
-  }
-}
-
-
-
-
-### 请求 /iot/think-model-function/update 接口 => 成功
-PUT {{baseUrl}}/iot/think-model-function/update
-Content-Type: application/json
-tenant-id: {{adminTenantId}}
-Authorization: Bearer {{token}}
-
-{
-  "id": 11,
-  "productId": 1001,
-  "productKey": "smart-sensor-001",
-  "identifier": "Temperature",
-  "name": "温度",
-  "description": "当前温度值",
-  "type": 1,
-  "property": {
-    "identifier": "Temperature",
-    "name": "温度",
-    "accessMode": "r",
-    "required": true,
-    "dataType": {
-      "type": "float",
-      "specs": {
-        "min": -111.0,
-        "max": 222.0,
-        "step": 0.1,
-        "unit": "℃"
-      }
-    },
-    "description": "当前温度值"
-  }
-}
-
-### 请求 /iot/think-model-function/delete 接口 => 成功
-DELETE {{baseUrl}}/iot/think-model-function/delete?id=7
-tenant-id: {{adminTenantId}}
-Authorization: Bearer {{token}}
-
-### 请求 /iot/think-model-function/get 接口 => 成功
-GET {{baseUrl}}/iot/think-model-function/get?id=10
-tenant-id: {{adminTenantId}}
-Authorization: Bearer {{token}}
-
-
-### 请求 /iot/think-model-function/list-by-product-id 接口 => 成功
-GET {{baseUrl}}/iot/think-model-function/list-by-product-id?productId=1001
-tenant-id: {{adminTenantId}}
-Authorization: Bearer {{token}}

+ 8 - 188
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/rule/IotRuleSceneDO.java

@@ -1,23 +1,19 @@
 package cn.iocoder.yudao.module.iot.dal.dataobject.rule;
 
 import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
-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.device.IotDeviceMessageIdentifierEnum;
-import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageTypeEnum;
-import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum;
-import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneTriggerConditionParameterOperatorEnum;
-import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneTriggerTypeEnum;
+import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config.IotRuleSceneActionConfig;
+import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config.IotRuleSceneTriggerConfig;
 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.*;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
 
 import java.util.List;
-import java.util.Map;
 
 /**
  * IoT 规则场景(场景联动) DO
@@ -56,188 +52,12 @@ public class IotRuleSceneDO extends TenantBaseDO {
      * 触发器数组
      */
     @TableField(typeHandler = JacksonTypeHandler.class)
-    private List<TriggerConfig> triggers;
+    private List<IotRuleSceneTriggerConfig> triggers;
 
     /**
      * 执行器数组
      */
     @TableField(typeHandler = JacksonTypeHandler.class)
-    private List<ActionConfig> actions;
-
-    /**
-     * 触发器配置
-     */
-    @Data
-    public static class TriggerConfig {
-
-        /**
-         * 触发类型
-         *
-         * 枚举 {@link IotRuleSceneTriggerTypeEnum}
-         */
-        private Integer type;
-
-        /**
-         * 产品标识
-         *
-         * 关联 {@link IotProductDO#getProductKey()}
-         */
-        private String productKey;
-        /**
-         * 设备名称数组
-         *
-         * 关联 {@link IotDeviceDO#getDeviceName()}
-         */
-        private List<String> deviceNames;
-
-        /**
-         * 触发条件数组
-         *
-         * 必填:当 {@link #type} 为 {@link IotRuleSceneTriggerTypeEnum#DEVICE} 时
-         * 条件与条件之间,是“或”的关系
-         */
-        private List<TriggerCondition> conditions;
-
-        /**
-         * CRON 表达式
-         *
-         * 必填:当 {@link #type} 为 {@link IotRuleSceneTriggerTypeEnum#TIMER} 时
-         */
-        private String cronExpression;
-
-    }
-
-    /**
-     * 触发条件
-     */
-    @Data
-    public static class TriggerCondition {
-
-        /**
-         * 消息类型
-         *
-         * 枚举 {@link IotDeviceMessageTypeEnum}
-         */
-        private String type;
-        /**
-         * 消息标识符
-         *
-         * 枚举 {@link IotDeviceMessageIdentifierEnum}
-         */
-        private String identifier;
-
-        /**
-         * 参数数组
-         *
-         * 参数与参数之间,是“或”的关系
-         */
-        private List<TriggerConditionParameter> parameters;
-
-    }
-
-    /**
-     * 触发条件参数
-     */
-    @Data
-    public static class TriggerConditionParameter {
-
-        /**
-         * 标识符(属性、事件、服务)
-         *
-         * 关联 {@link IotThingModelDO#getIdentifier()}
-         */
-        private String identifier;
-
-        /**
-         * 操作符
-         *
-         * 枚举 {@link IotRuleSceneTriggerConditionParameterOperatorEnum}
-         */
-        private String operator;
-
-        /**
-         * 比较值
-         *
-         * 如果有多个值,则使用 "," 分隔,类似 "1,2,3"。
-         * 例如说,{@link IotRuleSceneTriggerConditionParameterOperatorEnum#IN}、{@link IotRuleSceneTriggerConditionParameterOperatorEnum#BETWEEN}
-         */
-        private String value;
-
-    }
-
-    /**
-     * 执行器配置
-     */
-    @Data
-    public static class ActionConfig {
-
-        /**
-         * 执行类型
-         *
-         * 枚举 {@link IotRuleSceneActionTypeEnum}
-         */
-        private Integer type;
-
-        /**
-         * 设备控制
-         *
-         * 必填:当 {@link #type} 为 {@link IotRuleSceneActionTypeEnum#DEVICE_CONTROL} 时
-         */
-        private ActionDeviceControl deviceControl;
-
-        /**
-         * 数据桥接编号
-         *
-         * 必填:当 {@link #type} 为 {@link IotRuleSceneActionTypeEnum#DATA_BRIDGE} 时
-         * 关联:{@link IotDataBridgeDO#getId()}
-         */
-        private Long dataBridgeId;
-
-    }
-
-    /**
-     * 执行设备控制
-     */
-    @Data
-    public static class ActionDeviceControl {
-
-        /**
-         * 产品标识
-         *
-         * 关联 {@link IotProductDO#getProductKey()}
-         */
-        private String productKey;
-        /**
-         * 设备名称数组
-         *
-         * 关联 {@link IotDeviceDO#getDeviceName()}
-         */
-        private List<String> deviceNames;
-
-        /**
-         * 消息类型
-         *
-         * 枚举 {@link IotDeviceMessageTypeEnum#PROPERTY}、{@link IotDeviceMessageTypeEnum#SERVICE}
-         */
-        private String type;
-        /**
-         * 消息标识符
-         *
-         * 枚举 {@link IotDeviceMessageIdentifierEnum}
-         *
-         * 1. 属性设置:对应 {@link IotDeviceMessageIdentifierEnum#PROPERTY_SET}
-         * 2. 服务调用:对应 {@link IotDeviceMessageIdentifierEnum#SERVICE_INVOKE}
-         */
-        private String identifier;
-
-        /**
-         * 具体数据
-         *
-         * 1. 属性设置:在 {@link #type} 是 {@link IotDeviceMessageTypeEnum#PROPERTY} 时,对应 properties
-         * 2. 服务调用:在 {@link #type} 是 {@link IotDeviceMessageTypeEnum#SERVICE} 时,对应 params
-         */
-        private Map<String, Object> data;
-
-    }
+    private List<IotRuleSceneActionConfig> actions;
 
 }

+ 17 - 0
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/rule/IotRuleSceneMapper.java

@@ -1,10 +1,27 @@
 package cn.iocoder.yudao.module.iot.dal.mysql.rule;
 
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotRuleScenePageReqVO;
 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO;
 import org.apache.ibatis.annotations.Mapper;
 
+/**
+ * IoT 规则场景(场景联动) Mapper
+ *
+ * @author HUIHUI
+ */
 @Mapper
 public interface IotRuleSceneMapper extends BaseMapperX<IotRuleSceneDO> {
 
+    default PageResult<IotRuleSceneDO> selectPage(IotRuleScenePageReqVO reqVO) {
+        return selectPage(reqVO, new LambdaQueryWrapperX<IotRuleSceneDO>()
+                .likeIfPresent(IotRuleSceneDO::getName, reqVO.getName())
+                .likeIfPresent(IotRuleSceneDO::getDescription, reqVO.getDescription())
+                .eqIfPresent(IotRuleSceneDO::getStatus, reqVO.getStatus())
+                .betweenIfPresent(IotRuleSceneDO::getCreateTime, reqVO.getCreateTime())
+                .orderByDesc(IotRuleSceneDO::getId));
+    }
+
 }

+ 42 - 0
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/IotRuleSceneService.java

@@ -1,8 +1,12 @@
 package cn.iocoder.yudao.module.iot.service.rule;
 
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotRuleScenePageReqVO;
+import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotRuleSceneSaveReqVO;
 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO;
 import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneTriggerTypeEnum;
 import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;
+import jakarta.validation.Valid;
 
 import java.util.List;
 
@@ -13,6 +17,44 @@ import java.util.List;
  */
 public interface IotRuleSceneService {
 
+    /**
+     * 创建规则场景(场景联动)
+     *
+     * @param createReqVO 创建信息
+     * @return 编号
+     */
+    Long createRuleScene(@Valid IotRuleSceneSaveReqVO createReqVO);
+
+    /**
+     * 更新规则场景(场景联动)
+     *
+     * @param updateReqVO 更新信息
+     */
+    void updateRuleScene(@Valid IotRuleSceneSaveReqVO updateReqVO);
+
+    /**
+     * 删除规则场景(场景联动)
+     *
+     * @param id 编号
+     */
+    void deleteRuleScene(Long id);
+
+    /**
+     * 获得规则场景(场景联动)
+     *
+     * @param id 编号
+     * @return 规则场景(场景联动)
+     */
+    IotRuleSceneDO getRuleScene(Long id);
+
+    /**
+     * 获得规则场景(场景联动)分页
+     *
+     * @param pageReqVO 分页查询
+     * @return 规则场景(场景联动)分页
+     */
+    PageResult<IotRuleSceneDO> getRuleScenePage(IotRuleScenePageReqVO pageReqVO);
+
     /**
      * 【缓存】获得指定设备的场景列表
      *

+ 97 - 46
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/IotRuleSceneServiceImpl.java

@@ -8,11 +8,16 @@ import cn.hutool.core.util.NumberUtil;
 import cn.hutool.core.util.ObjUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
 import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
 import cn.iocoder.yudao.framework.common.util.spring.SpringExpressionUtils;
 import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
 import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
+import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotRuleScenePageReqVO;
+import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotRuleSceneSaveReqVO;
+import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config.*;
 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO;
 import cn.iocoder.yudao.module.iot.dal.mysql.rule.IotRuleSceneMapper;
 import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageIdentifierEnum;
@@ -39,8 +44,10 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList;
+import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.RULE_SCENE_NOT_EXISTS;
 
 /**
  * IoT 规则场景 Service 实现类
@@ -61,6 +68,49 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
     @Resource(name = "iotSchedulerManager")
     private IotSchedulerManager schedulerManager;
 
+    @Override
+    public Long createRuleScene(IotRuleSceneSaveReqVO createReqVO) {
+        // 插入
+        IotRuleSceneDO ruleScene = BeanUtils.toBean(createReqVO, IotRuleSceneDO.class);
+        ruleSceneMapper.insert(ruleScene);
+        // 返回
+        return ruleScene.getId();
+    }
+
+    @Override
+    public void updateRuleScene(IotRuleSceneSaveReqVO updateReqVO) {
+        // 校验存在
+        validateRuleSceneExists(updateReqVO.getId());
+        // 更新
+        IotRuleSceneDO updateObj = BeanUtils.toBean(updateReqVO, IotRuleSceneDO.class);
+        ruleSceneMapper.updateById(updateObj);
+    }
+
+    @Override
+    public void deleteRuleScene(Long id) {
+        // 校验存在
+        validateRuleSceneExists(id);
+        // 删除
+        ruleSceneMapper.deleteById(id);
+    }
+
+    private void validateRuleSceneExists(Long id) {
+        if (ruleSceneMapper.selectById(id) == null) {
+            throw exception(RULE_SCENE_NOT_EXISTS);
+        }
+    }
+
+    @Override
+    public IotRuleSceneDO getRuleScene(Long id) {
+        return ruleSceneMapper.selectById(id);
+    }
+
+    @Override
+    public PageResult<IotRuleSceneDO> getRuleScenePage(IotRuleScenePageReqVO pageReqVO) {
+        return ruleSceneMapper.selectPage(pageReqVO);
+    }
+
+
     // TODO 芋艿,缓存待实现
     @Override
     @TenantIgnore // 忽略租户隔离:因为 IotRuleSceneMessageHandler 调用时,一般未传递租户,所以需要忽略
@@ -68,82 +118,82 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
         if (true) {
             IotRuleSceneDO ruleScene01 = new IotRuleSceneDO();
             ruleScene01.setTriggers(CollUtil.newArrayList());
-            IotRuleSceneDO.TriggerConfig trigger01 = new IotRuleSceneDO.TriggerConfig();
+            IotRuleSceneTriggerConfig trigger01 = new IotRuleSceneTriggerConfig();
             trigger01.setType(IotRuleSceneTriggerTypeEnum.DEVICE.getType());
             trigger01.setConditions(CollUtil.newArrayList());
             // 属性
-            IotRuleSceneDO.TriggerCondition condition01 = new IotRuleSceneDO.TriggerCondition();
+            IotRuleSceneTriggerCondition condition01 = new IotRuleSceneTriggerCondition();
             condition01.setType(IotDeviceMessageTypeEnum.PROPERTY.getType());
             condition01.setIdentifier(IotDeviceMessageIdentifierEnum.PROPERTY_REPORT.getIdentifier());
             condition01.setParameters(CollUtil.newArrayList());
-//            IotRuleSceneDO.TriggerConditionParameter parameter010 = new IotRuleSceneDO.TriggerConditionParameter();
+//            IotRuleSceneTriggerConditionParameter parameter010 = new IotRuleSceneTriggerConditionParameter();
 //            parameter010.setIdentifier("width");
 //            parameter010.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.EQUALS.getOperator());
 //            parameter010.setValue("abc");
 //            condition01.getParameters().add(parameter010);
-            IotRuleSceneDO.TriggerConditionParameter parameter011 = new IotRuleSceneDO.TriggerConditionParameter();
+            IotRuleSceneTriggerConditionParameter parameter011 = new IotRuleSceneTriggerConditionParameter();
             parameter011.setIdentifier("width");
             parameter011.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.EQUALS.getOperator());
             parameter011.setValue("1");
             condition01.getParameters().add(parameter011);
-            IotRuleSceneDO.TriggerConditionParameter parameter012 = new IotRuleSceneDO.TriggerConditionParameter();
+            IotRuleSceneTriggerConditionParameter parameter012 = new IotRuleSceneTriggerConditionParameter();
             parameter012.setIdentifier("width");
             parameter012.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.NOT_EQUALS.getOperator());
             parameter012.setValue("2");
             condition01.getParameters().add(parameter012);
-            IotRuleSceneDO.TriggerConditionParameter parameter013 = new IotRuleSceneDO.TriggerConditionParameter();
+            IotRuleSceneTriggerConditionParameter parameter013 = new IotRuleSceneTriggerConditionParameter();
             parameter013.setIdentifier("width");
             parameter013.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.GREATER_THAN.getOperator());
             parameter013.setValue("0");
             condition01.getParameters().add(parameter013);
-            IotRuleSceneDO.TriggerConditionParameter parameter014 = new IotRuleSceneDO.TriggerConditionParameter();
+            IotRuleSceneTriggerConditionParameter parameter014 = new IotRuleSceneTriggerConditionParameter();
             parameter014.setIdentifier("width");
             parameter014.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.GREATER_THAN_OR_EQUALS.getOperator());
             parameter014.setValue("0");
             condition01.getParameters().add(parameter014);
-            IotRuleSceneDO.TriggerConditionParameter parameter015 = new IotRuleSceneDO.TriggerConditionParameter();
+            IotRuleSceneTriggerConditionParameter parameter015 = new IotRuleSceneTriggerConditionParameter();
             parameter015.setIdentifier("width");
             parameter015.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.LESS_THAN.getOperator());
             parameter015.setValue("2");
             condition01.getParameters().add(parameter015);
-            IotRuleSceneDO.TriggerConditionParameter parameter016 = new IotRuleSceneDO.TriggerConditionParameter();
+            IotRuleSceneTriggerConditionParameter parameter016 = new IotRuleSceneTriggerConditionParameter();
             parameter016.setIdentifier("width");
             parameter016.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.LESS_THAN_OR_EQUALS.getOperator());
             parameter016.setValue("2");
             condition01.getParameters().add(parameter016);
-            IotRuleSceneDO.TriggerConditionParameter parameter017 = new IotRuleSceneDO.TriggerConditionParameter();
+            IotRuleSceneTriggerConditionParameter parameter017 = new IotRuleSceneTriggerConditionParameter();
             parameter017.setIdentifier("width");
             parameter017.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.IN.getOperator());
             parameter017.setValue("1,2,3");
             condition01.getParameters().add(parameter017);
-            IotRuleSceneDO.TriggerConditionParameter parameter018 = new IotRuleSceneDO.TriggerConditionParameter();
+            IotRuleSceneTriggerConditionParameter parameter018 = new IotRuleSceneTriggerConditionParameter();
             parameter018.setIdentifier("width");
             parameter018.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.NOT_IN.getOperator());
             parameter018.setValue("0,2,3");
             condition01.getParameters().add(parameter018);
-            IotRuleSceneDO.TriggerConditionParameter parameter019 = new IotRuleSceneDO.TriggerConditionParameter();
+            IotRuleSceneTriggerConditionParameter parameter019 = new IotRuleSceneTriggerConditionParameter();
             parameter019.setIdentifier("width");
             parameter019.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.BETWEEN.getOperator());
             parameter019.setValue("1,3");
             condition01.getParameters().add(parameter019);
-            IotRuleSceneDO.TriggerConditionParameter parameter020 = new IotRuleSceneDO.TriggerConditionParameter();
+            IotRuleSceneTriggerConditionParameter parameter020 = new IotRuleSceneTriggerConditionParameter();
             parameter020.setIdentifier("width");
             parameter020.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.NOT_BETWEEN.getOperator());
             parameter020.setValue("2,3");
             condition01.getParameters().add(parameter020);
             trigger01.getConditions().add(condition01);
             // 状态
-            IotRuleSceneDO.TriggerCondition condition02 = new IotRuleSceneDO.TriggerCondition();
+            IotRuleSceneTriggerCondition condition02 = new IotRuleSceneTriggerCondition();
             condition02.setType(IotDeviceMessageTypeEnum.STATE.getType());
             condition02.setIdentifier(IotDeviceMessageIdentifierEnum.STATE_ONLINE.getIdentifier());
             condition02.setParameters(CollUtil.newArrayList());
             trigger01.getConditions().add(condition02);
             // 事件
-            IotRuleSceneDO.TriggerCondition condition03 = new IotRuleSceneDO.TriggerCondition();
+            IotRuleSceneTriggerCondition condition03 = new IotRuleSceneTriggerCondition();
             condition03.setType(IotDeviceMessageTypeEnum.EVENT.getType());
             condition03.setIdentifier("xxx");
             condition03.setParameters(CollUtil.newArrayList());
-            IotRuleSceneDO.TriggerConditionParameter parameter030 = new IotRuleSceneDO.TriggerConditionParameter();
+            IotRuleSceneTriggerConditionParameter parameter030 = new IotRuleSceneTriggerConditionParameter();
             parameter030.setIdentifier("width");
             parameter030.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.EQUALS.getOperator());
             parameter030.setValue("1");
@@ -152,21 +202,21 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
             // 动作
             ruleScene01.setActions(CollUtil.newArrayList());
             // 设备控制
-            IotRuleSceneDO.ActionConfig action01 = new IotRuleSceneDO.ActionConfig();
+            IotRuleSceneActionConfig action01 = new IotRuleSceneActionConfig();
             action01.setType(IotRuleSceneActionTypeEnum.DEVICE_CONTROL.getType());
-            IotRuleSceneDO.ActionDeviceControl actionDeviceControl01 = new IotRuleSceneDO.ActionDeviceControl();
-            actionDeviceControl01.setProductKey("4aymZgOTOOCrDKRT");
-            actionDeviceControl01.setDeviceNames(ListUtil.of("small"));
-            actionDeviceControl01.setType(IotDeviceMessageTypeEnum.PROPERTY.getType());
-            actionDeviceControl01.setIdentifier(IotDeviceMessageIdentifierEnum.PROPERTY_SET.getIdentifier());
-            actionDeviceControl01.setData(MapUtil.<String, Object>builder()
+            IotRuleSceneActionDeviceControl iotRuleSceneActionDeviceControl01 = new IotRuleSceneActionDeviceControl();
+            iotRuleSceneActionDeviceControl01.setProductKey("4aymZgOTOOCrDKRT");
+            iotRuleSceneActionDeviceControl01.setDeviceNames(ListUtil.of("small"));
+            iotRuleSceneActionDeviceControl01.setType(IotDeviceMessageTypeEnum.PROPERTY.getType());
+            iotRuleSceneActionDeviceControl01.setIdentifier(IotDeviceMessageIdentifierEnum.PROPERTY_SET.getIdentifier());
+            iotRuleSceneActionDeviceControl01.setData(MapUtil.<String, Object>builder()
                     .put("power", 1)
                     .put("color", "red")
                     .build());
-            action01.setDeviceControl(actionDeviceControl01);
+            action01.setDeviceControl(iotRuleSceneActionDeviceControl01);
 //            ruleScene01.getActions().add(action01); // TODO 芋艿:先不测试了
             // 数据桥接(http)
-            IotRuleSceneDO.ActionConfig action02 = new IotRuleSceneDO.ActionConfig();
+            IotRuleSceneActionConfig action02 = new IotRuleSceneActionConfig();
             action02.setType(IotRuleSceneActionTypeEnum.DATA_BRIDGE.getType());
             action02.setDataBridgeId(1L);
             ruleScene01.getActions().add(action02);
@@ -176,7 +226,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
         List<IotRuleSceneDO> list = ruleSceneMapper.selectList();
         // TODO @芋艿:需要考虑开启状态
         return filterList(list, ruleScene -> {
-            for (IotRuleSceneDO.TriggerConfig trigger : ruleScene.getTriggers()) {
+            for (IotRuleSceneTriggerConfig trigger : ruleScene.getTriggers()) {
                 if (ObjUtil.notEqual(trigger.getProductKey(), productKey)) {
                     continue;
                 }
@@ -211,22 +261,22 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
         IotRuleSceneDO scene = new IotRuleSceneDO().setStatus(CommonStatusEnum.ENABLE.getStatus());
         if (true) {
             scene.setTenantId(1L);
-            IotRuleSceneDO.TriggerConfig triggerConfig = new IotRuleSceneDO.TriggerConfig();
-            triggerConfig.setType(IotRuleSceneTriggerTypeEnum.TIMER.getType());
-            scene.setTriggers(ListUtil.toList(triggerConfig));
+            IotRuleSceneTriggerConfig iotRuleSceneTriggerConfig = new IotRuleSceneTriggerConfig();
+            iotRuleSceneTriggerConfig.setType(IotRuleSceneTriggerTypeEnum.TIMER.getType());
+            scene.setTriggers(ListUtil.toList(iotRuleSceneTriggerConfig));
             // 动作
-            IotRuleSceneDO.ActionConfig action01 = new IotRuleSceneDO.ActionConfig();
+            IotRuleSceneActionConfig action01 = new IotRuleSceneActionConfig();
             action01.setType(IotRuleSceneActionTypeEnum.DEVICE_CONTROL.getType());
-            IotRuleSceneDO.ActionDeviceControl actionDeviceControl01 = new IotRuleSceneDO.ActionDeviceControl();
-            actionDeviceControl01.setProductKey("4aymZgOTOOCrDKRT");
-            actionDeviceControl01.setDeviceNames(ListUtil.of("small"));
-            actionDeviceControl01.setType(IotDeviceMessageTypeEnum.PROPERTY.getType());
-            actionDeviceControl01.setIdentifier(IotDeviceMessageIdentifierEnum.PROPERTY_SET.getIdentifier());
-            actionDeviceControl01.setData(MapUtil.<String, Object>builder()
+            IotRuleSceneActionDeviceControl iotRuleSceneActionDeviceControl01 = new IotRuleSceneActionDeviceControl();
+            iotRuleSceneActionDeviceControl01.setProductKey("4aymZgOTOOCrDKRT");
+            iotRuleSceneActionDeviceControl01.setDeviceNames(ListUtil.of("small"));
+            iotRuleSceneActionDeviceControl01.setType(IotDeviceMessageTypeEnum.PROPERTY.getType());
+            iotRuleSceneActionDeviceControl01.setIdentifier(IotDeviceMessageIdentifierEnum.PROPERTY_SET.getIdentifier());
+            iotRuleSceneActionDeviceControl01.setData(MapUtil.<String, Object>builder()
                     .put("power", 1)
                     .put("color", "red")
                     .build());
-            action01.setDeviceControl(actionDeviceControl01);
+            action01.setDeviceControl(iotRuleSceneActionDeviceControl01);
             scene.setActions(ListUtil.toList(action01));
         }
         if (scene == null) {
@@ -238,7 +288,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
             return;
         }
         // 1.2 判断是否有定时触发器,避免脏数据
-        IotRuleSceneDO.TriggerConfig config = CollUtil.findOne(scene.getTriggers(),
+        IotRuleSceneTriggerConfig config = CollUtil.findOne(scene.getTriggers(),
                 trigger -> ObjUtil.equals(trigger.getType(), IotRuleSceneTriggerTypeEnum.TIMER.getType()));
         if (config == null) {
             log.error("[executeRuleSceneByTimer][规则场景({}) 不存在定时触发器]", scene);
@@ -267,7 +317,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
 
         // 2. 匹配 trigger 触发器的条件
         return filterList(ruleScenes, ruleScene -> {
-            for (IotRuleSceneDO.TriggerConfig trigger : ruleScene.getTriggers()) {
+            for (IotRuleSceneTriggerConfig trigger : ruleScene.getTriggers()) {
                 // 2.1 非设备触发,不匹配
                 if (ObjUtil.notEqual(trigger.getType(), IotRuleSceneTriggerTypeEnum.DEVICE.getType())) {
                     return false;
@@ -278,13 +328,13 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
                     return false;
                 }
                 // 2.3 多个条件,只需要满足一个即可
-                IotRuleSceneDO.TriggerCondition matchedCondition = CollUtil.findOne(trigger.getConditions(), condition -> {
+                IotRuleSceneTriggerCondition matchedCondition = CollUtil.findOne(trigger.getConditions(), condition -> {
                     if (ObjUtil.notEqual(message.getType(), condition.getType())
                             || ObjUtil.notEqual(message.getIdentifier(), condition.getIdentifier())) {
                         return false;
                     }
                     // 多个条件参数,必须全部满足。所以,下面的逻辑就是找到一个不满足的条件参数
-                    IotRuleSceneDO.TriggerConditionParameter notMatchedParameter = CollUtil.findOne(condition.getParameters(),
+                    IotRuleSceneTriggerConditionParameter notMatchedParameter = CollUtil.findOne(condition.getParameters(),
                             parameter -> !isTriggerConditionParameterMatched(message, parameter, ruleScene, trigger));
                     return notMatchedParameter == null;
                 });
@@ -299,6 +349,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
     }
 
     // TODO @芋艿:【可优化】可以考虑增加下单测,边界太多了。
+
     /**
      * 判断触发器的条件参数是否匹配
      *
@@ -309,8 +360,8 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
      * @return 是否匹配
      */
     @SuppressWarnings({"unchecked", "DataFlowIssue"})
-    private boolean isTriggerConditionParameterMatched(IotDeviceMessage message, IotRuleSceneDO.TriggerConditionParameter parameter,
-                                                       IotRuleSceneDO ruleScene, IotRuleSceneDO.TriggerConfig trigger) {
+    private boolean isTriggerConditionParameterMatched(IotDeviceMessage message, IotRuleSceneTriggerConditionParameter parameter,
+                                                       IotRuleSceneDO ruleScene, IotRuleSceneTriggerConfig trigger) {
         // 1.1 校验操作符是否合法
         IotRuleSceneTriggerConditionParameterOperatorEnum operator =
                 IotRuleSceneTriggerConditionParameterOperatorEnum.operatorOf(parameter.getOperator());
@@ -331,7 +382,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
             springExpressionVariables.put(IotRuleSceneTriggerConditionParameterOperatorEnum.SPRING_EXPRESSION_SOURCE, messageValue);
             springExpressionVariables.put(IotRuleSceneTriggerConditionParameterOperatorEnum.SPRING_EXPRESSION_VALUE, parameter.getValue());
             List<String> parameterValues = StrUtil.splitTrim(parameter.getValue(), CharPool.COMMA);
-            springExpressionVariables.put(IotRuleSceneTriggerConditionParameterOperatorEnum.SPRING_EXPRESSION_VALUE_List, parameterValues);
+            springExpressionVariables.put(IotRuleSceneTriggerConditionParameterOperatorEnum.SPRING_EXPRESSION_VALUE_LIST, parameterValues);
             // 特殊:解决数字的比较。因为 Spring 是基于它的 compareTo 方法,对数字的比较存在问题!
             if (ObjectUtils.equalsAny(operator, IotRuleSceneTriggerConditionParameterOperatorEnum.BETWEEN,
                     IotRuleSceneTriggerConditionParameterOperatorEnum.NOT_BETWEEN,
@@ -345,7 +396,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
                         NumberUtil.parseDouble(messageValue));
                 springExpressionVariables.put(IotRuleSceneTriggerConditionParameterOperatorEnum.SPRING_EXPRESSION_VALUE,
                         NumberUtil.parseDouble(parameter.getValue()));
-                springExpressionVariables.put(IotRuleSceneTriggerConditionParameterOperatorEnum.SPRING_EXPRESSION_VALUE_List,
+                springExpressionVariables.put(IotRuleSceneTriggerConditionParameterOperatorEnum.SPRING_EXPRESSION_VALUE_LIST,
                         convertList(parameterValues, NumberUtil::parseDouble));
             }
             // 2.2 计算 Spring 表达式
@@ -410,7 +461,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
             schedulerManager.addOrUpdateJob(IotRuleSceneJob.class,
                     IotRuleSceneJob.buildJobName(id),
                     "0/10 * * * * ?",
-                        jobDataMap);
+                    jobDataMap);
         }
         if (false) {
             Long id = 1L;

+ 4 - 3
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/IotRuleSceneAction.java

@@ -1,6 +1,6 @@
 package cn.iocoder.yudao.module.iot.service.rule.action;
 
-import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO;
+import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config.IotRuleSceneActionConfig;
 import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum;
 import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;
 
@@ -14,15 +14,16 @@ import javax.annotation.Nullable;
 public interface IotRuleSceneAction {
 
     // TODO @芋艿:groovy 或者 javascript 实现数据的转换;可以考虑基于 hutool 的 ScriptUtil 做
+
     /**
      * 执行场景
      *
      * @param message 消息,允许空
      *                1. 空的情况:定时触发
      *                2. 非空的情况:设备触发
-     * @param config 配置
+     * @param config  配置
      */
-    void execute(@Nullable IotDeviceMessage message, IotRuleSceneDO.ActionConfig config) throws Exception;
+    void execute(@Nullable IotDeviceMessage message, IotRuleSceneActionConfig config) throws Exception;
 
     /**
      * 获得类型

+ 2 - 2
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/IotRuleSceneAlertAction.java

@@ -1,6 +1,6 @@
 package cn.iocoder.yudao.module.iot.service.rule.action;
 
-import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO;
+import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config.IotRuleSceneActionConfig;
 import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum;
 import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;
 import org.springframework.stereotype.Component;
@@ -16,7 +16,7 @@ import javax.annotation.Nullable;
 public class IotRuleSceneAlertAction implements IotRuleSceneAction {
 
     @Override
-    public void execute(@Nullable IotDeviceMessage message, IotRuleSceneDO.ActionConfig config) {
+    public void execute(@Nullable IotDeviceMessage message, IotRuleSceneActionConfig config) {
         // TODO @芋艿:待实现
     }
 

+ 2 - 2
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/IotRuleSceneDataBridgeAction.java

@@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.iot.service.rule.action;
 
 import cn.hutool.core.lang.Assert;
 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
+import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config.IotRuleSceneActionConfig;
 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataBridgeDO;
-import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO;
 import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum;
 import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;
 import cn.iocoder.yudao.module.iot.service.rule.IotDataBridgeService;
@@ -29,7 +29,7 @@ public class IotRuleSceneDataBridgeAction implements IotRuleSceneAction {
     private List<IotDataBridgeExecute<?>> dataBridgeExecutes;
 
     @Override
-    public void execute(IotDeviceMessage message, IotRuleSceneDO.ActionConfig config) throws Exception {
+    public void execute(IotDeviceMessage message, IotRuleSceneActionConfig config) throws Exception {
         // 1.1 如果消息为空,直接返回
         if (message == null) {
             return;

+ 4 - 3
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/IotRuleSceneDeviceControlAction.java

@@ -2,8 +2,9 @@ package cn.iocoder.yudao.module.iot.service.rule.action;
 
 import cn.hutool.core.lang.Assert;
 import cn.iocoder.yudao.module.iot.controller.admin.device.vo.control.IotDeviceDownstreamReqVO;
+import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config.IotRuleSceneActionConfig;
+import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config.IotRuleSceneActionDeviceControl;
 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
-import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO;
 import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum;
 import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;
 import cn.iocoder.yudao.module.iot.service.device.IotDeviceService;
@@ -27,8 +28,8 @@ public class IotRuleSceneDeviceControlAction implements IotRuleSceneAction {
     private IotDeviceService deviceService;
 
     @Override
-    public void execute(IotDeviceMessage message, IotRuleSceneDO.ActionConfig config) {
-        IotRuleSceneDO.ActionDeviceControl control = config.getDeviceControl();
+    public void execute(IotDeviceMessage message, IotRuleSceneActionConfig config) {
+        IotRuleSceneActionDeviceControl control = config.getDeviceControl();
         Assert.notNull(control, "设备控制配置不能为空");
         // 遍历每个设备,下发消息
         control.getDeviceNames().forEach(deviceName -> {

+ 9 - 0
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelService.java

@@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelListReqVO;
 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelPageReqVO;
 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelSaveReqVO;
+import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelTSLRespVO;
 import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO;
 import jakarta.validation.Valid;
 
@@ -90,4 +91,12 @@ public interface IotThingModelService {
      */
     Long getThingModelCount(LocalDateTime createTime);
 
+    /**
+     * 通过产品 ID 获取产品物模型 TSL
+     *
+     * @param productId 产品 ID
+     * @return 产品物模型 TSL
+     */
+    IotThingModelTSLRespVO getThingModelTslByProductId(Long productId);
+
 }

+ 26 - 0
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelServiceImpl.java

@@ -1,6 +1,7 @@
 package cn.iocoder.yudao.module.iot.service.thingmodel;
 
 import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.ObjUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.extra.spring.SpringUtil;
@@ -13,6 +14,7 @@ import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.ThingModelS
 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelListReqVO;
 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelPageReqVO;
 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelSaveReqVO;
+import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelTSLRespVO;
 import cn.iocoder.yudao.module.iot.convert.thingmodel.IotThingModelConvert;
 import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
 import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO;
@@ -149,6 +151,30 @@ public class IotThingModelServiceImpl implements IotThingModelService {
         return thingModelMapper.selectList(reqVO);
     }
 
+    @Override
+    public IotThingModelTSLRespVO getThingModelTslByProductId(Long productId) {
+        IotThingModelTSLRespVO tslRespVO = new IotThingModelTSLRespVO();
+        // 1. 获得产品所有物模型定义
+        List<IotThingModelDO> thingModelList = thingModelMapper.selectListByProductId(productId);
+        if (CollUtil.isEmpty(thingModelList)) {
+            return tslRespVO;
+        }
+
+        // 2.1 设置公共部分参数
+        IotThingModelDO thingModel = thingModelList.get(0);
+        tslRespVO.setProductId(thingModel.getProductId()).setProductKey(thingModel.getProductKey());
+        // 2.2 处理属性列表
+        tslRespVO.setProperties(convertList(filterList(thingModelList, item ->
+                ObjUtil.equal(IotThingModelTypeEnum.PROPERTY.getType(), item.getType())), IotThingModelDO::getProperty));
+        // 2.3 处理服务列表
+        tslRespVO.setServices(convertList(filterList(thingModelList, item ->
+                ObjUtil.equal(IotThingModelTypeEnum.SERVICE.getType(), item.getType())), IotThingModelDO::getService));
+        // 2.4 处理事件列表
+        tslRespVO.setEvents(convertList(filterList(thingModelList, item ->
+                ObjUtil.equal(IotThingModelTypeEnum.EVENT.getType(), item.getType())), IotThingModelDO::getEvent));
+        return tslRespVO;
+    }
+
     /**
      * 校验功能是否存在
      *

+ 5 - 5
yudao-server/pom.xml

@@ -109,11 +109,11 @@
 <!--        </dependency>-->
 
         <!-- IoT 物联网相关模块。默认注释,保证编译速度 -->
-<!--        <dependency>-->
-<!--            <groupId>cn.iocoder.boot</groupId>-->
-<!--            <artifactId>yudao-module-iot-biz</artifactId>-->
-<!--            <version>${revision}</version>-->
-<!--        </dependency>-->
+        <dependency>
+            <groupId>cn.iocoder.boot</groupId>
+            <artifactId>yudao-module-iot-biz</artifactId>
+            <version>${revision}</version>
+        </dependency>
 
         <!-- spring boot 配置所需依赖 -->
         <dependency>

+ 6 - 5
yudao-server/src/main/resources/application-local.yaml

@@ -76,11 +76,12 @@ spring:
             validation-query: SELECT SERVER_STATUS() # TDengine 数据源的有效性检查 SQL
 
   # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
-  redis:
-    host: 127.0.0.1 # 地址
-    port: 6379 # 端口
-    database: 0 # 数据库索引
-#    password: dev # 密码,建议生产环境开启
+  data:
+    redis:
+      host: 127.0.0.1 # 地址
+      port: 6379 # 端口
+      database: 0 # 数据库索引
+#      password: dev # 密码,建议生产环境开启
 
 --- #################### 定时任务相关配置 ####################