【代码优化】IoT:优化插件 common 和 http 的配置类

This commit is contained in:
YunaiV 2025-01-31 21:51:06 +08:00
parent a74459e94e
commit 252366781d
16 changed files with 142 additions and 117 deletions

View File

@ -600,39 +600,42 @@
</exclusions>
</dependency>
<!-- MQTT -->
<dependency>
<groupId>org.eclipse.paho</groupId>
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
<version>${mqtt.version}</version>
</dependency>
<!-- PF4J -->
<dependency>
<groupId>org.pf4j</groupId>
<artifactId>pf4j-spring</artifactId>
<version>${pf4j-spring.version}</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Vert.x 核心依赖 -->
<!-- Vert.x -->
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-core</artifactId>
<version>${vertx.version}</version>
</dependency>
<!-- Vert.x Web 模块 -->
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-web</artifactId>
<version>${vertx.version}</version>
</dependency>
<!-- Vert.x MQTT 模块 -->
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-mqtt</artifactId>
<version>${vertx.version}</version>
</dependency>
<!-- MQTT -->
<dependency>
<groupId>org.eclipse.paho</groupId>
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
<version>${mqtt.version}</version>
</dependency>
</dependencies>
</dependencyManagement>

View File

@ -63,10 +63,6 @@
<artifactId>opengauss-jdbc</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.taosdata.jdbc</groupId>
<artifactId>taos-jdbcdriver</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>

View File

@ -40,13 +40,6 @@
<dependency>
<groupId>org.pf4j</groupId> <!-- PF4J内置插件机制 -->
<artifactId>pf4j-spring</artifactId>
<!-- TODO @芋艿:可以放到 bom 里配置 -->
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 参数校验 -->

View File

@ -52,6 +52,11 @@
<artifactId>yudao-spring-boot-starter-redis</artifactId>
</dependency>
<dependency>
<groupId>com.taosdata.jdbc</groupId>
<artifactId>taos-jdbcdriver</artifactId>
</dependency>
<!-- Test 测试相关 -->
<dependency>
<groupId>cn.iocoder.boot</groupId>
@ -64,12 +69,13 @@
<artifactId>yudao-spring-boot-starter-excel</artifactId>
</dependency>
<!-- 工具类相关 -->
<!-- TODO @haohao貌似不需要这个 -->
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-web</artifactId>
</dependency>
<!-- TODO @haohao貌似 biz 模块,不需要 MQTT -->
<dependency>
<groupId>org.eclipse.paho</groupId> <!-- MQTT -->
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
@ -78,13 +84,6 @@
<dependency>
<groupId>org.pf4j</groupId> <!-- PF4J内置插件机制 -->
<artifactId>pf4j-spring</artifactId>
<!-- TODO @芋艿:可以放到 bom 里配置 -->
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>

View File

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.iocoder.yudao.module.iot.dal.mysql.plugininfo.PluginInfoMapper">
<!--
一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
文档可见https://www.iocoder.cn/MyBatis/x-plugins/
-->
</mapper>

View File

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.iocoder.yudao.module.iot.dal.mysql.plugin.IotPluginInstanceMapper">
<!--
一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
文档可见https://www.iocoder.cn/MyBatis/x-plugins/
-->
</mapper>

View File

@ -40,6 +40,13 @@
<groupId>io.vertx</groupId>
<artifactId>vertx-web</artifactId>
</dependency>
<!-- 参数校验 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>

View File

