【代码优化】IoT:整理 plugins 的依赖,以及对应 server 的启动逻辑

This commit is contained in:
YunaiV 2025-01-30 20:00:54 +08:00
parent 4a251b19c4
commit 30ae986c1a
15 changed files with 66 additions and 80 deletions

View File

@ -30,11 +30,17 @@
<scope>provided</scope> <!-- 设置为 provided只有工具类需要使用到 --> <scope>provided</scope> <!-- 设置为 provided只有工具类需要使用到 -->
</dependency> </dependency>
<!-- PF4J --> <!-- 工具类相关 -->
<!-- TODO 芋艿:这个依赖,要不要放在 api 包 -->
<dependency> <dependency>
<groupId>org.pf4j</groupId> <groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<scope>provided</scope> <!-- 设置为 provided只有工具类需要使用到 -->
</dependency>
<dependency>
<groupId>org.pf4j</groupId> <!-- PF4J内置插件机制 -->
<artifactId>pf4j-spring</artifactId> <artifactId>pf4j-spring</artifactId>
<!-- TODO @芋艿:可以放到 bom 里配置 -->
<exclusions> <exclusions>
<exclusion> <exclusion>
<groupId>org.slf4j</groupId> <groupId>org.slf4j</groupId>
@ -43,13 +49,6 @@
</exclusions> </exclusions>
</dependency> </dependency>
<!-- 工具类相关 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<scope>provided</scope> <!-- 设置为 provided只有工具类需要使用到 -->
</dependency>
<!-- 参数校验 --> <!-- 参数校验 -->
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>

View File

@ -64,25 +64,19 @@
<artifactId>yudao-spring-boot-starter-excel</artifactId> <artifactId>yudao-spring-boot-starter-excel</artifactId>
</dependency> </dependency>
<!-- Vert.x 核心依赖 --> <!-- 工具类相关 -->
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-core</artifactId>
</dependency>
<!-- Vert.x Web 模块 -->
<dependency> <dependency>
<groupId>io.vertx</groupId> <groupId>io.vertx</groupId>
<artifactId>vertx-web</artifactId> <artifactId>vertx-web</artifactId>
</dependency> </dependency>
<!-- MQTT -->
<dependency> <dependency>
<groupId>org.eclipse.paho</groupId> <groupId>org.eclipse.paho</groupId> <!-- MQTT -->
<artifactId>org.eclipse.paho.client.mqttv3</artifactId> <artifactId>org.eclipse.paho.client.mqttv3</artifactId>
</dependency> </dependency>
<!-- PF4J -->
<dependency> <dependency>
<groupId>org.pf4j</groupId> <groupId>org.pf4j</groupId> <!-- PF4J内置插件机制 -->
<artifactId>pf4j-spring</artifactId> <artifactId>pf4j-spring</artifactId>
<!-- TODO @芋艿:可以放到 bom 里配置 --> <!-- TODO @芋艿:可以放到 bom 里配置 -->
<exclusions> <exclusions>

View File

@ -1,6 +1,6 @@
package cn.iocoder.yudao.module.iot.framework.plugin; package cn.iocoder.yudao.module.iot.framework.plugin.config;
import cn.iocoder.yudao.module.iot.framework.plugin.listener.CustomPluginStateListener; import cn.iocoder.yudao.module.iot.framework.plugin.core.CustomPluginStateListener;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.pf4j.spring.SpringPluginManager; import org.pf4j.spring.SpringPluginManager;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;

View File

@ -1,4 +1,4 @@
package cn.iocoder.yudao.module.iot.framework.plugin.listener; package cn.iocoder.yudao.module.iot.framework.plugin.core;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.pf4j.PluginStateEvent; import org.pf4j.PluginStateEvent;

View File

@ -1,4 +1,4 @@
package cn.iocoder.yudao.module.iot.framework.plugin; package cn.iocoder.yudao.module.iot.framework.plugin.core;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;

View File

@ -1,4 +1,4 @@
package cn.iocoder.yudao.module.iot.framework.aspect; package cn.iocoder.yudao.module.iot.framework.tdengine.core;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.ProceedingJoinPoint;

View File

