From 6eadbba34554f2364f7bb77daed829bec8945637 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=89=E6=B5=A9=E6=B5=A9?= <1036606149@qq.com> Date: Wed, 5 Feb 2025 21:44:23 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E3=80=91IoT=EF=BC=9A=E9=87=8D=E6=9E=84=E6=8F=92=E4=BB=B6?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E7=AE=A1=E7=90=86=EF=BC=8C=E6=9B=BF=E6=8D=A2?= =?UTF-8?q?=20PluginInfo=20=E4=B8=BA=20PluginConfig?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- .../yudao-spring-boot-starter-mybatis/pom.xml | 4 + .../module/iot/enums/ErrorCodeConstants.java | 7 +- yudao-module-iot/yudao-module-iot-biz/pom.xml | 5 - .../admin/plugin/PluginConfigController.java | 90 +++++++++ .../admin/plugin/PluginInfoController.java | 90 --------- .../PluginConfigImportReqVO.java} | 4 +- .../PluginConfigPageReqVO.java} | 6 +- .../PluginConfigRespVO.java} | 6 +- .../PluginConfigSaveReqVO.java} | 6 +- .../vo/config/PluginConfigStatusReqVO.java | 19 ++ ...uginInfoDO.java => IotPluginConfigDO.java} | 12 +- .../plugin/IotPluginInstanceDO.java | 2 +- .../mysql/plugin/IotPluginConfigMapper.java | 33 +++ .../dal/mysql/plugin/IotPluginInfoMapper.java | 32 --- .../plugin/config/IotPluginConfiguration.java | 7 +- .../plugin/core/IotPluginStartRunner.java | 27 +-- .../plugin/IotPluginConfigService.java | 100 ++++++++++ .../plugin/IotPluginConfigServiceImpl.java | 188 ++++++++++++++++++ .../service/plugin/IotPluginInfoService.java | 92 --------- .../plugin/IotPluginInfoServiceImpl.java | 158 --------------- .../plugin/IotPluginInstanceService.java | 10 +- .../plugin/IotPluginInstanceServiceImpl.java | 20 +- yudao-server/pom.xml | 10 +- 24 files changed, 494 insertions(+), 436 deletions(-) create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/plugin/PluginConfigController.java delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/plugin/PluginInfoController.java rename yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/plugin/vo/{info/PluginInfoImportReqVO.java => config/PluginConfigImportReqVO.java} (83%) rename yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/plugin/vo/{info/PluginInfoPageReqVO.java => config/PluginConfigPageReqVO.java} (71%) rename yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/plugin/vo/{info/PluginInfoRespVO.java => config/PluginConfigRespVO.java} (90%) rename yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/plugin/vo/{info/PluginInfoSaveReqVO.java => config/PluginConfigSaveReqVO.java} (91%) create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/plugin/vo/config/PluginConfigStatusReqVO.java rename yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/plugin/{IotPluginInfoDO.java => IotPluginConfigDO.java} (82%) create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/plugin/IotPluginConfigMapper.java delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/plugin/IotPluginInfoMapper.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/plugin/IotPluginConfigService.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/plugin/IotPluginConfigServiceImpl.java delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/plugin/IotPluginInfoService.java delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/plugin/IotPluginInfoServiceImpl.java diff --git a/pom.xml b/pom.xml index 43da0c8d03..a343309726 100644 --- a/pom.xml +++ b/pom.xml @@ -24,7 +24,7 @@ - + yudao-module-iot ${project.artifactId} diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml b/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml index 1f3c9144bf..2a14c88b87 100644 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml @@ -63,6 +63,10 @@ opengauss-jdbc true + + com.taosdata.jdbc + taos-jdbcdriver + com.alibaba 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 ed9b0ef138..e85d4b368f 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 @@ -39,12 +39,13 @@ public interface ErrorCodeConstants { ErrorCode DEVICE_GROUP_NOT_EXISTS = new ErrorCode(1_050_005_000, "设备分组不存在"); ErrorCode DEVICE_GROUP_DELETE_FAIL_DEVICE_EXISTS = new ErrorCode(1_050_005_001, "设备分组下存在设备,不允许删除"); - // ========== 插件信息 1-050-006-000 ========== - ErrorCode PLUGIN_INFO_NOT_EXISTS = new ErrorCode(1_050_006_000, "插件信息不存在"); + // ========== 插件配置 1-050-006-000 ========== + ErrorCode PLUGIN_CONFIG_NOT_EXISTS = new ErrorCode(1_050_006_000, "插件配置不存在"); ErrorCode PLUGIN_INSTALL_FAILED = new ErrorCode(1_050_006_001, "插件安装失败"); ErrorCode PLUGIN_INSTALL_FAILED_FILE_NAME_NOT_MATCH = new ErrorCode(1_050_006_002, "插件安装失败,文件名与原插件id不匹配"); - ErrorCode PLUGIN_INFO_DELETE_FAILED_RUNNING = new ErrorCode(1_050_006_003, "请先停止插件"); + ErrorCode PLUGIN_CONFIG_DELETE_FAILED_RUNNING = new ErrorCode(1_050_006_003, "请先停止插件"); ErrorCode PLUGIN_STATUS_INVALID = new ErrorCode(1_050_006_004, "插件状态无效"); + ErrorCode PLUGIN_CONFIG_KEY_DUPLICATE = new ErrorCode(1_050_006_005, "插件标识已存在"); // ========== 插件实例 1-050-007-000 ========== diff --git a/yudao-module-iot/yudao-module-iot-biz/pom.xml b/yudao-module-iot/yudao-module-iot-biz/pom.xml index cc3141939d..805205a167 100644 --- a/yudao-module-iot/yudao-module-iot-biz/pom.xml +++ b/yudao-module-iot/yudao-module-iot-biz/pom.xml @@ -52,11 +52,6 @@ yudao-spring-boot-starter-redis - - com.taosdata.jdbc - taos-jdbcdriver - - cn.iocoder.boot diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/plugin/PluginConfigController.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/plugin/PluginConfigController.java new file mode 100644 index 0000000000..e21b102410 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/plugin/PluginConfigController.java @@ -0,0 +1,90 @@ +package cn.iocoder.yudao.module.iot.controller.admin.plugin; + +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.plugin.vo.config.PluginConfigImportReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.plugin.vo.config.PluginConfigPageReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.plugin.vo.config.PluginConfigRespVO; +import cn.iocoder.yudao.module.iot.controller.admin.plugin.vo.config.PluginConfigSaveReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.plugin.vo.config.PluginConfigStatusReqVO; +import cn.iocoder.yudao.module.iot.dal.dataobject.plugin.IotPluginConfigDO; +import cn.iocoder.yudao.module.iot.service.plugin.IotPluginConfigService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - IoT 插件配置") +@RestController +@RequestMapping("/iot/plugin-config") +@Validated +public class PluginConfigController { + + @Resource + private IotPluginConfigService pluginConfigService; + + @PostMapping("/create") + @Operation(summary = "创建插件配置") + @PreAuthorize("@ss.hasPermission('iot:plugin-config:create')") + public CommonResult createPluginConfig(@Valid @RequestBody PluginConfigSaveReqVO createReqVO) { + return success(pluginConfigService.createPluginConfig(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新插件配置") + @PreAuthorize("@ss.hasPermission('iot:plugin-config:update')") + public CommonResult updatePluginConfig(@Valid @RequestBody PluginConfigSaveReqVO updateReqVO) { + pluginConfigService.updatePluginConfig(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除插件配置") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('iot:plugin-config:delete')") + public CommonResult deletePluginConfig(@RequestParam("id") Long id) { + pluginConfigService.deletePluginConfig(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得插件配置") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('iot:plugin-config:query')") + public CommonResult getPluginConfig(@RequestParam("id") Long id) { + IotPluginConfigDO pluginConfig = pluginConfigService.getPluginConfig(id); + return success(BeanUtils.toBean(pluginConfig, PluginConfigRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得插件配置分页") + @PreAuthorize("@ss.hasPermission('iot:plugin-config:query')") + public CommonResult> getPluginConfigPage(@Valid PluginConfigPageReqVO pageReqVO) { + PageResult pageResult = pluginConfigService.getPluginConfigPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, PluginConfigRespVO.class)); + } + + @PostMapping("/upload-file") + @Operation(summary = "上传插件文件") + @PreAuthorize("@ss.hasPermission('iot:plugin-config:update')") + public CommonResult uploadFile(@Valid PluginConfigImportReqVO reqVO) { + pluginConfigService.uploadFile(reqVO.getId(), reqVO.getFile()); + return success(true); + } + + @PutMapping("/update-status") + @Operation(summary = "修改插件状态") + @PreAuthorize("@ss.hasPermission('iot:plugin-config:update')") + public CommonResult updatePluginConfigStatus(@Valid @RequestBody PluginConfigStatusReqVO reqVO) { + pluginConfigService.updatePluginStatus(reqVO.getId(), reqVO.getStatus()); + return success(true); + } + +} \ 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/plugin/PluginInfoController.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/plugin/PluginInfoController.java deleted file mode 100644 index 9b78001595..0000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/plugin/PluginInfoController.java +++ /dev/null @@ -1,90 +0,0 @@ -package cn.iocoder.yudao.module.iot.controller.admin.plugin; - -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.plugin.vo.info.PluginInfoImportReqVO; -import cn.iocoder.yudao.module.iot.controller.admin.plugin.vo.info.PluginInfoPageReqVO; -import cn.iocoder.yudao.module.iot.controller.admin.plugin.vo.info.PluginInfoRespVO; -import cn.iocoder.yudao.module.iot.controller.admin.plugin.vo.info.PluginInfoSaveReqVO; -import cn.iocoder.yudao.module.iot.dal.dataobject.plugin.IotPluginInfoDO; -import cn.iocoder.yudao.module.iot.service.plugin.IotPluginInfoService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; - -@Tag(name = "管理后台 - IoT 插件信息") -@RestController -@RequestMapping("/iot/plugin-info") -@Validated -public class PluginInfoController { - - @Resource - private IotPluginInfoService pluginInfoService; - - @PostMapping("/create") - @Operation(summary = "创建插件信息") - @PreAuthorize("@ss.hasPermission('iot:plugin-info:create')") - public CommonResult createPluginInfo(@Valid @RequestBody PluginInfoSaveReqVO createReqVO) { - return success(pluginInfoService.createPluginInfo(createReqVO)); - } - - @PutMapping("/update") - @Operation(summary = "更新插件信息") - @PreAuthorize("@ss.hasPermission('iot:plugin-info:update')") - public CommonResult updatePluginInfo(@Valid @RequestBody PluginInfoSaveReqVO updateReqVO) { - pluginInfoService.updatePluginInfo(updateReqVO); - return success(true); - } - - @DeleteMapping("/delete") - @Operation(summary = "删除插件信息") - @Parameter(name = "id", description = "编号", required = true) - @PreAuthorize("@ss.hasPermission('iot:plugin-info:delete')") - public CommonResult deletePluginInfo(@RequestParam("id") Long id) { - pluginInfoService.deletePluginInfo(id); - return success(true); - } - - @GetMapping("/get") - @Operation(summary = "获得插件信息") - @Parameter(name = "id", description = "编号", required = true, example = "1024") - @PreAuthorize("@ss.hasPermission('iot:plugin-info:query')") - public CommonResult getPluginInfo(@RequestParam("id") Long id) { - IotPluginInfoDO pluginInfo = pluginInfoService.getPluginInfo(id); - return success(BeanUtils.toBean(pluginInfo, PluginInfoRespVO.class)); - } - - @GetMapping("/page") - @Operation(summary = "获得插件信息分页") - @PreAuthorize("@ss.hasPermission('iot:plugin-info:query')") - public CommonResult> getPluginInfoPage(@Valid PluginInfoPageReqVO pageReqVO) { - PageResult pageResult = pluginInfoService.getPluginInfoPage(pageReqVO); - return success(BeanUtils.toBean(pageResult, PluginInfoRespVO.class)); - } - - @PostMapping("/upload-file") - @Operation(summary = "上传插件文件") - @PreAuthorize("@ss.hasPermission('iot:plugin-info:update')") - public CommonResult uploadFile(@Valid PluginInfoImportReqVO reqVO) { - pluginInfoService.uploadFile(reqVO.getId(), reqVO.getFile()); - return success(true); - } - - // TODO @haohao:要不独立一个 VO,不用 PluginInfoSaveReqVO - @PutMapping("/update-status") - @Operation(summary = "修改插件状态") - @PreAuthorize("@ss.hasPermission('iot:plugin-info:update')") - public CommonResult updateUserStatus(@Valid @RequestBody PluginInfoSaveReqVO reqVO) { - pluginInfoService.updatePluginStatus(reqVO.getId(), reqVO.getStatus()); - return success(true); - } - -} \ 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/plugin/vo/info/PluginInfoImportReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/plugin/vo/config/PluginConfigImportReqVO.java similarity index 83% rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/plugin/vo/info/PluginInfoImportReqVO.java rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/plugin/vo/config/PluginConfigImportReqVO.java index fc2f8da8a9..b9b277a542 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/plugin/vo/info/PluginInfoImportReqVO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/plugin/vo/config/PluginConfigImportReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.iot.controller.admin.plugin.vo.info; +package cn.iocoder.yudao.module.iot.controller.admin.plugin.vo.config; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; @@ -7,7 +7,7 @@ import org.springframework.web.multipart.MultipartFile; @Schema(description = "管理后台 - IoT 插件上传 Request VO") @Data -public class PluginInfoImportReqVO { +public class PluginConfigImportReqVO { @Schema(description = "主键 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "11546") private Long id; diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/plugin/vo/info/PluginInfoPageReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/plugin/vo/config/PluginConfigPageReqVO.java similarity index 71% rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/plugin/vo/info/PluginInfoPageReqVO.java rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/plugin/vo/config/PluginConfigPageReqVO.java index cac975be18..1666d5d6bc 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/plugin/vo/info/PluginInfoPageReqVO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/plugin/vo/config/PluginConfigPageReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.iot.controller.admin.plugin.vo.info; +package cn.iocoder.yudao.module.iot.controller.admin.plugin.vo.config; import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.validation.InEnum; @@ -6,9 +6,9 @@ import cn.iocoder.yudao.module.iot.enums.plugin.IotPluginStatusEnum; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -@Schema(description = "管理后台 - IoT 插件信息分页 Request VO") +@Schema(description = "管理后台 - IoT 插件配置分页 Request VO") @Data -public class PluginInfoPageReqVO extends PageParam { +public class PluginConfigPageReqVO extends PageParam { @Schema(description = "插件名称", example = "http") private String name; diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/plugin/vo/info/PluginInfoRespVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/plugin/vo/config/PluginConfigRespVO.java similarity index 90% rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/plugin/vo/info/PluginInfoRespVO.java rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/plugin/vo/config/PluginConfigRespVO.java index 685d408de2..2b8c4dcde8 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/plugin/vo/info/PluginInfoRespVO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/plugin/vo/config/PluginConfigRespVO.java @@ -1,13 +1,13 @@ -package cn.iocoder.yudao.module.iot.controller.admin.plugin.vo.info; +package cn.iocoder.yudao.module.iot.controller.admin.plugin.vo.config; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.time.LocalDateTime; -@Schema(description = "管理后台 - IoT 插件信息 Response VO") +@Schema(description = "管理后台 - IoT 插件配置 Response VO") @Data -public class PluginInfoRespVO { +public class PluginConfigRespVO { @Schema(description = "主键 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "11546") private Long id; diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/plugin/vo/info/PluginInfoSaveReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/plugin/vo/config/PluginConfigSaveReqVO.java similarity index 91% rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/plugin/vo/info/PluginInfoSaveReqVO.java rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/plugin/vo/config/PluginConfigSaveReqVO.java index c2a16ac496..e48869d645 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/plugin/vo/info/PluginInfoSaveReqVO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/plugin/vo/config/PluginConfigSaveReqVO.java @@ -1,13 +1,13 @@ -package cn.iocoder.yudao.module.iot.controller.admin.plugin.vo.info; +package cn.iocoder.yudao.module.iot.controller.admin.plugin.vo.config; import cn.iocoder.yudao.framework.common.validation.InEnum; import cn.iocoder.yudao.module.iot.enums.plugin.IotPluginStatusEnum; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -@Schema(description = "管理后台 - IoT 插件信息新增/修改 Request VO") +@Schema(description = "管理后台 - IoT 插件配置新增/修改 Request VO") @Data -public class PluginInfoSaveReqVO { +public class PluginConfigSaveReqVO { // TODO @haohao:新增的字段有点多,每个都需要哇? diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/plugin/vo/config/PluginConfigStatusReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/plugin/vo/config/PluginConfigStatusReqVO.java new file mode 100644 index 0000000000..eae4aa0a2e --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/plugin/vo/config/PluginConfigStatusReqVO.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.module.iot.controller.admin.plugin.vo.config; + +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.iot.enums.plugin.IotPluginStatusEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "管理后台 - IoT 插件配置状态 Request VO") +@Data +public class PluginConfigStatusReqVO { + + @Schema(description = "主键编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11546") + private Long id; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED) + @InEnum(IotPluginStatusEnum.class) + private Integer status; + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/plugin/IotPluginInfoDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/plugin/IotPluginConfigDO.java similarity index 82% rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/plugin/IotPluginInfoDO.java rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/plugin/IotPluginConfigDO.java index 3a9c588d4a..d0695f8963 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/plugin/IotPluginInfoDO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/plugin/IotPluginConfigDO.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.iot.dal.dataobject.plugin; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.yudao.module.iot.enums.plugin.IotPluginDeployTypeEnum; import cn.iocoder.yudao.module.iot.enums.plugin.IotPluginStatusEnum; @@ -9,21 +10,20 @@ import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; -// TODO @haohao:建议 IotPluginInfoDO 改成 IotPluginConfigDO,插件配置。项目里,暂时没有用 info 作为配置的哈。 /** - * IoT 插件信息 DO + * IoT 插件配置 DO * * @author 芋道源码 */ -@TableName("iot_plugin_info") -@KeySequence("iot_plugin_info_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@TableName("iot_plugin_config") +@KeySequence("iot_plugin_config_seq") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) @Builder @NoArgsConstructor @AllArgsConstructor -public class IotPluginInfoDO extends BaseDO { +public class IotPluginConfigDO extends BaseDO { /** * 主键 ID @@ -73,7 +73,7 @@ public class IotPluginInfoDO extends BaseDO { /** * 状态 *

- * 枚举 {@link IotPluginStatusEnum} + * 枚举 {@link CommonStatusEnum} */ private Integer status; diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/plugin/IotPluginInstanceDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/plugin/IotPluginInstanceDO.java index 1def801855..71d741b052 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/plugin/IotPluginInstanceDO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/plugin/IotPluginInstanceDO.java @@ -31,7 +31,7 @@ public class IotPluginInstanceDO extends BaseDO { /** * 插件编号 *

- * 关联 {@link IotPluginInfoDO#getId()} + * 关联 {@link IotPluginConfigDO#getId()} */ private Long pluginId; /** diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/plugin/IotPluginConfigMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/plugin/IotPluginConfigMapper.java new file mode 100644 index 0000000000..0e2163a3fa --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/plugin/IotPluginConfigMapper.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.iot.dal.mysql.plugin; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.iot.controller.admin.plugin.vo.config.PluginConfigPageReqVO; +import cn.iocoder.yudao.module.iot.dal.dataobject.plugin.IotPluginConfigDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +@Mapper +public interface IotPluginConfigMapper extends BaseMapperX { + + default PageResult selectPage(PluginConfigPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(IotPluginConfigDO::getName, reqVO.getName()) + .eqIfPresent(IotPluginConfigDO::getStatus, reqVO.getStatus()) + .orderByDesc(IotPluginConfigDO::getId)); + } + + default List selectListByStatusAndDeployType(Integer status, Integer deployType) { + return selectList(new LambdaQueryWrapperX() + .eq(IotPluginConfigDO::getStatus, status) + .eq(IotPluginConfigDO::getDeployType, deployType) + .orderByAsc(IotPluginConfigDO::getId)); + } + + default IotPluginConfigDO selectByPluginKey(String pluginKey) { + return selectOne(IotPluginConfigDO::getPluginKey, pluginKey); + } + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/plugin/IotPluginInfoMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/plugin/IotPluginInfoMapper.java deleted file mode 100644 index 88058185f0..0000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/plugin/IotPluginInfoMapper.java +++ /dev/null @@ -1,32 +0,0 @@ -package cn.iocoder.yudao.module.iot.dal.mysql.plugin; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.iot.controller.admin.plugin.vo.info.PluginInfoPageReqVO; -import cn.iocoder.yudao.module.iot.dal.dataobject.plugin.IotPluginInfoDO; -import org.apache.ibatis.annotations.Mapper; - -import java.util.List; - -@Mapper -public interface IotPluginInfoMapper extends BaseMapperX { - - default PageResult selectPage(PluginInfoPageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .likeIfPresent(IotPluginInfoDO::getName, reqVO.getName()) - .eqIfPresent(IotPluginInfoDO::getStatus, reqVO.getStatus()) - .orderByDesc(IotPluginInfoDO::getId)); - } - - default List selectListByStatus(Integer status) { - return selectList(new LambdaQueryWrapperX() - .eq(IotPluginInfoDO::getStatus, status) - .orderByAsc(IotPluginInfoDO::getId)); - } - - default IotPluginInfoDO selectByPluginKey(String pluginKey) { - return selectOne(IotPluginInfoDO::getPluginKey, pluginKey); - } - -} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/plugin/config/IotPluginConfiguration.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/plugin/config/IotPluginConfiguration.java index b695cbe39f..0a2812ac87 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/plugin/config/IotPluginConfiguration.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/plugin/config/IotPluginConfiguration.java @@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.iot.framework.plugin.config; import cn.iocoder.yudao.module.iot.framework.plugin.core.IotPluginStartRunner; import cn.iocoder.yudao.module.iot.framework.plugin.core.IotPluginStateListener; -import cn.iocoder.yudao.module.iot.service.plugin.IotPluginInfoService; +import cn.iocoder.yudao.module.iot.service.plugin.IotPluginConfigService; import lombok.extern.slf4j.Slf4j; import org.pf4j.spring.SpringPluginManager; import org.springframework.beans.factory.annotation.Value; @@ -22,8 +22,8 @@ public class IotPluginConfiguration { @Bean public IotPluginStartRunner pluginStartRunner(SpringPluginManager pluginManager, - IotPluginInfoService pluginInfoService) { - return new IotPluginStartRunner(pluginManager, pluginInfoService); + IotPluginConfigService pluginConfigService) { + return new IotPluginStartRunner(pluginManager, pluginConfigService); } // TODO @芋艿:需要 review 下 @@ -31,7 +31,6 @@ public class IotPluginConfiguration { public SpringPluginManager pluginManager(@Value("${pf4j.pluginsDir:pluginsDir}") String pluginsDir) { log.info("[init][实例化 SpringPluginManager]"); SpringPluginManager springPluginManager = new SpringPluginManager(Paths.get(pluginsDir)) { -// SpringPluginManager springPluginManager = new SpringPluginManager() { @Override public void startPlugins() { diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/plugin/core/IotPluginStartRunner.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/plugin/core/IotPluginStartRunner.java index f3654bc305..8036eb2d47 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/plugin/core/IotPluginStartRunner.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/plugin/core/IotPluginStartRunner.java @@ -2,10 +2,10 @@ package cn.iocoder.yudao.module.iot.framework.plugin.core; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; -import cn.iocoder.yudao.module.iot.dal.dataobject.plugin.IotPluginInfoDO; +import cn.iocoder.yudao.module.iot.dal.dataobject.plugin.IotPluginConfigDO; import cn.iocoder.yudao.module.iot.enums.plugin.IotPluginDeployTypeEnum; import cn.iocoder.yudao.module.iot.enums.plugin.IotPluginStatusEnum; -import cn.iocoder.yudao.module.iot.service.plugin.IotPluginInfoService; +import cn.iocoder.yudao.module.iot.service.plugin.IotPluginConfigService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.pf4j.spring.SpringPluginManager; @@ -25,28 +25,29 @@ public class IotPluginStartRunner implements ApplicationRunner { private final SpringPluginManager springPluginManager; - private final IotPluginInfoService pluginInfoService; + private final IotPluginConfigService pluginConfigService; @Override public void run(ApplicationArguments args) { - List pluginInfoList = TenantUtils.executeIgnore( - // TODO @haohao:需要查询部署类型哈 - () -> pluginInfoService.getPluginInfoListByStatus(IotPluginStatusEnum.RUNNING.getStatus())); - if (CollUtil.isEmpty(pluginInfoList)) { + List pluginConfigList = TenantUtils.executeIgnore( + // 查询运行中且部署类型为 JAR 的插件 + () -> pluginConfigService.getPluginConfigListByStatusAndDeployType( + IotPluginStatusEnum.RUNNING.getStatus(), IotPluginDeployTypeEnum.JAR.getDeployType())); + if (CollUtil.isEmpty(pluginConfigList)) { log.info("[run][没有需要启动的插件]"); return; } // 遍历插件列表,逐个启动 - pluginInfoList.forEach(pluginInfo -> { + pluginConfigList.forEach(pluginConfig -> { try { - log.info("[run][插件({}) 启动开始]", pluginInfo.getPluginKey()); - springPluginManager.startPlugin(pluginInfo.getPluginKey()); - log.info("[run][插件({}) 启动完成]", pluginInfo.getPluginKey()); + log.info("[run][插件({}) 启动开始]", pluginConfig.getPluginKey()); + springPluginManager.startPlugin(pluginConfig.getPluginKey()); + log.info("[run][插件({}) 启动完成]", pluginConfig.getPluginKey()); } catch (Exception e) { - log.error("[run][插件({}) 启动异常]", pluginInfo.getPluginKey(), e); + log.error("[run][插件({}) 启动异常]", pluginConfig.getPluginKey(), e); } }); } -} +} \ 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/plugin/IotPluginConfigService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/plugin/IotPluginConfigService.java new file mode 100644 index 0000000000..8b6610f150 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/plugin/IotPluginConfigService.java @@ -0,0 +1,100 @@ +package cn.iocoder.yudao.module.iot.service.plugin; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.iot.controller.admin.plugin.vo.config.PluginConfigPageReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.plugin.vo.config.PluginConfigSaveReqVO; +import cn.iocoder.yudao.module.iot.dal.dataobject.plugin.IotPluginConfigDO; +import cn.iocoder.yudao.module.iot.enums.plugin.IotPluginDeployTypeEnum; +import cn.iocoder.yudao.module.iot.enums.plugin.IotPluginStatusEnum; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotEmpty; +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; + +/** + * IoT 插件配置 Service 接口 + * + * @author haohao + */ +public interface IotPluginConfigService { + + /** + * 创建插件配置 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createPluginConfig(@Valid PluginConfigSaveReqVO createReqVO); + + /** + * 更新插件配置 + * + * @param updateReqVO 更新信息 + */ + void updatePluginConfig(@Valid PluginConfigSaveReqVO updateReqVO); + + /** + * 删除插件配置 + * + * @param id 编号 + */ + void deletePluginConfig(Long id); + + /** + * 获得插件配置 + * + * @param id 编号 + * @return 插件配置 + */ + IotPluginConfigDO getPluginConfig(Long id); + + /** + * 获得插件配置分页 + * + * @param pageReqVO 分页查询 + * @return 插件配置分页 + */ + PageResult getPluginConfigPage(PluginConfigPageReqVO pageReqVO); + + /** + * 上传插件的 JAR 包 + * + * @param id 插件id + * @param file 文件 + */ + void uploadFile(Long id, MultipartFile file); + + /** + * 更新插件的状态 + * + * @param id 插件id + * @param status 状态 {@link IotPluginStatusEnum} + */ + void updatePluginStatus(Long id, Integer status); + + /** + * 获得插件配置列表 + * + * @return 插件配置列表 + */ + List getPluginConfigList(); + + /** + * 根据状态和部署类型获得插件配置列表 + * + * @param status 状态 {@link IotPluginStatusEnum} + * @param deployType 部署类型 {@link IotPluginDeployTypeEnum} + * @return 插件配置列表 + */ + List getPluginConfigListByStatusAndDeployType(Integer status, Integer deployType); + + /** + * 根据插件包标识符获取插件配置 + * + * @param pluginKey 插件包标识符 + * @return 插件配置 + */ + IotPluginConfigDO getPluginConfigByPluginKey(@NotEmpty(message = "插件包标识符不能为空") String pluginKey); + +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/plugin/IotPluginConfigServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/plugin/IotPluginConfigServiceImpl.java new file mode 100644 index 0000000000..18376bc578 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/plugin/IotPluginConfigServiceImpl.java @@ -0,0 +1,188 @@ +package cn.iocoder.yudao.module.iot.service.plugin; + +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.plugin.vo.config.PluginConfigPageReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.plugin.vo.config.PluginConfigSaveReqVO; +import cn.iocoder.yudao.module.iot.dal.dataobject.plugin.IotPluginConfigDO; +import cn.iocoder.yudao.module.iot.dal.mysql.plugin.IotPluginConfigMapper; +import cn.iocoder.yudao.module.iot.enums.plugin.IotPluginStatusEnum; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.pf4j.PluginWrapper; +import org.pf4j.spring.SpringPluginManager; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.*; +/** + * IoT 插件配置 Service 实现类 + * + * @author haohao + */ +@Service +@Validated +@Slf4j +public class IotPluginConfigServiceImpl implements IotPluginConfigService { + + @Resource + private IotPluginConfigMapper pluginConfigMapper; + + @Resource + private IotPluginInstanceService pluginInstanceService; + + @Resource + private SpringPluginManager springPluginManager; + + @Override + public Long createPluginConfig(PluginConfigSaveReqVO createReqVO) { + // 1. 校验插件标识唯一性:确保没有其他配置使用相同的 pluginKey(新建时 id 为 null) + validatePluginKeyUnique(null, createReqVO.getPluginKey()); + IotPluginConfigDO pluginConfig = BeanUtils.toBean(createReqVO, IotPluginConfigDO.class); + // 2. 插入插件配置到数据库 + pluginConfigMapper.insert(pluginConfig); + return pluginConfig.getId(); + } + + @Override + public void updatePluginConfig(PluginConfigSaveReqVO updateReqVO) { + // 1. 校验插件配置是否存在:根据传入 ID 判断记录是否存在 + validatePluginConfigExists(updateReqVO.getId()); + // 2. 校验插件标识唯一性:确保更新后的 pluginKey 没有被其他记录占用 + validatePluginKeyUnique(updateReqVO.getId(), updateReqVO.getPluginKey()); + // 3. 将更新请求对象转换为插件配置数据对象 + IotPluginConfigDO updateObj = BeanUtils.toBean(updateReqVO, IotPluginConfigDO.class); + pluginConfigMapper.updateById(updateObj); + } + + /** + * 校验插件标识唯一性 + * + * @param id 当前插件配置的 ID(如果为 null 则说明为新建操作) + * @param pluginKey 待校验的插件标识 + */ + private void validatePluginKeyUnique(Long id, String pluginKey) { + // 1. 根据 pluginKey 从数据库中查询已有的插件配置 + IotPluginConfigDO pluginConfig = pluginConfigMapper.selectByPluginKey(pluginKey); + // 2. 如果查询到记录且记录的 ID 与当前 ID 不相同,则认为存在重复,抛出异常 + if (pluginConfig != null && !pluginConfig.getId().equals(id)) { + throw exception(PLUGIN_CONFIG_KEY_DUPLICATE); + } + } + + @Override + public void deletePluginConfig(Long id) { + // 1. 校验存在 + IotPluginConfigDO pluginConfigDO = validatePluginConfigExists(id); + // 2. 未开启状态,才允许删除 + if (IotPluginStatusEnum.RUNNING.getStatus().equals(pluginConfigDO.getStatus())) { + throw exception(PLUGIN_CONFIG_DELETE_FAILED_RUNNING); + } + + // 3. 卸载插件 + pluginInstanceService.stopAndUnloadPlugin(pluginConfigDO.getPluginKey()); + // 4. 删除插件文件 + pluginInstanceService.deletePluginFile(pluginConfigDO); + + // 5. 删除插件配置 + pluginConfigMapper.deleteById(id); + } + + /** + * 校验插件配置是否存在 + * + * @param id 插件配置编号 + * @return 插件配置 + */ + private IotPluginConfigDO validatePluginConfigExists(Long id) { + IotPluginConfigDO pluginConfig = pluginConfigMapper.selectById(id); + if (pluginConfig == null) { + throw exception(PLUGIN_CONFIG_NOT_EXISTS); + } + return pluginConfig; + } + + @Override + public IotPluginConfigDO getPluginConfig(Long id) { + return pluginConfigMapper.selectById(id); + } + + @Override + public PageResult getPluginConfigPage(PluginConfigPageReqVO pageReqVO) { + return pluginConfigMapper.selectPage(pageReqVO); + } + + @Override + public void uploadFile(Long id, MultipartFile file) { + // 1. 校验插件配置是否存在 + IotPluginConfigDO pluginConfigDO = validatePluginConfigExists(id); + + // 2.1 停止并卸载旧的插件 + pluginInstanceService.stopAndUnloadPlugin(pluginConfigDO.getPluginKey()); + // 2.2 上传新的插件文件,更新插件启用状态文件 + String pluginKeyNew = pluginInstanceService.uploadAndLoadNewPlugin(file); + + // 3. 校验 file 相关参数,是否完整 + validatePluginConfigFile(pluginKeyNew); + + // 4. 更新插件配置 + IotPluginConfigDO updatedPluginConfig = new IotPluginConfigDO() + .setId(pluginConfigDO.getId()) + .setPluginKey(pluginKeyNew) + .setStatus(IotPluginStatusEnum.STOPPED.getStatus()) // TODO @haohao:这个状态,是不是非 stop 哈? + .setFileName(file.getOriginalFilename()) + .setScript("") // TODO @haohao:这个设置为 "" 会不会覆盖数据里的哈?应该从插件里读取?未来? + .setConfigSchema(springPluginManager.getPlugin(pluginKeyNew).getDescriptor().getPluginDescription()) + .setVersion(springPluginManager.getPlugin(pluginKeyNew).getDescriptor().getVersion()) + .setDescription(springPluginManager.getPlugin(pluginKeyNew).getDescriptor().getPluginDescription()); + pluginConfigMapper.updateById(updatedPluginConfig); + } + + /** + * 校验 file 相关参数 + * + * @param pluginKeyNew 插件标识符 + */ + private void validatePluginConfigFile(String pluginKeyNew) { + // TODO @haohao:校验 file 相关参数,是否完整,类似:version 之类是不是可以解析到 + PluginWrapper plugin = springPluginManager.getPlugin(pluginKeyNew); + if (plugin == null) { + throw exception(PLUGIN_INSTALL_FAILED); + } + if (plugin.getDescriptor().getVersion() == null) { + throw exception(PLUGIN_INSTALL_FAILED); + } + } + + @Override + public void updatePluginStatus(Long id, Integer status) { + // 1. 校验插件配置是否存在 + IotPluginConfigDO pluginConfigDo = validatePluginConfigExists(id); + + // 2. 更新插件状态 + pluginInstanceService.updatePluginStatus(pluginConfigDo, status); + + // 3. 更新数据库中的插件状态 + pluginConfigMapper.updateById(new IotPluginConfigDO().setId(id).setStatus(status)); + } + + @Override + public List getPluginConfigList() { + return pluginConfigMapper.selectList(); + } + + @Override + public List getPluginConfigListByStatusAndDeployType(Integer status, Integer deployType) { + return pluginConfigMapper.selectListByStatusAndDeployType(status, deployType); + } + + @Override + public IotPluginConfigDO getPluginConfigByPluginKey(String pluginKey) { + return pluginConfigMapper.selectByPluginKey(pluginKey); + } + +} \ 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/plugin/IotPluginInfoService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/plugin/IotPluginInfoService.java deleted file mode 100644 index 1a8654ebc6..0000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/plugin/IotPluginInfoService.java +++ /dev/null @@ -1,92 +0,0 @@ -package cn.iocoder.yudao.module.iot.service.plugin; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.iot.controller.admin.plugin.vo.info.PluginInfoPageReqVO; -import cn.iocoder.yudao.module.iot.controller.admin.plugin.vo.info.PluginInfoSaveReqVO; -import cn.iocoder.yudao.module.iot.dal.dataobject.plugin.IotPluginInfoDO; -import cn.iocoder.yudao.module.iot.enums.plugin.IotPluginStatusEnum; -import jakarta.validation.Valid; -import jakarta.validation.constraints.NotEmpty; -import org.springframework.web.multipart.MultipartFile; - -import java.util.List; - -/** - * IoT 插件信息 Service 接口 - * - * @author haohao - */ -public interface IotPluginInfoService { - - /** - * 创建插件信息 - * - * @param createReqVO 创建信息 - * @return 编号 - */ - Long createPluginInfo(@Valid PluginInfoSaveReqVO createReqVO); - - /** - * 更新插件信息 - * - * @param updateReqVO 更新信息 - */ - void updatePluginInfo(@Valid PluginInfoSaveReqVO updateReqVO); - - /** - * 删除插件信息 - * - * @param id 编号 - */ - void deletePluginInfo(Long id); - - /** - * 获得插件信息 - * - * @param id 编号 - * @return 插件信息 - */ - IotPluginInfoDO getPluginInfo(Long id); - - /** - * 获得插件信息分页 - * - * @param pageReqVO 分页查询 - * @return 插件信息分页 - */ - PageResult getPluginInfoPage(PluginInfoPageReqVO pageReqVO); - - /** - * 上传插件的 JAR 包 - * - * @param id 插件id - * @param file 文件 - */ - void uploadFile(Long id, MultipartFile file); - - /** - * 更新插件的状态 - * - * @param id 插件id - * @param status 状态 {@link IotPluginStatusEnum} - */ - void updatePluginStatus(Long id, Integer status); - - /** - * 获得插件信息列表 - * - * @return 插件信息列表 - */ - List getPluginInfoList(); - - /** - * 根据状态获得插件信息列表 - * - * @param status 状态 {@link IotPluginStatusEnum} - * @return 插件信息列表 - */ - List getPluginInfoListByStatus(Integer status); - - IotPluginInfoDO getPluginInfoByPluginKey(@NotEmpty(message = "插件包标识符不能为空") String pluginKey); - -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/plugin/IotPluginInfoServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/plugin/IotPluginInfoServiceImpl.java deleted file mode 100644 index 400f1e39ea..0000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/plugin/IotPluginInfoServiceImpl.java +++ /dev/null @@ -1,158 +0,0 @@ -package cn.iocoder.yudao.module.iot.service.plugin; - -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.plugin.vo.info.PluginInfoPageReqVO; -import cn.iocoder.yudao.module.iot.controller.admin.plugin.vo.info.PluginInfoSaveReqVO; -import cn.iocoder.yudao.module.iot.dal.dataobject.plugin.IotPluginInfoDO; -import cn.iocoder.yudao.module.iot.dal.mysql.plugin.IotPluginInfoMapper; -import cn.iocoder.yudao.module.iot.enums.plugin.IotPluginStatusEnum; -import jakarta.annotation.Resource; -import lombok.extern.slf4j.Slf4j; -import org.pf4j.spring.SpringPluginManager; -import org.springframework.stereotype.Service; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.multipart.MultipartFile; - -import java.util.List; - -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.PLUGIN_INFO_DELETE_FAILED_RUNNING; -import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.PLUGIN_INFO_NOT_EXISTS; - -/** - * IoT 插件信息 Service 实现类 - * - * @author haohao - */ -@Service -@Validated -@Slf4j -public class IotPluginInfoServiceImpl implements IotPluginInfoService { - - @Resource - private IotPluginInfoMapper pluginInfoMapper; - - @Resource - private IotPluginInstanceService pluginInstanceService; - - @Resource - private SpringPluginManager springPluginManager; - - @Override - public Long createPluginInfo(PluginInfoSaveReqVO createReqVO) { - // TODO @haohao:pluginKey 唯一值 - IotPluginInfoDO pluginInfo = BeanUtils.toBean(createReqVO, IotPluginInfoDO.class); - pluginInfoMapper.insert(pluginInfo); - return pluginInfo.getId(); - } - - @Override - public void updatePluginInfo(PluginInfoSaveReqVO updateReqVO) { - // 校验存在 - validatePluginInfoExists(updateReqVO.getId()); - // 更新 - IotPluginInfoDO updateObj = BeanUtils.toBean(updateReqVO, IotPluginInfoDO.class); - pluginInfoMapper.updateById(updateObj); - } - - @Override - public void deletePluginInfo(Long id) { - // 1.1 校验存在 - IotPluginInfoDO pluginInfoDO = validatePluginInfoExists(id); - // 1.2 未开启状态,才允许删除 - if (IotPluginStatusEnum.RUNNING.getStatus().equals(pluginInfoDO.getStatus())) { - throw exception(PLUGIN_INFO_DELETE_FAILED_RUNNING); - } - - // 2.1 卸载插件 - pluginInstanceService.stopAndUnloadPlugin(pluginInfoDO.getPluginKey()); - // 2.2 删除插件文件 - pluginInstanceService.deletePluginFile(pluginInfoDO); - - // 3. 删除插件信息 - pluginInfoMapper.deleteById(id); - } - - private IotPluginInfoDO validatePluginInfoExists(Long id) { - IotPluginInfoDO pluginInfo = pluginInfoMapper.selectById(id); - if (pluginInfo == null) { - throw exception(PLUGIN_INFO_NOT_EXISTS); - } - return pluginInfo; - } - - @Override - public IotPluginInfoDO getPluginInfo(Long id) { - return pluginInfoMapper.selectById(id); - } - - @Override - public PageResult getPluginInfoPage(PluginInfoPageReqVO pageReqVO) { - return pluginInfoMapper.selectPage(pageReqVO); - } - - @Override - public void uploadFile(Long id, MultipartFile file) { - // 1. 校验插件信息是否存在 - IotPluginInfoDO pluginInfoDo = validatePluginInfoExists(id); - // TODO @haohao:最好校验下 file 相关参数,是否完整,类似:version 之类是不是可以解析到 - - // 2.1 停止并卸载旧的插件 - pluginInstanceService.stopAndUnloadPlugin(pluginInfoDo.getPluginKey()); - // 2.2 上传新的插件文件,更新插件启用状态文件 - String pluginKeyNew = pluginInstanceService.uploadAndLoadNewPlugin(file); - - // 3. 更新插件信息 - updatePluginInfo(pluginInfoDo, pluginKeyNew, file); - } - - // TODO @haohao:这个方法,要不合并到 uploadFile 里; - /** - * 更新插件信息 - * - * @param pluginInfoDo 插件信息 - * @param pluginKeyNew 插件标识符 - * @param file 文件 - */ - private void updatePluginInfo(IotPluginInfoDO pluginInfoDo, String pluginKeyNew, MultipartFile file) { - IotPluginInfoDO updatedPluginInfo = new IotPluginInfoDO() - .setId(pluginInfoDo.getId()) - .setPluginKey(pluginKeyNew) - .setStatus(IotPluginStatusEnum.STOPPED.getStatus()) // TODO @haohao:这个状态,是不是非 stop 哈? - .setFileName(file.getOriginalFilename()) - .setScript("") // TODO @haohao:这个设置为 "" 会不会覆盖数据里的哈?应该从插件里读取?未来? - .setConfigSchema(springPluginManager.getPlugin(pluginKeyNew).getDescriptor().getPluginDescription()) - .setVersion(springPluginManager.getPlugin(pluginKeyNew).getDescriptor().getVersion()) - .setDescription(springPluginManager.getPlugin(pluginKeyNew).getDescriptor().getPluginDescription()); - pluginInfoMapper.updateById(updatedPluginInfo); - } - - @Override - public void updatePluginStatus(Long id, Integer status) { - // 1. 校验插件信息是否存在 - IotPluginInfoDO pluginInfoDo = validatePluginInfoExists(id); - - // 2. 更新插件状态 - pluginInstanceService.updatePluginStatus(pluginInfoDo, status); - - // 3. 更新数据库中的插件状态 - pluginInfoMapper.updateById(new IotPluginInfoDO().setId(id).setStatus(status)); - } - - @Override - public List getPluginInfoList() { - return pluginInfoMapper.selectList(); - } - - @Override - public List getPluginInfoListByStatus(Integer status) { - return pluginInfoMapper.selectListByStatus(status); - } - - @Override - public IotPluginInfoDO getPluginInfoByPluginKey(String pluginKey) { - return pluginInfoMapper.selectByPluginKey(pluginKey); - } - -} \ 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/plugin/IotPluginInstanceService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/plugin/IotPluginInstanceService.java index 1e48070806..56e1bf0f08 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/plugin/IotPluginInstanceService.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/plugin/IotPluginInstanceService.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.iot.service.plugin; import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.IotPluginInstanceHeartbeatReqDTO; -import cn.iocoder.yudao.module.iot.dal.dataobject.plugin.IotPluginInfoDO; +import cn.iocoder.yudao.module.iot.dal.dataobject.plugin.IotPluginConfigDO; import cn.iocoder.yudao.module.iot.dal.dataobject.plugin.IotPluginInstanceDO; import org.springframework.web.multipart.MultipartFile; @@ -38,9 +38,9 @@ public interface IotPluginInstanceService { /** * 删除插件文件 * - * @param pluginInfoDo 插件信息 + * @param pluginConfigDO 插件配置 */ - void deletePluginFile(IotPluginInfoDO pluginInfoDo); + void deletePluginFile(IotPluginConfigDO pluginConfigDO); /** * 上传并加载新的插件文件 @@ -53,10 +53,10 @@ public interface IotPluginInstanceService { /** * 更新插件状态 * - * @param pluginInfoDo 插件信息 + * @param pluginConfigDO 插件配置 * @param status 新状态 */ - void updatePluginStatus(IotPluginInfoDO pluginInfoDo, Integer status); + void updatePluginStatus(IotPluginConfigDO pluginConfigDO, Integer status); // ========== 设备与插件的映射操作 ========== diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/plugin/IotPluginInstanceServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/plugin/IotPluginInstanceServiceImpl.java index 6742eccd79..a3edbc1757 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/plugin/IotPluginInstanceServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/plugin/IotPluginInstanceServiceImpl.java @@ -4,7 +4,7 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.io.FileUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.IotPluginInstanceHeartbeatReqDTO; -import cn.iocoder.yudao.module.iot.dal.dataobject.plugin.IotPluginInfoDO; +import cn.iocoder.yudao.module.iot.dal.dataobject.plugin.IotPluginConfigDO; import cn.iocoder.yudao.module.iot.dal.dataobject.plugin.IotPluginInstanceDO; import cn.iocoder.yudao.module.iot.dal.mysql.plugin.IotPluginInstanceMapper; import cn.iocoder.yudao.module.iot.dal.redis.plugin.DevicePluginProcessIdRedisDAO; @@ -45,7 +45,7 @@ public class IotPluginInstanceServiceImpl implements IotPluginInstanceService { @Resource @Lazy // 延迟加载,避免循环依赖 - private IotPluginInfoService pluginInfoService; + private IotPluginConfigService pluginConfigService; @Resource private IotPluginInstanceMapper pluginInstanceMapper; @@ -79,7 +79,7 @@ public class IotPluginInstanceServiceImpl implements IotPluginInstanceService { } // 情况二:不存在,则创建 - IotPluginInfoDO info = pluginInfoService.getPluginInfoByPluginKey(heartbeatReqDTO.getPluginKey()); + IotPluginConfigDO info = pluginConfigService.getPluginConfigByPluginKey(heartbeatReqDTO.getPluginKey()); if (info == null) { log.error("[heartbeatPluginInstance][心跳({}) 对应的插件不存在]", heartbeatReqDTO); return; @@ -129,18 +129,18 @@ public class IotPluginInstanceServiceImpl implements IotPluginInstanceService { } @Override - public void deletePluginFile(IotPluginInfoDO pluginInfoDO) { - File file = new File(pluginsDir, pluginInfoDO.getFileName()); + public void deletePluginFile(IotPluginConfigDO pluginConfigDO) { + File file = new File(pluginsDir, pluginConfigDO.getFileName()); if (!file.exists()) { return; } try { TimeUnit.SECONDS.sleep(1); // 等待 1 秒,避免插件未卸载完毕 if (!file.delete()) { - log.error("[deletePluginInfo][删除插件文件({}) 失败]", pluginInfoDO.getFileName()); + log.error("[deletePluginFile][删除插件文件({}) 失败]", pluginConfigDO.getFileName()); } } catch (InterruptedException e) { - log.error("[deletePluginInfo][删除插件文件({}) 失败]", pluginInfoDO.getFileName(), e); + log.error("[deletePluginFile][删除插件文件({}) 失败]", pluginConfigDO.getFileName(), e); } } @@ -171,13 +171,13 @@ public class IotPluginInstanceServiceImpl implements IotPluginInstanceService { } @Override - public void updatePluginStatus(IotPluginInfoDO pluginInfoDo, Integer status) { - String pluginKey = pluginInfoDo.getPluginKey(); + public void updatePluginStatus(IotPluginConfigDO pluginConfigDO, Integer status) { + String pluginKey = pluginConfigDO.getPluginKey(); PluginWrapper plugin = pluginManager.getPlugin(pluginKey); if (plugin == null) { // 插件不存在且状态为停止,抛出异常 - if (IotPluginStatusEnum.STOPPED.getStatus().equals(pluginInfoDo.getStatus())) { + if (IotPluginStatusEnum.STOPPED.getStatus().equals(pluginConfigDO.getStatus())) { throw exception(ErrorCodeConstants.PLUGIN_STATUS_INVALID); } return; diff --git a/yudao-server/pom.xml b/yudao-server/pom.xml index efd53c84a5..492e31db56 100644 --- a/yudao-server/pom.xml +++ b/yudao-server/pom.xml @@ -109,11 +109,11 @@ - - - - - + + cn.iocoder.boot + yudao-module-iot-biz + ${revision} +