@ -3,59 +3,43 @@ package cn.iocoder.yudao.module.iot.plugin.common.config;
import cn.iocoder.yudao.module.iot.api.device.IotDeviceUpstreamApi;
import cn.iocoder.yudao.module.iot.plugin.common.downstream.IotDeviceDownstreamHandler;
import cn.iocoder.yudao.module.iot.plugin.common.downstream.IotDeviceDownstreamServer;
import cn.iocoder.yudao.module.iot.plugin.common.heartbeta.IotPluginInstanceHeartbeatJob;
import cn.iocoder.yudao.module.iot.plugin.common.heartbeat.IotPluginInstanceHeartbeatJob;
import cn.iocoder.yudao.module.iot.plugin.common.upstream.IotDeviceUpstreamClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.web.client.RestTemplate;
import java.time.Duration;
/**
* IoT 插件的通用自动配置类
*
* @author haohao
*/
@AutoConfiguration
@EnableConfigurationProperties(IotPluginCommonProperties.class)
@EnableScheduling // 开启定时任务因为 IotPluginInstanceHeartbeatJob 是一个定时任务
public class IotPluginCommonAutoConfiguration {
// TODO @haohao这个要不搞个配置类哈
@Value("${iot.device-data.url}")
private String deviceDataUrl;
/**
* 创建 RestTemplate 实例
*
* @return RestTemplate 实例
*/
@Bean
public RestTemplate restTemplate() {
// 如果你有更多的自定义需求比如连接池超时时间等可以在这里设置
public RestTemplate restTemplate(IotPluginCommonProperties properties) {
return new RestTemplateBuilder()
.connectTimeout(Duration.ofMillis(5000)) // 设置连接超时时间
.readTimeout(Duration.ofMillis(5000)) // 设置读取超时时间
.connectTimeout(properties.getUpstreamConnectTimeout())
.readTimeout(properties.getUpstreamReadTimeout())
.build();
}
/**
* 创建 DeviceDataApi 实例
*
* @param restTemplate RestTemplate 实例
* @return DeviceDataApi 实例
*/
@Bean
public IotDeviceUpstreamApi deviceDataApi(RestTemplate restTemplate) {
return new IotDeviceUpstreamClient(restTemplate, deviceDataUrl);
public IotDeviceUpstreamApi deviceUpstreamApi(IotPluginCommonProperties properties,
RestTemplate restTemplate) {
return new IotDeviceUpstreamClient(properties, restTemplate);
}
@Bean(initMethod = "start", destroyMethod = "stop")
@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
public IotDeviceDownstreamServer deviceDownstreamServer(IotDeviceDownstreamHandler deviceDownstreamHandler) {
return new IotDeviceDownstreamServer(deviceDownstreamHandler);
public IotDeviceDownstreamServer deviceDownstreamServer(IotPluginCommonProperties properties,
IotDeviceDownstreamHandler deviceDownstreamHandler) {
return new IotDeviceDownstreamServer(properties, deviceDownstreamHandler);
}
@Bean(initMethod = "init", destroyMethod = "stop")

View File

@ -0,0 +1,48 @@
package cn.iocoder.yudao.module.iot.plugin.common.config;
import jakarta.validation.constraints.NotEmpty;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.validation.annotation.Validated;
import java.time.Duration;
@ConfigurationProperties(prefix = "yudao.iot.plugin.common")
@Validated
@Data
public class IotPluginCommonProperties {
/**
* 上行连接超时的默认值
*/
public static final Duration UPSTREAM_CONNECT_TIMEOUT_DEFAULT = Duration.ofSeconds(30);
/**
* 上行读取超时的默认值
*/
public static final Duration UPSTREAM_READ_TIMEOUT_DEFAULT = Duration.ofSeconds(30);
/**
* 下行端口 - 随机
*/
public static final Integer DOWNSTREAM_PORT_RANDOM = 0;
/**
* 上行 URL
*/
@NotEmpty(message = "上行 URL 不能为空")
private String upstreamUrl;
/**
* 上行连接超时
*/
private Duration upstreamConnectTimeout = UPSTREAM_CONNECT_TIMEOUT_DEFAULT;
/**
* 上行读取超时
*/
private Duration upstreamReadTimeout = UPSTREAM_READ_TIMEOUT_DEFAULT;
/**
* 下行端口
*/
private Integer downstreamPort = DOWNSTREAM_PORT_RANDOM;
}

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.iot.plugin.common.downstream;
import cn.iocoder.yudao.module.iot.plugin.common.config.IotPluginCommonProperties;
import cn.iocoder.yudao.module.iot.plugin.common.downstream.router.IotDevicePropertyGetVertxHandler;
import cn.iocoder.yudao.module.iot.plugin.common.downstream.router.IotDevicePropertySetVertxHandler;
import cn.iocoder.yudao.module.iot.plugin.common.downstream.router.IotDeviceServiceInvokeVertxHandler;
@ -19,8 +20,11 @@ public class IotDeviceDownstreamServer {
private final Vertx vertx;
private final HttpServer server;
private final IotPluginCommonProperties properties;
public IotDeviceDownstreamServer(IotDeviceDownstreamHandler deviceDownstreamHandler) {
public IotDeviceDownstreamServer(IotPluginCommonProperties properties,
IotDeviceDownstreamHandler deviceDownstreamHandler) {
this.properties = properties;
// 创建 Vertx 实例
this.vertx = Vertx.vertx();
// 创建 Router 实例
@ -41,7 +45,7 @@ public class IotDeviceDownstreamServer {
*/
public void start() {
log.info("[start][开始启动]");
server.listen(0) // 通过 0 自动选择端口
server.listen(properties.getDownstreamPort())
.toCompletionStage()
.toCompletableFuture()
.join();

View File

@ -1,4 +1,4 @@
package cn.iocoder.yudao.module.iot.plugin.common.heartbeta;
package cn.iocoder.yudao.module.iot.plugin.common.heartbeat;
import cn.hutool.system.SystemUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.IotPluginInst
import cn.iocoder.yudao.module.iot.plugin.common.downstream.IotDeviceDownstreamServer;
import cn.iocoder.yudao.module.iot.plugin.common.util.IotPluginCommonUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import java.util.concurrent.TimeUnit;
@ -17,6 +18,7 @@ import java.util.concurrent.TimeUnit;
* 用于定时发送心跳给服务端
*/
@RequiredArgsConstructor
@Slf4j
public class IotPluginInstanceHeartbeatJob {
private final IotDeviceUpstreamApi deviceUpstreamApi;
@ -24,22 +26,22 @@ public class IotPluginInstanceHeartbeatJob {
public void init() {
CommonResult<Boolean> result = deviceUpstreamApi.heartbeatPluginInstance(buildPluginInstanceHeartbeatReqDTO(true));
// TODO @芋艿结果的处理
log.info("[init][上线结果:{})]", result);
}
public void stop() {
CommonResult<Boolean> result = deviceUpstreamApi.heartbeatPluginInstance(buildPluginInstanceHeartbeatReqDTO(false));
// TODO @芋艿结果的处理
log.info("[stop][下线结果:{})]", result);
}
@Scheduled(initialDelay = 3, fixedRate = 3, timeUnit = TimeUnit.MINUTES) // 3 分钟执行一次
public void execute() {
CommonResult<Boolean> result = deviceUpstreamApi.heartbeatPluginInstance(buildPluginInstanceHeartbeatReqDTO(true));
// TODO @芋艿结果的处理
log.info("[execute][心跳结果:{})]", result);
}
private IotPluginInstanceHeartbeatReqDTO buildPluginInstanceHeartbeatReqDTO(Boolean online) {
// TODO @芋艿pluginKey 的获取
// TODO @haohaopluginKey 的获取
return new IotPluginInstanceHeartbeatReqDTO()
.setPluginKey("yudao-module-iot-plugin-http").setProcessId(IotPluginCommonUtils.getProcessId())
.setHostIp(SystemUtil.getHostInfo().getAddress()).setDownstreamPort(deviceDownstreamServer.getPort())

View File

@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.IotDeviceEven
import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.IotDevicePropertyReportReqDTO;
import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.IotDeviceStateUpdateReqDTO;
import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.IotPluginInstanceHeartbeatReqDTO;
import cn.iocoder.yudao.module.iot.plugin.common.config.IotPluginCommonProperties;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.client.RestTemplate;
@ -25,32 +26,31 @@ public class IotDeviceUpstreamClient implements IotDeviceUpstreamApi {
public static final String URL_PREFIX = "/rpc-api/iot/device/upstream";
private final RestTemplate restTemplate;
private final IotPluginCommonProperties properties;
// TODO @芋艿改个名字
private final String deviceDataUrl;
private final RestTemplate restTemplate;
@Override
public CommonResult<Boolean> updateDeviceState(IotDeviceStateUpdateReqDTO updateReqDTO) {
String url = deviceDataUrl + URL_PREFIX + "/update-state";
String url = properties.getUpstreamUrl() + URL_PREFIX + "/update-state";
return doPost(url, updateReqDTO);
}
@Override
public CommonResult<Boolean> reportDeviceEvent(IotDeviceEventReportReqDTO reportReqDTO) {
String url = deviceDataUrl + URL_PREFIX + "/report-event";
String url = properties.getUpstreamUrl() + URL_PREFIX + "/report-event";
return doPost(url, reportReqDTO);
}
@Override
public CommonResult<Boolean> reportDeviceProperty(IotDevicePropertyReportReqDTO reportReqDTO) {
String url = deviceDataUrl + URL_PREFIX + "/report-property";
String url = properties.getUpstreamUrl() + URL_PREFIX + "/report-property";
return doPost(url, reportReqDTO);
}
@Override
public CommonResult<Boolean> heartbeatPluginInstance(IotPluginInstanceHeartbeatReqDTO heartbeatReqDTO) {
String url = deviceDataUrl + URL_PREFIX + "/heartbeat-plugin-instance";
String url = properties.getUpstreamUrl() + URL_PREFIX + "/heartbeat-plugin-instance";
return doPost(url, heartbeatReqDTO);
}

View File

@ -4,7 +4,7 @@ import cn.iocoder.yudao.module.iot.api.device.IotDeviceUpstreamApi;
import cn.iocoder.yudao.module.iot.plugin.common.downstream.IotDeviceDownstreamHandler;
import cn.iocoder.yudao.module.iot.plugin.http.downstream.IotDeviceDownstreamHandlerImpl;
import cn.iocoder.yudao.module.iot.plugin.http.upstream.IotDeviceUpstreamServer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@ -14,18 +14,13 @@ import org.springframework.context.annotation.Configuration;
* @author haohao
*/
@Configuration
@EnableConfigurationProperties(IotPluginHttpProperties.class)
public class IotPluginHttpAutoConfiguration {
// TODO @haohao这个要不要搞个配置类更容易维护
/**
* 可在 application.yml 中配置默认端口 8092
*/
@Value("${plugin.http.server.port:8092}")
private Integer port;
@Bean(initMethod = "start", destroyMethod = "stop")
public IotDeviceUpstreamServer deviceUpstreamServer(IotDeviceUpstreamApi deviceUpstreamApi) {
return new IotDeviceUpstreamServer(port, deviceUpstreamApi);
public IotDeviceUpstreamServer deviceUpstreamServer(IotDeviceUpstreamApi deviceUpstreamApi,
IotPluginHttpProperties properties) {
return new IotDeviceUpstreamServer(properties, deviceUpstreamApi);
}
@Bean

View File

@ -0,0 +1,17 @@
package cn.iocoder.yudao.module.iot.plugin.http.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.validation.annotation.Validated;
@ConfigurationProperties(prefix = "yudao.iot.plugin.http")
@Validated
@Data
public class IotPluginHttpProperties {
/**
* HTTP 服务端口
*/
private Integer serverPort;
}

View File

@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.iot.plugin.http.upstream;
import cn.iocoder.yudao.module.iot.api.device.IotDeviceUpstreamApi;
import cn.iocoder.yudao.module.iot.plugin.http.config.IotPluginHttpProperties;
import cn.iocoder.yudao.module.iot.plugin.http.upstream.router.IotDeviceEventReportVertxHandler;
import cn.iocoder.yudao.module.iot.plugin.http.upstream.router.IotDevicePropertyReportVertxHandler;
import io.vertx.core.Vertx;
@ -21,11 +22,11 @@ public class IotDeviceUpstreamServer {
private final Vertx vertx;
private final HttpServer server;
private final Integer port;
private final IotPluginHttpProperties properties;
public IotDeviceUpstreamServer(Integer port,
public IotDeviceUpstreamServer(IotPluginHttpProperties properties,
IotDeviceUpstreamApi deviceUpstreamApi) {
this.port = port;
this.properties = properties;
// 创建 Vertx 实例
this.vertx = Vertx.vertx();
// 创建 Router 实例
@ -44,7 +45,7 @@ public class IotDeviceUpstreamServer {
*/
public void start() {
log.info("[start][开始启动]");
server.listen(port)
server.listen(properties.getServerPort())
.toCompletionStage()
.toCompletableFuture()
.join();

View File

@ -2,11 +2,11 @@ spring:
application:
name: yudao-module-iot-plugin-http
iot:
device-data:
url: http://127.0.0.1:48080
plugin:
http:
server:
port: 8092
yudao:
iot:
plugin:
common:
upstream-url: http://127.0.0.1:48080
downstream-port: 8093
http:
server-port: 8092