@ -18,35 +18,24 @@
</description> </description>
<dependencies> <dependencies>
<!-- TODO 芋艿:依赖整理 -->
<dependency> <dependency>
<groupId>cn.iocoder.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>yudao-common</artifactId> <artifactId>spring-boot-starter</artifactId>
</dependency> </dependency>
<!-- 项目依赖 -->
<dependency> <dependency>
<groupId>cn.iocoder.boot</groupId> <groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-module-iot-api</artifactId> <artifactId>yudao-module-iot-api</artifactId>
<version>${revision}</version> <version>${revision}</version>
</dependency> </dependency>
<dependency> <!-- Web 相关 -->
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.springframework</groupId> <groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId> <artifactId>spring-web</artifactId>
</dependency> </dependency>
<!-- 其他依赖项 --> <!-- 工具类相关 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- Vert.x Web -->
<dependency> <dependency>
<groupId>io.vertx</groupId> <groupId>io.vertx</groupId>
<artifactId>vertx-web</artifactId> <artifactId>vertx-web</artifactId>

View File

@ -16,6 +16,7 @@
<name>${project.artifactId}</name> <name>${project.artifactId}</name>
<description> <description>
<!-- TODO @芋艿:注释 -->
物联网 插件模块 - http 插件 物联网 插件模块 - http 插件
</description> </description>
@ -31,7 +32,7 @@
<build> <build>
<plugins> <plugins>
<!-- 插件模式 zip --> <!-- 插件模式 zip -->
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId> <artifactId>maven-antrun-plugin</artifactId>
@ -75,7 +76,7 @@
</executions> </executions>
</plugin> </plugin>
<!-- 插件模式 jar --> <!-- 插件模式 jar -->
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId> <artifactId>maven-jar-plugin</artifactId>
@ -94,7 +95,7 @@
</configuration> </configuration>
</plugin> </plugin>
<!-- 独立模式 --> <!-- 独立模式 -->
<plugin> <plugin>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId> <artifactId>spring-boot-maven-plugin</artifactId>
@ -121,21 +122,13 @@
</build> </build>
<dependencies> <dependencies>
<!-- TODO 芋艿:优化下 -->
<!-- 项目依赖 -->
<dependency> <dependency>
<groupId>cn.iocoder.boot</groupId> <groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-module-iot-plugin-common</artifactId> <artifactId>yudao-module-iot-plugin-common</artifactId>
<version>${revision}</version> <version>${revision}</version>
</dependency> </dependency>
<!-- 其他依赖项 --> <!-- 工具类相关 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Vert.x Web -->
<dependency> <dependency>
<groupId>io.vertx</groupId> <groupId>io.vertx</groupId>
<artifactId>vertx-web</artifactId> <artifactId>vertx-web</artifactId>

View File

@ -1,9 +1,7 @@
package cn.iocoder.yudao.module.iot.plugin.http; package cn.iocoder.yudao.module.iot.plugin.http;
import cn.iocoder.yudao.module.iot.plugin.http.upstream.IotDeviceUpstreamServer;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.ConfigurableApplicationContext;
@ -15,16 +13,15 @@ import org.springframework.context.ConfigurableApplicationContext;
public class HttpPluginSpringbootApplication { public class HttpPluginSpringbootApplication {
public static void main(String[] args) { public static void main(String[] args) {
SpringApplication application = new SpringApplication(HttpPluginSpringbootApplication.class); ConfigurableApplicationContext context = SpringApplication.run(HttpPluginSpringbootApplication.class, args);
application.setWebApplicationType(WebApplicationType.NONE);
ConfigurableApplicationContext context = application.run(args);
// 手动获取 VertxService 并启动 // 手动获取 VertxService 并启动
// TODO @haohao可以放在 bean init 里么回复会和插件模式冲突 @芋艿测试下 // TODO @haohao可以放在 bean init 里么回复会和插件模式冲突 @芋艿测试下
IotDeviceUpstreamServer vertxService = context.getBean(IotDeviceUpstreamServer.class); // TODO @haohao貌似去掉没有问题额
vertxService.start(); // IotDeviceUpstreamServer vertxService = context.getBean(IotDeviceUpstreamServer.class);
// vertxService.start();
log.info("[HttpPluginSpringbootApplication] 独立模式启动完成"); log.info("[main][独立模式启动完成]");
} }
} }

View File

