Commit 37fdd6247d3572a60bd7a5afea34a1fca51b2844

Authored by 芋道源码
Committed by Gitee
2 parents eeb1dc4a 6e48154f

!1302 【代码优化】IoT: 物模型、场景联动

Merge pull request !1302 from puhui999/iot
Showing 33 changed files with 436 additions and 490 deletions
yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/ErrorCodeConstants.java
@@ -72,8 +72,8 @@ public interface ErrorCodeConstants { @@ -72,8 +72,8 @@ public interface ErrorCodeConstants {
72 // ========== IoT 数据桥梁 1-050-010-000 ========== 72 // ========== IoT 数据桥梁 1-050-010-000 ==========
73 ErrorCode DATA_BRIDGE_NOT_EXISTS = new ErrorCode(1_050_010_000, "IoT 数据桥梁不存在"); 73 ErrorCode DATA_BRIDGE_NOT_EXISTS = new ErrorCode(1_050_010_000, "IoT 数据桥梁不存在");
74 74
75 - // ========== IoT 规则场景(场景联动) 1-050-011-000 ==========  
76 - ErrorCode RULE_SCENE_NOT_EXISTS = new ErrorCode(1_050_011_000, "IoT 规则场景(场景联动)不存在"); 75 + // ========== IoT 场景联动 1-050-011-000 ==========
  76 + ErrorCode RULE_SCENE_NOT_EXISTS = new ErrorCode(1_050_011_000, "IoT 场景联动不存在");
77 77
78 // ========== IoT 产品脚本信息 1-050-012-000 ========== 78 // ========== IoT 产品脚本信息 1-050-012-000 ==========
79 ErrorCode PRODUCT_SCRIPT_NOT_EXISTS = new ErrorCode(1_050_012_000, "IoT 产品脚本信息不存在"); 79 ErrorCode PRODUCT_SCRIPT_NOT_EXISTS = new ErrorCode(1_050_012_000, "IoT 产品脚本信息不存在");
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/IotRuleSceneController.java
@@ -20,8 +20,7 @@ import org.springframework.web.bind.annotation.*; @@ -20,8 +20,7 @@ import org.springframework.web.bind.annotation.*;
20 20
21 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 21 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
22 22
23 -// TODO @芋艿:规则场景 要不要,统一改成 场景联动  
24 -@Tag(name = "管理后台 - IoT 规则场景") 23 +@Tag(name = "管理后台 - IoT 场景联动")
25 @RestController 24 @RestController
26 @RequestMapping("/iot/rule-scene") 25 @RequestMapping("/iot/rule-scene")
27 @Validated 26 @Validated
@@ -31,14 +30,14 @@ public class IotRuleSceneController { @@ -31,14 +30,14 @@ public class IotRuleSceneController {
31 private IotRuleSceneService ruleSceneService; 30 private IotRuleSceneService ruleSceneService;
32 31
33 @PostMapping("/create") 32 @PostMapping("/create")
34 - @Operation(summary = "创建规则场景(场景联动)") 33 + @Operation(summary = "创建场景联动")
35 @PreAuthorize("@ss.hasPermission('iot:rule-scene:create')") 34 @PreAuthorize("@ss.hasPermission('iot:rule-scene:create')")
36 public CommonResult<Long> createRuleScene(@Valid @RequestBody IotRuleSceneSaveReqVO createReqVO) { 35 public CommonResult<Long> createRuleScene(@Valid @RequestBody IotRuleSceneSaveReqVO createReqVO) {
37 return success(ruleSceneService.createRuleScene(createReqVO)); 36 return success(ruleSceneService.createRuleScene(createReqVO));
38 } 37 }
39 38
40 @PutMapping("/update") 39 @PutMapping("/update")
41 - @Operation(summary = "更新规则场景(场景联动)") 40 + @Operation(summary = "更新场景联动")
42 @PreAuthorize("@ss.hasPermission('iot:rule-scene:update')") 41 @PreAuthorize("@ss.hasPermission('iot:rule-scene:update')")
43 public CommonResult<Boolean> updateRuleScene(@Valid @RequestBody IotRuleSceneSaveReqVO updateReqVO) { 42 public CommonResult<Boolean> updateRuleScene(@Valid @RequestBody IotRuleSceneSaveReqVO updateReqVO) {
44 ruleSceneService.updateRuleScene(updateReqVO); 43 ruleSceneService.updateRuleScene(updateReqVO);
@@ -46,7 +45,7 @@ public class IotRuleSceneController { @@ -46,7 +45,7 @@ public class IotRuleSceneController {
46 } 45 }
47 46
48 @DeleteMapping("/delete") 47 @DeleteMapping("/delete")
49 - @Operation(summary = "删除规则场景(场景联动)") 48 + @Operation(summary = "删除场景联动")
50 @Parameter(name = "id", description = "编号", required = true) 49 @Parameter(name = "id", description = "编号", required = true)
51 @PreAuthorize("@ss.hasPermission('iot:rule-scene:delete')") 50 @PreAuthorize("@ss.hasPermission('iot:rule-scene:delete')")
52 public CommonResult<Boolean> deleteRuleScene(@RequestParam("id") Long id) { 51 public CommonResult<Boolean> deleteRuleScene(@RequestParam("id") Long id) {
@@ -55,7 +54,7 @@ public class IotRuleSceneController { @@ -55,7 +54,7 @@ public class IotRuleSceneController {
55 } 54 }
56 55
57 @GetMapping("/get") 56 @GetMapping("/get")
58 - @Operation(summary = "获得规则场景(场景联动)") 57 + @Operation(summary = "获得场景联动")
59 @Parameter(name = "id", description = "编号", required = true, example = "1024") 58 @Parameter(name = "id", description = "编号", required = true, example = "1024")
60 @PreAuthorize("@ss.hasPermission('iot:rule-scene:query')") 59 @PreAuthorize("@ss.hasPermission('iot:rule-scene:query')")
61 public CommonResult<IotRuleSceneRespVO> getRuleScene(@RequestParam("id") Long id) { 60 public CommonResult<IotRuleSceneRespVO> getRuleScene(@RequestParam("id") Long id) {
@@ -64,7 +63,7 @@ public class IotRuleSceneController { @@ -64,7 +63,7 @@ public class IotRuleSceneController {
64 } 63 }
65 64
66 @GetMapping("/page") 65 @GetMapping("/page")
67 - @Operation(summary = "获得规则场景(场景联动)分页") 66 + @Operation(summary = "获得场景联动分页")
68 @PreAuthorize("@ss.hasPermission('iot:rule-scene:query')") 67 @PreAuthorize("@ss.hasPermission('iot:rule-scene:query')")
69 public CommonResult<PageResult<IotRuleSceneRespVO>> getRuleScenePage(@Valid IotRuleScenePageReqVO pageReqVO) { 68 public CommonResult<PageResult<IotRuleSceneRespVO>> getRuleScenePage(@Valid IotRuleScenePageReqVO pageReqVO) {
70 PageResult<IotRuleSceneDO> pageResult = ruleSceneService.getRuleScenePage(pageReqVO); 69 PageResult<IotRuleSceneDO> pageResult = ruleSceneService.getRuleScenePage(pageReqVO);
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/databridge/config/IotDataBridgeAbstractConfig.java
@@ -18,7 +18,7 @@ import lombok.Data; @@ -18,7 +18,7 @@ import lombok.Data;
18 @JsonSubTypes({ 18 @JsonSubTypes({
19 @JsonSubTypes.Type(value = IotDataBridgeHttpConfig.class, name = "1"), 19 @JsonSubTypes.Type(value = IotDataBridgeHttpConfig.class, name = "1"),
20 @JsonSubTypes.Type(value = IotDataBridgeMqttConfig.class, name = "10"), 20 @JsonSubTypes.Type(value = IotDataBridgeMqttConfig.class, name = "10"),
21 - @JsonSubTypes.Type(value = IotDataBridgeRedisStreamMQConfig.class, name = "21"), 21 + @JsonSubTypes.Type(value = IotDataBridgeRedisStreamConfig.class, name = "21"),
22 @JsonSubTypes.Type(value = IotDataBridgeRocketMQConfig.class, name = "30"), 22 @JsonSubTypes.Type(value = IotDataBridgeRocketMQConfig.class, name = "30"),
23 @JsonSubTypes.Type(value = IotDataBridgeRabbitMQConfig.class, name = "31"), 23 @JsonSubTypes.Type(value = IotDataBridgeRabbitMQConfig.class, name = "31"),
24 @JsonSubTypes.Type(value = IotDataBridgeKafkaMQConfig.class, name = "32"), 24 @JsonSubTypes.Type(value = IotDataBridgeKafkaMQConfig.class, name = "32"),
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/databridge/config/IotDataBridgeRedisStreamMQConfig.java renamed to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/databridge/config/IotDataBridgeRedisStreamConfig.java
@@ -2,14 +2,13 @@ package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge.config; @@ -2,14 +2,13 @@ package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge.config;
2 2
3 import lombok.Data; 3 import lombok.Data;
4 4
5 -// TODO @puhui999:MQ 可以去掉哈。stream 更精准  
6 /** 5 /**
7 * IoT Redis Stream 配置 {@link IotDataBridgeAbstractConfig} 实现类 6 * IoT Redis Stream 配置 {@link IotDataBridgeAbstractConfig} 实现类
8 * 7 *
9 * @author HUIHUI 8 * @author HUIHUI
10 */ 9 */
11 @Data 10 @Data
12 -public class IotDataBridgeRedisStreamMQConfig extends IotDataBridgeAbstractConfig { 11 +public class IotDataBridgeRedisStreamConfig extends IotDataBridgeAbstractConfig {
13 12
14 /** 13 /**
15 * Redis 服务器地址 14 * Redis 服务器地址
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/package-info.java deleted
1 -// TODO @芋艿:占位  
2 -package cn.iocoder.yudao.module.iot.controller.admin.rule.vo;  
3 \ No newline at end of file 0 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/scene/IotRuleScenePageReqVO.java
@@ -13,7 +13,7 @@ import java.time.LocalDateTime; @@ -13,7 +13,7 @@ import java.time.LocalDateTime;
13 13
14 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; 14 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
15 15
16 -@Schema(description = "管理后台 - IoT 规则场景(场景联动)分页 Request VO") 16 +@Schema(description = "管理后台 - IoT 场景联动分页 Request VO")
17 @Data 17 @Data
18 @EqualsAndHashCode(callSuper = true) 18 @EqualsAndHashCode(callSuper = true)
19 @ToString(callSuper = true) 19 @ToString(callSuper = true)
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/scene/IotRuleSceneRespVO.java
1 package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene; 1 package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene;
2 2
3 -import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config.IotRuleSceneActionConfig;  
4 -import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config.IotRuleSceneTriggerConfig; 3 +import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO;
5 import io.swagger.v3.oas.annotations.media.Schema; 4 import io.swagger.v3.oas.annotations.media.Schema;
6 import lombok.Data; 5 import lombok.Data;
7 6
8 import java.time.LocalDateTime; 7 import java.time.LocalDateTime;
9 import java.util.List; 8 import java.util.List;
10 9
11 -@Schema(description = "管理后台 - IoT 规则场景(场景联动) Response VO") 10 +@Schema(description = "管理后台 - IoT 场景联动 Response VO")
12 @Data 11 @Data
13 public class IotRuleSceneRespVO { 12 public class IotRuleSceneRespVO {
14 13
@@ -25,10 +24,10 @@ public class IotRuleSceneRespVO { @@ -25,10 +24,10 @@ public class IotRuleSceneRespVO {
25 private Integer status; 24 private Integer status;
26 25
27 @Schema(description = "触发器数组", requiredMode = Schema.RequiredMode.REQUIRED) 26 @Schema(description = "触发器数组", requiredMode = Schema.RequiredMode.REQUIRED)
28 - private List<IotRuleSceneTriggerConfig> triggers; 27 + private List<IotRuleSceneDO.TriggerConfig> triggers;
29 28
30 @Schema(description = "执行器数组", requiredMode = Schema.RequiredMode.REQUIRED) 29 @Schema(description = "执行器数组", requiredMode = Schema.RequiredMode.REQUIRED)
31 - private List<IotRuleSceneActionConfig> actions; 30 + private List<IotRuleSceneDO.ActionConfig> actions;
32 31
33 @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) 32 @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
34 private LocalDateTime createTime; 33 private LocalDateTime createTime;
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/scene/IotRuleSceneSaveReqVO.java
@@ -2,8 +2,7 @@ package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene; @@ -2,8 +2,7 @@ package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene;
2 2
3 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 3 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
4 import cn.iocoder.yudao.framework.common.validation.InEnum; 4 import cn.iocoder.yudao.framework.common.validation.InEnum;
5 -import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config.IotRuleSceneActionConfig;  
6 -import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config.IotRuleSceneTriggerConfig; 5 +import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO;
7 import io.swagger.v3.oas.annotations.media.Schema; 6 import io.swagger.v3.oas.annotations.media.Schema;
8 import jakarta.validation.constraints.NotEmpty; 7 import jakarta.validation.constraints.NotEmpty;
9 import jakarta.validation.constraints.NotNull; 8 import jakarta.validation.constraints.NotNull;
@@ -11,7 +10,7 @@ import lombok.Data; @@ -11,7 +10,7 @@ import lombok.Data;
11 10
12 import java.util.List; 11 import java.util.List;
13 12
14 -@Schema(description = "管理后台 - IoT 规则场景(场景联动)新增/修改 Request VO") 13 +@Schema(description = "管理后台 - IoT 场景联动新增/修改 Request VO")
15 @Data 14 @Data
16 public class IotRuleSceneSaveReqVO { 15 public class IotRuleSceneSaveReqVO {
17 16
@@ -32,10 +31,10 @@ public class IotRuleSceneSaveReqVO { @@ -32,10 +31,10 @@ public class IotRuleSceneSaveReqVO {
32 31
33 @Schema(description = "触发器数组", requiredMode = Schema.RequiredMode.REQUIRED) 32 @Schema(description = "触发器数组", requiredMode = Schema.RequiredMode.REQUIRED)
34 @NotEmpty(message = "触发器数组不能为空") 33 @NotEmpty(message = "触发器数组不能为空")
35 - private List<IotRuleSceneTriggerConfig> triggers; 34 + private List<IotRuleSceneDO.TriggerConfig> triggers;
36 35
37 @Schema(description = "执行器数组", requiredMode = Schema.RequiredMode.REQUIRED) 36 @Schema(description = "执行器数组", requiredMode = Schema.RequiredMode.REQUIRED)
38 @NotEmpty(message = "执行器数组不能为空") 37 @NotEmpty(message = "执行器数组不能为空")
39 - private List<IotRuleSceneActionConfig> actions; 38 + private List<IotRuleSceneDO.ActionConfig> actions;
40 39
41 } 40 }
42 \ No newline at end of file 41 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/scene/config/IotRuleSceneActionConfig.java deleted
1 -package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config;  
2 -  
3 -import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataBridgeDO;  
4 -import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum;  
5 -import lombok.Data;  
6 -  
7 -// TODO @puhui999:这个要不内嵌到 IoTRuleSceneDO 里面?  
8 -/**  
9 - * 执行器配置  
10 - *  
11 - * @author 芋道源码  
12 - */  
13 -@Data  
14 -public class IotRuleSceneActionConfig {  
15 -  
16 - /**  
17 - * 执行类型  
18 - *  
19 - * 枚举 {@link IotRuleSceneActionTypeEnum}  
20 - */  
21 - private Integer type;  
22 -  
23 - /**  
24 - * 设备控制  
25 - *  
26 - * 必填:当 {@link #type} 为 {@link IotRuleSceneActionTypeEnum#DEVICE_CONTROL} 时  
27 - */  
28 - private IotRuleSceneActionDeviceControl deviceControl;  
29 -  
30 - /**  
31 - * 数据桥接编号  
32 - *  
33 - * 必填:当 {@link #type} 为 {@link IotRuleSceneActionTypeEnum#DATA_BRIDGE} 时  
34 - * 关联:{@link IotDataBridgeDO#getId()}  
35 - */  
36 - private Long dataBridgeId;  
37 -  
38 -}  
39 \ No newline at end of file 0 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/scene/config/IotRuleSceneActionDeviceControl.java deleted
1 -package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config;  
2 -  
3 -import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;  
4 -import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;  
5 -import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageIdentifierEnum;  
6 -import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageTypeEnum;  
7 -import lombok.Data;  
8 -  
9 -import java.util.List;  
10 -import java.util.Map;  
11 -  
12 -// TODO @puhui999:这个要不内嵌到 IoTRuleSceneDO 里面?  
13 -/**  
14 - * 执行设备控制  
15 - *  
16 - * @author 芋道源码  
17 - */  
18 -@Data  
19 -public class IotRuleSceneActionDeviceControl {  
20 -  
21 - /**  
22 - * 产品标识  
23 - *  
24 - * 关联 {@link IotProductDO#getProductKey()}  
25 - */  
26 - private String productKey;  
27 - /**  
28 - * 设备名称数组  
29 - *  
30 - * 关联 {@link IotDeviceDO#getDeviceName()}  
31 - */  
32 - private List<String> deviceNames;  
33 -  
34 - /**  
35 - * 消息类型  
36 - *  
37 - * 枚举 {@link IotDeviceMessageTypeEnum#PROPERTY}、{@link IotDeviceMessageTypeEnum#SERVICE}  
38 - */  
39 - private String type;  
40 - /**  
41 - * 消息标识符  
42 - *  
43 - * 枚举 {@link IotDeviceMessageIdentifierEnum}  
44 - *  
45 - * 1. 属性设置:对应 {@link IotDeviceMessageIdentifierEnum#PROPERTY_SET}  
46 - * 2. 服务调用:对应 {@link IotDeviceMessageIdentifierEnum#SERVICE_INVOKE}  
47 - */  
48 - private String identifier;  
49 -  
50 - /**  
51 - * 具体数据  
52 - *  
53 - * 1. 属性设置:在 {@link #type} 是 {@link IotDeviceMessageTypeEnum#PROPERTY} 时,对应 properties  
54 - * 2. 服务调用:在 {@link #type} 是 {@link IotDeviceMessageTypeEnum#SERVICE} 时,对应 params  
55 - */  
56 - private Map<String, Object> data;  
57 -  
58 -}  
59 \ No newline at end of file 0 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/scene/config/IotRuleSceneTriggerCondition.java deleted
1 -package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config;  
2 -  
3 -import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageIdentifierEnum;  
4 -import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageTypeEnum;  
5 -import lombok.Data;  
6 -  
7 -import java.util.List;  
8 -  
9 -// TODO @puhui999:这个要不内嵌到 IoTRuleSceneDO 里面?  
10 -/**  
11 - * 触发条件  
12 - *  
13 - * @author 芋道源码  
14 - */  
15 -@Data  
16 -public class IotRuleSceneTriggerCondition {  
17 -  
18 - /**  
19 - * 消息类型  
20 - *  
21 - * 枚举 {@link IotDeviceMessageTypeEnum}  
22 - */  
23 - private String type;  
24 - /**  
25 - * 消息标识符  
26 - *  
27 - * 枚举 {@link IotDeviceMessageIdentifierEnum}  
28 - */  
29 - private String identifier;  
30 -  
31 - /**  
32 - * 参数数组  
33 - *  
34 - * 参数与参数之间,是“或”的关系  
35 - */  
36 - private List<IotRuleSceneTriggerConditionParameter> parameters;  
37 -  
38 -}  
39 \ No newline at end of file 0 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/scene/config/IotRuleSceneTriggerConditionParameter.java deleted
1 -package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config;  
2 -  
3 -import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO;  
4 -import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneTriggerConditionParameterOperatorEnum;  
5 -import lombok.Data;  
6 -  
7 -// TODO @puhui999:这个要不内嵌到 IoTRuleSceneDO 里面?  
8 -/**  
9 - * 触发条件参数  
10 - *  
11 - * @author 芋道源码  
12 - */  
13 -@Data  
14 -public class IotRuleSceneTriggerConditionParameter {  
15 -  
16 - /**  
17 - * 标识符(属性、事件、服务)  
18 - *  
19 - * 关联 {@link IotThingModelDO#getIdentifier()}  
20 - */  
21 - private String identifier;  
22 -  
23 - /**  
24 - * 操作符  
25 - *  
26 - * 枚举 {@link IotRuleSceneTriggerConditionParameterOperatorEnum}  
27 - */  
28 - private String operator;  
29 -  
30 - /**  
31 - * 比较值  
32 - *  
33 - * 如果有多个值,则使用 "," 分隔,类似 "1,2,3"。  
34 - * 例如说,{@link IotRuleSceneTriggerConditionParameterOperatorEnum#IN}、{@link IotRuleSceneTriggerConditionParameterOperatorEnum#BETWEEN}  
35 - */  
36 - private String value;  
37 -  
38 -}  
39 \ No newline at end of file 0 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/scene/config/IotRuleSceneTriggerConfig.java deleted
1 -package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config;  
2 -  
3 -import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;  
4 -import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;  
5 -import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneTriggerTypeEnum;  
6 -import lombok.Data;  
7 -  
8 -import java.util.List;  
9 -  
10 -// TODO @puhui999:这个要不内嵌到 IoTRuleSceneDO 里面?  
11 -/**  
12 - * 触发器配置  
13 - *  
14 - * @author 芋道源码  
15 - */  
16 -@Data  
17 -public class IotRuleSceneTriggerConfig {  
18 -  
19 - /**  
20 - * 触发类型  
21 - *  
22 - * 枚举 {@link IotRuleSceneTriggerTypeEnum}  
23 - */  
24 - private Integer type;  
25 -  
26 - /**  
27 - * 产品标识  
28 - *  
29 - * 关联 {@link IotProductDO#getProductKey()}  
30 - */  
31 - private String productKey;  
32 - /**  
33 - * 设备名称数组  
34 - *  
35 - * 关联 {@link IotDeviceDO#getDeviceName()}  
36 - */  
37 - private List<String> deviceNames;  
38 -  
39 - /**  
40 - * 触发条件数组  
41 - *  
42 - * 必填:当 {@link #type} 为 {@link IotRuleSceneTriggerTypeEnum#DEVICE} 时  
43 - * 条件与条件之间,是“或”的关系  
44 - */  
45 - private List<IotRuleSceneTriggerCondition> conditions;  
46 -  
47 - /**  
48 - * CRON 表达式  
49 - *  
50 - * 必填:当 {@link #type} 为 {@link IotRuleSceneTriggerTypeEnum#TIMER} 时  
51 - */  
52 - private String cronExpression;  
53 -  
54 -}  
55 \ No newline at end of file 0 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/IotThingModelController.http
@@ -174,7 +174,7 @@ GET {{baseUrl}}/iot/product-thing-model/get?id=67 @@ -174,7 +174,7 @@ GET {{baseUrl}}/iot/product-thing-model/get?id=67
174 tenant-id: {{adminTenentId}} 174 tenant-id: {{adminTenentId}}
175 Authorization: Bearer {{token}} 175 Authorization: Bearer {{token}}
176 176
177 -### 请求 /iot/product-thing-model/tsl-by-product-id 接口 => 成功  
178 -GET {{baseUrl}}/iot/product-thing-model/tsl-by-product-id?productId=1001 177 +### 请求 /iot/product-thing-model/get-tsl 接口 => 成功
  178 +GET {{baseUrl}}/iot/product-thing-model/get-tsl?productId=1001
179 tenant-id: {{adminTenentId}} 179 tenant-id: {{adminTenentId}}
180 Authorization: Bearer {{token}} 180 Authorization: Bearer {{token}}
181 \ No newline at end of file 181 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/IotThingModelController.java
1 package cn.iocoder.yudao.module.iot.controller.admin.thingmodel; 1 package cn.iocoder.yudao.module.iot.controller.admin.thingmodel;
2 2
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.util.ObjUtil;
3 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 5 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 import cn.iocoder.yudao.framework.common.pojo.PageResult; 6 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 7 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
6 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.*; 8 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.*;
7 import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO; 9 import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO;
  10 +import cn.iocoder.yudao.module.iot.enums.thingmodel.IotThingModelTypeEnum;
8 import cn.iocoder.yudao.module.iot.service.thingmodel.IotThingModelService; 11 import cn.iocoder.yudao.module.iot.service.thingmodel.IotThingModelService;
9 import io.swagger.v3.oas.annotations.Operation; 12 import io.swagger.v3.oas.annotations.Operation;
10 import io.swagger.v3.oas.annotations.Parameter; 13 import io.swagger.v3.oas.annotations.Parameter;
@@ -18,6 +21,8 @@ import org.springframework.web.bind.annotation.*; @@ -18,6 +21,8 @@ import org.springframework.web.bind.annotation.*;
18 import java.util.List; 21 import java.util.List;
19 22
20 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 23 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  24 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
  25 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList;
21 26
22 @Tag(name = "管理后台 - IoT 产品物模型") 27 @Tag(name = "管理后台 - IoT 产品物模型")
23 @RestController 28 @RestController
@@ -61,13 +66,31 @@ public class IotThingModelController { @@ -61,13 +66,31 @@ public class IotThingModelController {
61 return success(BeanUtils.toBean(thingModel, IotThingModelRespVO.class)); 66 return success(BeanUtils.toBean(thingModel, IotThingModelRespVO.class));
62 } 67 }
63 68
64 - // TODO @puhui999:要不叫 get-tsl,去掉 product-id;后续,把  
65 - @GetMapping("/tsl-by-product-id") 69 + @GetMapping("/get-tsl")
66 @Operation(summary = "获得产品物模型 TSL") 70 @Operation(summary = "获得产品物模型 TSL")
67 @Parameter(name = "productId", description = "产品 ID", required = true, example = "1024") 71 @Parameter(name = "productId", description = "产品 ID", required = true, example = "1024")
68 @PreAuthorize("@ss.hasPermission('iot:thing-model:query')") 72 @PreAuthorize("@ss.hasPermission('iot:thing-model:query')")
69 - public CommonResult<IotThingModelTSLRespVO> getThingModelTslByProductId(@RequestParam("productId") Long productId) {  
70 - return success(thingModelService.getThingModelTslByProductId(productId)); 73 + public CommonResult<IotThingModelTSLRespVO> getThingModelTsl(@RequestParam("productId") Long productId) {
  74 + IotThingModelTSLRespVO tslRespVO = new IotThingModelTSLRespVO();
  75 + // 1. 获得产品所有物模型定义
  76 + List<IotThingModelDO> thingModels = thingModelService.getThingModelListByProductId(productId);
  77 + if (CollUtil.isEmpty(thingModels)) {
  78 + return success(tslRespVO);
  79 + }
  80 +
  81 + // 2.1 设置公共部分参数
  82 + IotThingModelDO thingModel = thingModels.get(0);
  83 + tslRespVO.setProductId(thingModel.getProductId()).setProductKey(thingModel.getProductKey());
  84 + // 2.2 处理属性列表
  85 + tslRespVO.setProperties(convertList(filterList(thingModels, item ->
  86 + ObjUtil.equal(IotThingModelTypeEnum.PROPERTY.getType(), item.getType())), IotThingModelDO::getProperty));
  87 + // 2.3 处理服务列表
  88 + tslRespVO.setServices(convertList(filterList(thingModels, item ->
  89 + ObjUtil.equal(IotThingModelTypeEnum.SERVICE.getType(), item.getType())), IotThingModelDO::getService));
  90 + // 2.4 处理事件列表
  91 + tslRespVO.setEvents(convertList(filterList(thingModels, item ->
  92 + ObjUtil.equal(IotThingModelTypeEnum.EVENT.getType(), item.getType())), IotThingModelDO::getEvent));
  93 + return success(tslRespVO);
71 } 94 }
72 95
73 @GetMapping("/list") 96 @GetMapping("/list")
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/model/dataType/ThingModelArrayDataSpecs.java
1 package cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.dataType; 1 package cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.dataType;
2 2
3 import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 3 import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
  4 +import jakarta.validation.Valid;
  5 +import jakarta.validation.constraints.NotEmpty;
  6 +import jakarta.validation.constraints.NotNull;
  7 +import jakarta.validation.constraints.Pattern;
4 import lombok.Data; 8 import lombok.Data;
5 import lombok.EqualsAndHashCode; 9 import lombok.EqualsAndHashCode;
6 10
@@ -16,18 +20,17 @@ import java.util.List; @@ -16,18 +20,17 @@ import java.util.List;
16 @JsonIgnoreProperties({"dataType"}) // 忽略子类中的 dataType 字段,从而避免重复 20 @JsonIgnoreProperties({"dataType"}) // 忽略子类中的 dataType 字段,从而避免重复
17 public class ThingModelArrayDataSpecs extends ThingModelDataSpecs { 21 public class ThingModelArrayDataSpecs extends ThingModelDataSpecs {
18 22
19 - /**  
20 - * 数组中的元素个数  
21 - */ 23 + @NotNull(message = "数组元素个数不能为空")
22 private Integer size; 24 private Integer size;
23 - /**  
24 - * 数组中的元素的数据类型。可选值:struct、int、float、double 或 text  
25 - */ 25 +
  26 + @NotEmpty(message = "数组元素的数据类型不能为空")
  27 + @Pattern(regexp = "^(struct|int|float|double|text)$", message = "数组元素的数据类型必须为:struct、int、float、double 或 text")
26 private String childDataType; 28 private String childDataType;
27 /** 29 /**
28 * 数据类型(childDataType)为列表型 struct 的数据规范存储在 dataSpecsList 中 30 * 数据类型(childDataType)为列表型 struct 的数据规范存储在 dataSpecsList 中
29 * 此时 struct 取值范围为:int、float、double、text、date、enum、bool 31 * 此时 struct 取值范围为:int、float、double、text、date、enum、bool
30 */ 32 */
  33 + @Valid
31 private List<ThingModelDataSpecs> dataSpecsList; 34 private List<ThingModelDataSpecs> dataSpecsList;
32 35
33 } 36 }
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/model/dataType/ThingModelBoolOrEnumDataSpecs.java
1 package cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.dataType; 1 package cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.dataType;
2 2
3 import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 3 import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
  4 +import jakarta.validation.constraints.NotEmpty;
  5 +import jakarta.validation.constraints.NotNull;
  6 +import jakarta.validation.constraints.Pattern;
4 import lombok.Data; 7 import lombok.Data;
5 import lombok.EqualsAndHashCode; 8 import lombok.EqualsAndHashCode;
6 9
@@ -16,16 +19,12 @@ import lombok.EqualsAndHashCode; @@ -16,16 +19,12 @@ import lombok.EqualsAndHashCode;
16 @JsonIgnoreProperties({"dataType"}) // 忽略子类中的 dataType 字段,从而避免重复 19 @JsonIgnoreProperties({"dataType"}) // 忽略子类中的 dataType 字段,从而避免重复
17 public class ThingModelBoolOrEnumDataSpecs extends ThingModelDataSpecs { 20 public class ThingModelBoolOrEnumDataSpecs extends ThingModelDataSpecs {
18 21
19 - // TODO @puhui999:要不写下参数校验?这样,注释可以简洁一点  
20 - /**  
21 - * 枚举项的名称。  
22 - * 可包含中文、大小写英文字母、数字、下划线(_)和短划线(-)  
23 - * 必须以中文、英文字母或数字开头,长度不超过 20 个字符  
24 - */ 22 + @NotEmpty(message = "枚举项的名称不能为空")
  23 + @Pattern(regexp = "^[\\u4e00-\\u9fa5a-zA-Z0-9][\\u4e00-\\u9fa5a-zA-Z0-9_-]{0,19}$",
  24 + message = "枚举项的名称只能包含中文、大小写英文字母、数字、下划线和短划线,必须以中文、英文字母或数字开头,长度不超过 20 个字符")
25 private String name; 25 private String name;
26 - /**  
27 - * 枚举值。  
28 - */ 26 +
  27 + @NotNull(message = "枚举值不能为空")
29 private Integer value; 28 private Integer value;
30 29
31 } 30 }
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/model/dataType/ThingModelDateOrTextDataSpecs.java
1 package cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.dataType; 1 package cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.dataType;
2 2
3 import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 3 import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
  4 +import jakarta.validation.constraints.Max;
4 import lombok.Data; 5 import lombok.Data;
5 import lombok.EqualsAndHashCode; 6 import lombok.EqualsAndHashCode;
6 7
@@ -20,6 +21,7 @@ public class ThingModelDateOrTextDataSpecs extends ThingModelDataSpecs { @@ -20,6 +21,7 @@ public class ThingModelDateOrTextDataSpecs extends ThingModelDataSpecs {
20 * 数据长度,单位为字节。取值不能超过 2048。 21 * 数据长度,单位为字节。取值不能超过 2048。
21 * 当 dataType 为 text 时,需传入该参数。 22 * 当 dataType 为 text 时,需传入该参数。
22 */ 23 */
  24 + @Max(value = 2048, message = "数据长度不能超过 2048")
23 private Integer length; 25 private Integer length;
24 /** 26 /**
25 * 默认值,可选参数,用于存储默认值。 27 * 默认值,可选参数,用于存储默认值。
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/model/dataType/ThingModelNumericDataSpec.java
1 package cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.dataType; 1 package cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.dataType;
2 2
3 import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 3 import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
  4 +import jakarta.validation.constraints.NotEmpty;
  5 +import jakarta.validation.constraints.Pattern;
4 import lombok.Data; 6 import lombok.Data;
5 import lombok.EqualsAndHashCode; 7 import lombok.EqualsAndHashCode;
6 8
@@ -18,18 +20,21 @@ public class ThingModelNumericDataSpec extends ThingModelDataSpecs { @@ -18,18 +20,21 @@ public class ThingModelNumericDataSpec extends ThingModelDataSpecs {
18 20
19 /** 21 /**
20 * 最大值,需转为字符串类型。值必须与 dataType 类型一致。 22 * 最大值,需转为字符串类型。值必须与 dataType 类型一致。
21 - * 例如,当 dataType 为 int 时,取值为 "200",而不是 200。  
22 */ 23 */
  24 + @NotEmpty(message = "最大值不能为空")
  25 + @Pattern(regexp = "^-?\\d+(\\.\\d+)?$", message = "最大值必须为数值类型")
23 private String max; 26 private String max;
24 /** 27 /**
25 * 最小值,需转为字符串类型。值必须与 dataType 类型一致。 28 * 最小值,需转为字符串类型。值必须与 dataType 类型一致。
26 - * 例如,当 dataType 为 int 时,取值为 "0",而不是 0。  
27 */ 29 */
  30 + @NotEmpty(message = "最小值不能为空")
  31 + @Pattern(regexp = "^-?\\d+(\\.\\d+)?$", message = "最小值必须为数值类型")
28 private String min; 32 private String min;
29 /** 33 /**
30 * 步长,需转为字符串类型。值必须与 dataType 类型一致。 34 * 步长,需转为字符串类型。值必须与 dataType 类型一致。
31 - * 例如,当 dataType 为 int 时,取值为 "10",而不是 10。  
32 */ 35 */
  36 + @NotEmpty(message = "步长不能为空")
  37 + @Pattern(regexp = "^-?\\d+(\\.\\d+)?$", message = "步长必须为数值类型")
33 private String step; 38 private String step;
34 /** 39 /**
35 * 精度。当 dataType 为 float 或 double 时可选传入。 40 * 精度。当 dataType 为 float 或 double 时可选传入。
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/model/dataType/ThingModelStructDataSpecs.java
1 package cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.dataType; 1 package cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.dataType;
2 2
  3 +import cn.iocoder.yudao.framework.common.validation.InEnum;
3 import cn.iocoder.yudao.module.iot.enums.thingmodel.IotThingModelAccessModeEnum; 4 import cn.iocoder.yudao.module.iot.enums.thingmodel.IotThingModelAccessModeEnum;
4 import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 5 import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
  6 +import jakarta.validation.Valid;
  7 +import jakarta.validation.constraints.NotEmpty;
  8 +import jakarta.validation.constraints.Pattern;
5 import lombok.Data; 9 import lombok.Data;
6 import lombok.EqualsAndHashCode; 10 import lombok.EqualsAndHashCode;
7 11
@@ -17,35 +21,36 @@ import java.util.List; @@ -17,35 +21,36 @@ import java.util.List;
17 @JsonIgnoreProperties({"dataType"}) // 忽略子类中的 dataType 字段,从而避免重复 21 @JsonIgnoreProperties({"dataType"}) // 忽略子类中的 dataType 字段,从而避免重复
18 public class ThingModelStructDataSpecs extends ThingModelDataSpecs { 22 public class ThingModelStructDataSpecs extends ThingModelDataSpecs {
19 23
20 - /**  
21 - * 属性标识符  
22 - */ 24 + @NotEmpty(message = "属性标识符不能为空")
  25 + @Pattern(regexp = "^[a-zA-Z][a-zA-Z0-9_]{0,31}$", message = "属性标识符只能由字母、数字和下划线组成,必须以字母开头,长度不超过 32 个字符")
23 private String identifier; 26 private String identifier;
24 - /**  
25 - * 属性名称  
26 - */ 27 +
  28 + @NotEmpty(message = "属性名称不能为空")
27 private String name; 29 private String name;
28 - /**  
29 - * 云端可以对该属性进行的操作类型  
30 - *  
31 - * 枚举 {@link IotThingModelAccessModeEnum}  
32 - */ 30 +
  31 + @NotEmpty(message = "操作类型不能为空")
  32 + @InEnum(IotThingModelAccessModeEnum.class)
33 private String accessMode; 33 private String accessMode;
  34 +
34 /** 35 /**
35 * 是否是标准品类的必选服务 36 * 是否是标准品类的必选服务
36 */ 37 */
37 private Boolean required; 38 private Boolean required;
38 - /**  
39 - * struct 数据的数据类型  
40 - */ 39 +
  40 + @NotEmpty(message = "数据类型不能为空")
  41 + @Pattern(regexp = "^(int|float|double|text|date|enum|bool)$", message = "数据类型必须为:int、float、double、text、date、enum、bool")
41 private String childDataType; 42 private String childDataType;
  43 +
42 /** 44 /**
43 * 数据类型(dataType)为非列表型(int、float、double、text、date、array)的数据规范存储在 dataSpecs 中 45 * 数据类型(dataType)为非列表型(int、float、double、text、date、array)的数据规范存储在 dataSpecs 中
44 */ 46 */
  47 + @Valid
45 private ThingModelDataSpecs dataSpecs; 48 private ThingModelDataSpecs dataSpecs;
  49 +
46 /** 50 /**
47 * 数据类型(dataType)为列表型(enum、bool、struct)的数据规范存储在 dataSpecsList 中 51 * 数据类型(dataType)为列表型(enum、bool、struct)的数据规范存储在 dataSpecsList 中
48 */ 52 */
  53 + @Valid
49 private List<ThingModelDataSpecs> dataSpecsList; 54 private List<ThingModelDataSpecs> dataSpecsList;
50 55
51 } 56 }
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/rule/IotRuleSceneDO.java
1 package cn.iocoder.yudao.module.iot.dal.dataobject.rule; 1 package cn.iocoder.yudao.module.iot.dal.dataobject.rule;
2 2
3 import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO; 3 import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
4 -import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config.IotRuleSceneActionConfig;  
5 -import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config.IotRuleSceneTriggerConfig; 4 +import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
  5 +import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
  6 +import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO;
  7 +import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageIdentifierEnum;
  8 +import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageTypeEnum;
  9 +import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum;
  10 +import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneTriggerConditionParameterOperatorEnum;
  11 +import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneTriggerTypeEnum;
6 import com.baomidou.mybatisplus.annotation.KeySequence; 12 import com.baomidou.mybatisplus.annotation.KeySequence;
7 import com.baomidou.mybatisplus.annotation.TableField; 13 import com.baomidou.mybatisplus.annotation.TableField;
8 import com.baomidou.mybatisplus.annotation.TableId; 14 import com.baomidou.mybatisplus.annotation.TableId;
@@ -14,13 +20,14 @@ import lombok.Data; @@ -14,13 +20,14 @@ import lombok.Data;
14 import lombok.NoArgsConstructor; 20 import lombok.NoArgsConstructor;
15 21
16 import java.util.List; 22 import java.util.List;
  23 +import java.util.Map;
17 24
18 /** 25 /**
19 - * IoT 规则场景(场景联动) DO 26 + * IoT 场景联动 DO
20 * 27 *
21 * @author 芋道源码 28 * @author 芋道源码
22 */ 29 */
23 -@TableName("iot_rule_scene") 30 +@TableName(value = "iot_rule_scene", autoResultMap = true)
24 @KeySequence("iot_rule_scene_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 31 @KeySequence("iot_rule_scene_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
25 @Data 32 @Data
26 @Builder 33 @Builder
@@ -52,12 +59,188 @@ public class IotRuleSceneDO extends TenantBaseDO { @@ -52,12 +59,188 @@ public class IotRuleSceneDO extends TenantBaseDO {
52 * 触发器数组 59 * 触发器数组
53 */ 60 */
54 @TableField(typeHandler = JacksonTypeHandler.class) 61 @TableField(typeHandler = JacksonTypeHandler.class)
55 - private List<IotRuleSceneTriggerConfig> triggers; 62 + private List<TriggerConfig> triggers;
56 63
57 /** 64 /**
58 * 执行器数组 65 * 执行器数组
59 */ 66 */
60 @TableField(typeHandler = JacksonTypeHandler.class) 67 @TableField(typeHandler = JacksonTypeHandler.class)
61 - private List<IotRuleSceneActionConfig> actions; 68 + private List<ActionConfig> actions;
  69 +
  70 + /**
  71 + * 触发器配置
  72 + */
  73 + @Data
  74 + public static class TriggerConfig {
  75 +
  76 + /**
  77 + * 触发类型
  78 + *
  79 + * 枚举 {@link IotRuleSceneTriggerTypeEnum}
  80 + */
  81 + private Integer type;
  82 +
  83 + /**
  84 + * 产品标识
  85 + *
  86 + * 关联 {@link IotProductDO#getProductKey()}
  87 + */
  88 + private String productKey;
  89 + /**
  90 + * 设备名称数组
  91 + *
  92 + * 关联 {@link IotDeviceDO#getDeviceName()}
  93 + */
  94 + private List<String> deviceNames;
  95 +
  96 + /**
  97 + * 触发条件数组
  98 + *
  99 + * 必填:当 {@link #type} 为 {@link IotRuleSceneTriggerTypeEnum#DEVICE} 时
  100 + * 条件与条件之间,是“或”的关系
  101 + */
  102 + private List<TriggerCondition> conditions;
  103 +
  104 + /**
  105 + * CRON 表达式
  106 + *
  107 + * 必填:当 {@link #type} 为 {@link IotRuleSceneTriggerTypeEnum#TIMER} 时
  108 + */
  109 + private String cronExpression;
  110 +
  111 + }
  112 +
  113 + /**
  114 + * 触发条件
  115 + */
  116 + @Data
  117 + public static class TriggerCondition {
  118 +
  119 + /**
  120 + * 消息类型
  121 + *
  122 + * 枚举 {@link IotDeviceMessageTypeEnum}
  123 + */
  124 + private String type;
  125 + /**
  126 + * 消息标识符
  127 + *
  128 + * 枚举 {@link IotDeviceMessageIdentifierEnum}
  129 + */
  130 + private String identifier;
  131 +
  132 + /**
  133 + * 参数数组
  134 + *
  135 + * 参数与参数之间,是“或”的关系
  136 + */
  137 + private List<TriggerConditionParameter> parameters;
  138 +
  139 + }
  140 +
  141 + /**
  142 + * 触发条件参数
  143 + */
  144 + @Data
  145 + public static class TriggerConditionParameter {
  146 +
  147 + /**
  148 + * 标识符(属性、事件、服务)
  149 + *
  150 + * 关联 {@link IotThingModelDO#getIdentifier()}
  151 + */
  152 + private String identifier;
  153 +
  154 + /**
  155 + * 操作符
  156 + *
  157 + * 枚举 {@link IotRuleSceneTriggerConditionParameterOperatorEnum}
  158 + */
  159 + private String operator;
  160 +
  161 + /**
  162 + * 比较值
  163 + *
  164 + * 如果有多个值,则使用 "," 分隔,类似 "1,2,3"。
  165 + * 例如说,{@link IotRuleSceneTriggerConditionParameterOperatorEnum#IN}、{@link IotRuleSceneTriggerConditionParameterOperatorEnum#BETWEEN}
  166 + */
  167 + private String value;
  168 +
  169 + }
  170 +
  171 + /**
  172 + * 执行器配置
  173 + */
  174 + @Data
  175 + public static class ActionConfig {
  176 +
  177 + /**
  178 + * 执行类型
  179 + *
  180 + * 枚举 {@link IotRuleSceneActionTypeEnum}
  181 + */
  182 + private Integer type;
  183 +
  184 + /**
  185 + * 设备控制
  186 + *
  187 + * 必填:当 {@link #type} 为 {@link IotRuleSceneActionTypeEnum#DEVICE_CONTROL} 时
  188 + */
  189 + private ActionDeviceControl deviceControl;
  190 +
  191 + /**
  192 + * 数据桥接编号
  193 + *
  194 + * 必填:当 {@link #type} 为 {@link IotRuleSceneActionTypeEnum#DATA_BRIDGE} 时
  195 + * 关联:{@link IotDataBridgeDO#getId()}
  196 + */
  197 + private Long dataBridgeId;
  198 +
  199 + }
  200 +
  201 + /**
  202 + * 执行设备控制
  203 + */
  204 + @Data
  205 + public static class ActionDeviceControl {
  206 +
  207 + /**
  208 + * 产品标识
  209 + *
  210 + * 关联 {@link IotProductDO#getProductKey()}
  211 + */
  212 + private String productKey;
  213 + /**
  214 + * 设备名称数组
  215 + *
  216 + * 关联 {@link IotDeviceDO#getDeviceName()}
  217 + */
  218 + private List<String> deviceNames;
  219 +
  220 + /**
  221 + * 消息类型
  222 + *
  223 + * 枚举 {@link IotDeviceMessageTypeEnum#PROPERTY}、{@link IotDeviceMessageTypeEnum#SERVICE}
  224 + */
  225 + private String type;
  226 + /**
  227 + * 消息标识符
  228 + *
  229 + * 枚举 {@link IotDeviceMessageIdentifierEnum}
  230 + *
  231 + * 1. 属性设置:对应 {@link IotDeviceMessageIdentifierEnum#PROPERTY_SET}
  232 + * 2. 服务调用:对应 {@link IotDeviceMessageIdentifierEnum#SERVICE_INVOKE}
  233 + */
  234 + private String identifier;
  235 +
  236 + /**
  237 + * 具体数据
  238 + *
  239 + * 1. 属性设置:在 {@link #type} 是 {@link IotDeviceMessageTypeEnum#PROPERTY} 时,对应 properties
  240 + * 2. 服务调用:在 {@link #type} 是 {@link IotDeviceMessageTypeEnum#SERVICE} 时,对应 params
  241 + */
  242 + private Map<String, Object> data;
  243 +
  244 + }
62 245
63 } 246 }
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/rule/IotRuleSceneMapper.java
@@ -8,7 +8,7 @@ import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO; @@ -8,7 +8,7 @@ import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO;
8 import org.apache.ibatis.annotations.Mapper; 8 import org.apache.ibatis.annotations.Mapper;
9 9
10 /** 10 /**
11 - * IoT 规则场景(场景联动) Mapper 11 + * IoT 场景联动 Mapper
12 * 12 *
13 * @author HUIHUI 13 * @author HUIHUI
14 */ 14 */
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/IotRuleSceneService.java
@@ -18,7 +18,7 @@ import java.util.List; @@ -18,7 +18,7 @@ import java.util.List;
18 public interface IotRuleSceneService { 18 public interface IotRuleSceneService {
19 19
20 /** 20 /**
21 - * 创建规则场景(场景联动) 21 + * 创建场景联动
22 * 22 *
23 * @param createReqVO 创建信息 23 * @param createReqVO 创建信息
24 * @return 编号 24 * @return 编号
@@ -26,32 +26,32 @@ public interface IotRuleSceneService { @@ -26,32 +26,32 @@ public interface IotRuleSceneService {
26 Long createRuleScene(@Valid IotRuleSceneSaveReqVO createReqVO); 26 Long createRuleScene(@Valid IotRuleSceneSaveReqVO createReqVO);
27 27
28 /** 28 /**
29 - * 更新规则场景(场景联动) 29 + * 更新场景联动
30 * 30 *
31 * @param updateReqVO 更新信息 31 * @param updateReqVO 更新信息
32 */ 32 */
33 void updateRuleScene(@Valid IotRuleSceneSaveReqVO updateReqVO); 33 void updateRuleScene(@Valid IotRuleSceneSaveReqVO updateReqVO);
34 34
35 /** 35 /**
36 - * 删除规则场景(场景联动) 36 + * 删除场景联动
37 * 37 *
38 * @param id 编号 38 * @param id 编号
39 */ 39 */
40 void deleteRuleScene(Long id); 40 void deleteRuleScene(Long id);
41 41
42 /** 42 /**
43 - * 获得规则场景(场景联动) 43 + * 获得场景联动
44 * 44 *
45 * @param id 编号 45 * @param id 编号
46 - * @return 规则场景(场景联动) 46 + * @return 场景联动
47 */ 47 */
48 IotRuleSceneDO getRuleScene(Long id); 48 IotRuleSceneDO getRuleScene(Long id);
49 49
50 /** 50 /**
51 - * 获得规则场景(场景联动)分页 51 + * 获得场景联动分页
52 * 52 *
53 * @param pageReqVO 分页查询 53 * @param pageReqVO 分页查询
54 - * @return 规则场景(场景联动)分页 54 + * @return 场景联动分页
55 */ 55 */
56 PageResult<IotRuleSceneDO> getRuleScenePage(IotRuleScenePageReqVO pageReqVO); 56 PageResult<IotRuleSceneDO> getRuleScenePage(IotRuleScenePageReqVO pageReqVO);
57 57
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/IotRuleSceneServiceImpl.java
@@ -17,7 +17,6 @@ import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; @@ -17,7 +17,6 @@ import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
17 import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; 17 import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
18 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotRuleScenePageReqVO; 18 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotRuleScenePageReqVO;
19 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotRuleSceneSaveReqVO; 19 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotRuleSceneSaveReqVO;
20 -import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config.*;  
21 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO; 20 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO;
22 import cn.iocoder.yudao.module.iot.dal.mysql.rule.IotRuleSceneMapper; 21 import cn.iocoder.yudao.module.iot.dal.mysql.rule.IotRuleSceneMapper;
23 import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageIdentifierEnum; 22 import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageIdentifierEnum;
@@ -118,82 +117,82 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService { @@ -118,82 +117,82 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
118 if (true) { 117 if (true) {
119 IotRuleSceneDO ruleScene01 = new IotRuleSceneDO(); 118 IotRuleSceneDO ruleScene01 = new IotRuleSceneDO();
120 ruleScene01.setTriggers(CollUtil.newArrayList()); 119 ruleScene01.setTriggers(CollUtil.newArrayList());
121 - IotRuleSceneTriggerConfig trigger01 = new IotRuleSceneTriggerConfig(); 120 + IotRuleSceneDO.TriggerConfig trigger01 = new IotRuleSceneDO.TriggerConfig();
122 trigger01.setType(IotRuleSceneTriggerTypeEnum.DEVICE.getType()); 121 trigger01.setType(IotRuleSceneTriggerTypeEnum.DEVICE.getType());
123 trigger01.setConditions(CollUtil.newArrayList()); 122 trigger01.setConditions(CollUtil.newArrayList());
124 // 属性 123 // 属性
125 - IotRuleSceneTriggerCondition condition01 = new IotRuleSceneTriggerCondition(); 124 + IotRuleSceneDO.TriggerCondition condition01 = new IotRuleSceneDO.TriggerCondition();
126 condition01.setType(IotDeviceMessageTypeEnum.PROPERTY.getType()); 125 condition01.setType(IotDeviceMessageTypeEnum.PROPERTY.getType());
127 condition01.setIdentifier(IotDeviceMessageIdentifierEnum.PROPERTY_REPORT.getIdentifier()); 126 condition01.setIdentifier(IotDeviceMessageIdentifierEnum.PROPERTY_REPORT.getIdentifier());
128 condition01.setParameters(CollUtil.newArrayList()); 127 condition01.setParameters(CollUtil.newArrayList());
129 -// IotRuleSceneTriggerConditionParameter parameter010 = new IotRuleSceneTriggerConditionParameter(); 128 +// IotRuleSceneDO.TriggerConditionParameter parameter010 = new IotRuleSceneDO.TriggerConditionParameter();
130 // parameter010.setIdentifier("width"); 129 // parameter010.setIdentifier("width");
131 // parameter010.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.EQUALS.getOperator()); 130 // parameter010.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.EQUALS.getOperator());
132 // parameter010.setValue("abc"); 131 // parameter010.setValue("abc");
133 // condition01.getParameters().add(parameter010); 132 // condition01.getParameters().add(parameter010);
134 - IotRuleSceneTriggerConditionParameter parameter011 = new IotRuleSceneTriggerConditionParameter(); 133 + IotRuleSceneDO.TriggerConditionParameter parameter011 = new IotRuleSceneDO.TriggerConditionParameter();
135 parameter011.setIdentifier("width"); 134 parameter011.setIdentifier("width");
136 parameter011.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.EQUALS.getOperator()); 135 parameter011.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.EQUALS.getOperator());
137 parameter011.setValue("1"); 136 parameter011.setValue("1");
138 condition01.getParameters().add(parameter011); 137 condition01.getParameters().add(parameter011);
139 - IotRuleSceneTriggerConditionParameter parameter012 = new IotRuleSceneTriggerConditionParameter(); 138 + IotRuleSceneDO.TriggerConditionParameter parameter012 = new IotRuleSceneDO.TriggerConditionParameter();
140 parameter012.setIdentifier("width"); 139 parameter012.setIdentifier("width");
141 parameter012.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.NOT_EQUALS.getOperator()); 140 parameter012.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.NOT_EQUALS.getOperator());
142 parameter012.setValue("2"); 141 parameter012.setValue("2");
143 condition01.getParameters().add(parameter012); 142 condition01.getParameters().add(parameter012);
144 - IotRuleSceneTriggerConditionParameter parameter013 = new IotRuleSceneTriggerConditionParameter(); 143 + IotRuleSceneDO.TriggerConditionParameter parameter013 = new IotRuleSceneDO.TriggerConditionParameter();
145 parameter013.setIdentifier("width"); 144 parameter013.setIdentifier("width");
146 parameter013.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.GREATER_THAN.getOperator()); 145 parameter013.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.GREATER_THAN.getOperator());
147 parameter013.setValue("0"); 146 parameter013.setValue("0");
148 condition01.getParameters().add(parameter013); 147 condition01.getParameters().add(parameter013);
149 - IotRuleSceneTriggerConditionParameter parameter014 = new IotRuleSceneTriggerConditionParameter(); 148 + IotRuleSceneDO.TriggerConditionParameter parameter014 = new IotRuleSceneDO.TriggerConditionParameter();
150 parameter014.setIdentifier("width"); 149 parameter014.setIdentifier("width");
151 parameter014.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.GREATER_THAN_OR_EQUALS.getOperator()); 150 parameter014.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.GREATER_THAN_OR_EQUALS.getOperator());
152 parameter014.setValue("0"); 151 parameter014.setValue("0");
153 condition01.getParameters().add(parameter014); 152 condition01.getParameters().add(parameter014);
154 - IotRuleSceneTriggerConditionParameter parameter015 = new IotRuleSceneTriggerConditionParameter(); 153 + IotRuleSceneDO.TriggerConditionParameter parameter015 = new IotRuleSceneDO.TriggerConditionParameter();
155 parameter015.setIdentifier("width"); 154 parameter015.setIdentifier("width");
156 parameter015.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.LESS_THAN.getOperator()); 155 parameter015.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.LESS_THAN.getOperator());
157 parameter015.setValue("2"); 156 parameter015.setValue("2");
158 condition01.getParameters().add(parameter015); 157 condition01.getParameters().add(parameter015);
159 - IotRuleSceneTriggerConditionParameter parameter016 = new IotRuleSceneTriggerConditionParameter(); 158 + IotRuleSceneDO.TriggerConditionParameter parameter016 = new IotRuleSceneDO.TriggerConditionParameter();
160 parameter016.setIdentifier("width"); 159 parameter016.setIdentifier("width");
161 parameter016.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.LESS_THAN_OR_EQUALS.getOperator()); 160 parameter016.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.LESS_THAN_OR_EQUALS.getOperator());
162 parameter016.setValue("2"); 161 parameter016.setValue("2");
163 condition01.getParameters().add(parameter016); 162 condition01.getParameters().add(parameter016);
164 - IotRuleSceneTriggerConditionParameter parameter017 = new IotRuleSceneTriggerConditionParameter(); 163 + IotRuleSceneDO.TriggerConditionParameter parameter017 = new IotRuleSceneDO.TriggerConditionParameter();
165 parameter017.setIdentifier("width"); 164 parameter017.setIdentifier("width");
166 parameter017.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.IN.getOperator()); 165 parameter017.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.IN.getOperator());
167 parameter017.setValue("1,2,3"); 166 parameter017.setValue("1,2,3");
168 condition01.getParameters().add(parameter017); 167 condition01.getParameters().add(parameter017);
169 - IotRuleSceneTriggerConditionParameter parameter018 = new IotRuleSceneTriggerConditionParameter(); 168 + IotRuleSceneDO.TriggerConditionParameter parameter018 = new IotRuleSceneDO.TriggerConditionParameter();
170 parameter018.setIdentifier("width"); 169 parameter018.setIdentifier("width");
171 parameter018.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.NOT_IN.getOperator()); 170 parameter018.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.NOT_IN.getOperator());
172 parameter018.setValue("0,2,3"); 171 parameter018.setValue("0,2,3");
173 condition01.getParameters().add(parameter018); 172 condition01.getParameters().add(parameter018);
174 - IotRuleSceneTriggerConditionParameter parameter019 = new IotRuleSceneTriggerConditionParameter(); 173 + IotRuleSceneDO.TriggerConditionParameter parameter019 = new IotRuleSceneDO.TriggerConditionParameter();
175 parameter019.setIdentifier("width"); 174 parameter019.setIdentifier("width");
176 parameter019.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.BETWEEN.getOperator()); 175 parameter019.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.BETWEEN.getOperator());
177 parameter019.setValue("1,3"); 176 parameter019.setValue("1,3");
178 condition01.getParameters().add(parameter019); 177 condition01.getParameters().add(parameter019);
179 - IotRuleSceneTriggerConditionParameter parameter020 = new IotRuleSceneTriggerConditionParameter(); 178 + IotRuleSceneDO.TriggerConditionParameter parameter020 = new IotRuleSceneDO.TriggerConditionParameter();
180 parameter020.setIdentifier("width"); 179 parameter020.setIdentifier("width");
181 parameter020.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.NOT_BETWEEN.getOperator()); 180 parameter020.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.NOT_BETWEEN.getOperator());
182 parameter020.setValue("2,3"); 181 parameter020.setValue("2,3");
183 condition01.getParameters().add(parameter020); 182 condition01.getParameters().add(parameter020);
184 trigger01.getConditions().add(condition01); 183 trigger01.getConditions().add(condition01);
185 // 状态 184 // 状态
186 - IotRuleSceneTriggerCondition condition02 = new IotRuleSceneTriggerCondition(); 185 + IotRuleSceneDO.TriggerCondition condition02 = new IotRuleSceneDO.TriggerCondition();
187 condition02.setType(IotDeviceMessageTypeEnum.STATE.getType()); 186 condition02.setType(IotDeviceMessageTypeEnum.STATE.getType());
188 condition02.setIdentifier(IotDeviceMessageIdentifierEnum.STATE_ONLINE.getIdentifier()); 187 condition02.setIdentifier(IotDeviceMessageIdentifierEnum.STATE_ONLINE.getIdentifier());
189 condition02.setParameters(CollUtil.newArrayList()); 188 condition02.setParameters(CollUtil.newArrayList());
190 trigger01.getConditions().add(condition02); 189 trigger01.getConditions().add(condition02);
191 // 事件 190 // 事件
192 - IotRuleSceneTriggerCondition condition03 = new IotRuleSceneTriggerCondition(); 191 + IotRuleSceneDO.TriggerCondition condition03 = new IotRuleSceneDO.TriggerCondition();
193 condition03.setType(IotDeviceMessageTypeEnum.EVENT.getType()); 192 condition03.setType(IotDeviceMessageTypeEnum.EVENT.getType());
194 condition03.setIdentifier("xxx"); 193 condition03.setIdentifier("xxx");
195 condition03.setParameters(CollUtil.newArrayList()); 194 condition03.setParameters(CollUtil.newArrayList());
196 - IotRuleSceneTriggerConditionParameter parameter030 = new IotRuleSceneTriggerConditionParameter(); 195 + IotRuleSceneDO.TriggerConditionParameter parameter030 = new IotRuleSceneDO.TriggerConditionParameter();
197 parameter030.setIdentifier("width"); 196 parameter030.setIdentifier("width");
198 parameter030.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.EQUALS.getOperator()); 197 parameter030.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.EQUALS.getOperator());
199 parameter030.setValue("1"); 198 parameter030.setValue("1");
@@ -202,21 +201,21 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService { @@ -202,21 +201,21 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
202 // 动作 201 // 动作
203 ruleScene01.setActions(CollUtil.newArrayList()); 202 ruleScene01.setActions(CollUtil.newArrayList());
204 // 设备控制 203 // 设备控制
205 - IotRuleSceneActionConfig action01 = new IotRuleSceneActionConfig(); 204 + IotRuleSceneDO.ActionConfig action01 = new IotRuleSceneDO.ActionConfig();
206 action01.setType(IotRuleSceneActionTypeEnum.DEVICE_CONTROL.getType()); 205 action01.setType(IotRuleSceneActionTypeEnum.DEVICE_CONTROL.getType());
207 - IotRuleSceneActionDeviceControl iotRuleSceneActionDeviceControl01 = new IotRuleSceneActionDeviceControl();  
208 - iotRuleSceneActionDeviceControl01.setProductKey("4aymZgOTOOCrDKRT");  
209 - iotRuleSceneActionDeviceControl01.setDeviceNames(ListUtil.of("small"));  
210 - iotRuleSceneActionDeviceControl01.setType(IotDeviceMessageTypeEnum.PROPERTY.getType());  
211 - iotRuleSceneActionDeviceControl01.setIdentifier(IotDeviceMessageIdentifierEnum.PROPERTY_SET.getIdentifier());  
212 - iotRuleSceneActionDeviceControl01.setData(MapUtil.<String, Object>builder() 206 + IotRuleSceneDO.ActionDeviceControl actionDeviceControl01 = new IotRuleSceneDO.ActionDeviceControl();
  207 + actionDeviceControl01.setProductKey("4aymZgOTOOCrDKRT");
  208 + actionDeviceControl01.setDeviceNames(ListUtil.of("small"));
  209 + actionDeviceControl01.setType(IotDeviceMessageTypeEnum.PROPERTY.getType());
  210 + actionDeviceControl01.setIdentifier(IotDeviceMessageIdentifierEnum.PROPERTY_SET.getIdentifier());
  211 + actionDeviceControl01.setData(MapUtil.<String, Object>builder()
213 .put("power", 1) 212 .put("power", 1)
214 .put("color", "red") 213 .put("color", "red")
215 .build()); 214 .build());
216 - action01.setDeviceControl(iotRuleSceneActionDeviceControl01); 215 + action01.setDeviceControl(actionDeviceControl01);
217 // ruleScene01.getActions().add(action01); // TODO 芋艿:先不测试了 216 // ruleScene01.getActions().add(action01); // TODO 芋艿:先不测试了
218 // 数据桥接(http) 217 // 数据桥接(http)
219 - IotRuleSceneActionConfig action02 = new IotRuleSceneActionConfig(); 218 + IotRuleSceneDO.ActionConfig action02 = new IotRuleSceneDO.ActionConfig();
220 action02.setType(IotRuleSceneActionTypeEnum.DATA_BRIDGE.getType()); 219 action02.setType(IotRuleSceneActionTypeEnum.DATA_BRIDGE.getType());
221 action02.setDataBridgeId(1L); 220 action02.setDataBridgeId(1L);
222 ruleScene01.getActions().add(action02); 221 ruleScene01.getActions().add(action02);
@@ -226,7 +225,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService { @@ -226,7 +225,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
226 List<IotRuleSceneDO> list = ruleSceneMapper.selectList(); 225 List<IotRuleSceneDO> list = ruleSceneMapper.selectList();
227 // TODO @芋艿:需要考虑开启状态 226 // TODO @芋艿:需要考虑开启状态
228 return filterList(list, ruleScene -> { 227 return filterList(list, ruleScene -> {
229 - for (IotRuleSceneTriggerConfig trigger : ruleScene.getTriggers()) { 228 + for (IotRuleSceneDO.TriggerConfig trigger : ruleScene.getTriggers()) {
230 if (ObjUtil.notEqual(trigger.getProductKey(), productKey)) { 229 if (ObjUtil.notEqual(trigger.getProductKey(), productKey)) {
231 continue; 230 continue;
232 } 231 }
@@ -261,13 +260,13 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService { @@ -261,13 +260,13 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
261 IotRuleSceneDO scene = new IotRuleSceneDO().setStatus(CommonStatusEnum.ENABLE.getStatus()); 260 IotRuleSceneDO scene = new IotRuleSceneDO().setStatus(CommonStatusEnum.ENABLE.getStatus());
262 if (true) { 261 if (true) {
263 scene.setTenantId(1L); 262 scene.setTenantId(1L);
264 - IotRuleSceneTriggerConfig iotRuleSceneTriggerConfig = new IotRuleSceneTriggerConfig();  
265 - iotRuleSceneTriggerConfig.setType(IotRuleSceneTriggerTypeEnum.TIMER.getType());  
266 - scene.setTriggers(ListUtil.toList(iotRuleSceneTriggerConfig)); 263 + IotRuleSceneDO.TriggerConfig triggerConfig = new IotRuleSceneDO.TriggerConfig();
  264 + triggerConfig.setType(IotRuleSceneTriggerTypeEnum.TIMER.getType());
  265 + scene.setTriggers(ListUtil.toList(triggerConfig));
267 // 动作 266 // 动作
268 - IotRuleSceneActionConfig action01 = new IotRuleSceneActionConfig(); 267 + IotRuleSceneDO.ActionConfig action01 = new IotRuleSceneDO.ActionConfig();
269 action01.setType(IotRuleSceneActionTypeEnum.DEVICE_CONTROL.getType()); 268 action01.setType(IotRuleSceneActionTypeEnum.DEVICE_CONTROL.getType());
270 - IotRuleSceneActionDeviceControl iotRuleSceneActionDeviceControl01 = new IotRuleSceneActionDeviceControl(); 269 + IotRuleSceneDO.ActionDeviceControl iotRuleSceneActionDeviceControl01 = new IotRuleSceneDO.ActionDeviceControl();
271 iotRuleSceneActionDeviceControl01.setProductKey("4aymZgOTOOCrDKRT"); 270 iotRuleSceneActionDeviceControl01.setProductKey("4aymZgOTOOCrDKRT");
272 iotRuleSceneActionDeviceControl01.setDeviceNames(ListUtil.of("small")); 271 iotRuleSceneActionDeviceControl01.setDeviceNames(ListUtil.of("small"));
273 iotRuleSceneActionDeviceControl01.setType(IotDeviceMessageTypeEnum.PROPERTY.getType()); 272 iotRuleSceneActionDeviceControl01.setType(IotDeviceMessageTypeEnum.PROPERTY.getType());
@@ -288,7 +287,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService { @@ -288,7 +287,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
288 return; 287 return;
289 } 288 }
290 // 1.2 判断是否有定时触发器,避免脏数据 289 // 1.2 判断是否有定时触发器,避免脏数据
291 - IotRuleSceneTriggerConfig config = CollUtil.findOne(scene.getTriggers(), 290 + IotRuleSceneDO.TriggerConfig config = CollUtil.findOne(scene.getTriggers(),
292 trigger -> ObjUtil.equals(trigger.getType(), IotRuleSceneTriggerTypeEnum.TIMER.getType())); 291 trigger -> ObjUtil.equals(trigger.getType(), IotRuleSceneTriggerTypeEnum.TIMER.getType()));
293 if (config == null) { 292 if (config == null) {
294 log.error("[executeRuleSceneByTimer][规则场景({}) 不存在定时触发器]", scene); 293 log.error("[executeRuleSceneByTimer][规则场景({}) 不存在定时触发器]", scene);
@@ -317,7 +316,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService { @@ -317,7 +316,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
317 316
318 // 2. 匹配 trigger 触发器的条件 317 // 2. 匹配 trigger 触发器的条件
319 return filterList(ruleScenes, ruleScene -> { 318 return filterList(ruleScenes, ruleScene -> {
320 - for (IotRuleSceneTriggerConfig trigger : ruleScene.getTriggers()) { 319 + for (IotRuleSceneDO.TriggerConfig trigger : ruleScene.getTriggers()) {
321 // 2.1 非设备触发,不匹配 320 // 2.1 非设备触发,不匹配
322 if (ObjUtil.notEqual(trigger.getType(), IotRuleSceneTriggerTypeEnum.DEVICE.getType())) { 321 if (ObjUtil.notEqual(trigger.getType(), IotRuleSceneTriggerTypeEnum.DEVICE.getType())) {
323 return false; 322 return false;
@@ -328,13 +327,13 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService { @@ -328,13 +327,13 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
328 return false; 327 return false;
329 } 328 }
330 // 2.3 多个条件,只需要满足一个即可 329 // 2.3 多个条件,只需要满足一个即可
331 - IotRuleSceneTriggerCondition matchedCondition = CollUtil.findOne(trigger.getConditions(), condition -> { 330 + IotRuleSceneDO.TriggerCondition matchedCondition = CollUtil.findOne(trigger.getConditions(), condition -> {
332 if (ObjUtil.notEqual(message.getType(), condition.getType()) 331 if (ObjUtil.notEqual(message.getType(), condition.getType())
333 || ObjUtil.notEqual(message.getIdentifier(), condition.getIdentifier())) { 332 || ObjUtil.notEqual(message.getIdentifier(), condition.getIdentifier())) {
334 return false; 333 return false;
335 } 334 }
336 // 多个条件参数,必须全部满足。所以,下面的逻辑就是找到一个不满足的条件参数 335 // 多个条件参数,必须全部满足。所以,下面的逻辑就是找到一个不满足的条件参数
337 - IotRuleSceneTriggerConditionParameter notMatchedParameter = CollUtil.findOne(condition.getParameters(), 336 + IotRuleSceneDO.TriggerConditionParameter notMatchedParameter = CollUtil.findOne(condition.getParameters(),
338 parameter -> !isTriggerConditionParameterMatched(message, parameter, ruleScene, trigger)); 337 parameter -> !isTriggerConditionParameterMatched(message, parameter, ruleScene, trigger));
339 return notMatchedParameter == null; 338 return notMatchedParameter == null;
340 }); 339 });
@@ -360,8 +359,8 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService { @@ -360,8 +359,8 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
360 * @return 是否匹配 359 * @return 是否匹配
361 */ 360 */
362 @SuppressWarnings({"unchecked", "DataFlowIssue"}) 361 @SuppressWarnings({"unchecked", "DataFlowIssue"})
363 - private boolean isTriggerConditionParameterMatched(IotDeviceMessage message, IotRuleSceneTriggerConditionParameter parameter,  
364 - IotRuleSceneDO ruleScene, IotRuleSceneTriggerConfig trigger) { 362 + private boolean isTriggerConditionParameterMatched(IotDeviceMessage message, IotRuleSceneDO.TriggerConditionParameter parameter,
  363 + IotRuleSceneDO ruleScene, IotRuleSceneDO.TriggerConfig trigger) {
365 // 1.1 校验操作符是否合法 364 // 1.1 校验操作符是否合法
366 IotRuleSceneTriggerConditionParameterOperatorEnum operator = 365 IotRuleSceneTriggerConditionParameterOperatorEnum operator =
367 IotRuleSceneTriggerConditionParameterOperatorEnum.operatorOf(parameter.getOperator()); 366 IotRuleSceneTriggerConditionParameterOperatorEnum.operatorOf(parameter.getOperator());
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/IotRuleSceneAction.java
1 package cn.iocoder.yudao.module.iot.service.rule.action; 1 package cn.iocoder.yudao.module.iot.service.rule.action;
2 2
3 -import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config.IotRuleSceneActionConfig; 3 +import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO;
4 import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum; 4 import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum;
5 import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage; 5 import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;
6 6
@@ -23,7 +23,7 @@ public interface IotRuleSceneAction { @@ -23,7 +23,7 @@ public interface IotRuleSceneAction {
23 * 2. 非空的情况:设备触发 23 * 2. 非空的情况:设备触发
24 * @param config 配置 24 * @param config 配置
25 */ 25 */
26 - void execute(@Nullable IotDeviceMessage message, IotRuleSceneActionConfig config) throws Exception; 26 + void execute(@Nullable IotDeviceMessage message, IotRuleSceneDO.ActionConfig config) throws Exception;
27 27
28 /** 28 /**
29 * 获得类型 29 * 获得类型
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/IotRuleSceneAlertAction.java
1 package cn.iocoder.yudao.module.iot.service.rule.action; 1 package cn.iocoder.yudao.module.iot.service.rule.action;
2 2
3 -import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config.IotRuleSceneActionConfig; 3 +import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO;
4 import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum; 4 import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum;
5 import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage; 5 import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;
6 import org.springframework.stereotype.Component; 6 import org.springframework.stereotype.Component;
@@ -16,7 +16,7 @@ import javax.annotation.Nullable; @@ -16,7 +16,7 @@ import javax.annotation.Nullable;
16 public class IotRuleSceneAlertAction implements IotRuleSceneAction { 16 public class IotRuleSceneAlertAction implements IotRuleSceneAction {
17 17
18 @Override 18 @Override
19 - public void execute(@Nullable IotDeviceMessage message, IotRuleSceneActionConfig config) { 19 + public void execute(@Nullable IotDeviceMessage message, IotRuleSceneDO.ActionConfig config) {
20 // TODO @芋艿:待实现 20 // TODO @芋艿:待实现
21 } 21 }
22 22
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; @@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.iot.service.rule.action;
2 2
3 import cn.hutool.core.lang.Assert; 3 import cn.hutool.core.lang.Assert;
4 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 4 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
5 -import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config.IotRuleSceneActionConfig;  
6 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataBridgeDO; 5 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataBridgeDO;
  6 +import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO;
7 import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum; 7 import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum;
8 import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage; 8 import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;
9 import cn.iocoder.yudao.module.iot.service.rule.IotDataBridgeService; 9 import cn.iocoder.yudao.module.iot.service.rule.IotDataBridgeService;
@@ -29,7 +29,7 @@ public class IotRuleSceneDataBridgeAction implements IotRuleSceneAction { @@ -29,7 +29,7 @@ public class IotRuleSceneDataBridgeAction implements IotRuleSceneAction {
29 private List<IotDataBridgeExecute<?>> dataBridgeExecutes; 29 private List<IotDataBridgeExecute<?>> dataBridgeExecutes;
30 30
31 @Override 31 @Override
32 - public void execute(IotDeviceMessage message, IotRuleSceneActionConfig config) throws Exception { 32 + public void execute(IotDeviceMessage message, IotRuleSceneDO.ActionConfig config) throws Exception {
33 // 1.1 如果消息为空,直接返回 33 // 1.1 如果消息为空,直接返回
34 if (message == null) { 34 if (message == null) {
35 return; 35 return;
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/IotRuleSceneDeviceControlAction.java
@@ -2,9 +2,8 @@ package cn.iocoder.yudao.module.iot.service.rule.action; @@ -2,9 +2,8 @@ package cn.iocoder.yudao.module.iot.service.rule.action;
2 2
3 import cn.hutool.core.lang.Assert; 3 import cn.hutool.core.lang.Assert;
4 import cn.iocoder.yudao.module.iot.controller.admin.device.vo.control.IotDeviceDownstreamReqVO; 4 import cn.iocoder.yudao.module.iot.controller.admin.device.vo.control.IotDeviceDownstreamReqVO;
5 -import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config.IotRuleSceneActionConfig;  
6 -import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config.IotRuleSceneActionDeviceControl;  
7 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; 5 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
  6 +import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO;
8 import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum; 7 import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum;
9 import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage; 8 import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;
10 import cn.iocoder.yudao.module.iot.service.device.IotDeviceService; 9 import cn.iocoder.yudao.module.iot.service.device.IotDeviceService;
@@ -28,8 +27,8 @@ public class IotRuleSceneDeviceControlAction implements IotRuleSceneAction { @@ -28,8 +27,8 @@ public class IotRuleSceneDeviceControlAction implements IotRuleSceneAction {
28 private IotDeviceService deviceService; 27 private IotDeviceService deviceService;
29 28
30 @Override 29 @Override
31 - public void execute(IotDeviceMessage message, IotRuleSceneActionConfig config) {  
32 - IotRuleSceneActionDeviceControl control = config.getDeviceControl(); 30 + public void execute(IotDeviceMessage message, IotRuleSceneDO.ActionConfig config) {
  31 + IotRuleSceneDO.ActionDeviceControl control = config.getDeviceControl();
33 Assert.notNull(control, "设备控制配置不能为空"); 32 Assert.notNull(control, "设备控制配置不能为空");
34 // 遍历每个设备,下发消息 33 // 遍历每个设备,下发消息
35 control.getDeviceNames().forEach(deviceName -> { 34 control.getDeviceNames().forEach(deviceName -> {
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/databridge/AbstractCacheableDataBridgeExecute.java
@@ -101,7 +101,7 @@ public abstract class AbstractCacheableDataBridgeExecute&lt;Config, Producer&gt; imple @@ -101,7 +101,7 @@ public abstract class AbstractCacheableDataBridgeExecute&lt;Config, Producer&gt; imple
101 @Override 101 @Override
102 @SuppressWarnings({"unchecked"}) 102 @SuppressWarnings({"unchecked"})
103 public void execute(IotDeviceMessage message, IotDataBridgeDO dataBridge) { 103 public void execute(IotDeviceMessage message, IotDataBridgeDO dataBridge) {
104 - if (ObjUtil.notEqual(message.getType(), getType())) { 104 + if (ObjUtil.notEqual(dataBridge.getType(), getType())) {
105 return; 105 return;
106 } 106 }
107 try { 107 try {
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/databridge/IotRedisStreamMQDataBridgeExecute.java renamed to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/databridge/IotRedisStreamDataBridgeExecute.java
1 package cn.iocoder.yudao.module.iot.service.rule.action.databridge; 1 package cn.iocoder.yudao.module.iot.service.rule.action.databridge;
2 2
3 -import cn.hutool.core.util.ReflectUtil;  
4 import cn.hutool.core.util.StrUtil; 3 import cn.hutool.core.util.StrUtil;
5 -import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge.config.IotDataBridgeRedisStreamMQConfig; 4 +import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge.config.IotDataBridgeRedisStreamConfig;
6 import cn.iocoder.yudao.module.iot.enums.rule.IotDataBridgeTypeEnum; 5 import cn.iocoder.yudao.module.iot.enums.rule.IotDataBridgeTypeEnum;
7 import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage; 6 import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;
8 -import com.fasterxml.jackson.databind.ObjectMapper;  
9 -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;  
10 import lombok.extern.slf4j.Slf4j; 7 import lombok.extern.slf4j.Slf4j;
11 import org.redisson.Redisson; 8 import org.redisson.Redisson;
12 import org.redisson.api.RedissonClient; 9 import org.redisson.api.RedissonClient;
@@ -21,14 +18,14 @@ import org.springframework.data.redis.serializer.RedisSerializer; @@ -21,14 +18,14 @@ import org.springframework.data.redis.serializer.RedisSerializer;
21 import org.springframework.stereotype.Component; 18 import org.springframework.stereotype.Component;
22 19
23 /** 20 /**
24 - * Redis Stream MQ 的 {@link IotDataBridgeExecute} 实现类 21 + * Redis Stream 的 {@link IotDataBridgeExecute} 实现类
25 * 22 *
26 * @author HUIHUI 23 * @author HUIHUI
27 */ 24 */
28 @Component 25 @Component
29 @Slf4j 26 @Slf4j
30 -public class IotRedisStreamMQDataBridgeExecute extends  
31 - AbstractCacheableDataBridgeExecute<IotDataBridgeRedisStreamMQConfig, RedisTemplate<String, Object>> { 27 +public class IotRedisStreamDataBridgeExecute extends
  28 + AbstractCacheableDataBridgeExecute<IotDataBridgeRedisStreamConfig, RedisTemplate<String, Object>> {
32 29
33 @Override 30 @Override
34 public Integer getType() { 31 public Integer getType() {
@@ -36,7 +33,7 @@ public class IotRedisStreamMQDataBridgeExecute extends @@ -36,7 +33,7 @@ public class IotRedisStreamMQDataBridgeExecute extends
36 } 33 }
37 34
38 @Override 35 @Override
39 - public void execute0(IotDeviceMessage message, IotDataBridgeRedisStreamMQConfig config) throws Exception { 36 + public void execute0(IotDeviceMessage message, IotDataBridgeRedisStreamConfig config) throws Exception {
40 // 1. 获取 RedisTemplate 37 // 1. 获取 RedisTemplate
41 RedisTemplate<String, Object> redisTemplate = getProducer(config); 38 RedisTemplate<String, Object> redisTemplate = getProducer(config);
42 39
@@ -48,7 +45,7 @@ public class IotRedisStreamMQDataBridgeExecute extends @@ -48,7 +45,7 @@ public class IotRedisStreamMQDataBridgeExecute extends
48 } 45 }
49 46
50 @Override 47 @Override
51 - protected RedisTemplate<String, Object> initProducer(IotDataBridgeRedisStreamMQConfig config) { 48 + protected RedisTemplate<String, Object> initProducer(IotDataBridgeRedisStreamConfig config) {
52 // 1.1 创建 Redisson 配置 49 // 1.1 创建 Redisson 配置
53 Config redissonConfig = new Config(); 50 Config redissonConfig = new Config();
54 SingleServerConfig serverConfig = redissonConfig.useSingleServer() 51 SingleServerConfig serverConfig = redissonConfig.useSingleServer()
@@ -59,20 +56,17 @@ public class IotRedisStreamMQDataBridgeExecute extends @@ -59,20 +56,17 @@ public class IotRedisStreamMQDataBridgeExecute extends
59 serverConfig.setPassword(config.getPassword()); 56 serverConfig.setPassword(config.getPassword());
60 } 57 }
61 58
62 - // TODO @huihui:看看能不能简化一些。按道理说,不用这么多的哈。  
63 - // 2.1 创建 RedissonClient 59 + // TODO @芋艿:看看怎么优化
  60 + // 创建 RedisTemplate 并配置
64 RedissonClient redisson = Redisson.create(redissonConfig); 61 RedissonClient redisson = Redisson.create(redissonConfig);
65 - // 2.2 创建并配置 RedisTemplate  
66 RedisTemplate<String, Object> template = new RedisTemplate<>(); 62 RedisTemplate<String, Object> template = new RedisTemplate<>();
67 - // 设置 RedisConnection 工厂。😈 它就是实现多种 Java Redis 客户端接入的秘密工厂。感兴趣的胖友,可以自己去撸下。  
68 template.setConnectionFactory(new RedissonConnectionFactory(redisson)); 63 template.setConnectionFactory(new RedissonConnectionFactory(redisson));
69 - // 使用 String 序列化方式,序列化 KEY 。 64 + // 设置序列化器
70 template.setKeySerializer(RedisSerializer.string()); 65 template.setKeySerializer(RedisSerializer.string());
71 template.setHashKeySerializer(RedisSerializer.string()); 66 template.setHashKeySerializer(RedisSerializer.string());
72 - // 使用 JSON 序列化方式(库是 Jackson ),序列化 VALUE 。  
73 - template.setValueSerializer(buildRedisSerializer());  
74 - template.setHashValueSerializer(buildRedisSerializer());  
75 - template.afterPropertiesSet();// 初始化 67 + template.setValueSerializer(RedisSerializer.json());
  68 + template.setHashValueSerializer(RedisSerializer.json());
  69 + template.afterPropertiesSet();
76 return template; 70 return template;
77 } 71 }
78 72
@@ -84,13 +78,4 @@ public class IotRedisStreamMQDataBridgeExecute extends @@ -84,13 +78,4 @@ public class IotRedisStreamMQDataBridgeExecute extends
84 } 78 }
85 } 79 }
86 80
87 - // TODO @huihui:看看能不能简化一些。按道理说,不用这么多的哈。  
88 - public static RedisSerializer<?> buildRedisSerializer() {  
89 - RedisSerializer<Object> json = RedisSerializer.json();  
90 - // 解决 LocalDateTime 的序列化  
91 - ObjectMapper objectMapper = (ObjectMapper) ReflectUtil.getFieldValue(json, "mapper");  
92 - objectMapper.registerModules(new JavaTimeModule());  
93 - return json;  
94 - }  
95 -  
96 } 81 }
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelService.java
@@ -4,7 +4,6 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; @@ -4,7 +4,6 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelListReqVO; 4 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelListReqVO;
5 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelPageReqVO; 5 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelPageReqVO;
6 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelSaveReqVO; 6 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelSaveReqVO;
7 -import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelTSLRespVO;  
8 import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO; 7 import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO;
9 import jakarta.validation.Valid; 8 import jakarta.validation.Valid;
10 9
@@ -91,12 +90,4 @@ public interface IotThingModelService { @@ -91,12 +90,4 @@ public interface IotThingModelService {
91 */ 90 */
92 Long getThingModelCount(LocalDateTime createTime); 91 Long getThingModelCount(LocalDateTime createTime);
93 92
94 - /**  
95 - * 通过产品 ID 获取产品物模型 TSL  
96 - *  
97 - * @param productId 产品 ID  
98 - * @return 产品物模型 TSL  
99 - */  
100 - IotThingModelTSLRespVO getThingModelTslByProductId(Long productId);  
101 -  
102 } 93 }
103 \ No newline at end of file 94 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelServiceImpl.java
1 package cn.iocoder.yudao.module.iot.service.thingmodel; 1 package cn.iocoder.yudao.module.iot.service.thingmodel;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 -import cn.hutool.core.util.ObjUtil;  
5 import cn.hutool.core.util.ObjectUtil; 4 import cn.hutool.core.util.ObjectUtil;
6 import cn.hutool.core.util.StrUtil; 5 import cn.hutool.core.util.StrUtil;
7 import cn.hutool.extra.spring.SpringUtil; 6 import cn.hutool.extra.spring.SpringUtil;
@@ -14,7 +13,6 @@ import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.ThingModelS @@ -14,7 +13,6 @@ import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.ThingModelS
14 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelListReqVO; 13 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelListReqVO;
15 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelPageReqVO; 14 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelPageReqVO;
16 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelSaveReqVO; 15 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelSaveReqVO;
17 -import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelTSLRespVO;  
18 import cn.iocoder.yudao.module.iot.convert.thingmodel.IotThingModelConvert; 16 import cn.iocoder.yudao.module.iot.convert.thingmodel.IotThingModelConvert;
19 import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; 17 import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
20 import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO; 18 import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO;
@@ -151,31 +149,6 @@ public class IotThingModelServiceImpl implements IotThingModelService { @@ -151,31 +149,6 @@ public class IotThingModelServiceImpl implements IotThingModelService {
151 return thingModelMapper.selectList(reqVO); 149 return thingModelMapper.selectList(reqVO);
152 } 150 }
153 151
154 - // TODO @puhui999:这个转换,放在 controller 貌似也行?  
155 - @Override  
156 - public IotThingModelTSLRespVO getThingModelTslByProductId(Long productId) {  
157 - IotThingModelTSLRespVO tslRespVO = new IotThingModelTSLRespVO();  
158 - // 1. 获得产品所有物模型定义  
159 - List<IotThingModelDO> thingModels = thingModelMapper.selectListByProductId(productId);  
160 - if (CollUtil.isEmpty(thingModels)) {  
161 - return tslRespVO;  
162 - }  
163 -  
164 - // 2.1 设置公共部分参数  
165 - IotThingModelDO thingModel = thingModels.get(0);  
166 - tslRespVO.setProductId(thingModel.getProductId()).setProductKey(thingModel.getProductKey());  
167 - // 2.2 处理属性列表  
168 - tslRespVO.setProperties(convertList(filterList(thingModels, item ->  
169 - ObjUtil.equal(IotThingModelTypeEnum.PROPERTY.getType(), item.getType())), IotThingModelDO::getProperty));  
170 - // 2.3 处理服务列表  
171 - tslRespVO.setServices(convertList(filterList(thingModels, item ->  
172 - ObjUtil.equal(IotThingModelTypeEnum.SERVICE.getType(), item.getType())), IotThingModelDO::getService));  
173 - // 2.4 处理事件列表  
174 - tslRespVO.setEvents(convertList(filterList(thingModels, item ->  
175 - ObjUtil.equal(IotThingModelTypeEnum.EVENT.getType(), item.getType())), IotThingModelDO::getEvent));  
176 - return tslRespVO;  
177 - }  
178 -  
179 /** 152 /**
180 * 校验功能是否存在 153 * 校验功能是否存在
181 * 154 *
yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/rule/action/databridge/IotDataBridgeExecuteTest.java
@@ -22,7 +22,7 @@ import static org.mockito.ArgumentMatchers.anyString; @@ -22,7 +22,7 @@ import static org.mockito.ArgumentMatchers.anyString;
22 import static org.mockito.Mockito.when; 22 import static org.mockito.Mockito.when;
23 23
24 /** 24 /**
25 - * {@link IotDataBridgeExecute} 实现类的测试 25 + * {@link IotDataBridgeExecute} 实现类的单元测试
26 * 26 *
27 * @author HUIHUI 27 * @author HUIHUI
28 */ 28 */
@@ -41,114 +41,125 @@ public class IotDataBridgeExecuteTest extends BaseMockitoUnitTest { @@ -41,114 +41,125 @@ public class IotDataBridgeExecuteTest extends BaseMockitoUnitTest {
41 @BeforeEach 41 @BeforeEach
42 public void setUp() { 42 public void setUp() {
43 // 创建共享的测试消息 43 // 创建共享的测试消息
44 - message = IotDeviceMessage.builder().requestId("TEST-001").reportTime(LocalDateTime.now()).tenantId(1L)  
45 - .productKey("testProduct").deviceName("testDevice").deviceKey("testDeviceKey")  
46 - .type("property").identifier("temperature").data("{\"value\": 60}") 44 + message = IotDeviceMessage.builder()
  45 + .requestId("TEST-001")
  46 + .reportTime(LocalDateTime.now())
  47 + .tenantId(1L)
  48 + .productKey("testProduct")
  49 + .deviceName("testDevice")
  50 + .deviceKey("testDeviceKey")
  51 + .type("property")
  52 + .identifier("temperature")
  53 + .data("{\"value\": 60}")
47 .build(); 54 .build();
48 -  
49 - // 配置 RestTemplate mock 返回成功响应  
50 - // TODO @puhui999:这个应该放到 testHttpDataBridge 里  
51 - when(restTemplate.exchange(anyString(), any(HttpMethod.class), any(), any(Class.class)))  
52 - .thenReturn(new ResponseEntity<>("Success", HttpStatus.OK));  
53 } 55 }
54 56
55 @Test 57 @Test
56 - public void testKafkaMQDataBridge() { 58 + public void testKafkaMQDataBridge() throws Exception {
57 // 1. 创建执行器实例 59 // 1. 创建执行器实例
58 IotKafkaMQDataBridgeExecute action = new IotKafkaMQDataBridgeExecute(); 60 IotKafkaMQDataBridgeExecute action = new IotKafkaMQDataBridgeExecute();
59 61
60 // 2. 创建配置 62 // 2. 创建配置
61 - // TODO @puhui999:可以改成链式哈。  
62 - IotDataBridgeKafkaMQConfig config = new IotDataBridgeKafkaMQConfig();  
63 - config.setBootstrapServers("127.0.0.1:9092");  
64 - config.setTopic("test-topic");  
65 - config.setSsl(false);  
66 - config.setUsername(null);  
67 - config.setPassword(null);  
68 -  
69 - // 3. 执行两次测试,验证缓存  
70 - log.info("[testKafkaMQDataBridge][第一次执行,应该会创建新的 producer]");  
71 - action.execute(message, new IotDataBridgeDO().setType(action.getType()).setConfig(config));  
72 -  
73 - log.info("[testKafkaMQDataBridge][第二次执行,应该会复用缓存的 producer]");  
74 - action.execute(message, new IotDataBridgeDO().setType(action.getType()).setConfig(config)); 63 + IotDataBridgeKafkaMQConfig config = new IotDataBridgeKafkaMQConfig()
  64 + .setBootstrapServers("127.0.0.1:9092")
  65 + .setTopic("test-topic")
  66 + .setSsl(false)
  67 + .setUsername(null)
  68 + .setPassword(null);
  69 +
  70 + // 3. 执行测试并验证缓存
  71 + executeAndVerifyCache(action, config, "KafkaMQ");
75 } 72 }
76 73
77 @Test 74 @Test
78 - public void testRabbitMQDataBridge() { 75 + public void testRabbitMQDataBridge() throws Exception {
79 // 1. 创建执行器实例 76 // 1. 创建执行器实例
80 IotRabbitMQDataBridgeExecute action = new IotRabbitMQDataBridgeExecute(); 77 IotRabbitMQDataBridgeExecute action = new IotRabbitMQDataBridgeExecute();
81 78
82 // 2. 创建配置 79 // 2. 创建配置
83 - IotDataBridgeRabbitMQConfig config = new IotDataBridgeRabbitMQConfig();  
84 - config.setHost("localhost");  
85 - config.setPort(5672);  
86 - config.setVirtualHost("/");  
87 - config.setUsername("admin");  
88 - config.setPassword("123456");  
89 - config.setExchange("test-exchange");  
90 - config.setRoutingKey("test-key");  
91 - config.setQueue("test-queue");  
92 -  
93 - // 3. 执行两次测试,验证缓存  
94 - log.info("[testRabbitMQDataBridge][第一次执行,应该会创建新的 producer]");  
95 - action.execute(message, new IotDataBridgeDO().setType(action.getType()).setConfig(config));  
96 -  
97 - log.info("[testRabbitMQDataBridge][第二次执行,应该会复用缓存的 producer]");  
98 - action.execute(message, new IotDataBridgeDO().setType(action.getType()).setConfig(config)); 80 + IotDataBridgeRabbitMQConfig config = new IotDataBridgeRabbitMQConfig()
  81 + .setHost("localhost")
  82 + .setPort(5672)
  83 + .setVirtualHost("/")
  84 + .setUsername("admin")
  85 + .setPassword("123456")
  86 + .setExchange("test-exchange")
  87 + .setRoutingKey("test-key")
  88 + .setQueue("test-queue");
  89 +
  90 + // 3. 执行测试并验证缓存
  91 + executeAndVerifyCache(action, config, "RabbitMQ");
99 } 92 }
100 93
101 @Test 94 @Test
102 - public void testRedisStreamMQDataBridge() { 95 + public void testRedisStreamDataBridge() throws Exception {
103 // 1. 创建执行器实例 96 // 1. 创建执行器实例
104 - IotRedisStreamMQDataBridgeExecute action = new IotRedisStreamMQDataBridgeExecute(); 97 + IotRedisStreamDataBridgeExecute action = new IotRedisStreamDataBridgeExecute();
105 98
106 // 2. 创建配置 99 // 2. 创建配置
107 - IotDataBridgeRedisStreamMQConfig config = new IotDataBridgeRedisStreamMQConfig();  
108 - config.setHost("127.0.0.1");  
109 - config.setPort(6379);  
110 - config.setDatabase(0);  
111 - config.setPassword("123456");  
112 - config.setTopic("test-stream");  
113 -  
114 - // 3. 执行两次测试,验证缓存  
115 - log.info("[testRedisStreamMQDataBridge][第一次执行,应该会创建新的 producer]");  
116 - action.execute(message, new IotDataBridgeDO().setType(action.getType()).setConfig(config));  
117 -  
118 - log.info("[testRedisStreamMQDataBridge][第二次执行,应该会复用缓存的 producer]");  
119 - action.execute(message, new IotDataBridgeDO().setType(action.getType()).setConfig(config)); 100 + IotDataBridgeRedisStreamConfig config = new IotDataBridgeRedisStreamConfig()
  101 + .setHost("127.0.0.1")
  102 + .setPort(6379)
  103 + .setDatabase(0)
  104 + .setPassword("123456")
  105 + .setTopic("test-stream");
  106 +
  107 + // 3. 执行测试并验证缓存
  108 + executeAndVerifyCache(action, config, "RedisStream");
120 } 109 }
121 110
122 @Test 111 @Test
123 - public void testRocketMQDataBridge() { 112 + public void testRocketMQDataBridge() throws Exception {
124 // 1. 创建执行器实例 113 // 1. 创建执行器实例
125 IotRocketMQDataBridgeExecute action = new IotRocketMQDataBridgeExecute(); 114 IotRocketMQDataBridgeExecute action = new IotRocketMQDataBridgeExecute();
126 115
127 // 2. 创建配置 116 // 2. 创建配置
128 - IotDataBridgeRocketMQConfig config = new IotDataBridgeRocketMQConfig();  
129 - config.setNameServer("127.0.0.1:9876");  
130 - config.setGroup("test-group");  
131 - config.setTopic("test-topic");  
132 - config.setTags("test-tag");  
133 -  
134 - // 3. 执行两次测试,验证缓存  
135 - log.info("[testRocketMQDataBridge][第一次执行,应该会创建新的 producer]");  
136 - action.execute(message, new IotDataBridgeDO().setType(action.getType()).setConfig(config));  
137 -  
138 - log.info("[testRocketMQDataBridge][第二次执行,应该会复用缓存的 producer]");  
139 - action.execute(message, new IotDataBridgeDO().setType(action.getType()).setConfig(config)); 117 + IotDataBridgeRocketMQConfig config = new IotDataBridgeRocketMQConfig()
  118 + .setNameServer("127.0.0.1:9876")
  119 + .setGroup("test-group")
  120 + .setTopic("test-topic")
  121 + .setTags("test-tag");
  122 +
  123 + // 3. 执行测试并验证缓存
  124 + executeAndVerifyCache(action, config, "RocketMQ");
140 } 125 }
141 126
142 @Test 127 @Test
143 public void testHttpDataBridge() throws Exception { 128 public void testHttpDataBridge() throws Exception {
144 - // 创建配置  
145 - IotDataBridgeHttpConfig config = new IotDataBridgeHttpConfig();  
146 - config.setUrl("https://doc.iocoder.cn/");  
147 - config.setMethod(HttpMethod.GET.name()); 129 + // 1. 配置 RestTemplate mock 返回成功响应
  130 + when(restTemplate.exchange(anyString(), any(HttpMethod.class), any(), any(Class.class)))
  131 + .thenReturn(new ResponseEntity<>("Success", HttpStatus.OK));
148 132
149 - // 执行测试 133 + // 2. 创建配置
  134 + IotDataBridgeHttpConfig config = new IotDataBridgeHttpConfig()
  135 + .setUrl("https://doc.iocoder.cn/")
  136 + .setMethod(HttpMethod.GET.name());
  137 +
  138 + // 3. 执行测试
150 log.info("[testHttpDataBridge][执行HTTP数据桥接测试]"); 139 log.info("[testHttpDataBridge][执行HTTP数据桥接测试]");
151 - httpDataBridgeExecute.execute(message, new IotDataBridgeDO().setType(httpDataBridgeExecute.getType()).setConfig(config)); 140 + httpDataBridgeExecute.execute(message, new IotDataBridgeDO()
  141 + .setType(httpDataBridgeExecute.getType())
  142 + .setConfig(config));
  143 + }
  144 +
  145 + /**
  146 + * 执行测试并验证缓存的通用方法
  147 + *
  148 + * @param action 执行器实例
  149 + * @param config 配置对象
  150 + * @param mqType MQ类型
  151 + * @throws Exception 如果执行过程中发生异常
  152 + */
  153 + private void executeAndVerifyCache(IotDataBridgeExecute<?> action, IotDataBridgeAbstractConfig config, String mqType) throws Exception {
  154 + log.info("[test{}DataBridge][第一次执行,应该会创建新的 producer]", mqType);
  155 + action.execute(message, new IotDataBridgeDO()
  156 + .setType(action.getType())
  157 + .setConfig(config));
  158 +
  159 + log.info("[test{}DataBridge][第二次执行,应该会复用缓存的 producer]", mqType);
  160 + action.execute(message, new IotDataBridgeDO()
  161 + .setType(action.getType())
  162 + .setConfig(config));
152 } 163 }
153 164
154 } 165 }