diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/ErrorCodeConstants.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/ErrorCodeConstants.java index a19b800061..7247b0cb3c 100644 --- a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/ErrorCodeConstants.java +++ b/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 { // ========== IoT 数据桥梁 1-050-010-000 ========== ErrorCode DATA_BRIDGE_NOT_EXISTS = new ErrorCode(1_050_010_000, "IoT 数据桥梁不存在"); - // ========== IoT 规则场景(场景联动) 1-050-011-000 ========== - ErrorCode RULE_SCENE_NOT_EXISTS = new ErrorCode(1_050_011_000, "IoT 规则场景(场景联动)不存在"); + // ========== IoT 场景联动 1-050-011-000 ========== + ErrorCode RULE_SCENE_NOT_EXISTS = new ErrorCode(1_050_011_000, "IoT 场景联动不存在"); // ========== IoT 产品脚本信息 1-050-012-000 ========== ErrorCode PRODUCT_SCRIPT_NOT_EXISTS = new ErrorCode(1_050_012_000, "IoT 产品脚本信息不存在"); diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/IotRuleSceneController.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/IotRuleSceneController.java index 1ddc20a9ca..5a9cf37db7 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/IotRuleSceneController.java +++ b/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.*; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -// TODO @芋艿:规则场景 要不要,统一改成 场景联动 -@Tag(name = "管理后台 - IoT 规则场景") +@Tag(name = "管理后台 - IoT 场景联动") @RestController @RequestMapping("/iot/rule-scene") @Validated @@ -31,14 +30,14 @@ public class IotRuleSceneController { private IotRuleSceneService ruleSceneService; @PostMapping("/create") - @Operation(summary = "创建规则场景(场景联动)") + @Operation(summary = "创建场景联动") @PreAuthorize("@ss.hasPermission('iot:rule-scene:create')") public CommonResult createRuleScene(@Valid @RequestBody IotRuleSceneSaveReqVO createReqVO) { return success(ruleSceneService.createRuleScene(createReqVO)); } @PutMapping("/update") - @Operation(summary = "更新规则场景(场景联动)") + @Operation(summary = "更新场景联动") @PreAuthorize("@ss.hasPermission('iot:rule-scene:update')") public CommonResult updateRuleScene(@Valid @RequestBody IotRuleSceneSaveReqVO updateReqVO) { ruleSceneService.updateRuleScene(updateReqVO); @@ -46,7 +45,7 @@ public class IotRuleSceneController { } @DeleteMapping("/delete") - @Operation(summary = "删除规则场景(场景联动)") + @Operation(summary = "删除场景联动") @Parameter(name = "id", description = "编号", required = true) @PreAuthorize("@ss.hasPermission('iot:rule-scene:delete')") public CommonResult deleteRuleScene(@RequestParam("id") Long id) { @@ -55,7 +54,7 @@ public class IotRuleSceneController { } @GetMapping("/get") - @Operation(summary = "获得规则场景(场景联动)") + @Operation(summary = "获得场景联动") @Parameter(name = "id", description = "编号", required = true, example = "1024") @PreAuthorize("@ss.hasPermission('iot:rule-scene:query')") public CommonResult getRuleScene(@RequestParam("id") Long id) { @@ -64,7 +63,7 @@ public class IotRuleSceneController { } @GetMapping("/page") - @Operation(summary = "获得规则场景(场景联动)分页") + @Operation(summary = "获得场景联动分页") @PreAuthorize("@ss.hasPermission('iot:rule-scene:query')") public CommonResult> getRuleScenePage(@Valid IotRuleScenePageReqVO pageReqVO) { PageResult pageResult = ruleSceneService.getRuleScenePage(pageReqVO); diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/databridge/config/IotDataBridgeAbstractConfig.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/databridge/config/IotDataBridgeAbstractConfig.java index 527e79b351..7bf714f617 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/databridge/config/IotDataBridgeAbstractConfig.java +++ b/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; @JsonSubTypes({ @JsonSubTypes.Type(value = IotDataBridgeHttpConfig.class, name = "1"), @JsonSubTypes.Type(value = IotDataBridgeMqttConfig.class, name = "10"), - @JsonSubTypes.Type(value = IotDataBridgeRedisStreamMQConfig.class, name = "21"), + @JsonSubTypes.Type(value = IotDataBridgeRedisStreamConfig.class, name = "21"), @JsonSubTypes.Type(value = IotDataBridgeRocketMQConfig.class, name = "30"), @JsonSubTypes.Type(value = IotDataBridgeRabbitMQConfig.class, name = "31"), @JsonSubTypes.Type(value = IotDataBridgeKafkaMQConfig.class, name = "32"), diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/databridge/config/IotDataBridgeRedisStreamMQConfig.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/databridge/config/IotDataBridgeRedisStreamConfig.java similarity index 78% rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/databridge/config/IotDataBridgeRedisStreamMQConfig.java rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/databridge/config/IotDataBridgeRedisStreamConfig.java index 3c9bb330fe..fc7a4c3f2e 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/databridge/config/IotDataBridgeRedisStreamMQConfig.java +++ b/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; import lombok.Data; -// TODO @puhui999:MQ 可以去掉哈。stream 更精准 /** * IoT Redis Stream 配置 {@link IotDataBridgeAbstractConfig} 实现类 * * @author HUIHUI */ @Data -public class IotDataBridgeRedisStreamMQConfig extends IotDataBridgeAbstractConfig { +public class IotDataBridgeRedisStreamConfig extends IotDataBridgeAbstractConfig { /** * Redis 服务器地址 diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/package-info.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/package-info.java deleted file mode 100644 index f397e0acdb..0000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/package-info.java +++ /dev/null @@ -1,2 +0,0 @@ -// TODO @芋艿:占位 -package cn.iocoder.yudao.module.iot.controller.admin.rule.vo; \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/scene/IotRuleScenePageReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/scene/IotRuleScenePageReqVO.java index 794434cc8f..66e75b42a8 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/scene/IotRuleScenePageReqVO.java +++ b/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; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -@Schema(description = "管理后台 - IoT 规则场景(场景联动)分页 Request VO") +@Schema(description = "管理后台 - IoT 场景联动分页 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/scene/IotRuleSceneRespVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/scene/IotRuleSceneRespVO.java index 17aad11859..b3adfa7e57 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/scene/IotRuleSceneRespVO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/scene/IotRuleSceneRespVO.java @@ -1,14 +1,13 @@ package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene; -import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config.IotRuleSceneActionConfig; -import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config.IotRuleSceneTriggerConfig; +import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.time.LocalDateTime; import java.util.List; -@Schema(description = "管理后台 - IoT 规则场景(场景联动) Response VO") +@Schema(description = "管理后台 - IoT 场景联动 Response VO") @Data public class IotRuleSceneRespVO { @@ -25,10 +24,10 @@ public class IotRuleSceneRespVO { private Integer status; @Schema(description = "触发器数组", requiredMode = Schema.RequiredMode.REQUIRED) - private List triggers; + private List triggers; @Schema(description = "执行器数组", requiredMode = Schema.RequiredMode.REQUIRED) - private List actions; + private List actions; @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) private LocalDateTime createTime; diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/scene/IotRuleSceneSaveReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/scene/IotRuleSceneSaveReqVO.java index 4bfc19d9a2..813d005e4f 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/scene/IotRuleSceneSaveReqVO.java +++ b/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; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.validation.InEnum; -import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config.IotRuleSceneActionConfig; -import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config.IotRuleSceneTriggerConfig; +import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; @@ -11,7 +10,7 @@ import lombok.Data; import java.util.List; -@Schema(description = "管理后台 - IoT 规则场景(场景联动)新增/修改 Request VO") +@Schema(description = "管理后台 - IoT 场景联动新增/修改 Request VO") @Data public class IotRuleSceneSaveReqVO { @@ -32,10 +31,10 @@ public class IotRuleSceneSaveReqVO { @Schema(description = "触发器数组", requiredMode = Schema.RequiredMode.REQUIRED) @NotEmpty(message = "触发器数组不能为空") - private List triggers; + private List triggers; @Schema(description = "执行器数组", requiredMode = Schema.RequiredMode.REQUIRED) @NotEmpty(message = "执行器数组不能为空") - private List actions; + private List actions; } \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/scene/config/IotRuleSceneActionConfig.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/scene/config/IotRuleSceneActionConfig.java deleted file mode 100644 index c2332395e5..0000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/scene/config/IotRuleSceneActionConfig.java +++ /dev/null @@ -1,38 +0,0 @@ -package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config; - -import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataBridgeDO; -import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum; -import lombok.Data; - -// TODO @puhui999:这个要不内嵌到 IoTRuleSceneDO 里面? -/** - * 执行器配置 - * - * @author 芋道源码 - */ -@Data -public class IotRuleSceneActionConfig { - - /** - * 执行类型 - * - * 枚举 {@link IotRuleSceneActionTypeEnum} - */ - private Integer type; - - /** - * 设备控制 - * - * 必填:当 {@link #type} 为 {@link IotRuleSceneActionTypeEnum#DEVICE_CONTROL} 时 - */ - private IotRuleSceneActionDeviceControl deviceControl; - - /** - * 数据桥接编号 - * - * 必填:当 {@link #type} 为 {@link IotRuleSceneActionTypeEnum#DATA_BRIDGE} 时 - * 关联:{@link IotDataBridgeDO#getId()} - */ - private Long dataBridgeId; - -} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/scene/config/IotRuleSceneActionDeviceControl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/scene/config/IotRuleSceneActionDeviceControl.java deleted file mode 100644 index f184afe2ad..0000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/scene/config/IotRuleSceneActionDeviceControl.java +++ /dev/null @@ -1,58 +0,0 @@ -package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config; - -import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; -import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; -import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageIdentifierEnum; -import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageTypeEnum; -import lombok.Data; - -import java.util.List; -import java.util.Map; - -// TODO @puhui999:这个要不内嵌到 IoTRuleSceneDO 里面? -/** - * 执行设备控制 - * - * @author 芋道源码 - */ -@Data -public class IotRuleSceneActionDeviceControl { - - /** - * 产品标识 - * - * 关联 {@link IotProductDO#getProductKey()} - */ - private String productKey; - /** - * 设备名称数组 - * - * 关联 {@link IotDeviceDO#getDeviceName()} - */ - private List deviceNames; - - /** - * 消息类型 - * - * 枚举 {@link IotDeviceMessageTypeEnum#PROPERTY}、{@link IotDeviceMessageTypeEnum#SERVICE} - */ - private String type; - /** - * 消息标识符 - * - * 枚举 {@link IotDeviceMessageIdentifierEnum} - * - * 1. 属性设置:对应 {@link IotDeviceMessageIdentifierEnum#PROPERTY_SET} - * 2. 服务调用:对应 {@link IotDeviceMessageIdentifierEnum#SERVICE_INVOKE} - */ - private String identifier; - - /** - * 具体数据 - * - * 1. 属性设置:在 {@link #type} 是 {@link IotDeviceMessageTypeEnum#PROPERTY} 时,对应 properties - * 2. 服务调用:在 {@link #type} 是 {@link IotDeviceMessageTypeEnum#SERVICE} 时,对应 params - */ - private Map data; - -} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/scene/config/IotRuleSceneTriggerCondition.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/scene/config/IotRuleSceneTriggerCondition.java deleted file mode 100644 index 46c0769e84..0000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/scene/config/IotRuleSceneTriggerCondition.java +++ /dev/null @@ -1,38 +0,0 @@ -package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config; - -import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageIdentifierEnum; -import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageTypeEnum; -import lombok.Data; - -import java.util.List; - -// TODO @puhui999:这个要不内嵌到 IoTRuleSceneDO 里面? -/** - * 触发条件 - * - * @author 芋道源码 - */ -@Data -public class IotRuleSceneTriggerCondition { - - /** - * 消息类型 - * - * 枚举 {@link IotDeviceMessageTypeEnum} - */ - private String type; - /** - * 消息标识符 - * - * 枚举 {@link IotDeviceMessageIdentifierEnum} - */ - private String identifier; - - /** - * 参数数组 - * - * 参数与参数之间,是“或”的关系 - */ - private List parameters; - -} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/scene/config/IotRuleSceneTriggerConditionParameter.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/scene/config/IotRuleSceneTriggerConditionParameter.java deleted file mode 100644 index b57be1f4cc..0000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/scene/config/IotRuleSceneTriggerConditionParameter.java +++ /dev/null @@ -1,38 +0,0 @@ -package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config; - -import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO; -import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneTriggerConditionParameterOperatorEnum; -import lombok.Data; - -// TODO @puhui999:这个要不内嵌到 IoTRuleSceneDO 里面? -/** - * 触发条件参数 - * - * @author 芋道源码 - */ -@Data -public class IotRuleSceneTriggerConditionParameter { - - /** - * 标识符(属性、事件、服务) - * - * 关联 {@link IotThingModelDO#getIdentifier()} - */ - private String identifier; - - /** - * 操作符 - * - * 枚举 {@link IotRuleSceneTriggerConditionParameterOperatorEnum} - */ - private String operator; - - /** - * 比较值 - * - * 如果有多个值,则使用 "," 分隔,类似 "1,2,3"。 - * 例如说,{@link IotRuleSceneTriggerConditionParameterOperatorEnum#IN}、{@link IotRuleSceneTriggerConditionParameterOperatorEnum#BETWEEN} - */ - private String value; - -} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/scene/config/IotRuleSceneTriggerConfig.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/scene/config/IotRuleSceneTriggerConfig.java deleted file mode 100644 index 4077729d45..0000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/scene/config/IotRuleSceneTriggerConfig.java +++ /dev/null @@ -1,54 +0,0 @@ -package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config; - -import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; -import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; -import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneTriggerTypeEnum; -import lombok.Data; - -import java.util.List; - -// TODO @puhui999:这个要不内嵌到 IoTRuleSceneDO 里面? -/** - * 触发器配置 - * - * @author 芋道源码 - */ -@Data -public class IotRuleSceneTriggerConfig { - - /** - * 触发类型 - * - * 枚举 {@link IotRuleSceneTriggerTypeEnum} - */ - private Integer type; - - /** - * 产品标识 - * - * 关联 {@link IotProductDO#getProductKey()} - */ - private String productKey; - /** - * 设备名称数组 - * - * 关联 {@link IotDeviceDO#getDeviceName()} - */ - private List deviceNames; - - /** - * 触发条件数组 - * - * 必填:当 {@link #type} 为 {@link IotRuleSceneTriggerTypeEnum#DEVICE} 时 - * 条件与条件之间,是“或”的关系 - */ - private List conditions; - - /** - * CRON 表达式 - * - * 必填:当 {@link #type} 为 {@link IotRuleSceneTriggerTypeEnum#TIMER} 时 - */ - private String cronExpression; - -} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/IotThingModelController.http b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/IotThingModelController.http index e041cdc8af..4f579c4536 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/IotThingModelController.http +++ b/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 tenant-id: {{adminTenentId}} Authorization: Bearer {{token}} -### 请求 /iot/product-thing-model/tsl-by-product-id 接口 => 成功 -GET {{baseUrl}}/iot/product-thing-model/tsl-by-product-id?productId=1001 +### 请求 /iot/product-thing-model/get-tsl 接口 => 成功 +GET {{baseUrl}}/iot/product-thing-model/get-tsl?productId=1001 tenant-id: {{adminTenentId}} Authorization: Bearer {{token}} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/IotThingModelController.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/IotThingModelController.java index f35f95a85e..862c07dfdc 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/IotThingModelController.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/IotThingModelController.java @@ -1,10 +1,13 @@ package cn.iocoder.yudao.module.iot.controller.admin.thingmodel; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.*; import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO; +import cn.iocoder.yudao.module.iot.enums.thingmodel.IotThingModelTypeEnum; import cn.iocoder.yudao.module.iot.service.thingmodel.IotThingModelService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -18,6 +21,8 @@ import org.springframework.web.bind.annotation.*; import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList; @Tag(name = "管理后台 - IoT 产品物模型") @RestController @@ -61,13 +66,31 @@ public class IotThingModelController { return success(BeanUtils.toBean(thingModel, IotThingModelRespVO.class)); } - // TODO @puhui999:要不叫 get-tsl,去掉 product-id;后续,把 - @GetMapping("/tsl-by-product-id") + @GetMapping("/get-tsl") @Operation(summary = "获得产品物模型 TSL") @Parameter(name = "productId", description = "产品 ID", required = true, example = "1024") @PreAuthorize("@ss.hasPermission('iot:thing-model:query')") - public CommonResult getThingModelTslByProductId(@RequestParam("productId") Long productId) { - return success(thingModelService.getThingModelTslByProductId(productId)); + public CommonResult getThingModelTsl(@RequestParam("productId") Long productId) { + IotThingModelTSLRespVO tslRespVO = new IotThingModelTSLRespVO(); + // 1. 获得产品所有物模型定义 + List thingModels = thingModelService.getThingModelListByProductId(productId); + if (CollUtil.isEmpty(thingModels)) { + return success(tslRespVO); + } + + // 2.1 设置公共部分参数 + IotThingModelDO thingModel = thingModels.get(0); + tslRespVO.setProductId(thingModel.getProductId()).setProductKey(thingModel.getProductKey()); + // 2.2 处理属性列表 + tslRespVO.setProperties(convertList(filterList(thingModels, item -> + ObjUtil.equal(IotThingModelTypeEnum.PROPERTY.getType(), item.getType())), IotThingModelDO::getProperty)); + // 2.3 处理服务列表 + tslRespVO.setServices(convertList(filterList(thingModels, item -> + ObjUtil.equal(IotThingModelTypeEnum.SERVICE.getType(), item.getType())), IotThingModelDO::getService)); + // 2.4 处理事件列表 + tslRespVO.setEvents(convertList(filterList(thingModels, item -> + ObjUtil.equal(IotThingModelTypeEnum.EVENT.getType(), item.getType())), IotThingModelDO::getEvent)); + return success(tslRespVO); } @GetMapping("/list") diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/model/dataType/ThingModelArrayDataSpecs.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/model/dataType/ThingModelArrayDataSpecs.java index 50011aabf4..554bd2a83d 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/model/dataType/ThingModelArrayDataSpecs.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/model/dataType/ThingModelArrayDataSpecs.java @@ -1,6 +1,10 @@ package cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.dataType; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Pattern; import lombok.Data; import lombok.EqualsAndHashCode; @@ -16,18 +20,17 @@ import java.util.List; @JsonIgnoreProperties({"dataType"}) // 忽略子类中的 dataType 字段,从而避免重复 public class ThingModelArrayDataSpecs extends ThingModelDataSpecs { - /** - * 数组中的元素个数 - */ + @NotNull(message = "数组元素个数不能为空") private Integer size; - /** - * 数组中的元素的数据类型。可选值:struct、int、float、double 或 text - */ + + @NotEmpty(message = "数组元素的数据类型不能为空") + @Pattern(regexp = "^(struct|int|float|double|text)$", message = "数组元素的数据类型必须为:struct、int、float、double 或 text") private String childDataType; /** * 数据类型(childDataType)为列表型 struct 的数据规范存储在 dataSpecsList 中 * 此时 struct 取值范围为:int、float、double、text、date、enum、bool */ + @Valid private List dataSpecsList; } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/model/dataType/ThingModelBoolOrEnumDataSpecs.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/model/dataType/ThingModelBoolOrEnumDataSpecs.java index 925bc67196..80a4e0d970 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/model/dataType/ThingModelBoolOrEnumDataSpecs.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/model/dataType/ThingModelBoolOrEnumDataSpecs.java @@ -1,6 +1,9 @@ package cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.dataType; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Pattern; import lombok.Data; import lombok.EqualsAndHashCode; @@ -16,16 +19,12 @@ import lombok.EqualsAndHashCode; @JsonIgnoreProperties({"dataType"}) // 忽略子类中的 dataType 字段,从而避免重复 public class ThingModelBoolOrEnumDataSpecs extends ThingModelDataSpecs { - // TODO @puhui999:要不写下参数校验?这样,注释可以简洁一点 - /** - * 枚举项的名称。 - * 可包含中文、大小写英文字母、数字、下划线(_)和短划线(-) - * 必须以中文、英文字母或数字开头,长度不超过 20 个字符 - */ + @NotEmpty(message = "枚举项的名称不能为空") + @Pattern(regexp = "^[\\u4e00-\\u9fa5a-zA-Z0-9][\\u4e00-\\u9fa5a-zA-Z0-9_-]{0,19}$", + message = "枚举项的名称只能包含中文、大小写英文字母、数字、下划线和短划线,必须以中文、英文字母或数字开头,长度不超过 20 个字符") private String name; - /** - * 枚举值。 - */ + + @NotNull(message = "枚举值不能为空") private Integer value; } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/model/dataType/ThingModelDateOrTextDataSpecs.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/model/dataType/ThingModelDateOrTextDataSpecs.java index 62500bc560..489833d4ba 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/model/dataType/ThingModelDateOrTextDataSpecs.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/model/dataType/ThingModelDateOrTextDataSpecs.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.dataType; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import jakarta.validation.constraints.Max; import lombok.Data; import lombok.EqualsAndHashCode; @@ -20,6 +21,7 @@ public class ThingModelDateOrTextDataSpecs extends ThingModelDataSpecs { * 数据长度,单位为字节。取值不能超过 2048。 * 当 dataType 为 text 时,需传入该参数。 */ + @Max(value = 2048, message = "数据长度不能超过 2048") private Integer length; /** * 默认值,可选参数,用于存储默认值。 diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/model/dataType/ThingModelNumericDataSpec.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/model/dataType/ThingModelNumericDataSpec.java index 8d0827c011..bd3457d7d5 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/model/dataType/ThingModelNumericDataSpec.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/model/dataType/ThingModelNumericDataSpec.java @@ -1,6 +1,8 @@ package cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.dataType; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.Pattern; import lombok.Data; import lombok.EqualsAndHashCode; @@ -18,18 +20,21 @@ public class ThingModelNumericDataSpec extends ThingModelDataSpecs { /** * 最大值,需转为字符串类型。值必须与 dataType 类型一致。 - * 例如,当 dataType 为 int 时,取值为 "200",而不是 200。 */ + @NotEmpty(message = "最大值不能为空") + @Pattern(regexp = "^-?\\d+(\\.\\d+)?$", message = "最大值必须为数值类型") private String max; /** * 最小值,需转为字符串类型。值必须与 dataType 类型一致。 - * 例如,当 dataType 为 int 时,取值为 "0",而不是 0。 */ + @NotEmpty(message = "最小值不能为空") + @Pattern(regexp = "^-?\\d+(\\.\\d+)?$", message = "最小值必须为数值类型") private String min; /** * 步长,需转为字符串类型。值必须与 dataType 类型一致。 - * 例如,当 dataType 为 int 时,取值为 "10",而不是 10。 */ + @NotEmpty(message = "步长不能为空") + @Pattern(regexp = "^-?\\d+(\\.\\d+)?$", message = "步长必须为数值类型") private String step; /** * 精度。当 dataType 为 float 或 double 时可选传入。 diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/model/dataType/ThingModelStructDataSpecs.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/model/dataType/ThingModelStructDataSpecs.java index 6d483eeaa9..6ab7902e9f 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/model/dataType/ThingModelStructDataSpecs.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/model/dataType/ThingModelStructDataSpecs.java @@ -1,7 +1,11 @@ package cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.dataType; +import cn.iocoder.yudao.framework.common.validation.InEnum; import cn.iocoder.yudao.module.iot.enums.thingmodel.IotThingModelAccessModeEnum; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.Pattern; import lombok.Data; import lombok.EqualsAndHashCode; @@ -17,35 +21,36 @@ import java.util.List; @JsonIgnoreProperties({"dataType"}) // 忽略子类中的 dataType 字段,从而避免重复 public class ThingModelStructDataSpecs extends ThingModelDataSpecs { - /** - * 属性标识符 - */ + @NotEmpty(message = "属性标识符不能为空") + @Pattern(regexp = "^[a-zA-Z][a-zA-Z0-9_]{0,31}$", message = "属性标识符只能由字母、数字和下划线组成,必须以字母开头,长度不超过 32 个字符") private String identifier; - /** - * 属性名称 - */ + + @NotEmpty(message = "属性名称不能为空") private String name; - /** - * 云端可以对该属性进行的操作类型 - * - * 枚举 {@link IotThingModelAccessModeEnum} - */ + + @NotEmpty(message = "操作类型不能为空") + @InEnum(IotThingModelAccessModeEnum.class) private String accessMode; + /** * 是否是标准品类的必选服务 */ private Boolean required; - /** - * struct 数据的数据类型 - */ + + @NotEmpty(message = "数据类型不能为空") + @Pattern(regexp = "^(int|float|double|text|date|enum|bool)$", message = "数据类型必须为:int、float、double、text、date、enum、bool") private String childDataType; + /** * 数据类型(dataType)为非列表型(int、float、double、text、date、array)的数据规范存储在 dataSpecs 中 */ + @Valid private ThingModelDataSpecs dataSpecs; + /** * 数据类型(dataType)为列表型(enum、bool、struct)的数据规范存储在 dataSpecsList 中 */ + @Valid private List dataSpecsList; } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/rule/IotRuleSceneDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/rule/IotRuleSceneDO.java index 49741cc79b..af4d39b67f 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/rule/IotRuleSceneDO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/rule/IotRuleSceneDO.java @@ -1,8 +1,14 @@ package cn.iocoder.yudao.module.iot.dal.dataobject.rule; import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO; -import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config.IotRuleSceneActionConfig; -import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config.IotRuleSceneTriggerConfig; +import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; +import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; +import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO; +import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageIdentifierEnum; +import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageTypeEnum; +import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum; +import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneTriggerConditionParameterOperatorEnum; +import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneTriggerTypeEnum; import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; @@ -14,13 +20,14 @@ import lombok.Data; import lombok.NoArgsConstructor; import java.util.List; +import java.util.Map; /** - * IoT 规则场景(场景联动) DO + * IoT 场景联动 DO * * @author 芋道源码 */ -@TableName("iot_rule_scene") +@TableName(value = "iot_rule_scene", autoResultMap = true) @KeySequence("iot_rule_scene_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 @Data @Builder @@ -52,12 +59,188 @@ public class IotRuleSceneDO extends TenantBaseDO { * 触发器数组 */ @TableField(typeHandler = JacksonTypeHandler.class) - private List triggers; + private List triggers; /** * 执行器数组 */ @TableField(typeHandler = JacksonTypeHandler.class) - private List actions; + private List actions; + + /** + * 触发器配置 + */ + @Data + public static class TriggerConfig { + + /** + * 触发类型 + * + * 枚举 {@link IotRuleSceneTriggerTypeEnum} + */ + private Integer type; + + /** + * 产品标识 + * + * 关联 {@link IotProductDO#getProductKey()} + */ + private String productKey; + /** + * 设备名称数组 + * + * 关联 {@link IotDeviceDO#getDeviceName()} + */ + private List deviceNames; + + /** + * 触发条件数组 + * + * 必填:当 {@link #type} 为 {@link IotRuleSceneTriggerTypeEnum#DEVICE} 时 + * 条件与条件之间,是“或”的关系 + */ + private List conditions; + + /** + * CRON 表达式 + * + * 必填:当 {@link #type} 为 {@link IotRuleSceneTriggerTypeEnum#TIMER} 时 + */ + private String cronExpression; + + } + + /** + * 触发条件 + */ + @Data + public static class TriggerCondition { + + /** + * 消息类型 + * + * 枚举 {@link IotDeviceMessageTypeEnum} + */ + private String type; + /** + * 消息标识符 + * + * 枚举 {@link IotDeviceMessageIdentifierEnum} + */ + private String identifier; + + /** + * 参数数组 + * + * 参数与参数之间,是“或”的关系 + */ + private List parameters; + + } + + /** + * 触发条件参数 + */ + @Data + public static class TriggerConditionParameter { + + /** + * 标识符(属性、事件、服务) + * + * 关联 {@link IotThingModelDO#getIdentifier()} + */ + private String identifier; + + /** + * 操作符 + * + * 枚举 {@link IotRuleSceneTriggerConditionParameterOperatorEnum} + */ + private String operator; + + /** + * 比较值 + * + * 如果有多个值,则使用 "," 分隔,类似 "1,2,3"。 + * 例如说,{@link IotRuleSceneTriggerConditionParameterOperatorEnum#IN}、{@link IotRuleSceneTriggerConditionParameterOperatorEnum#BETWEEN} + */ + private String value; + + } + + /** + * 执行器配置 + */ + @Data + public static class ActionConfig { + + /** + * 执行类型 + * + * 枚举 {@link IotRuleSceneActionTypeEnum} + */ + private Integer type; + + /** + * 设备控制 + * + * 必填:当 {@link #type} 为 {@link IotRuleSceneActionTypeEnum#DEVICE_CONTROL} 时 + */ + private ActionDeviceControl deviceControl; + + /** + * 数据桥接编号 + * + * 必填:当 {@link #type} 为 {@link IotRuleSceneActionTypeEnum#DATA_BRIDGE} 时 + * 关联:{@link IotDataBridgeDO#getId()} + */ + private Long dataBridgeId; + + } + + /** + * 执行设备控制 + */ + @Data + public static class ActionDeviceControl { + + /** + * 产品标识 + * + * 关联 {@link IotProductDO#getProductKey()} + */ + private String productKey; + /** + * 设备名称数组 + * + * 关联 {@link IotDeviceDO#getDeviceName()} + */ + private List deviceNames; + + /** + * 消息类型 + * + * 枚举 {@link IotDeviceMessageTypeEnum#PROPERTY}、{@link IotDeviceMessageTypeEnum#SERVICE} + */ + private String type; + /** + * 消息标识符 + * + * 枚举 {@link IotDeviceMessageIdentifierEnum} + * + * 1. 属性设置:对应 {@link IotDeviceMessageIdentifierEnum#PROPERTY_SET} + * 2. 服务调用:对应 {@link IotDeviceMessageIdentifierEnum#SERVICE_INVOKE} + */ + private String identifier; + + /** + * 具体数据 + * + * 1. 属性设置:在 {@link #type} 是 {@link IotDeviceMessageTypeEnum#PROPERTY} 时,对应 properties + * 2. 服务调用:在 {@link #type} 是 {@link IotDeviceMessageTypeEnum#SERVICE} 时,对应 params + */ + private Map data; + + } } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/rule/IotRuleSceneMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/rule/IotRuleSceneMapper.java index 4f933727e7..c5bf13b2f3 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/rule/IotRuleSceneMapper.java +++ b/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; import org.apache.ibatis.annotations.Mapper; /** - * IoT 规则场景(场景联动) Mapper + * IoT 场景联动 Mapper * * @author HUIHUI */ diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/IotRuleSceneService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/IotRuleSceneService.java index e2be7f40f7..fcd3b4cda9 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/IotRuleSceneService.java +++ b/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; public interface IotRuleSceneService { /** - * 创建规则场景(场景联动) + * 创建场景联动 * * @param createReqVO 创建信息 * @return 编号 @@ -26,32 +26,32 @@ public interface IotRuleSceneService { Long createRuleScene(@Valid IotRuleSceneSaveReqVO createReqVO); /** - * 更新规则场景(场景联动) + * 更新场景联动 * * @param updateReqVO 更新信息 */ void updateRuleScene(@Valid IotRuleSceneSaveReqVO updateReqVO); /** - * 删除规则场景(场景联动) + * 删除场景联动 * * @param id 编号 */ void deleteRuleScene(Long id); /** - * 获得规则场景(场景联动) + * 获得场景联动 * * @param id 编号 - * @return 规则场景(场景联动) + * @return 场景联动 */ IotRuleSceneDO getRuleScene(Long id); /** - * 获得规则场景(场景联动)分页 + * 获得场景联动分页 * * @param pageReqVO 分页查询 - * @return 规则场景(场景联动)分页 + * @return 场景联动分页 */ PageResult getRuleScenePage(IotRuleScenePageReqVO pageReqVO); diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/IotRuleSceneServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/IotRuleSceneServiceImpl.java index d5ca74f555..cefc68dd01 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/IotRuleSceneServiceImpl.java +++ b/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; import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotRuleScenePageReqVO; import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotRuleSceneSaveReqVO; -import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config.*; import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO; import cn.iocoder.yudao.module.iot.dal.mysql.rule.IotRuleSceneMapper; import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageIdentifierEnum; @@ -118,82 +117,82 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService { if (true) { IotRuleSceneDO ruleScene01 = new IotRuleSceneDO(); ruleScene01.setTriggers(CollUtil.newArrayList()); - IotRuleSceneTriggerConfig trigger01 = new IotRuleSceneTriggerConfig(); + IotRuleSceneDO.TriggerConfig trigger01 = new IotRuleSceneDO.TriggerConfig(); trigger01.setType(IotRuleSceneTriggerTypeEnum.DEVICE.getType()); trigger01.setConditions(CollUtil.newArrayList()); // 属性 - IotRuleSceneTriggerCondition condition01 = new IotRuleSceneTriggerCondition(); + IotRuleSceneDO.TriggerCondition condition01 = new IotRuleSceneDO.TriggerCondition(); condition01.setType(IotDeviceMessageTypeEnum.PROPERTY.getType()); condition01.setIdentifier(IotDeviceMessageIdentifierEnum.PROPERTY_REPORT.getIdentifier()); condition01.setParameters(CollUtil.newArrayList()); -// IotRuleSceneTriggerConditionParameter parameter010 = new IotRuleSceneTriggerConditionParameter(); +// IotRuleSceneDO.TriggerConditionParameter parameter010 = new IotRuleSceneDO.TriggerConditionParameter(); // parameter010.setIdentifier("width"); // parameter010.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.EQUALS.getOperator()); // parameter010.setValue("abc"); // condition01.getParameters().add(parameter010); - IotRuleSceneTriggerConditionParameter parameter011 = new IotRuleSceneTriggerConditionParameter(); + IotRuleSceneDO.TriggerConditionParameter parameter011 = new IotRuleSceneDO.TriggerConditionParameter(); parameter011.setIdentifier("width"); parameter011.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.EQUALS.getOperator()); parameter011.setValue("1"); condition01.getParameters().add(parameter011); - IotRuleSceneTriggerConditionParameter parameter012 = new IotRuleSceneTriggerConditionParameter(); + IotRuleSceneDO.TriggerConditionParameter parameter012 = new IotRuleSceneDO.TriggerConditionParameter(); parameter012.setIdentifier("width"); parameter012.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.NOT_EQUALS.getOperator()); parameter012.setValue("2"); condition01.getParameters().add(parameter012); - IotRuleSceneTriggerConditionParameter parameter013 = new IotRuleSceneTriggerConditionParameter(); + IotRuleSceneDO.TriggerConditionParameter parameter013 = new IotRuleSceneDO.TriggerConditionParameter(); parameter013.setIdentifier("width"); parameter013.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.GREATER_THAN.getOperator()); parameter013.setValue("0"); condition01.getParameters().add(parameter013); - IotRuleSceneTriggerConditionParameter parameter014 = new IotRuleSceneTriggerConditionParameter(); + IotRuleSceneDO.TriggerConditionParameter parameter014 = new IotRuleSceneDO.TriggerConditionParameter(); parameter014.setIdentifier("width"); parameter014.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.GREATER_THAN_OR_EQUALS.getOperator()); parameter014.setValue("0"); condition01.getParameters().add(parameter014); - IotRuleSceneTriggerConditionParameter parameter015 = new IotRuleSceneTriggerConditionParameter(); + IotRuleSceneDO.TriggerConditionParameter parameter015 = new IotRuleSceneDO.TriggerConditionParameter(); parameter015.setIdentifier("width"); parameter015.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.LESS_THAN.getOperator()); parameter015.setValue("2"); condition01.getParameters().add(parameter015); - IotRuleSceneTriggerConditionParameter parameter016 = new IotRuleSceneTriggerConditionParameter(); + IotRuleSceneDO.TriggerConditionParameter parameter016 = new IotRuleSceneDO.TriggerConditionParameter(); parameter016.setIdentifier("width"); parameter016.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.LESS_THAN_OR_EQUALS.getOperator()); parameter016.setValue("2"); condition01.getParameters().add(parameter016); - IotRuleSceneTriggerConditionParameter parameter017 = new IotRuleSceneTriggerConditionParameter(); + IotRuleSceneDO.TriggerConditionParameter parameter017 = new IotRuleSceneDO.TriggerConditionParameter(); parameter017.setIdentifier("width"); parameter017.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.IN.getOperator()); parameter017.setValue("1,2,3"); condition01.getParameters().add(parameter017); - IotRuleSceneTriggerConditionParameter parameter018 = new IotRuleSceneTriggerConditionParameter(); + IotRuleSceneDO.TriggerConditionParameter parameter018 = new IotRuleSceneDO.TriggerConditionParameter(); parameter018.setIdentifier("width"); parameter018.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.NOT_IN.getOperator()); parameter018.setValue("0,2,3"); condition01.getParameters().add(parameter018); - IotRuleSceneTriggerConditionParameter parameter019 = new IotRuleSceneTriggerConditionParameter(); + IotRuleSceneDO.TriggerConditionParameter parameter019 = new IotRuleSceneDO.TriggerConditionParameter(); parameter019.setIdentifier("width"); parameter019.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.BETWEEN.getOperator()); parameter019.setValue("1,3"); condition01.getParameters().add(parameter019); - IotRuleSceneTriggerConditionParameter parameter020 = new IotRuleSceneTriggerConditionParameter(); + IotRuleSceneDO.TriggerConditionParameter parameter020 = new IotRuleSceneDO.TriggerConditionParameter(); parameter020.setIdentifier("width"); parameter020.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.NOT_BETWEEN.getOperator()); parameter020.setValue("2,3"); condition01.getParameters().add(parameter020); trigger01.getConditions().add(condition01); // 状态 - IotRuleSceneTriggerCondition condition02 = new IotRuleSceneTriggerCondition(); + IotRuleSceneDO.TriggerCondition condition02 = new IotRuleSceneDO.TriggerCondition(); condition02.setType(IotDeviceMessageTypeEnum.STATE.getType()); condition02.setIdentifier(IotDeviceMessageIdentifierEnum.STATE_ONLINE.getIdentifier()); condition02.setParameters(CollUtil.newArrayList()); trigger01.getConditions().add(condition02); // 事件 - IotRuleSceneTriggerCondition condition03 = new IotRuleSceneTriggerCondition(); + IotRuleSceneDO.TriggerCondition condition03 = new IotRuleSceneDO.TriggerCondition(); condition03.setType(IotDeviceMessageTypeEnum.EVENT.getType()); condition03.setIdentifier("xxx"); condition03.setParameters(CollUtil.newArrayList()); - IotRuleSceneTriggerConditionParameter parameter030 = new IotRuleSceneTriggerConditionParameter(); + IotRuleSceneDO.TriggerConditionParameter parameter030 = new IotRuleSceneDO.TriggerConditionParameter(); parameter030.setIdentifier("width"); parameter030.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.EQUALS.getOperator()); parameter030.setValue("1"); @@ -202,21 +201,21 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService { // 动作 ruleScene01.setActions(CollUtil.newArrayList()); // 设备控制 - IotRuleSceneActionConfig action01 = new IotRuleSceneActionConfig(); + IotRuleSceneDO.ActionConfig action01 = new IotRuleSceneDO.ActionConfig(); action01.setType(IotRuleSceneActionTypeEnum.DEVICE_CONTROL.getType()); - IotRuleSceneActionDeviceControl iotRuleSceneActionDeviceControl01 = new IotRuleSceneActionDeviceControl(); - iotRuleSceneActionDeviceControl01.setProductKey("4aymZgOTOOCrDKRT"); - iotRuleSceneActionDeviceControl01.setDeviceNames(ListUtil.of("small")); - iotRuleSceneActionDeviceControl01.setType(IotDeviceMessageTypeEnum.PROPERTY.getType()); - iotRuleSceneActionDeviceControl01.setIdentifier(IotDeviceMessageIdentifierEnum.PROPERTY_SET.getIdentifier()); - iotRuleSceneActionDeviceControl01.setData(MapUtil.builder() + IotRuleSceneDO.ActionDeviceControl actionDeviceControl01 = new IotRuleSceneDO.ActionDeviceControl(); + actionDeviceControl01.setProductKey("4aymZgOTOOCrDKRT"); + actionDeviceControl01.setDeviceNames(ListUtil.of("small")); + actionDeviceControl01.setType(IotDeviceMessageTypeEnum.PROPERTY.getType()); + actionDeviceControl01.setIdentifier(IotDeviceMessageIdentifierEnum.PROPERTY_SET.getIdentifier()); + actionDeviceControl01.setData(MapUtil.builder() .put("power", 1) .put("color", "red") .build()); - action01.setDeviceControl(iotRuleSceneActionDeviceControl01); + action01.setDeviceControl(actionDeviceControl01); // ruleScene01.getActions().add(action01); // TODO 芋艿:先不测试了 // 数据桥接(http) - IotRuleSceneActionConfig action02 = new IotRuleSceneActionConfig(); + IotRuleSceneDO.ActionConfig action02 = new IotRuleSceneDO.ActionConfig(); action02.setType(IotRuleSceneActionTypeEnum.DATA_BRIDGE.getType()); action02.setDataBridgeId(1L); ruleScene01.getActions().add(action02); @@ -226,7 +225,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService { List list = ruleSceneMapper.selectList(); // TODO @芋艿:需要考虑开启状态 return filterList(list, ruleScene -> { - for (IotRuleSceneTriggerConfig trigger : ruleScene.getTriggers()) { + for (IotRuleSceneDO.TriggerConfig trigger : ruleScene.getTriggers()) { if (ObjUtil.notEqual(trigger.getProductKey(), productKey)) { continue; } @@ -261,13 +260,13 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService { IotRuleSceneDO scene = new IotRuleSceneDO().setStatus(CommonStatusEnum.ENABLE.getStatus()); if (true) { scene.setTenantId(1L); - IotRuleSceneTriggerConfig iotRuleSceneTriggerConfig = new IotRuleSceneTriggerConfig(); - iotRuleSceneTriggerConfig.setType(IotRuleSceneTriggerTypeEnum.TIMER.getType()); - scene.setTriggers(ListUtil.toList(iotRuleSceneTriggerConfig)); + IotRuleSceneDO.TriggerConfig triggerConfig = new IotRuleSceneDO.TriggerConfig(); + triggerConfig.setType(IotRuleSceneTriggerTypeEnum.TIMER.getType()); + scene.setTriggers(ListUtil.toList(triggerConfig)); // 动作 - IotRuleSceneActionConfig action01 = new IotRuleSceneActionConfig(); + IotRuleSceneDO.ActionConfig action01 = new IotRuleSceneDO.ActionConfig(); action01.setType(IotRuleSceneActionTypeEnum.DEVICE_CONTROL.getType()); - IotRuleSceneActionDeviceControl iotRuleSceneActionDeviceControl01 = new IotRuleSceneActionDeviceControl(); + IotRuleSceneDO.ActionDeviceControl iotRuleSceneActionDeviceControl01 = new IotRuleSceneDO.ActionDeviceControl(); iotRuleSceneActionDeviceControl01.setProductKey("4aymZgOTOOCrDKRT"); iotRuleSceneActionDeviceControl01.setDeviceNames(ListUtil.of("small")); iotRuleSceneActionDeviceControl01.setType(IotDeviceMessageTypeEnum.PROPERTY.getType()); @@ -288,7 +287,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService { return; } // 1.2 判断是否有定时触发器,避免脏数据 - IotRuleSceneTriggerConfig config = CollUtil.findOne(scene.getTriggers(), + IotRuleSceneDO.TriggerConfig config = CollUtil.findOne(scene.getTriggers(), trigger -> ObjUtil.equals(trigger.getType(), IotRuleSceneTriggerTypeEnum.TIMER.getType())); if (config == null) { log.error("[executeRuleSceneByTimer][规则场景({}) 不存在定时触发器]", scene); @@ -317,7 +316,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService { // 2. 匹配 trigger 触发器的条件 return filterList(ruleScenes, ruleScene -> { - for (IotRuleSceneTriggerConfig trigger : ruleScene.getTriggers()) { + for (IotRuleSceneDO.TriggerConfig trigger : ruleScene.getTriggers()) { // 2.1 非设备触发,不匹配 if (ObjUtil.notEqual(trigger.getType(), IotRuleSceneTriggerTypeEnum.DEVICE.getType())) { return false; @@ -328,13 +327,13 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService { return false; } // 2.3 多个条件,只需要满足一个即可 - IotRuleSceneTriggerCondition matchedCondition = CollUtil.findOne(trigger.getConditions(), condition -> { + IotRuleSceneDO.TriggerCondition matchedCondition = CollUtil.findOne(trigger.getConditions(), condition -> { if (ObjUtil.notEqual(message.getType(), condition.getType()) || ObjUtil.notEqual(message.getIdentifier(), condition.getIdentifier())) { return false; } // 多个条件参数,必须全部满足。所以,下面的逻辑就是找到一个不满足的条件参数 - IotRuleSceneTriggerConditionParameter notMatchedParameter = CollUtil.findOne(condition.getParameters(), + IotRuleSceneDO.TriggerConditionParameter notMatchedParameter = CollUtil.findOne(condition.getParameters(), parameter -> !isTriggerConditionParameterMatched(message, parameter, ruleScene, trigger)); return notMatchedParameter == null; }); @@ -360,8 +359,8 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService { * @return 是否匹配 */ @SuppressWarnings({"unchecked", "DataFlowIssue"}) - private boolean isTriggerConditionParameterMatched(IotDeviceMessage message, IotRuleSceneTriggerConditionParameter parameter, - IotRuleSceneDO ruleScene, IotRuleSceneTriggerConfig trigger) { + private boolean isTriggerConditionParameterMatched(IotDeviceMessage message, IotRuleSceneDO.TriggerConditionParameter parameter, + IotRuleSceneDO ruleScene, IotRuleSceneDO.TriggerConfig trigger) { // 1.1 校验操作符是否合法 IotRuleSceneTriggerConditionParameterOperatorEnum operator = IotRuleSceneTriggerConditionParameterOperatorEnum.operatorOf(parameter.getOperator()); diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/IotRuleSceneAction.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/IotRuleSceneAction.java index e115c629b5..202c3fb67e 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/IotRuleSceneAction.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/IotRuleSceneAction.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.iot.service.rule.action; -import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config.IotRuleSceneActionConfig; +import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO; import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum; import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage; @@ -23,7 +23,7 @@ public interface IotRuleSceneAction { * 2. 非空的情况:设备触发 * @param config 配置 */ - void execute(@Nullable IotDeviceMessage message, IotRuleSceneActionConfig config) throws Exception; + void execute(@Nullable IotDeviceMessage message, IotRuleSceneDO.ActionConfig config) throws Exception; /** * 获得类型 diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/IotRuleSceneAlertAction.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/IotRuleSceneAlertAction.java index a9c475a2b1..eadc173787 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/IotRuleSceneAlertAction.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/IotRuleSceneAlertAction.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.iot.service.rule.action; -import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config.IotRuleSceneActionConfig; +import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO; import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum; import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage; import org.springframework.stereotype.Component; @@ -16,7 +16,7 @@ import javax.annotation.Nullable; public class IotRuleSceneAlertAction implements IotRuleSceneAction { @Override - public void execute(@Nullable IotDeviceMessage message, IotRuleSceneActionConfig config) { + public void execute(@Nullable IotDeviceMessage message, IotRuleSceneDO.ActionConfig config) { // TODO @芋艿:待实现 } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/IotRuleSceneDataBridgeAction.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/IotRuleSceneDataBridgeAction.java index 86405ca444..b38e181f93 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/IotRuleSceneDataBridgeAction.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/IotRuleSceneDataBridgeAction.java @@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.iot.service.rule.action; import cn.hutool.core.lang.Assert; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config.IotRuleSceneActionConfig; import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataBridgeDO; +import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO; import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum; import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage; import cn.iocoder.yudao.module.iot.service.rule.IotDataBridgeService; @@ -29,7 +29,7 @@ public class IotRuleSceneDataBridgeAction implements IotRuleSceneAction { private List> dataBridgeExecutes; @Override - public void execute(IotDeviceMessage message, IotRuleSceneActionConfig config) throws Exception { + public void execute(IotDeviceMessage message, IotRuleSceneDO.ActionConfig config) throws Exception { // 1.1 如果消息为空,直接返回 if (message == null) { return; diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/IotRuleSceneDeviceControlAction.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/IotRuleSceneDeviceControlAction.java index 3408ea0317..d8fd76b5e7 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/IotRuleSceneDeviceControlAction.java +++ b/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; import cn.hutool.core.lang.Assert; import cn.iocoder.yudao.module.iot.controller.admin.device.vo.control.IotDeviceDownstreamReqVO; -import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config.IotRuleSceneActionConfig; -import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config.IotRuleSceneActionDeviceControl; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; +import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO; import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum; import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage; import cn.iocoder.yudao.module.iot.service.device.IotDeviceService; @@ -28,8 +27,8 @@ public class IotRuleSceneDeviceControlAction implements IotRuleSceneAction { private IotDeviceService deviceService; @Override - public void execute(IotDeviceMessage message, IotRuleSceneActionConfig config) { - IotRuleSceneActionDeviceControl control = config.getDeviceControl(); + public void execute(IotDeviceMessage message, IotRuleSceneDO.ActionConfig config) { + IotRuleSceneDO.ActionDeviceControl control = config.getDeviceControl(); Assert.notNull(control, "设备控制配置不能为空"); // 遍历每个设备,下发消息 control.getDeviceNames().forEach(deviceName -> { diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/databridge/AbstractCacheableDataBridgeExecute.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/databridge/AbstractCacheableDataBridgeExecute.java index e7f84dd6ca..f557e7b467 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/databridge/AbstractCacheableDataBridgeExecute.java +++ b/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 imple @Override @SuppressWarnings({"unchecked"}) public void execute(IotDeviceMessage message, IotDataBridgeDO dataBridge) { - if (ObjUtil.notEqual(message.getType(), getType())) { + if (ObjUtil.notEqual(dataBridge.getType(), getType())) { return; } try { diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/databridge/IotRedisStreamMQDataBridgeExecute.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/databridge/IotRedisStreamDataBridgeExecute.java similarity index 65% rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/databridge/IotRedisStreamMQDataBridgeExecute.java rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/databridge/IotRedisStreamDataBridgeExecute.java index 2aac76619a..a2d4200b41 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/databridge/IotRedisStreamMQDataBridgeExecute.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/databridge/IotRedisStreamDataBridgeExecute.java @@ -1,12 +1,9 @@ package cn.iocoder.yudao.module.iot.service.rule.action.databridge; -import cn.hutool.core.util.ReflectUtil; import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge.config.IotDataBridgeRedisStreamMQConfig; +import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge.config.IotDataBridgeRedisStreamConfig; import cn.iocoder.yudao.module.iot.enums.rule.IotDataBridgeTypeEnum; import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import lombok.extern.slf4j.Slf4j; import org.redisson.Redisson; import org.redisson.api.RedissonClient; @@ -21,14 +18,14 @@ import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.stereotype.Component; /** - * Redis Stream MQ 的 {@link IotDataBridgeExecute} 实现类 + * Redis Stream 的 {@link IotDataBridgeExecute} 实现类 * * @author HUIHUI */ @Component @Slf4j -public class IotRedisStreamMQDataBridgeExecute extends - AbstractCacheableDataBridgeExecute> { +public class IotRedisStreamDataBridgeExecute extends + AbstractCacheableDataBridgeExecute> { @Override public Integer getType() { @@ -36,7 +33,7 @@ public class IotRedisStreamMQDataBridgeExecute extends } @Override - public void execute0(IotDeviceMessage message, IotDataBridgeRedisStreamMQConfig config) throws Exception { + public void execute0(IotDeviceMessage message, IotDataBridgeRedisStreamConfig config) throws Exception { // 1. 获取 RedisTemplate RedisTemplate redisTemplate = getProducer(config); @@ -48,7 +45,7 @@ public class IotRedisStreamMQDataBridgeExecute extends } @Override - protected RedisTemplate initProducer(IotDataBridgeRedisStreamMQConfig config) { + protected RedisTemplate initProducer(IotDataBridgeRedisStreamConfig config) { // 1.1 创建 Redisson 配置 Config redissonConfig = new Config(); SingleServerConfig serverConfig = redissonConfig.useSingleServer() @@ -59,20 +56,17 @@ public class IotRedisStreamMQDataBridgeExecute extends serverConfig.setPassword(config.getPassword()); } - // TODO @huihui:看看能不能简化一些。按道理说,不用这么多的哈。 - // 2.1 创建 RedissonClient + // TODO @芋艿:看看怎么优化 + // 创建 RedisTemplate 并配置 RedissonClient redisson = Redisson.create(redissonConfig); - // 2.2 创建并配置 RedisTemplate RedisTemplate template = new RedisTemplate<>(); - // 设置 RedisConnection 工厂。😈 它就是实现多种 Java Redis 客户端接入的秘密工厂。感兴趣的胖友,可以自己去撸下。 template.setConnectionFactory(new RedissonConnectionFactory(redisson)); - // 使用 String 序列化方式,序列化 KEY 。 + // 设置序列化器 template.setKeySerializer(RedisSerializer.string()); template.setHashKeySerializer(RedisSerializer.string()); - // 使用 JSON 序列化方式(库是 Jackson ),序列化 VALUE 。 - template.setValueSerializer(buildRedisSerializer()); - template.setHashValueSerializer(buildRedisSerializer()); - template.afterPropertiesSet();// 初始化 + template.setValueSerializer(RedisSerializer.json()); + template.setHashValueSerializer(RedisSerializer.json()); + template.afterPropertiesSet(); return template; } @@ -84,13 +78,4 @@ public class IotRedisStreamMQDataBridgeExecute extends } } - // TODO @huihui:看看能不能简化一些。按道理说,不用这么多的哈。 - public static RedisSerializer buildRedisSerializer() { - RedisSerializer json = RedisSerializer.json(); - // 解决 LocalDateTime 的序列化 - ObjectMapper objectMapper = (ObjectMapper) ReflectUtil.getFieldValue(json, "mapper"); - objectMapper.registerModules(new JavaTimeModule()); - return json; - } - } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelService.java index e15465e9b6..8834772d35 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelService.java +++ b/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; import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelListReqVO; import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelPageReqVO; import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelSaveReqVO; -import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelTSLRespVO; import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO; import jakarta.validation.Valid; @@ -91,12 +90,4 @@ public interface IotThingModelService { */ Long getThingModelCount(LocalDateTime createTime); - /** - * 通过产品 ID 获取产品物模型 TSL - * - * @param productId 产品 ID - * @return 产品物模型 TSL - */ - IotThingModelTSLRespVO getThingModelTslByProductId(Long productId); - } \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelServiceImpl.java index 55a264b1e0..9487ff2de6 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelServiceImpl.java @@ -1,7 +1,6 @@ package cn.iocoder.yudao.module.iot.service.thingmodel; import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.extra.spring.SpringUtil; @@ -14,7 +13,6 @@ import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.ThingModelS import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelListReqVO; import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelPageReqVO; import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelSaveReqVO; -import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelTSLRespVO; import cn.iocoder.yudao.module.iot.convert.thingmodel.IotThingModelConvert; import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO; @@ -151,31 +149,6 @@ public class IotThingModelServiceImpl implements IotThingModelService { return thingModelMapper.selectList(reqVO); } - // TODO @puhui999:这个转换,放在 controller 貌似也行? - @Override - public IotThingModelTSLRespVO getThingModelTslByProductId(Long productId) { - IotThingModelTSLRespVO tslRespVO = new IotThingModelTSLRespVO(); - // 1. 获得产品所有物模型定义 - List thingModels = thingModelMapper.selectListByProductId(productId); - if (CollUtil.isEmpty(thingModels)) { - return tslRespVO; - } - - // 2.1 设置公共部分参数 - IotThingModelDO thingModel = thingModels.get(0); - tslRespVO.setProductId(thingModel.getProductId()).setProductKey(thingModel.getProductKey()); - // 2.2 处理属性列表 - tslRespVO.setProperties(convertList(filterList(thingModels, item -> - ObjUtil.equal(IotThingModelTypeEnum.PROPERTY.getType(), item.getType())), IotThingModelDO::getProperty)); - // 2.3 处理服务列表 - tslRespVO.setServices(convertList(filterList(thingModels, item -> - ObjUtil.equal(IotThingModelTypeEnum.SERVICE.getType(), item.getType())), IotThingModelDO::getService)); - // 2.4 处理事件列表 - tslRespVO.setEvents(convertList(filterList(thingModels, item -> - ObjUtil.equal(IotThingModelTypeEnum.EVENT.getType(), item.getType())), IotThingModelDO::getEvent)); - return tslRespVO; - } - /** * 校验功能是否存在 * diff --git a/yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/rule/action/databridge/IotDataBridgeExecuteTest.java b/yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/rule/action/databridge/IotDataBridgeExecuteTest.java index 38586afdd7..4a4ca55b74 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/rule/action/databridge/IotDataBridgeExecuteTest.java +++ b/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; import static org.mockito.Mockito.when; /** - * {@link IotDataBridgeExecute} 实现类的测试 + * {@link IotDataBridgeExecute} 实现类的单元测试 * * @author HUIHUI */ @@ -41,114 +41,125 @@ public class IotDataBridgeExecuteTest extends BaseMockitoUnitTest { @BeforeEach public void setUp() { // 创建共享的测试消息 - message = IotDeviceMessage.builder().requestId("TEST-001").reportTime(LocalDateTime.now()).tenantId(1L) - .productKey("testProduct").deviceName("testDevice").deviceKey("testDeviceKey") - .type("property").identifier("temperature").data("{\"value\": 60}") + message = IotDeviceMessage.builder() + .requestId("TEST-001") + .reportTime(LocalDateTime.now()) + .tenantId(1L) + .productKey("testProduct") + .deviceName("testDevice") + .deviceKey("testDeviceKey") + .type("property") + .identifier("temperature") + .data("{\"value\": 60}") .build(); - - // 配置 RestTemplate mock 返回成功响应 - // TODO @puhui999:这个应该放到 testHttpDataBridge 里 - when(restTemplate.exchange(anyString(), any(HttpMethod.class), any(), any(Class.class))) - .thenReturn(new ResponseEntity<>("Success", HttpStatus.OK)); } @Test - public void testKafkaMQDataBridge() { + public void testKafkaMQDataBridge() throws Exception { // 1. 创建执行器实例 IotKafkaMQDataBridgeExecute action = new IotKafkaMQDataBridgeExecute(); // 2. 创建配置 - // TODO @puhui999:可以改成链式哈。 - IotDataBridgeKafkaMQConfig config = new IotDataBridgeKafkaMQConfig(); - config.setBootstrapServers("127.0.0.1:9092"); - config.setTopic("test-topic"); - config.setSsl(false); - config.setUsername(null); - config.setPassword(null); + IotDataBridgeKafkaMQConfig config = new IotDataBridgeKafkaMQConfig() + .setBootstrapServers("127.0.0.1:9092") + .setTopic("test-topic") + .setSsl(false) + .setUsername(null) + .setPassword(null); - // 3. 执行两次测试,验证缓存 - log.info("[testKafkaMQDataBridge][第一次执行,应该会创建新的 producer]"); - action.execute(message, new IotDataBridgeDO().setType(action.getType()).setConfig(config)); - - log.info("[testKafkaMQDataBridge][第二次执行,应该会复用缓存的 producer]"); - action.execute(message, new IotDataBridgeDO().setType(action.getType()).setConfig(config)); + // 3. 执行测试并验证缓存 + executeAndVerifyCache(action, config, "KafkaMQ"); } @Test - public void testRabbitMQDataBridge() { + public void testRabbitMQDataBridge() throws Exception { // 1. 创建执行器实例 IotRabbitMQDataBridgeExecute action = new IotRabbitMQDataBridgeExecute(); // 2. 创建配置 - IotDataBridgeRabbitMQConfig config = new IotDataBridgeRabbitMQConfig(); - config.setHost("localhost"); - config.setPort(5672); - config.setVirtualHost("/"); - config.setUsername("admin"); - config.setPassword("123456"); - config.setExchange("test-exchange"); - config.setRoutingKey("test-key"); - config.setQueue("test-queue"); + IotDataBridgeRabbitMQConfig config = new IotDataBridgeRabbitMQConfig() + .setHost("localhost") + .setPort(5672) + .setVirtualHost("/") + .setUsername("admin") + .setPassword("123456") + .setExchange("test-exchange") + .setRoutingKey("test-key") + .setQueue("test-queue"); - // 3. 执行两次测试,验证缓存 - log.info("[testRabbitMQDataBridge][第一次执行,应该会创建新的 producer]"); - action.execute(message, new IotDataBridgeDO().setType(action.getType()).setConfig(config)); - - log.info("[testRabbitMQDataBridge][第二次执行,应该会复用缓存的 producer]"); - action.execute(message, new IotDataBridgeDO().setType(action.getType()).setConfig(config)); + // 3. 执行测试并验证缓存 + executeAndVerifyCache(action, config, "RabbitMQ"); } @Test - public void testRedisStreamMQDataBridge() { + public void testRedisStreamDataBridge() throws Exception { // 1. 创建执行器实例 - IotRedisStreamMQDataBridgeExecute action = new IotRedisStreamMQDataBridgeExecute(); + IotRedisStreamDataBridgeExecute action = new IotRedisStreamDataBridgeExecute(); // 2. 创建配置 - IotDataBridgeRedisStreamMQConfig config = new IotDataBridgeRedisStreamMQConfig(); - config.setHost("127.0.0.1"); - config.setPort(6379); - config.setDatabase(0); - config.setPassword("123456"); - config.setTopic("test-stream"); + IotDataBridgeRedisStreamConfig config = new IotDataBridgeRedisStreamConfig() + .setHost("127.0.0.1") + .setPort(6379) + .setDatabase(0) + .setPassword("123456") + .setTopic("test-stream"); - // 3. 执行两次测试,验证缓存 - log.info("[testRedisStreamMQDataBridge][第一次执行,应该会创建新的 producer]"); - action.execute(message, new IotDataBridgeDO().setType(action.getType()).setConfig(config)); - - log.info("[testRedisStreamMQDataBridge][第二次执行,应该会复用缓存的 producer]"); - action.execute(message, new IotDataBridgeDO().setType(action.getType()).setConfig(config)); + // 3. 执行测试并验证缓存 + executeAndVerifyCache(action, config, "RedisStream"); } @Test - public void testRocketMQDataBridge() { + public void testRocketMQDataBridge() throws Exception { // 1. 创建执行器实例 IotRocketMQDataBridgeExecute action = new IotRocketMQDataBridgeExecute(); // 2. 创建配置 - IotDataBridgeRocketMQConfig config = new IotDataBridgeRocketMQConfig(); - config.setNameServer("127.0.0.1:9876"); - config.setGroup("test-group"); - config.setTopic("test-topic"); - config.setTags("test-tag"); + IotDataBridgeRocketMQConfig config = new IotDataBridgeRocketMQConfig() + .setNameServer("127.0.0.1:9876") + .setGroup("test-group") + .setTopic("test-topic") + .setTags("test-tag"); - // 3. 执行两次测试,验证缓存 - log.info("[testRocketMQDataBridge][第一次执行,应该会创建新的 producer]"); - action.execute(message, new IotDataBridgeDO().setType(action.getType()).setConfig(config)); - - log.info("[testRocketMQDataBridge][第二次执行,应该会复用缓存的 producer]"); - action.execute(message, new IotDataBridgeDO().setType(action.getType()).setConfig(config)); + // 3. 执行测试并验证缓存 + executeAndVerifyCache(action, config, "RocketMQ"); } @Test public void testHttpDataBridge() throws Exception { - // 创建配置 - IotDataBridgeHttpConfig config = new IotDataBridgeHttpConfig(); - config.setUrl("https://doc.iocoder.cn/"); - config.setMethod(HttpMethod.GET.name()); + // 1. 配置 RestTemplate mock 返回成功响应 + when(restTemplate.exchange(anyString(), any(HttpMethod.class), any(), any(Class.class))) + .thenReturn(new ResponseEntity<>("Success", HttpStatus.OK)); - // 执行测试 + // 2. 创建配置 + IotDataBridgeHttpConfig config = new IotDataBridgeHttpConfig() + .setUrl("https://doc.iocoder.cn/") + .setMethod(HttpMethod.GET.name()); + + // 3. 执行测试 log.info("[testHttpDataBridge][执行HTTP数据桥接测试]"); - httpDataBridgeExecute.execute(message, new IotDataBridgeDO().setType(httpDataBridgeExecute.getType()).setConfig(config)); + httpDataBridgeExecute.execute(message, new IotDataBridgeDO() + .setType(httpDataBridgeExecute.getType()) + .setConfig(config)); + } + + /** + * 执行测试并验证缓存的通用方法 + * + * @param action 执行器实例 + * @param config 配置对象 + * @param mqType MQ类型 + * @throws Exception 如果执行过程中发生异常 + */ + private void executeAndVerifyCache(IotDataBridgeExecute action, IotDataBridgeAbstractConfig config, String mqType) throws Exception { + log.info("[test{}DataBridge][第一次执行,应该会创建新的 producer]", mqType); + action.execute(message, new IotDataBridgeDO() + .setType(action.getType()) + .setConfig(config)); + + log.info("[test{}DataBridge][第二次执行,应该会复用缓存的 producer]", mqType); + action.execute(message, new IotDataBridgeDO() + .setType(action.getType()) + .setConfig(config)); } }