Commit dc1f9338f153d2351d3c473d08a582c00842745b
1 parent
24a660b5
【功能完善】IoT: 添加 MQTT 插件支持,重构插件管理,新增获取运行状态插件信息接口,优化插件信息存储逻辑,移除不必要的 Spring 注解。
Showing
14 changed files
with
272 additions
and
18 deletions
plugins/enabled.txt
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/plugin/PluginInfoMapper.java
| ... | ... | @@ -4,6 +4,9 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | 4 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; |
| 5 | 5 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| 6 | 6 | import cn.iocoder.yudao.module.iot.dal.dataobject.plugininfo.PluginInfoDO; |
| 7 | + | |
| 8 | +import java.util.List; | |
| 9 | + | |
| 7 | 10 | import org.apache.ibatis.annotations.Mapper; |
| 8 | 11 | import cn.iocoder.yudao.module.iot.controller.admin.plugin.vo.*; |
| 9 | 12 | |
| ... | ... | @@ -22,4 +25,10 @@ public interface PluginInfoMapper extends BaseMapperX<PluginInfoDO> { |
| 22 | 25 | .orderByDesc(PluginInfoDO::getId)); |
| 23 | 26 | } |
| 24 | 27 | |
| 28 | + default List<PluginInfoDO> selectListByStatus(Integer status) { | |
| 29 | + return selectList(new LambdaQueryWrapperX<PluginInfoDO>() | |
| 30 | + .eq(PluginInfoDO::getStatus, status) | |
| 31 | + .orderByAsc(PluginInfoDO::getId)); | |
| 32 | + } | |
| 33 | + | |
| 25 | 34 | } |
| 26 | 35 | \ No newline at end of file | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/emq/callback/EmqxCallback.java
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/emq/client/EmqxClient.java
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/emq/config/MqttConfig.java
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/emq/service/EmqxServiceImpl.java
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/emq/start/EmqxStart.java
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/plugin/PluginInfoService.java
| ... | ... | @@ -76,4 +76,11 @@ public interface PluginInfoService { |
| 76 | 76 | * @return 插件信息列表 |
| 77 | 77 | */ |
| 78 | 78 | List<PluginInfoDO> getPluginInfoList(); |
| 79 | -} | |
| 80 | 79 | \ No newline at end of file |
| 80 | + | |
| 81 | + /** | |
| 82 | + * 获得运行状态的插件信息列表 | |
| 83 | + * | |
| 84 | + * @return 运行状态的插件信息列表 | |
| 85 | + */ | |
| 86 | + List<PluginInfoDO> getRunningPluginInfoList(); | |
| 87 | +} | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/plugin/PluginInfoServiceImpl.java
| ... | ... | @@ -18,6 +18,7 @@ import org.springframework.stereotype.Service; |
| 18 | 18 | import org.springframework.validation.annotation.Validated; |
| 19 | 19 | import org.springframework.web.multipart.MultipartFile; |
| 20 | 20 | |
| 21 | +import javax.annotation.PostConstruct; | |
| 21 | 22 | import java.io.File; |
| 22 | 23 | import java.io.IOException; |
| 23 | 24 | import java.nio.file.*; |
| ... | ... | @@ -186,20 +187,19 @@ public class PluginInfoServiceImpl implements PluginInfoService { |
| 186 | 187 | if (pluginWrapper == null) { |
| 187 | 188 | throw exception(PLUGIN_INSTALL_FAILED); |
| 188 | 189 | } |
| 189 | - String pluginInfo = pluginKeyNew + "@" + pluginWrapper.getDescriptor().getVersion(); | |
| 190 | 190 | List<String> targetLines = Files.exists(targetFilePath) ? Files.readAllLines(targetFilePath) |
| 191 | 191 | : new ArrayList<>(); |
| 192 | 192 | List<String> oppositeLines = Files.exists(oppositeFilePath) ? Files.readAllLines(oppositeFilePath) |
| 193 | 193 | : new ArrayList<>(); |
| 194 | 194 | |
| 195 | - if (!targetLines.contains(pluginInfo)) { | |
| 196 | - targetLines.add(pluginInfo); | |
| 195 | + if (!targetLines.contains(pluginKeyNew)) { | |
| 196 | + targetLines.add(pluginKeyNew); | |
| 197 | 197 | Files.write(targetFilePath, targetLines, StandardOpenOption.CREATE, |
| 198 | 198 | StandardOpenOption.TRUNCATE_EXISTING); |
| 199 | 199 | } |
| 200 | 200 | |
| 201 | - if (oppositeLines.contains(pluginInfo)) { | |
| 202 | - oppositeLines.remove(pluginInfo); | |
| 201 | + if (oppositeLines.contains(pluginKeyNew)) { | |
| 202 | + oppositeLines.remove(pluginKeyNew); | |
| 203 | 203 | Files.write(oppositeFilePath, oppositeLines, StandardOpenOption.CREATE, |
| 204 | 204 | StandardOpenOption.TRUNCATE_EXISTING); |
| 205 | 205 | } |
| ... | ... | @@ -267,4 +267,8 @@ public class PluginInfoServiceImpl implements PluginInfoService { |
| 267 | 267 | return pluginInfoMapper.selectList(null); |
| 268 | 268 | } |
| 269 | 269 | |
| 270 | + @Override | |
| 271 | + public List<PluginInfoDO> getRunningPluginInfoList() { | |
| 272 | + return pluginInfoMapper.selectListByStatus(IotPluginStatusEnum.RUNNING.getStatus()); | |
| 273 | + } | |
| 270 | 274 | } |
| 271 | 275 | \ No newline at end of file | ... | ... |
yudao-module-iot/yudao-module-iot-plugin/pom.xml
| ... | ... | @@ -2,11 +2,6 @@ |
| 2 | 2 | <project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
| 3 | 3 | xmlns="http://maven.apache.org/POM/4.0.0" |
| 4 | 4 | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
| 5 | -<!-- <modelVersion>4.0.0</modelVersion>--> | |
| 6 | -<!-- <groupId>cn.iocoder.boot</groupId>--> | |
| 7 | -<!-- <artifactId>yudao-module-iot-plugin</artifactId>--> | |
| 8 | -<!-- <version>0.0.1</version>--> | |
| 9 | -<!-- <packaging>pom</packaging>--> | |
| 10 | 5 | <parent> |
| 11 | 6 | <artifactId>yudao-module-iot</artifactId> |
| 12 | 7 | <groupId>cn.iocoder.boot</groupId> |
| ... | ... | @@ -15,6 +10,7 @@ |
| 15 | 10 | <modules> |
| 16 | 11 | <module>yudao-module-iot-demo-plugin</module> |
| 17 | 12 | <module>yudao-module-iot-http-plugin</module> |
| 13 | + <module>yudao-module-iot-mqtt-plugin</module> | |
| 18 | 14 | </modules> |
| 19 | 15 | |
| 20 | 16 | <modelVersion>4.0.0</modelVersion> | ... | ... |
yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-mqtt-plugin/plugin.properties
0 → 100644
yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-mqtt-plugin/pom.xml
0 → 100644
| 1 | +<?xml version="1.0" encoding="UTF-8"?> | |
| 2 | +<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
| 3 | + xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation=" | |
| 4 | + http://maven.apache.org/POM/4.0.0 | |
| 5 | + http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |
| 6 | + <parent> | |
| 7 | + <artifactId>yudao-module-iot-plugin</artifactId> | |
| 8 | + <groupId>cn.iocoder.boot</groupId> | |
| 9 | + <version>${revision}</version> | |
| 10 | + </parent> | |
| 11 | + <modelVersion>4.0.0</modelVersion> | |
| 12 | + <packaging>jar</packaging> | |
| 13 | + | |
| 14 | + <artifactId>yudao-module-iot-mqtt-plugin</artifactId> | |
| 15 | + | |
| 16 | + <name>${project.artifactId}</name> | |
| 17 | + <description> | |
| 18 | + 物联网 插件模块 - mqtt 插件 | |
| 19 | + </description> | |
| 20 | + | |
| 21 | + <properties> | |
| 22 | + <!-- 插件相关 --> | |
| 23 | + <plugin.id>mqtt-plugin</plugin.id> | |
| 24 | + <plugin.class>cn.iocoder.yudao.module.iot.plugin.MqttPlugin</plugin.class> | |
| 25 | + <plugin.version>0.0.1</plugin.version> | |
| 26 | + <plugin.provider>ahh</plugin.provider> | |
| 27 | + <plugin.description>mqtt-plugin-0.0.1</plugin.description> | |
| 28 | + <plugin.dependencies/> | |
| 29 | + </properties> | |
| 30 | + | |
| 31 | + <build> | |
| 32 | + <plugins> | |
| 33 | + <!-- DOESN'T WORK WITH MAVEN 3 (I defined the plugin metadata in properties section) | |
| 34 | + <plugin> | |
| 35 | + <groupId>org.codehaus.mojo</groupId> | |
| 36 | + <artifactId>properties-maven-plugin</artifactId> | |
| 37 | + <version>1.0-alpha-2</version> | |
| 38 | + <executions> | |
| 39 | + <execution> | |
| 40 | + <phase>initialize</phase> | |
| 41 | + <goals> | |
| 42 | + <goal>read-project-properties</goal> | |
| 43 | + </goals> | |
| 44 | + <configuration> | |
| 45 | + <files> | |
| 46 | + <file>plugin.properties</file> | |
| 47 | + </files> | |
| 48 | + </configuration> | |
| 49 | + </execution> | |
| 50 | + </executions> | |
| 51 | + </plugin> | |
| 52 | + --> | |
| 53 | + | |
| 54 | + <plugin> | |
| 55 | + <groupId>org.apache.maven.plugins</groupId> | |
| 56 | + <artifactId>maven-antrun-plugin</artifactId> | |
| 57 | + <version>1.6</version> | |
| 58 | + <executions> | |
| 59 | + <execution> | |
| 60 | + <id>unzip jar file</id> | |
| 61 | + <phase>package</phase> | |
| 62 | + <configuration> | |
| 63 | + <target> | |
| 64 | + <unzip src="target/${project.artifactId}-${project.version}.${project.packaging}" | |
| 65 | + dest="target/plugin-classes"/> | |
| 66 | + </target> | |
| 67 | + </configuration> | |
| 68 | + <goals> | |
| 69 | + <goal>run</goal> | |
| 70 | + </goals> | |
| 71 | + </execution> | |
| 72 | + </executions> | |
| 73 | + </plugin> | |
| 74 | + | |
| 75 | + <plugin> | |
| 76 | + <artifactId>maven-assembly-plugin</artifactId> | |
| 77 | + <version>2.3</version> | |
| 78 | + <configuration> | |
| 79 | + <descriptors> | |
| 80 | + <descriptor> | |
| 81 | + src/main/assembly/assembly.xml | |
| 82 | + </descriptor> | |
| 83 | + </descriptors> | |
| 84 | + <appendAssemblyId>false</appendAssemblyId> | |
| 85 | + </configuration> | |
| 86 | + <executions> | |
| 87 | + <execution> | |
| 88 | + <id>make-assembly</id> | |
| 89 | + <phase>package</phase> | |
| 90 | + <goals> | |
| 91 | + <goal>attached</goal> | |
| 92 | + </goals> | |
| 93 | + </execution> | |
| 94 | + </executions> | |
| 95 | + </plugin> | |
| 96 | + | |
| 97 | + <plugin> | |
| 98 | + <groupId>org.apache.maven.plugins</groupId> | |
| 99 | + <artifactId>maven-jar-plugin</artifactId> | |
| 100 | + <version>2.4</version> | |
| 101 | + <configuration> | |
| 102 | + <archive> | |
| 103 | + <manifestEntries> | |
| 104 | + <Plugin-Id>${plugin.id}</Plugin-Id> | |
| 105 | + <Plugin-Class>${plugin.class}</Plugin-Class> | |
| 106 | + <Plugin-Version>${plugin.version}</Plugin-Version> | |
| 107 | + <Plugin-Provider>${plugin.provider}</Plugin-Provider> | |
| 108 | + <Plugin-Description>${plugin.description}</Plugin-Description> | |
| 109 | + <Plugin-Dependencies>${plugin.dependencies}</Plugin-Dependencies> | |
| 110 | + </manifestEntries> | |
| 111 | + </archive> | |
| 112 | + </configuration> | |
| 113 | + </plugin> | |
| 114 | + | |
| 115 | + <plugin> | |
| 116 | + <artifactId>maven-deploy-plugin</artifactId> | |
| 117 | + <configuration> | |
| 118 | + <skip>true</skip> | |
| 119 | + </configuration> | |
| 120 | + </plugin> | |
| 121 | + </plugins> | |
| 122 | + </build> | |
| 123 | + | |
| 124 | + <dependencies> | |
| 125 | + <!-- 其他依赖项 --> | |
| 126 | + <dependency> | |
| 127 | + <groupId>org.springframework.boot</groupId> | |
| 128 | + <artifactId>spring-boot-starter-web</artifactId> | |
| 129 | + </dependency> | |
| 130 | + <!-- PF4J Spring 集成 --> | |
| 131 | + <dependency> | |
| 132 | + <groupId>org.pf4j</groupId> | |
| 133 | + <artifactId>pf4j-spring</artifactId> | |
| 134 | + <scope>provided</scope> | |
| 135 | + </dependency> | |
| 136 | + <!-- 项目依赖 --> | |
| 137 | + <dependency> | |
| 138 | + <groupId>cn.iocoder.boot</groupId> | |
| 139 | + <artifactId>yudao-module-iot-api</artifactId> | |
| 140 | + <version>${revision}</version> | |
| 141 | + </dependency> | |
| 142 | + <dependency> | |
| 143 | + <groupId>org.projectlombok</groupId> | |
| 144 | + <artifactId>lombok</artifactId> | |
| 145 | + <version>${lombok.version}</version> | |
| 146 | + <scope>provided</scope> | |
| 147 | + </dependency> | |
| 148 | + <dependency> | |
| 149 | + <groupId>io.netty</groupId> | |
| 150 | + <artifactId>netty-all</artifactId> | |
| 151 | + <version>4.1.63.Final</version> <!-- 版本可根据需要调整 --> | |
| 152 | + </dependency> | |
| 153 | + </dependencies> | |
| 154 | +</project> | |
| 0 | 155 | \ No newline at end of file | ... | ... |
yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-mqtt-plugin/src/main/assembly/assembly.xml
0 → 100644
| 1 | +<assembly> | |
| 2 | + <id>plugin</id> | |
| 3 | + <formats> | |
| 4 | + <format>zip</format> | |
| 5 | + </formats> | |
| 6 | + <includeBaseDirectory>false</includeBaseDirectory> | |
| 7 | + <dependencySets> | |
| 8 | + <dependencySet> | |
| 9 | + <useProjectArtifact>false</useProjectArtifact> | |
| 10 | + <scope>runtime</scope> | |
| 11 | + <outputDirectory>lib</outputDirectory> | |
| 12 | + <includes> | |
| 13 | + <include>*:jar:*</include> | |
| 14 | + </includes> | |
| 15 | + </dependencySet> | |
| 16 | + </dependencySets> | |
| 17 | + <!-- | |
| 18 | + <fileSets> | |
| 19 | + <fileSet> | |
| 20 | + <directory>target/classes</directory> | |
| 21 | + <outputDirectory>classes</outputDirectory> | |
| 22 | + </fileSet> | |
| 23 | + </fileSets> | |
| 24 | + --> | |
| 25 | + <fileSets> | |
| 26 | + <fileSet> | |
| 27 | + <directory>target/plugin-classes</directory> | |
| 28 | + <outputDirectory>classes</outputDirectory> | |
| 29 | + </fileSet> | |
| 30 | + </fileSets> | |
| 31 | +</assembly> | ... | ... |
yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-mqtt-plugin/src/main/java/cn/iocoder/yudao/module/iot/plugin/MqttPlugin.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.iot.plugin; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.module.iot.api.device.DeviceDataApi; | |
| 4 | +import cn.iocoder.yudao.module.iot.api.ServiceRegistry; | |
| 5 | +import lombok.extern.slf4j.Slf4j; | |
| 6 | +import org.pf4j.PluginWrapper; | |
| 7 | +import org.pf4j.Plugin; | |
| 8 | + | |
| 9 | +import java.util.concurrent.ExecutorService; | |
| 10 | +import java.util.concurrent.Executors; | |
| 11 | + | |
| 12 | +@Slf4j | |
| 13 | +public class MqttPlugin extends Plugin { | |
| 14 | + | |
| 15 | + private ExecutorService executorService; | |
| 16 | + private DeviceDataApi deviceDataApi; | |
| 17 | + | |
| 18 | + public MqttPlugin(PluginWrapper wrapper) { | |
| 19 | + super(wrapper); | |
| 20 | + // 初始化线程池 | |
| 21 | + this.executorService = Executors.newSingleThreadExecutor(); | |
| 22 | + } | |
| 23 | + | |
| 24 | + @Override | |
| 25 | + public void start() { | |
| 26 | + log.info("MqttPlugin.start()"); | |
| 27 | + | |
| 28 | + // 重新初始化线程池,确保它是活跃的 | |
| 29 | + if (executorService.isShutdown() || executorService.isTerminated()) { | |
| 30 | + executorService = Executors.newSingleThreadExecutor(); | |
| 31 | + } | |
| 32 | + | |
| 33 | + // 从 ServiceRegistry 中获取主程序暴露的 DeviceDataApi 接口实例 | |
| 34 | + deviceDataApi = ServiceRegistry.getService(DeviceDataApi.class); | |
| 35 | + if (deviceDataApi == null) { | |
| 36 | + log.error("未能从 ServiceRegistry 获取 DeviceDataApi 实例,请确保主程序已正确注册!"); | |
| 37 | + return; | |
| 38 | + } | |
| 39 | + } | |
| 40 | + | |
| 41 | + @Override | |
| 42 | + public void stop() { | |
| 43 | + log.info("MqttPlugin.stop()"); | |
| 44 | + // 停止线程池 | |
| 45 | + executorService.shutdownNow(); | |
| 46 | + } | |
| 47 | + | |
| 48 | +} | |
| 0 | 49 | \ No newline at end of file | ... | ... |