@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.iot.plugin.http.config;
import cn.hutool.core.lang.Assert; import cn.hutool.core.lang.Assert;
import cn.hutool.extra.spring.SpringUtil; import cn.hutool.extra.spring.SpringUtil;
import cn.iocoder.yudao.module.iot.api.device.IotDeviceUpstreamApi; import cn.iocoder.yudao.module.iot.api.device.IotDeviceUpstreamApi;
import cn.iocoder.yudao.module.iot.plugin.http.upstream.IotDeviceUpstreamServer;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.pf4j.PluginWrapper; import org.pf4j.PluginWrapper;
import org.pf4j.spring.SpringPlugin; import org.pf4j.spring.SpringPlugin;
@ -11,6 +10,7 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext;
// TODO @芋艿完善注释
/** /**
* 负责插件的启动和停止 Vert.x 的生命周期管理 * 负责插件的启动和停止 Vert.x 的生命周期管理
*/ */
@ -30,8 +30,9 @@ public class IotHttpVertxPlugin extends SpringPlugin {
Assert.notNull(pluginContext, "pluginContext 不能为空"); Assert.notNull(pluginContext, "pluginContext 不能为空");
// 2. 启动 Vert.x // 2. 启动 Vert.x
IotDeviceUpstreamServer vertxService = pluginContext.getBean(IotDeviceUpstreamServer.class); // TODO @haohao貌似去掉没有问题额
vertxService.start(); // IotDeviceUpstreamServer vertxService = pluginContext.getBean(IotDeviceUpstreamServer.class);
// vertxService.start();
log.info("[HttpVertxPlugin][HttpVertxPlugin 插件启动成功...]"); log.info("[HttpVertxPlugin][HttpVertxPlugin 插件启动成功...]");
} catch (Exception e) { } catch (Exception e) {
@ -44,11 +45,11 @@ public class IotHttpVertxPlugin extends SpringPlugin {
log.info("[HttpVertxPlugin][HttpVertxPlugin 插件停止开始...]"); log.info("[HttpVertxPlugin][HttpVertxPlugin 插件停止开始...]");
try { try {
// 停止服务器 // 停止服务器
ApplicationContext pluginContext = getApplicationContext(); // ApplicationContext pluginContext = getApplicationContext();
if (pluginContext != null) { // if (pluginContext != null) {
IotDeviceUpstreamServer vertxService = pluginContext.getBean(IotDeviceUpstreamServer.class); // IotDeviceUpstreamServer vertxService = pluginContext.getBean(IotDeviceUpstreamServer.class);
vertxService.stopServer(); // vertxService.stop();
} // }
log.info("[HttpVertxPlugin][HttpVertxPlugin 插件停止成功...]"); log.info("[HttpVertxPlugin][HttpVertxPlugin 插件停止成功...]");
} catch (Exception e) { } catch (Exception e) {

View File

@ -7,7 +7,9 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
/** /**
* 插件与独立运行都可复用的配置类 * IoT 插件 HTTP 的专用自动配置类
*
* @author haohao
*/ */
@Configuration @Configuration
public class IotPluginHttpAutoConfiguration { public class IotPluginHttpAutoConfiguration {
@ -19,8 +21,8 @@ public class IotPluginHttpAutoConfiguration {
@Value("${plugin.http.server.port:8092}") @Value("${plugin.http.server.port:8092}")
private Integer port; private Integer port;
@Bean @Bean(initMethod = "start", destroyMethod = "stop")
public IotDeviceUpstreamServer vertxService(IotDeviceUpstreamApi deviceUpstreamApi) { public IotDeviceUpstreamServer deviceUpstreamServer(IotDeviceUpstreamApi deviceUpstreamApi) {
return new IotDeviceUpstreamServer(port, deviceUpstreamApi); return new IotDeviceUpstreamServer(port, deviceUpstreamApi);
} }

View File

@ -7,6 +7,14 @@ import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDeviceSe
import cn.iocoder.yudao.module.iot.plugin.common.downstream.IotDeviceDownstreamHandler; import cn.iocoder.yudao.module.iot.plugin.common.downstream.IotDeviceDownstreamHandler;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
/**
* HTTP 插件的 {@link IotDeviceDownstreamHandler} 实现类
*
* 但是由于设备通过 HTTP 短链接接入导致其实无法下行指导给 device 设备所以基本都是直接返回失败
* 类似 MQTTWebSocketTCP 插件是可以实现下行指令的
*
* @author 芋道源码
*/
@Component // TODO @芋艿后续统一处理 @Component // TODO @芋艿后续统一处理
public class IotDeviceDownstreamHandlerImpl implements IotDeviceDownstreamHandler { public class IotDeviceDownstreamHandlerImpl implements IotDeviceDownstreamHandler {

View File

@ -51,7 +51,7 @@ public class IotDeviceUpstreamServer {
/** /**
* 停止所有 * 停止所有
*/ */
public void stopServer() { public void stop() {
log.info("[stop][开始关闭]"); log.info("[stop][开始关闭]");
try { try {
// 关闭 HTTP 服务器 // 关闭 HTTP 服务器

View File

@ -10,21 +10,22 @@ import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStateEnum;
import io.vertx.core.Handler; import io.vertx.core.Handler;
import io.vertx.ext.web.RequestBody; import io.vertx.ext.web.RequestBody;
import io.vertx.ext.web.RoutingContext; import io.vertx.ext.web.RoutingContext;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.Map; import java.util.Map;
/**
* IoT 设备属性上报的 Vert.x Handler
*/
@RequiredArgsConstructor
@Slf4j @Slf4j
public class IotDevicePropertyReportVertxHandler implements Handler<RoutingContext> { public class IotDevicePropertyReportVertxHandler implements Handler<RoutingContext> {
public static final String PATH = "/sys/:productKey/:deviceName/thing/event/property/post"; public static final String PATH = "/sys/:productKey/:deviceName/thing/event/property/post";
private final IotDeviceUpstreamApi deviceDataApi; private final IotDeviceUpstreamApi deviceUpstreamApi;
public IotDevicePropertyReportVertxHandler(IotDeviceUpstreamApi deviceDataApi) {
this.deviceDataApi = deviceDataApi;
}
@Override @Override
public void handle(RoutingContext ctx) { public void handle(RoutingContext ctx) {
@ -51,7 +52,7 @@ public class IotDevicePropertyReportVertxHandler implements Handler<RoutingConte
try { try {
// TODO @haohaopluginKey 需要设置 // TODO @haohaopluginKey 需要设置
// 设备上线 // 设备上线
deviceDataApi.updateDeviceState(((IotDeviceStateUpdateReqDTO) deviceUpstreamApi.updateDeviceState(((IotDeviceStateUpdateReqDTO)
new IotDeviceStateUpdateReqDTO().setRequestId(IdUtil.fastSimpleUUID()) new IotDeviceStateUpdateReqDTO().setRequestId(IdUtil.fastSimpleUUID())
.setPluginKey("http") .setPluginKey("http")
.setReportTime(LocalDateTime.now()) .setReportTime(LocalDateTime.now())
@ -59,7 +60,7 @@ public class IotDevicePropertyReportVertxHandler implements Handler<RoutingConte
.setState(IotDeviceStateEnum.ONLINE.getState())); .setState(IotDeviceStateEnum.ONLINE.getState()));
// 属性上报 // 属性上报
deviceDataApi.reportDeviceProperty(((IotDevicePropertyReportReqDTO) deviceUpstreamApi.reportDeviceProperty(((IotDevicePropertyReportReqDTO)
new IotDevicePropertyReportReqDTO().setRequestId(IdUtil.fastSimpleUUID()) new IotDevicePropertyReportReqDTO().setRequestId(IdUtil.fastSimpleUUID())
.setPluginKey("http").setReportTime(LocalDateTime.now()) .setPluginKey("http").setReportTime(LocalDateTime.now())
.setProductKey(productKey).setDeviceName(deviceName)) .setProductKey(productKey).setDeviceName(deviceName))
@ -81,6 +82,7 @@ public class IotDevicePropertyReportVertxHandler implements Handler<RoutingConte
} }
} }
// TODO @芋艿抽一个 IotPluginCommonResult 出来 mqttwebsocket 出来后再考虑优化
private JSONObject createResponseJson(int code, JSONObject data, String id, private JSONObject createResponseJson(int code, JSONObject data, String id,
String message, String method, String version) { String message, String method, String version) {
JSONObject res = new JSONObject(); JSONObject res = new JSONObject();
@ -92,4 +94,5 @@ public class IotDevicePropertyReportVertxHandler implements Handler<RoutingConte
res.set("version", version); res.set("version", version);
return res; return res;
} }
} }