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
index 7d9472d249..9b78001595 100644
--- 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
@@ -78,6 +78,7 @@ public class PluginInfoController {
return success(true);
}
+ // TODO @haohao:要不独立一个 VO,不用 PluginInfoSaveReqVO
@PutMapping("/update-status")
@Operation(summary = "修改插件状态")
@PreAuthorize("@ss.hasPermission('iot:plugin-info:update')")
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/info/PluginInfoSaveReqVO.java
index e6453b4570..c2a16ac496 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/info/PluginInfoSaveReqVO.java
@@ -13,7 +13,7 @@ public class PluginInfoSaveReqVO {
// TODO @haohao:一些枚举字段,需要加枚举校验。例如说,deployType、status、type 等
- @Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "11546")
+ @Schema(description = "主键编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11546")
private Long id;
@Schema(description = "插件包标识符", requiredMode = Schema.RequiredMode.REQUIRED, example = "24627")
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/IotPluginInfoDO.java
index f55a9f5ba4..3a9c588d4a 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/IotPluginInfoDO.java
@@ -9,6 +9,7 @@ import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
+// TODO @haohao:建议 IotPluginInfoDO 改成 IotPluginConfigDO,插件配置。项目里,暂时没有用 info 作为配置的哈。
/**
* IoT 插件信息 DO
*
@@ -38,7 +39,7 @@ public class IotPluginInfoDO extends BaseDO {
*/
private String name;
/**
- * 描述
+ * 插件描述
*/
private String description;
/**
@@ -68,12 +69,14 @@ public class IotPluginInfoDO extends BaseDO {
*/
// TODO @芋艿:枚举字段
private String protocol;
+ // TODO @haohao:这个字段,是不是直接用 CommonStatus,开启、禁用;然后插件实例那,online 是否在线
/**
* 状态
*
* 枚举 {@link IotPluginStatusEnum}
*/
private Integer status;
+
// TODO @芋艿:configSchema、config 示例字段
/**
* 插件配置项描述信息
@@ -83,6 +86,7 @@ public class IotPluginInfoDO extends BaseDO {
* 插件配置信息
*/
private String config;
+
// TODO @芋艿:script 后续的使用
/**
* 插件脚本
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/plugin/config/UnifiedConfiguration.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/plugin/config/IotPluginConfiguration.java
similarity index 52%
rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/plugin/config/UnifiedConfiguration.java
rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/plugin/config/IotPluginConfiguration.java
index 849b6b16ff..b695cbe39f 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/plugin/config/UnifiedConfiguration.java
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/plugin/config/IotPluginConfiguration.java
@@ -1,6 +1,8 @@
package cn.iocoder.yudao.module.iot.framework.plugin.config;
-import cn.iocoder.yudao.module.iot.framework.plugin.core.CustomPluginStateListener;
+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 lombok.extern.slf4j.Slf4j;
import org.pf4j.spring.SpringPluginManager;
import org.springframework.beans.factory.annotation.Value;
@@ -9,16 +11,24 @@ import org.springframework.context.annotation.Configuration;
import java.nio.file.Paths;
-// TODO @芋艿:需要 review 下
-@Slf4j
+/**
+ * IoT 插件配置类
+ *
+ * @author haohao
+ */
@Configuration
-public class UnifiedConfiguration {
-
- @Value("${pf4j.pluginsDir:pluginsDir}")
- private String pluginsDir;
+@Slf4j
+public class IotPluginConfiguration {
@Bean
- public SpringPluginManager pluginManager() {
+ public IotPluginStartRunner pluginStartRunner(SpringPluginManager pluginManager,
+ IotPluginInfoService pluginInfoService) {
+ return new IotPluginStartRunner(pluginManager, pluginInfoService);
+ }
+
+ // TODO @芋艿:需要 review 下
+ @Bean
+ public SpringPluginManager pluginManager(@Value("${pf4j.pluginsDir:pluginsDir}") String pluginsDir) {
log.info("[init][实例化 SpringPluginManager]");
SpringPluginManager springPluginManager = new SpringPluginManager(Paths.get(pluginsDir)) {
// SpringPluginManager springPluginManager = new SpringPluginManager() {
@@ -30,7 +40,7 @@ public class UnifiedConfiguration {
}
};
- springPluginManager.addPluginStateListener(new CustomPluginStateListener());
+ springPluginManager.addPluginStateListener(new IotPluginStateListener());
return springPluginManager;
}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/plugin/core/CustomPluginStateListener.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/plugin/core/CustomPluginStateListener.java
deleted file mode 100644
index 9833a815b6..0000000000
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/plugin/core/CustomPluginStateListener.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package cn.iocoder.yudao.module.iot.framework.plugin.core;
-
-import lombok.extern.slf4j.Slf4j;
-import org.pf4j.PluginStateEvent;
-import org.pf4j.PluginStateListener;
-import org.springframework.stereotype.Component;
-
-// TODO @芋艿:需要 review 下
-@Component
-@Slf4j
-public class CustomPluginStateListener implements PluginStateListener {
-
- @Override
- public void pluginStateChanged(PluginStateEvent event) {
- // 1. 获取插件ID
- String pluginId = event.getPlugin().getPluginId();
- // 2. 获取插件旧状态
- String oldState = event.getOldState().toString();
- // 3. 获取插件新状态
- String newState = event.getPluginState().toString();
- // 4. 打印日志信息
- log.info("插件的状态 '{}' 已更改为 '{}' 至 '{}'", pluginId, oldState, newState);
- }
-
-}
\ 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/core/IotPluginStartRunner.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/plugin/core/IotPluginStartRunner.java
new file mode 100644
index 0000000000..f3654bc305
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/plugin/core/IotPluginStartRunner.java
@@ -0,0 +1,52 @@
+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.enums.plugin.IotPluginDeployTypeEnum;
+import cn.iocoder.yudao.module.iot.enums.plugin.IotPluginStatusEnum;
+import cn.iocoder.yudao.module.iot.service.plugin.IotPluginInfoService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.pf4j.spring.SpringPluginManager;
+import org.springframework.boot.ApplicationArguments;
+import org.springframework.boot.ApplicationRunner;
+
+import java.util.List;
+
+/**
+ * IoT 插件启动 Runner
+ *
+ * 用于 Spring Boot 启动时,启动 {@link IotPluginDeployTypeEnum#JAR} 部署类型的插件
+ */
+@RequiredArgsConstructor
+@Slf4j
+public class IotPluginStartRunner implements ApplicationRunner {
+
+ private final SpringPluginManager springPluginManager;
+
+ private final IotPluginInfoService pluginInfoService;
+
+ @Override
+ public void run(ApplicationArguments args) {
+ List pluginInfoList = TenantUtils.executeIgnore(
+ // TODO @haohao:需要查询部署类型哈
+ () -> pluginInfoService.getPluginInfoListByStatus(IotPluginStatusEnum.RUNNING.getStatus()));
+ if (CollUtil.isEmpty(pluginInfoList)) {
+ log.info("[run][没有需要启动的插件]");
+ return;
+ }
+
+ // 遍历插件列表,逐个启动
+ pluginInfoList.forEach(pluginInfo -> {
+ try {
+ log.info("[run][插件({}) 启动开始]", pluginInfo.getPluginKey());
+ springPluginManager.startPlugin(pluginInfo.getPluginKey());
+ log.info("[run][插件({}) 启动完成]", pluginInfo.getPluginKey());
+ } catch (Exception e) {
+ log.error("[run][插件({}) 启动异常]", pluginInfo.getPluginKey(), e);
+ }
+ });
+ }
+
+}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/plugin/core/IotPluginStateListener.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/plugin/core/IotPluginStateListener.java
new file mode 100644
index 0000000000..bbc73c619e
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/plugin/core/IotPluginStateListener.java
@@ -0,0 +1,21 @@
+package cn.iocoder.yudao.module.iot.framework.plugin.core;
+
+import lombok.extern.slf4j.Slf4j;
+import org.pf4j.PluginStateEvent;
+import org.pf4j.PluginStateListener;
+
+/**
+ * IoT 插件状态监听器,用于 log 插件的状态变化
+ *
+ * @author haohao
+ */
+@Slf4j
+public class IotPluginStateListener implements PluginStateListener {
+
+ @Override
+ public void pluginStateChanged(PluginStateEvent event) {
+ log.info("[pluginStateChanged][插件({}) 状态变化,从 {} 变为 {}]", event.getPlugin().getPluginId(),
+ event.getOldState().toString(), event.getPluginState().toString());
+ }
+
+}
\ 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/core/PluginStart.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/plugin/core/PluginStart.java
deleted file mode 100644
index 76b0fa67bd..0000000000
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/plugin/core/PluginStart.java
+++ /dev/null
@@ -1,49 +0,0 @@
-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.enums.plugin.IotPluginStatusEnum;
-import cn.iocoder.yudao.module.iot.service.plugin.IotPluginInfoService;
-import lombok.extern.slf4j.Slf4j;
-import org.pf4j.spring.SpringPluginManager;
-import org.springframework.boot.ApplicationArguments;
-import org.springframework.boot.ApplicationRunner;
-import org.springframework.stereotype.Component;
-
-import javax.annotation.Resource;
-import java.util.List;
-
-// TODO @芋艿:需要 review 下
-@Component
-@Slf4j
-public class PluginStart implements ApplicationRunner {
-
- @Resource
- private IotPluginInfoService pluginInfoService;
-
- @Resource
- private SpringPluginManager pluginManager;
-
- @Override
- public void run(ApplicationArguments args) {
- TenantUtils.executeIgnore(() -> { // 1. 忽略租户上下文执行
- List pluginInfoList = pluginInfoService
- .getPluginInfoListByStatus(IotPluginStatusEnum.RUNNING.getStatus()); // 2. 获取运行中的插件列表
- if (CollUtil.isEmpty(pluginInfoList)) { // 3. 检查插件列表是否为空
- log.info("[run] 没有需要启动的插件"); // 4. 日志记录没有插件需要启动
- return;
- }
- pluginInfoList.forEach(pluginInfo -> { // 5. 使用lambda表达式遍历插件列表
- try {
- log.info("[run][启动插件] pluginKey = {}", pluginInfo.getPluginKey()); // 6. 日志记录插件启动信息
- pluginManager.startPlugin(pluginInfo.getPluginKey()); // 7. 启动插件
- } catch (Exception e) {
- log.error("[run][启动插件失败] pluginKey = {}", pluginInfo.getPluginKey(), e); // 8. 记录启动失败的日志
- }
- });
- });
-
- }
-
-}
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
index 3ac8680b8d..1a8654ebc6 100644
--- 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
@@ -14,7 +14,7 @@ import java.util.List;
/**
* IoT 插件信息 Service 接口
*
- * @author 芋道源码
+ * @author haohao
*/
public interface IotPluginInfoService {
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
index c111da3267..400f1e39ea 100644
--- 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
@@ -23,7 +23,7 @@ import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.PLUGIN_INFO_N
/**
* IoT 插件信息 Service 实现类
*
- * @author 芋道源码
+ * @author haohao
*/
@Service
@Validated
@@ -37,7 +37,7 @@ public class IotPluginInfoServiceImpl implements IotPluginInfoService {
private IotPluginInstanceService pluginInstanceService;
@Resource
- private SpringPluginManager pluginManager;
+ private SpringPluginManager springPluginManager;
@Override
public Long createPluginInfo(PluginInfoSaveReqVO createReqVO) {
@@ -60,18 +60,17 @@ public class IotPluginInfoServiceImpl implements IotPluginInfoService {
public void deletePluginInfo(Long id) {
// 1.1 校验存在
IotPluginInfoDO pluginInfoDO = validatePluginInfoExists(id);
- // 1.2 停止插件
+ // 1.2 未开启状态,才允许删除
if (IotPluginStatusEnum.RUNNING.getStatus().equals(pluginInfoDO.getStatus())) {
throw exception(PLUGIN_INFO_DELETE_FAILED_RUNNING);
}
- // 2. 卸载插件
+ // 2.1 卸载插件
pluginInstanceService.stopAndUnloadPlugin(pluginInfoDO.getPluginKey());
-
- // 3. 删除插件文件
+ // 2.2 删除插件文件
pluginInstanceService.deletePluginFile(pluginInfoDO);
- // 4. 删除插件信息
+ // 3. 删除插件信息
pluginInfoMapper.deleteById(id);
}
@@ -97,17 +96,18 @@ public class IotPluginInfoServiceImpl implements IotPluginInfoService {
public void uploadFile(Long id, MultipartFile file) {
// 1. 校验插件信息是否存在
IotPluginInfoDO pluginInfoDo = validatePluginInfoExists(id);
+ // TODO @haohao:最好校验下 file 相关参数,是否完整,类似:version 之类是不是可以解析到
- // 2. 停止并卸载旧的插件
+ // 2.1 停止并卸载旧的插件
pluginInstanceService.stopAndUnloadPlugin(pluginInfoDo.getPluginKey());
-
- // 3 上传新的插件文件,更新插件启用状态文件
+ // 2.2 上传新的插件文件,更新插件启用状态文件
String pluginKeyNew = pluginInstanceService.uploadAndLoadNewPlugin(file);
- // 4. 更新插件信息
+ // 3. 更新插件信息
updatePluginInfo(pluginInfoDo, pluginKeyNew, file);
}
+ // TODO @haohao:这个方法,要不合并到 uploadFile 里;
/**
* 更新插件信息
*
@@ -116,18 +116,15 @@ public class IotPluginInfoServiceImpl implements IotPluginInfoService {
* @param file 文件
*/
private void updatePluginInfo(IotPluginInfoDO pluginInfoDo, String pluginKeyNew, MultipartFile file) {
- // 创建新的插件信息对象并链式设置属性
IotPluginInfoDO updatedPluginInfo = new IotPluginInfoDO()
.setId(pluginInfoDo.getId())
.setPluginKey(pluginKeyNew)
- .setStatus(IotPluginStatusEnum.STOPPED.getStatus())
+ .setStatus(IotPluginStatusEnum.STOPPED.getStatus()) // TODO @haohao:这个状态,是不是非 stop 哈?
.setFileName(file.getOriginalFilename())
- .setScript("")
- .setConfigSchema(pluginManager.getPlugin(pluginKeyNew).getDescriptor().getPluginDescription())
- .setVersion(pluginManager.getPlugin(pluginKeyNew).getDescriptor().getVersion())
- .setDescription(pluginManager.getPlugin(pluginKeyNew).getDescriptor().getPluginDescription());
-
- // 执行更新
+ .setScript("") // TODO @haohao:这个设置为 "" 会不会覆盖数据里的哈?应该从插件里读取?未来?
+ .setConfigSchema(springPluginManager.getPlugin(pluginKeyNew).getDescriptor().getPluginDescription())
+ .setVersion(springPluginManager.getPlugin(pluginKeyNew).getDescriptor().getVersion())
+ .setDescription(springPluginManager.getPlugin(pluginKeyNew).getDescriptor().getPluginDescription());
pluginInfoMapper.updateById(updatedPluginInfo);
}
@@ -140,10 +137,7 @@ public class IotPluginInfoServiceImpl implements IotPluginInfoService {
pluginInstanceService.updatePluginStatus(pluginInfoDo, status);
// 3. 更新数据库中的插件状态
- IotPluginInfoDO updatedPluginInfo = new IotPluginInfoDO();
- updatedPluginInfo.setId(id);
- updatedPluginInfo.setStatus(status);
- pluginInfoMapper.updateById(updatedPluginInfo);
+ pluginInfoMapper.updateById(new IotPluginInfoDO().setId(id).setStatus(status));
}
@Override
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 7f8ff51f10..2219d4bad1 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
@@ -404,7 +404,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
// 无 + 禁用、开启:1)存在,删除;TODO 测试:直接删除???(结论:可以)deleteJob
//
- if (true) {
+ if (false) {
Long id = 1L;
Map jobDataMap = IotRuleSceneJob.buildJobDataMap(id);
schedulerManager.addOrUpdateJob(IotRuleSceneJob.class,
@@ -417,7 +417,8 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
schedulerManager.pauseJob(IotRuleSceneJob.buildJobName(id));
}
if (true) {
-
+ Long id = 1L;
+ schedulerManager.deleteJob(IotRuleSceneJob.buildJobName(id));
}
}