事件:实时数据+故障报警
commit
80a6fb6992
|
@ -0,0 +1,38 @@
|
||||||
|
target/
|
||||||
|
!.mvn/wrapper/maven-wrapper.jar
|
||||||
|
!**/src/main/**/target/
|
||||||
|
!**/src/test/**/target/
|
||||||
|
|
||||||
|
### IntelliJ IDEA ###
|
||||||
|
.idea/modules.xml
|
||||||
|
.idea/jarRepositories.xml
|
||||||
|
.idea/compiler.xml
|
||||||
|
.idea/libraries/
|
||||||
|
*.iws
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
|
||||||
|
### Eclipse ###
|
||||||
|
.apt_generated
|
||||||
|
.classpath
|
||||||
|
.factorypath
|
||||||
|
.project
|
||||||
|
.settings
|
||||||
|
.springBeans
|
||||||
|
.sts4-cache
|
||||||
|
|
||||||
|
### NetBeans ###
|
||||||
|
/nbproject/private/
|
||||||
|
/nbbuild/
|
||||||
|
/dist/
|
||||||
|
/nbdist/
|
||||||
|
/.nb-gradle/
|
||||||
|
build/
|
||||||
|
!**/src/main/**/build/
|
||||||
|
!**/src/test/**/build/
|
||||||
|
|
||||||
|
### VS Code ###
|
||||||
|
.vscode/
|
||||||
|
|
||||||
|
### Mac OS ###
|
||||||
|
.DS_Store
|
|
@ -0,0 +1,8 @@
|
||||||
|
# 默认忽略的文件
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# 基于编辑器的 HTTP 客户端请求
|
||||||
|
/httpRequests/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Encoding" defaultCharsetForPropertiesFiles="UTF-8">
|
||||||
|
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
|
||||||
|
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
|
||||||
|
<file url="PROJECT" charset="UTF-8" />
|
||||||
|
</component>
|
||||||
|
</project>
|
|
@ -0,0 +1,5 @@
|
||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<profile version="1.0">
|
||||||
|
<option name="myName" value="Project Default" />
|
||||||
|
</profile>
|
||||||
|
</component>
|
|
@ -0,0 +1,14 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||||
|
<component name="MavenProjectsManager">
|
||||||
|
<option name="originalFiles">
|
||||||
|
<list>
|
||||||
|
<option value="$PROJECT_DIR$/pom.xml" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="17" project-jdk-type="JavaSDK">
|
||||||
|
<output url="file://$PROJECT_DIR$/out" />
|
||||||
|
</component>
|
||||||
|
</project>
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
|
@ -0,0 +1,162 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>com.muyu</groupId>
|
||||||
|
<artifactId>event</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
<description>事件驱动系统</description>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>17</maven.compiler.source>
|
||||||
|
<maven.compiler.target>17</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<spring-boot.version>2.3.7.RELEASE</spring-boot.version>
|
||||||
|
</properties>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.fastjson2</groupId>
|
||||||
|
<artifactId>fastjson2</artifactId>
|
||||||
|
<version>2.0.47</version>
|
||||||
|
</dependency> <!-- rabbit -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.amqp</groupId>
|
||||||
|
<artifactId>spring-rabbit-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-amqp</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<!-- caffeine -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.ben-manes.caffeine</groupId>
|
||||||
|
<artifactId>caffeine</artifactId>
|
||||||
|
<version>2.9.3</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- SpringBoot Boot Redis -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<!-- Kafka -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.kafka</groupId>
|
||||||
|
<artifactId>spring-kafka</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.kafka</groupId>
|
||||||
|
<artifactId>kafka-clients</artifactId>
|
||||||
|
<version>3.3.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.kafka</groupId>
|
||||||
|
<artifactId>spring-kafka-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<!-- SpringBoot Boot Redis -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Mysql Connector -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>mysql</groupId>
|
||||||
|
<artifactId>mysql-connector-java</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<!-- Mybatis 依赖配置 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mybatis.spring.boot</groupId>
|
||||||
|
<artifactId>mybatis-spring-boot-starter</artifactId>
|
||||||
|
<version>2.2.2</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- https://mvnrepository.com/artifact/org.apache.iotdb/iotdb-session -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.iotdb</groupId>
|
||||||
|
<artifactId>iotdb-session</artifactId>
|
||||||
|
<version>0.14.0-preview1</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.hutool</groupId>
|
||||||
|
<artifactId>hutool-all</artifactId>
|
||||||
|
<version>5.6.3</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba</groupId>
|
||||||
|
<artifactId>fastjson</artifactId>
|
||||||
|
<version>1.2.83</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<version>1.18.22</version>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.junit.vintage</groupId>
|
||||||
|
<artifactId>junit-vintage-engine</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<dependencyManagement>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-dependencies</artifactId>
|
||||||
|
<version>${spring-boot.version}</version>
|
||||||
|
<type>pom</type>
|
||||||
|
<scope>import</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</dependencyManagement>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.8.1</version>
|
||||||
|
<configuration>
|
||||||
|
<source>1.8</source>
|
||||||
|
<target>1.8</target>
|
||||||
|
<encoding>UTF-8</encoding>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
<version>2.3.7.RELEASE</version>
|
||||||
|
<configuration>
|
||||||
|
<mainClass>com.zhouhong.iotdbdemo.IotdbDemoApplication</mainClass>
|
||||||
|
</configuration>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>repackage</id>
|
||||||
|
<goals>
|
||||||
|
<goal>repackage</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
|
@ -0,0 +1,15 @@
|
||||||
|
package com.muyu.eventdriven;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.cache.annotation.EnableCaching;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
@EnableCaching
|
||||||
|
public class EventDrivenApplication {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(EventDrivenApplication.class, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,151 @@
|
||||||
|
package com.muyu.eventdriven;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.muyu.eventdriven.domain.VehicleData;
|
||||||
|
import com.muyu.eventdriven.server.EventInfoService;
|
||||||
|
import com.muyu.eventdriven.server.impl.EventInfoServiceImpl;
|
||||||
|
import com.muyu.eventdriven.tactics.EventTactics;
|
||||||
|
import lombok.extern.log4j.Log4j2;
|
||||||
|
import org.apache.kafka.clients.consumer.ConsumerRecord;
|
||||||
|
import org.apache.kafka.clients.consumer.ConsumerRecords;
|
||||||
|
import org.apache.kafka.clients.consumer.KafkaConsumer;
|
||||||
|
import org.apache.kafka.common.TopicPartition;
|
||||||
|
import org.checkerframework.checker.units.qual.A;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.ApplicationArguments;
|
||||||
|
import org.springframework.boot.ApplicationRunner;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName EventDriveenApplication
|
||||||
|
* @Description 描述
|
||||||
|
* @Author YunFei.Du
|
||||||
|
* @Date 2024/6/25 10:03
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Log4j2
|
||||||
|
@Component
|
||||||
|
public class EventDrivenRunner implements ApplicationRunner {
|
||||||
|
@Autowired
|
||||||
|
private EventInfoServiceImpl eventInfoService;
|
||||||
|
@Autowired
|
||||||
|
private RedisTemplate< String, String > redisTemplate;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ApplicationContext applicationContext;
|
||||||
|
@Autowired
|
||||||
|
private EventTactics eventTactics;
|
||||||
|
private final AtomicInteger start = new AtomicInteger();
|
||||||
|
|
||||||
|
private static List<String> classNameList = new ArrayList<>((Arrays.asList(
|
||||||
|
"StorageEvent",
|
||||||
|
"ElectronicFenceEvent",
|
||||||
|
"FaultAlarmEvent",
|
||||||
|
"RealTimeDataEvent",
|
||||||
|
"IndexWarningEvent")));
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run(ApplicationArguments args) throws Exception {
|
||||||
|
if (start.get() != 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
synchronized (this) {
|
||||||
|
if (start.get() != 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
start.set(1);
|
||||||
|
|
||||||
|
// kafka分区监听器
|
||||||
|
new Thread(() -> {
|
||||||
|
ArrayList< TopicPartition > topicPartitions = new ArrayList<>();
|
||||||
|
// List< String > topics = redisTemplate.opsForList ( ).range ( "ipList", 0, -1 ).stream ().distinct ().collect( Collectors.toList());
|
||||||
|
List<String> topics = new ArrayList<String> ( ){{
|
||||||
|
add ( "47.92.213.100" );
|
||||||
|
add ( "47.92.95.98" );
|
||||||
|
}};
|
||||||
|
for (String topic : topics) {
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
TopicPartition topicPartition = new TopicPartition(topic, i);
|
||||||
|
topicPartitions.add(topicPartition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Properties props = new Properties(){{
|
||||||
|
put("bootstrap.servers", "43.142.12.243:9092");
|
||||||
|
put("auto.commit.interval.ms", "1000");
|
||||||
|
put("group.id", "test");
|
||||||
|
put("enable.auto.commit", "true");
|
||||||
|
put("session.timeout.ms", "30000");
|
||||||
|
put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
|
||||||
|
put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
|
||||||
|
}};
|
||||||
|
KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props);
|
||||||
|
consumer.assign(topicPartitions);
|
||||||
|
try {
|
||||||
|
while (true) {
|
||||||
|
ConcurrentHashMap< String, ArrayList< VehicleData > > stringListHashMap = new ConcurrentHashMap<>();
|
||||||
|
ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(100));
|
||||||
|
ConcurrentHashMap< String, ArrayList< VehicleData > > map = new ConcurrentHashMap<> ( );
|
||||||
|
stringListHashMap= eventInfoService.getVehicleData(records, map);
|
||||||
|
if (!records.isEmpty()) {
|
||||||
|
ArrayList< VehicleData > vehicleData1 = new ArrayList<> ( );
|
||||||
|
ConcurrentHashMap< String, ArrayList< VehicleData > > finalStringListHashMap = stringListHashMap;
|
||||||
|
new Thread(() -> {
|
||||||
|
for (TopicPartition partition : records.partitions()) {
|
||||||
|
String value="";
|
||||||
|
String key1="";
|
||||||
|
|
||||||
|
List< ConsumerRecord<String, String> > partitionRecords = records.records(partition);
|
||||||
|
for (ConsumerRecord<String, String> record : partitionRecords) {
|
||||||
|
key1=record.key ( );
|
||||||
|
log.info("Offset = {}, Key = {}, Value = {}", record.offset(), key1, record.value());
|
||||||
|
value= record.value ( );
|
||||||
|
System.out.println (value );
|
||||||
|
VehicleData vehicleData = JSON.parseObject ( value, VehicleData.class );
|
||||||
|
vehicleData1.add ( vehicleData );
|
||||||
|
// VehicleData vehicle = kafkaConsumerListenerExample.getVehicle(record.value());
|
||||||
|
// VehicleEvent events = eventsService.getEvents(vehicle.getVin());
|
||||||
|
// HandlerHelper.doHandler(events, vehicle, redisService);
|
||||||
|
}
|
||||||
|
// 处理拉取到的消息,将消息按车辆事件类型分类
|
||||||
|
|
||||||
|
finalStringListHashMap.forEach((key, value1) -> {
|
||||||
|
// 从 Redis 中获取车辆事件处理类的列表
|
||||||
|
// String vehicleEventString = redisTemplate.opsForHash().get(RedisConstants.VEHICLE_EVENT, key).toString();
|
||||||
|
String vehicleEventString = "1,2,3,4,5";
|
||||||
|
for (String str : vehicleEventString.split(",")) {
|
||||||
|
CompletableFuture.runAsync(() -> {
|
||||||
|
applicationContext.getBean(classNameList.get(Integer.parseInt(str)), EventTactics.class).eventManage(key,value1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Thread.sleep(10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
log.error("Consumer was interrupted.", e);
|
||||||
|
} finally {
|
||||||
|
consumer.close();
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.muyu.eventdriven.config;
|
||||||
|
|
||||||
|
import com.github.benmanes.caffeine.cache.Cache;
|
||||||
|
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName CaffeineCacheConfig
|
||||||
|
* @Description 描述
|
||||||
|
* @Author YunFei.Du
|
||||||
|
* @Date 2024/6/25 11:41
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class CaffeineCacheConfig {
|
||||||
|
@Bean
|
||||||
|
public Cache<String, Object> caffeineCache() {
|
||||||
|
return Caffeine.newBuilder()
|
||||||
|
// 设置最后一次写入或访问后经过固定时间过期
|
||||||
|
.expireAfterWrite(5, TimeUnit.SECONDS)
|
||||||
|
// 初始的缓存空间大小
|
||||||
|
.initialCapacity(100)
|
||||||
|
// 缓存的最大条数
|
||||||
|
.maximumSize(1000)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
package com.muyu.eventdriven.config;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName DataAccessClientConfig
|
||||||
|
* @Description 描述
|
||||||
|
* @Author Yunfei.Du
|
||||||
|
* @Date 2024/5/9 19:52
|
||||||
|
*/
|
||||||
|
//@ComponentScan
|
||||||
|
//@Import({EventDrivenRunner.class})
|
||||||
|
//public class EventDrivenConfig {
|
||||||
|
//}
|
|
@ -0,0 +1,20 @@
|
||||||
|
package com.muyu.eventdriven.config;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName DataAccessClientRunner
|
||||||
|
* @Description 描述
|
||||||
|
* @Author Yunfei.Du
|
||||||
|
* @Date 2024/5/9 19:53
|
||||||
|
*/
|
||||||
|
//@Log4j2
|
||||||
|
//@Component
|
||||||
|
//public class EventDrivenRunner implements ApplicationRunner {
|
||||||
|
// @Autowired
|
||||||
|
// private EventTacticsManage eventTacticsManage;
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public void run(ApplicationArguments args){
|
||||||
|
// eventTacticsManage.initEventTacticsManage();
|
||||||
|
// }
|
||||||
|
//}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package com.muyu.eventdriven.config.caffeine;
|
||||||
|
|
||||||
|
import com.github.benmanes.caffeine.cache.Cache;
|
||||||
|
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName CaffeineCacheConfig
|
||||||
|
* @Description 本地缓存配置类
|
||||||
|
* @Author Yunfei.Du
|
||||||
|
* @Date 2024/6/21 上午9:39
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class CaffeineCacheConfig {
|
||||||
|
@Bean
|
||||||
|
public Cache<String, Object> caffeineCache() {
|
||||||
|
return Caffeine.newBuilder()
|
||||||
|
// 设置最后一次写入或访问后经过固定时间过期
|
||||||
|
.expireAfterWrite(5, TimeUnit.SECONDS)
|
||||||
|
// 初始的缓存空间大小
|
||||||
|
.initialCapacity(100)
|
||||||
|
// 缓存的最大条数
|
||||||
|
.maximumSize(1000)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,189 @@
|
||||||
|
package com.muyu.eventdriven.config.iotdb;
|
||||||
|
|
||||||
|
import lombok.extern.log4j.Log4j2;
|
||||||
|
import org.apache.iotdb.rpc.IoTDBConnectionException;
|
||||||
|
import org.apache.iotdb.rpc.StatementExecutionException;
|
||||||
|
import org.apache.iotdb.session.Session;
|
||||||
|
import org.apache.iotdb.session.SessionDataSet;
|
||||||
|
import org.apache.iotdb.session.util.Version;
|
||||||
|
import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
|
||||||
|
import org.apache.iotdb.tsfile.write.record.Tablet;
|
||||||
|
import org.apache.iotdb.tsfile.write.schema.MeasurementSchema;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.rmi.ServerException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName AsVehicleEvent
|
||||||
|
* @Description iotdb配置工具类
|
||||||
|
* @Author Yunfei.Du
|
||||||
|
* @Date 2024/6/16 下午3:29
|
||||||
|
*/
|
||||||
|
@Log4j2
|
||||||
|
@Component
|
||||||
|
@Configuration
|
||||||
|
public class IotDBSessionConfig {
|
||||||
|
|
||||||
|
private static Session session;
|
||||||
|
|
||||||
|
@Value("${spring.iotdb.ip}")
|
||||||
|
private String LOCAL_HOST ;
|
||||||
|
@Bean
|
||||||
|
public Session getSession() throws IoTDBConnectionException, StatementExecutionException {
|
||||||
|
if (session == null) {
|
||||||
|
log.info("正在连接iotdb.......");
|
||||||
|
session = new Session.Builder().host(LOCAL_HOST).port(6667).username("root").password("root").version(Version.V_0_13).build();
|
||||||
|
session.open(false);
|
||||||
|
session.setFetchSize(100);
|
||||||
|
log.info("iotdb连接成功~");
|
||||||
|
// 设置时区
|
||||||
|
session.setTimeZone("+08:00");
|
||||||
|
}
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* description: 带有数据类型的添加操作 - insertRecord没有指定类型
|
||||||
|
* author: zhouhong
|
||||||
|
* @param * @param deviceId:节点路径如:root.a1eaKSRpRty.CA3013A303A25467
|
||||||
|
* time:时间戳
|
||||||
|
* measurementsList:物理量 即:属性
|
||||||
|
* type:数据类型: BOOLEAN((byte)0), INT32((byte)1),INT64((byte)2),FLOAT((byte)3),DOUBLE((byte)4),TEXT((byte)5),VECTOR((byte)6);
|
||||||
|
* valuesList:属性值 --- 属性必须与属性值一一对应
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public void insertRecordType(String deviceId, Long time,List<String> measurementsList, TSDataType type,List<Object> valuesList) throws StatementExecutionException, IoTDBConnectionException, ServerException {
|
||||||
|
if (measurementsList.size() != valuesList.size()) {
|
||||||
|
throw new ServerException("measurementsList 与 valuesList 值不对应");
|
||||||
|
}
|
||||||
|
List<TSDataType> types = new ArrayList<>();
|
||||||
|
measurementsList.forEach(item -> {
|
||||||
|
types.add(type);
|
||||||
|
});
|
||||||
|
session.insertRecord(deviceId, time, measurementsList, types, valuesList);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* description: 带有数据类型的添加操作 - insertRecord没有指定类型
|
||||||
|
* author: zhouhong
|
||||||
|
* @param deviceId:节点路径如:root.a1eaKSRpRty.CA3013A303A25467
|
||||||
|
* @param time:时间戳
|
||||||
|
* @param measurementsList:物理量 即:属性
|
||||||
|
* @param valuesList:属性值 --- 属性必须与属性值一一对应
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public void insertRecord(String deviceId, Long time,List<String> measurementsList, List<String> valuesList) throws StatementExecutionException, IoTDBConnectionException, ServerException {
|
||||||
|
if (measurementsList.size() == valuesList.size()) {
|
||||||
|
session.insertRecord(deviceId, time, measurementsList, valuesList);
|
||||||
|
} else {
|
||||||
|
log.error("measurementsList 与 valuesList 值不对应");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* description: 批量插入
|
||||||
|
* author: zhouhong
|
||||||
|
*/
|
||||||
|
public void insertRecords(List<String> deviceIdList, List<Long> timeList, List<List<String>> measurementsList, List<List<String>> valuesList) throws StatementExecutionException, IoTDBConnectionException, ServerException {
|
||||||
|
if (measurementsList.size() == valuesList.size()) {
|
||||||
|
session.insertRecords(deviceIdList, timeList, measurementsList, valuesList);
|
||||||
|
} else {
|
||||||
|
log.error("measurementsList 与 valuesList 值不对应");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* description: 插入操作
|
||||||
|
* author: zhouhong
|
||||||
|
* @param deviceId:节点路径如:root.a1eaKSRpRty.CA3013A303A25467
|
||||||
|
* @param time:时间戳
|
||||||
|
* @param schemaList: 属性值 + 数据类型 例子: List<MeasurementSchema> schemaList = new ArrayList<>(); schemaList.add(new MeasurementSchema("breath", TSDataType.INT64));
|
||||||
|
* @param maxRowNumber:
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public void insertTablet(String deviceId, Long time,List<MeasurementSchema> schemaList, List<Object> valueList,int maxRowNumber) throws StatementExecutionException, IoTDBConnectionException {
|
||||||
|
|
||||||
|
Tablet tablet = new Tablet(deviceId, schemaList, maxRowNumber);
|
||||||
|
// 向iotdb里面添加数据
|
||||||
|
int rowIndex = tablet.rowSize++;
|
||||||
|
tablet.addTimestamp(rowIndex, time);
|
||||||
|
for (int i = 0; i < valueList.size(); i++) {
|
||||||
|
tablet.addValue(schemaList.get(i).getMeasurementId(), rowIndex, valueList.get(i));
|
||||||
|
}
|
||||||
|
if (tablet.rowSize == tablet.getMaxRowNumber()) {
|
||||||
|
session.insertTablet(tablet, true);
|
||||||
|
tablet.reset();
|
||||||
|
}
|
||||||
|
if (tablet.rowSize != 0) {
|
||||||
|
session.insertTablet(tablet);
|
||||||
|
tablet.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* description: 根据SQL查询
|
||||||
|
* author: zhouhong
|
||||||
|
*/
|
||||||
|
public SessionDataSet query(String sql) throws StatementExecutionException, IoTDBConnectionException {
|
||||||
|
return session.executeQueryStatement(sql);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* description: 删除分组 如 root.a1eaKSRpRty
|
||||||
|
* author: zhouhong
|
||||||
|
* @param groupName:分组名称
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public void deleteStorageGroup(String groupName) throws StatementExecutionException, IoTDBConnectionException {
|
||||||
|
session.deleteStorageGroup(groupName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* description: 根据Timeseries删除 如:root.a1eaKSRpRty.CA3013A303A25467.breath (个人理解:为具体的物理量)
|
||||||
|
* author: zhouhong
|
||||||
|
*/
|
||||||
|
public void deleteTimeseries(String timeseries) throws StatementExecutionException, IoTDBConnectionException {
|
||||||
|
session.deleteTimeseries(timeseries);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* description: 根据Timeseries批量删除
|
||||||
|
* author: zhouhong
|
||||||
|
*/
|
||||||
|
public void deleteTimeserieList(List<String> timeseriesList) throws StatementExecutionException, IoTDBConnectionException {
|
||||||
|
session.deleteTimeseries(timeseriesList);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* description: 根据分组批量删除
|
||||||
|
* author: zhouhong
|
||||||
|
*/
|
||||||
|
public void deleteStorageGroupList(List<String> storageGroupList) throws StatementExecutionException, IoTDBConnectionException {
|
||||||
|
session.deleteStorageGroups(storageGroupList);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* description: 根据路径和结束时间删除 结束时间之前的所有数据
|
||||||
|
* author: zhouhong
|
||||||
|
*/
|
||||||
|
public void deleteDataByPathAndEndTime(String path, Long endTime) throws StatementExecutionException, IoTDBConnectionException {
|
||||||
|
session.deleteData(path, endTime);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* description: 根据路径集合和结束时间批量删除 结束时间之前的所有数据
|
||||||
|
* author: zhouhong
|
||||||
|
*/
|
||||||
|
public void deleteDataByPathListAndEndTime(List<String> pathList, Long endTime) throws StatementExecutionException, IoTDBConnectionException {
|
||||||
|
session.deleteData(pathList, endTime);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* description: 根据路径集合和时间段批量删除
|
||||||
|
* author: zhouhong
|
||||||
|
*/
|
||||||
|
public void deleteDataByPathListAndTime(List<String> pathList, Long startTime,Long endTime) throws StatementExecutionException, IoTDBConnectionException {
|
||||||
|
session.deleteData(pathList, startTime, endTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
package com.muyu.eventdriven.config.rabbit;
|
||||||
|
|
||||||
|
import com.muyu.eventdriven.constants.RabbitConstants;
|
||||||
|
import org.springframework.amqp.core.Binding;
|
||||||
|
import org.springframework.amqp.core.BindingBuilder;
|
||||||
|
import org.springframework.amqp.core.DirectExchange;
|
||||||
|
import org.springframework.amqp.core.Queue;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName RabbitRoutingConfig
|
||||||
|
* @Description rabbit配置类
|
||||||
|
* @Author Yunfei.Du
|
||||||
|
* @Date 2024/6/21 上午11:35
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class RabbitRoutingConfig {
|
||||||
|
/**
|
||||||
|
* Queue 可以有4个参数
|
||||||
|
* 1.name 队列名
|
||||||
|
* 2.durable 持久化消息队列 ,rabbitmq重启的时候不需要创建新的队列 默认true
|
||||||
|
* 3.auto-delete 表示消息队列没有在使用时将被自动删除 默认是false
|
||||||
|
* 4.exclusive 表示该消息队列是否只在当前connection生效,默认是false
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public Queue createRoutingQueueA() {
|
||||||
|
return new Queue(RabbitConstants.QUEUE_STATUS_ABNORMAL, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public Queue createRoutingQueueB() {
|
||||||
|
return new Queue(RabbitConstants.QUEUE_STATUS_NORMAL, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public DirectExchange routingExchange() {
|
||||||
|
//配置广播路由器
|
||||||
|
return new DirectExchange(RabbitConstants.EXCHANGE_STATUS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public Binding bingQueueAToRoutingExchange() {
|
||||||
|
return BindingBuilder.bind(createRoutingQueueA()).to(routingExchange()).with(RabbitConstants.STATUS_ABNORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public Binding bingQueueBToRoutingExchange() {
|
||||||
|
return BindingBuilder.bind(createRoutingQueueB()).to(routingExchange()).with(RabbitConstants.STATUS_NORMAL);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
package com.muyu.eventdriven.config.redis;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||||
|
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName RedisListenerConfig
|
||||||
|
* @Description redis键过期监听配置类
|
||||||
|
* @Author Yunfei.Du
|
||||||
|
* @Date 2024/6/21 上午11:23
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class RedisListenerConfig {
|
||||||
|
@Bean
|
||||||
|
public RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) {
|
||||||
|
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
|
||||||
|
container.setConnectionFactory(connectionFactory);
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,134 @@
|
||||||
|
package com.muyu.eventdriven.constants;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通用常量信息
|
||||||
|
*
|
||||||
|
* @author muyu
|
||||||
|
*/
|
||||||
|
public class Constants {
|
||||||
|
/**
|
||||||
|
* UTF-8 字符集
|
||||||
|
*/
|
||||||
|
public static final String UTF8 = "UTF-8";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GBK 字符集
|
||||||
|
*/
|
||||||
|
public static final String GBK = "GBK";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* www主域
|
||||||
|
*/
|
||||||
|
public static final String WWW = "www.";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RMI 远程方法调用
|
||||||
|
*/
|
||||||
|
public static final String LOOKUP_RMI = "rmi:";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LDAP 远程方法调用
|
||||||
|
*/
|
||||||
|
public static final String LOOKUP_LDAP = "ldap:";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LDAPS 远程方法调用
|
||||||
|
*/
|
||||||
|
public static final String LOOKUP_LDAPS = "ldaps:";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* http请求
|
||||||
|
*/
|
||||||
|
public static final String HTTP = "http://";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* https请求
|
||||||
|
*/
|
||||||
|
public static final String HTTPS = "https://";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 成功标记
|
||||||
|
*/
|
||||||
|
public static final Integer SUCCESS = 200;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 失败标记
|
||||||
|
*/
|
||||||
|
public static final Integer FAIL = 500;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录成功状态
|
||||||
|
*/
|
||||||
|
public static final String LOGIN_SUCCESS_STATUS = "0";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录失败状态
|
||||||
|
*/
|
||||||
|
public static final String LOGIN_FAIL_STATUS = "1";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录成功
|
||||||
|
*/
|
||||||
|
public static final String LOGIN_SUCCESS = "Success";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注销
|
||||||
|
*/
|
||||||
|
public static final String LOGOUT = "Logout";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注册
|
||||||
|
*/
|
||||||
|
public static final String REGISTER = "Register";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录失败
|
||||||
|
*/
|
||||||
|
public static final String LOGIN_FAIL = "Error";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前记录起始索引
|
||||||
|
*/
|
||||||
|
public static final String PAGE_NUM = "pageNum";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 每页显示记录数
|
||||||
|
*/
|
||||||
|
public static final String PAGE_SIZE = "pageSize";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 排序列
|
||||||
|
*/
|
||||||
|
public static final String ORDER_BY_COLUMN = "orderByColumn";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 排序的方向 "desc" 或者 "asc".
|
||||||
|
*/
|
||||||
|
public static final String IS_ASC = "isAsc";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证码有效期(分钟)
|
||||||
|
*/
|
||||||
|
public static final long CAPTCHA_EXPIRATION = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 资源映射路径 前缀
|
||||||
|
*/
|
||||||
|
public static final String RESOURCE_PREFIX = "/profile";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自动识别json对象白名单配置(仅允许解析的包名,范围越小越安全)
|
||||||
|
*/
|
||||||
|
public static final String[] JSON_WHITELIST_STR = {"org.springframework", "com.muyu"};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 定时任务白名单配置(仅允许访问的包名,如其他需要可以自行添加)
|
||||||
|
*/
|
||||||
|
public static final String[] JOB_WHITELIST_STR = {"com.muyu"};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 定时任务违规的字符
|
||||||
|
*/
|
||||||
|
public static final String[] JOB_ERROR_STR = {"java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml",
|
||||||
|
"org.springframework", "org.apache", "com.muyu.common.core.utils.file"};
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package com.muyu.eventdriven.constants;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName FaultCodeConstants
|
||||||
|
* @Description 故障码常量
|
||||||
|
* @Author Yunfei.Du
|
||||||
|
* @Date 2024/6/21 上午11:49
|
||||||
|
*/
|
||||||
|
public class FaultCodeConstants {
|
||||||
|
public static final String VEHICLESTATUS = "GZ001";
|
||||||
|
public static final String CHARGINGSTATUS = "GZ002";
|
||||||
|
public static final String OPERATINGSTATUS = "GZ003";
|
||||||
|
public static final String SOCSTATUS = "GZ004";
|
||||||
|
public static final String CHARGINGENERGYSTORAGESTATUS = "GZ005";
|
||||||
|
public static final String DRIVEMOTORSTATUS = "GZ006";
|
||||||
|
public static final String POSITIONSTATUS = "GZ007";
|
||||||
|
public static final String EASSTATUS = "GZ008";
|
||||||
|
public static final String PTCSTATUS = "GZ009";
|
||||||
|
public static final String EPSSTATUS = "GZ010";
|
||||||
|
public static final String ABSSTATUS = "GZ011";
|
||||||
|
public static final String MCUSTATUS = "GZ012";
|
||||||
|
public static final String HEATINGSTATUS = "GZ013";
|
||||||
|
public static final String BATTERYSTATUS = "GZ014";
|
||||||
|
public static final String BATTERYINSULATIONSTATUS = "GZ015";
|
||||||
|
public static final String DCDCSTATUS = "GZ016";
|
||||||
|
public static final String CHGSTATUS = "GZ017";
|
||||||
|
}
|
|
@ -0,0 +1,93 @@
|
||||||
|
package com.muyu.eventdriven.constants;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回状态码
|
||||||
|
*
|
||||||
|
* @author muyu
|
||||||
|
*/
|
||||||
|
public class HttpStatus {
|
||||||
|
/**
|
||||||
|
* 操作成功
|
||||||
|
*/
|
||||||
|
public static final int SUCCESS = 200;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 对象创建成功
|
||||||
|
*/
|
||||||
|
public static final int CREATED = 201;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求已经被接受
|
||||||
|
*/
|
||||||
|
public static final int ACCEPTED = 202;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作已经执行成功,但是没有返回数据
|
||||||
|
*/
|
||||||
|
public static final int NO_CONTENT = 204;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 资源已被移除
|
||||||
|
*/
|
||||||
|
public static final int MOVED_PERM = 301;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重定向
|
||||||
|
*/
|
||||||
|
public static final int SEE_OTHER = 303;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 资源没有被修改
|
||||||
|
*/
|
||||||
|
public static final int NOT_MODIFIED = 304;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 参数列表错误(缺少,格式不匹配)
|
||||||
|
*/
|
||||||
|
public static final int BAD_REQUEST = 400;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 未授权
|
||||||
|
*/
|
||||||
|
public static final int UNAUTHORIZED = 401;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 访问受限,授权过期
|
||||||
|
*/
|
||||||
|
public static final int FORBIDDEN = 403;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 资源,服务未找到
|
||||||
|
*/
|
||||||
|
public static final int NOT_FOUND = 404;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 不允许的http方法
|
||||||
|
*/
|
||||||
|
public static final int BAD_METHOD = 405;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 资源冲突,或者资源被锁
|
||||||
|
*/
|
||||||
|
public static final int CONFLICT = 409;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 不支持的数据,媒体类型
|
||||||
|
*/
|
||||||
|
public static final int UNSUPPORTED_TYPE = 415;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统内部错误
|
||||||
|
*/
|
||||||
|
public static final int ERROR = 500;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 接口未实现
|
||||||
|
*/
|
||||||
|
public static final int NOT_IMPLEMENTED = 501;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统警告消息
|
||||||
|
*/
|
||||||
|
public static final int WARN = 601;
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package com.muyu.eventdriven.constants;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName RabbitConstants
|
||||||
|
* @Description Rabbit常量类
|
||||||
|
* @Author Yunfei.Du
|
||||||
|
* @Date 2024/6/21 上午11:39
|
||||||
|
*/
|
||||||
|
public class RabbitConstants {
|
||||||
|
public static final String QUEUE_STATUS_ABNORMAL = "zhiLian-vehicle-end";
|
||||||
|
public static final String QUEUE_STATUS_NORMAL = "zhiLian-vehicle-start";
|
||||||
|
public static final String EXCHANGE_STATUS = "exchange_status";
|
||||||
|
public static final String STATUS_ABNORMAL = "abnormal";
|
||||||
|
public static final String STATUS_NORMAL = "normal";
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
package com.muyu.eventdriven.constants;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName RedisConstants
|
||||||
|
* @Description Redis常量
|
||||||
|
* @Author Yunfei.Du
|
||||||
|
* @Date 2024/6/20 下午3:30
|
||||||
|
*/
|
||||||
|
public class RedisConstants {
|
||||||
|
public static final String VEHICLE_EVENT = "vehicle_event";
|
||||||
|
public static final String VEHICLE_FAULT_KEY = "vehicle_fault_key:";
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
package com.muyu.eventdriven.consumer;
|
||||||
|
|
||||||
|
import com.muyu.eventdriven.domain.VehicleKafka;
|
||||||
|
import org.apache.kafka.clients.consumer.ConsumerConfig;
|
||||||
|
import org.apache.kafka.clients.consumer.KafkaConsumer;
|
||||||
|
import org.apache.kafka.common.TopicPartition;
|
||||||
|
import org.apache.kafka.common.serialization.StringDeserializer;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName KafkaConsumers
|
||||||
|
* @Description 描述
|
||||||
|
* @Author Yunfei.Du
|
||||||
|
* @Date 2024/6/9 上午9:54
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class KafkaConsumers {
|
||||||
|
@Value("${spring.kafka.bootstrap-servers}")
|
||||||
|
private String bootstrapServers;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public KafkaConsumer kafkaConsumer(VehicleKafka vehicleKafka){
|
||||||
|
Properties properties = new Properties();
|
||||||
|
properties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
|
||||||
|
properties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
|
||||||
|
properties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
|
||||||
|
// 指定分区策略
|
||||||
|
properties.put(ConsumerConfig.PARTITION_ASSIGNMENT_STRATEGY_CONFIG, "org.apache.kafka.clients.consumer.RoundRobinAssignor");
|
||||||
|
// 指定消费者组,必须参数
|
||||||
|
properties.put(ConsumerConfig.GROUP_ID_CONFIG, "test1");
|
||||||
|
properties.put(ConsumerConfig.MAX_POLL_RECORDS_CONFIG, "500");
|
||||||
|
KafkaConsumer<String, String> consumer = new KafkaConsumer<>(properties);
|
||||||
|
// 订阅主题分区
|
||||||
|
List<TopicPartition> topicPartitions = new ArrayList<>();
|
||||||
|
//第一个是主题名 第二个是分区
|
||||||
|
topicPartitions.add(new TopicPartition(vehicleKafka.getConsumerName(), vehicleKafka.getPartitions()));
|
||||||
|
consumer.assign(topicPartitions);
|
||||||
|
return consumer;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
package com.muyu.eventdriven.consumer.redis;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.muyu.eventdriven.constants.RabbitConstants;
|
||||||
|
import com.muyu.eventdriven.constants.RedisConstants;
|
||||||
|
import com.muyu.eventdriven.domain.RabbitFalut;
|
||||||
|
import com.muyu.eventdriven.domain.VehicleFaultStatus;
|
||||||
|
import lombok.extern.log4j.Log4j2;
|
||||||
|
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.data.redis.connection.Message;
|
||||||
|
import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;
|
||||||
|
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName RedisKeyExpirationListener
|
||||||
|
* @Description redsi键过期监听类
|
||||||
|
* @Author Yunfei.Du
|
||||||
|
* @Date 2024/6/21 上午11:27
|
||||||
|
*/
|
||||||
|
@Log4j2
|
||||||
|
@Component
|
||||||
|
public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener {
|
||||||
|
@Autowired
|
||||||
|
private RabbitTemplate rabbitTemplate;
|
||||||
|
|
||||||
|
public RedisKeyExpirationListener(RedisMessageListenerContainer listenerContainer) {
|
||||||
|
super(listenerContainer);
|
||||||
|
}
|
||||||
|
|
||||||
|
//拿到过期key的信息并做处理
|
||||||
|
@Override
|
||||||
|
public void onMessage(Message messages, byte[] pattern) {
|
||||||
|
String key = messages.toString();
|
||||||
|
if (key.contains(RedisConstants.VEHICLE_FAULT_KEY)){
|
||||||
|
String[] split = key.split(":");
|
||||||
|
RabbitFalut rabbitFalut = new RabbitFalut();
|
||||||
|
rabbitFalut.setEndTime(new Date());
|
||||||
|
rabbitFalut.setVin(split[1]);
|
||||||
|
rabbitFalut.setFaultCode(split[2]);
|
||||||
|
rabbitTemplate.convertAndSend(RabbitConstants.EXCHANGE_STATUS,RabbitConstants.QUEUE_STATUS_ABNORMAL, JSON.toJSONString(rabbitFalut),message ->{
|
||||||
|
message.getMessageProperties().setMessageId( UUID.randomUUID().toString());
|
||||||
|
//设置消息延迟时间为5秒
|
||||||
|
message.getMessageProperties().setDelay(5000);
|
||||||
|
log.info ( "消息发送成功" );
|
||||||
|
return message;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
package com.muyu.eventdriven.controller;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.muyu.eventdriven.domain.rest.Result;
|
||||||
|
import com.muyu.eventdriven.server.EventInfoService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName EventInfoController
|
||||||
|
* @Description 事件信息控制层
|
||||||
|
* @Author Yunfei.Du
|
||||||
|
* @Date 2024/6/16 下午3:58
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/eventInfo")
|
||||||
|
public class EventInfoController {
|
||||||
|
@Autowired
|
||||||
|
private EventInfoService eventInfoService;
|
||||||
|
|
||||||
|
@GetMapping("/CreatKafkaConsumer")
|
||||||
|
public void creatKafkaConsumer(@RequestParam("vin") String vin) throws JsonProcessingException {
|
||||||
|
eventInfoService.creatKafkaConsumer(vin);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/CloseKafkaConsumer")
|
||||||
|
public Result closeKafkaConsumer(@RequestParam("vin") String vin) {
|
||||||
|
return eventInfoService.closeKafkaConsumer(vin);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
package com.muyu.eventdriven.controller;
|
||||||
|
|
||||||
|
import com.muyu.eventdriven.config.iotdb.IotDBSessionConfig;
|
||||||
|
import com.muyu.eventdriven.domain.VehicleData;
|
||||||
|
import com.muyu.eventdriven.model.param.IotDbParam;
|
||||||
|
import com.muyu.eventdriven.response.ResponseData;
|
||||||
|
import com.muyu.eventdriven.server.IotDbServer;
|
||||||
|
import lombok.extern.log4j.Log4j2;
|
||||||
|
import org.apache.iotdb.rpc.IoTDBConnectionException;
|
||||||
|
import org.apache.iotdb.rpc.StatementExecutionException;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.rmi.ServerException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName AsVehicleEvent
|
||||||
|
* @Description iotdb控制层
|
||||||
|
* @Author Yunfei.Du
|
||||||
|
* @Date 2024/6/16 下午3:29
|
||||||
|
*/
|
||||||
|
@Log4j2
|
||||||
|
@RestController
|
||||||
|
public class IotDbController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private IotDbServer iotDbServer;
|
||||||
|
@Resource
|
||||||
|
private IotDBSessionConfig iotDBSessionConfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插入数据
|
||||||
|
* @param iotDbParam
|
||||||
|
*/
|
||||||
|
@PostMapping("/api/device/insert")
|
||||||
|
public ResponseData insert(@RequestBody VehicleData vehicleData) throws StatementExecutionException, ServerException, IoTDBConnectionException {
|
||||||
|
iotDbServer.insertData(vehicleData);
|
||||||
|
return ResponseData.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询数据
|
||||||
|
* @param iotDbParam
|
||||||
|
*/
|
||||||
|
@PostMapping("/api/device/queryData")
|
||||||
|
public ResponseData queryDataFromIotDb(@RequestBody IotDbParam iotDbParam) throws Exception {
|
||||||
|
return ResponseData.success(iotDbServer.queryDataFromIotDb(iotDbParam));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除分组
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@PostMapping("/api/device/deleteGroup")
|
||||||
|
public ResponseData deleteGroup() throws StatementExecutionException, IoTDBConnectionException {
|
||||||
|
iotDBSessionConfig.deleteStorageGroup("root.a1eaKSRpRty");
|
||||||
|
iotDBSessionConfig.deleteStorageGroup("root.smartretirement");
|
||||||
|
return ResponseData.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
package com.muyu.eventdriven.domain;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.SuperBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName AsVehicleEvent
|
||||||
|
* @Description 车辆拥有事件
|
||||||
|
* @Author Yunfei.Du
|
||||||
|
* @Date 2024/6/16 下午3:29
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@SuperBuilder
|
||||||
|
public class AsVehicleEvent {
|
||||||
|
private Integer id;
|
||||||
|
private String vehicleVin;
|
||||||
|
private Integer eventInfoId;
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
package com.muyu.eventdriven.domain;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.SuperBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName EventInfo
|
||||||
|
* @Description 描述
|
||||||
|
* @Author Yunfei.Du
|
||||||
|
* @Date 2024/6/16 下午3:14
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@SuperBuilder
|
||||||
|
public class EventInfo {
|
||||||
|
private Integer id;
|
||||||
|
private String eventName;
|
||||||
|
private Integer eventTypeId;
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
package com.muyu.eventdriven.domain;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName EventTactics
|
||||||
|
* @Description 事件
|
||||||
|
* @Author Yunfei.Du
|
||||||
|
* @Date 2024/6/20 下午3:57
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class EventTacticsManage {
|
||||||
|
|
||||||
|
// public void initEventTacticsManage(){
|
||||||
|
// ArrayList<String> strings = new ArrayList<>();
|
||||||
|
// strings.add("com.muyu.eventdriven.tactics.basics.StorageEvent");
|
||||||
|
// strings.add("com.muyu.eventdriven.tactics.system.ElectronicFenceEvent");
|
||||||
|
// strings.add("com.muyu.eventdriven.tactics.system.FaultAlarmEvent");
|
||||||
|
// strings.add("com.muyu.eventdriven.tactics.system.RealTimeDataEvent");
|
||||||
|
// strings.add("com.muyu.eventdriven.tactics.system.IndexWarningEvent");
|
||||||
|
// for (int i = 1; i <= strings.size(); i++) {
|
||||||
|
// eventContextMap.put(String.valueOf(i),new EventContext(strings.get(i-1)));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// public EventContext getEventContext(String key){
|
||||||
|
// return eventContextMap.get(key);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// public void setEventContext(String key,EventContext eventContext){
|
||||||
|
// eventContextMap.put(key,eventContext);
|
||||||
|
// }
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package com.muyu.eventdriven.domain;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.SuperBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName EventType
|
||||||
|
* @Description 事件类型实体类
|
||||||
|
* @Author Yunfei.Du
|
||||||
|
* @Date 2024/6/16 下午3:15
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@SuperBuilder
|
||||||
|
public class EventType {
|
||||||
|
private Integer id;
|
||||||
|
private String EventTypeName;
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package com.muyu.eventdriven.domain;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName RabbitFalut
|
||||||
|
* @Description 描述
|
||||||
|
* @Author YunFei.Du
|
||||||
|
* @Date 2024/6/25 11:42
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class RabbitFalut {
|
||||||
|
private String faultCode;
|
||||||
|
private String vin;
|
||||||
|
private Date startTime;
|
||||||
|
private Date endTime;
|
||||||
|
}
|
|
@ -0,0 +1,261 @@
|
||||||
|
package com.muyu.eventdriven.domain;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.SuperBuilder;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName VehicleData
|
||||||
|
* @Description 描述
|
||||||
|
* @Author Yunfei.Du
|
||||||
|
* @Date 2024/6/5 下午6:52
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@SuperBuilder
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class VehicleData {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* VIN
|
||||||
|
*/
|
||||||
|
private String vin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 行驶路线
|
||||||
|
*/
|
||||||
|
private String drivingRoute;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 经度
|
||||||
|
*/
|
||||||
|
private String longitude;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 维度
|
||||||
|
*/
|
||||||
|
private String latitude;
|
||||||
|
/**
|
||||||
|
* 速度
|
||||||
|
*/
|
||||||
|
private String speed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 里程
|
||||||
|
*/
|
||||||
|
private BigDecimal mileage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 总电压
|
||||||
|
*/
|
||||||
|
private String voltage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 总电流
|
||||||
|
*/
|
||||||
|
private String current;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 绝缘电阻
|
||||||
|
*/
|
||||||
|
private String resistance;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 档位
|
||||||
|
*/
|
||||||
|
private String gear = "P";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加速踏板行程值
|
||||||
|
*/
|
||||||
|
private String accelerationPedal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 制动踏板行程值
|
||||||
|
*/
|
||||||
|
private String brakePedal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 燃料消耗率
|
||||||
|
*/
|
||||||
|
private String fuelConsumptionRate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 电机控制器温度
|
||||||
|
*/
|
||||||
|
private String motorControllerTemperature;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 电机转速
|
||||||
|
*/
|
||||||
|
private String motorSpeed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 电机转矩
|
||||||
|
*/
|
||||||
|
private String motorTorque;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 电机温度
|
||||||
|
*/
|
||||||
|
private String motorTemperature;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 电机电压
|
||||||
|
*/
|
||||||
|
private String motorVoltage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 电机电流
|
||||||
|
*/
|
||||||
|
private String motorCurrent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 动力电池剩余电量SOC
|
||||||
|
*/
|
||||||
|
private BigDecimal remainingBattery;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 电池总容量
|
||||||
|
*/
|
||||||
|
private BigDecimal batteryLevel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前状态允许的最大反馈功率
|
||||||
|
*/
|
||||||
|
private String maximumFeedbackPower;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前状态允许最大放电功率
|
||||||
|
*/
|
||||||
|
private String maximumDischargePower;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BMS自检计数器
|
||||||
|
*/
|
||||||
|
private String selfCheckCounter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 动力电池充放电电流
|
||||||
|
*/
|
||||||
|
private String totalBatteryCurrent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 动力电池负载端总电压V3
|
||||||
|
*/
|
||||||
|
private String totalBatteryVoltage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单次最大电压
|
||||||
|
*/
|
||||||
|
private String singleBatteryMaxVoltage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单体电池最低电压
|
||||||
|
*/
|
||||||
|
private String singleBatteryMinVoltage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单体电池最高温度
|
||||||
|
*/
|
||||||
|
private String singleBatteryMaxTemperature;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单体电池最低温度
|
||||||
|
*/
|
||||||
|
private String singleBatteryMinTemperature;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 动力电池可用容量
|
||||||
|
*/
|
||||||
|
private String availableBatteryCapacity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 车辆状态
|
||||||
|
*/
|
||||||
|
private int vehicleStatus = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 充电状态
|
||||||
|
*/
|
||||||
|
private int chargingStatus = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 运行状态
|
||||||
|
*/
|
||||||
|
private int operatingStatus = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SOC
|
||||||
|
*/
|
||||||
|
private int socStatus = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 可充电储能装置工作状态
|
||||||
|
*/
|
||||||
|
private int chargingEnergyStorageStatus = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 驱动电机状态
|
||||||
|
*/
|
||||||
|
private int driveMotorStatus = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 定位是否有效
|
||||||
|
*/
|
||||||
|
private int positionStatus = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* EAS(汽车防盗系统)状态
|
||||||
|
*/
|
||||||
|
private int easStatus = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PTC(电动加热器)状态
|
||||||
|
*/
|
||||||
|
private int ptcStatus = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* EPS(电动助力系统)状态
|
||||||
|
*/
|
||||||
|
private int epsStatus = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ABS(防抱死)状态
|
||||||
|
*/
|
||||||
|
private int absStatus = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MCU(电机/逆变器)状态
|
||||||
|
*/
|
||||||
|
private int mcuStatus = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 动力电池加热状态
|
||||||
|
*/
|
||||||
|
private int heatingStatus = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 动力电池当前状态
|
||||||
|
*/
|
||||||
|
private int batteryStatus = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 动力电池保温状态
|
||||||
|
*/
|
||||||
|
private int batteryInsulationStatus = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DCDC(电力交换系统)状态
|
||||||
|
*/
|
||||||
|
private int dcdcStatus = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CHG(充电机)状态
|
||||||
|
*/
|
||||||
|
private int chgStatus = 1;
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package com.muyu.eventdriven.domain;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.SuperBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName VehicleFaultStatus
|
||||||
|
* @Description 车辆状态报警类
|
||||||
|
* @Author Yunfei.Du
|
||||||
|
* @Date 2024/6/21 上午11:46
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@SuperBuilder
|
||||||
|
public class VehicleFaultStatus {
|
||||||
|
public String vin;
|
||||||
|
public Long timestamp;
|
||||||
|
public String faultCode;
|
||||||
|
public String faultType;
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package com.muyu.eventdriven.domain;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName Test
|
||||||
|
* @Description 描述
|
||||||
|
* @Author Yunfei.Du
|
||||||
|
* @Date 2024/6/9 上午10:56
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class VehicleKafka {
|
||||||
|
//分区
|
||||||
|
private Integer partitions;
|
||||||
|
|
||||||
|
private String key;
|
||||||
|
//主题
|
||||||
|
private String consumerName;
|
||||||
|
}
|
|
@ -0,0 +1,112 @@
|
||||||
|
package com.muyu.eventdriven.domain.rest;
|
||||||
|
|
||||||
|
import com.muyu.eventdriven.constants.Constants;
|
||||||
|
import com.muyu.eventdriven.constants.HttpStatus;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 响应信息主体
|
||||||
|
*
|
||||||
|
* @author muyu
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class Result<T> implements Serializable {
|
||||||
|
/**
|
||||||
|
* 成功
|
||||||
|
*/
|
||||||
|
public static final int SUCCESS = Constants.SUCCESS;
|
||||||
|
/**
|
||||||
|
* 失败
|
||||||
|
*/
|
||||||
|
public static final int FAIL = Constants.FAIL;
|
||||||
|
/**
|
||||||
|
* 警告
|
||||||
|
*/
|
||||||
|
public static final int WARN = HttpStatus.WARN;
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private int code;
|
||||||
|
|
||||||
|
private String msg;
|
||||||
|
|
||||||
|
private T data;
|
||||||
|
|
||||||
|
public static <T> Result<T> success () {
|
||||||
|
return restResult(null, SUCCESS, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> Result<T> success (T data) {
|
||||||
|
return restResult(data, SUCCESS, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> Result<T> success (T data, String msg) {
|
||||||
|
return restResult(data, SUCCESS, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> Result<T> error () {
|
||||||
|
return restResult(null, FAIL, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> Result<T> error (String msg) {
|
||||||
|
return restResult(null, FAIL, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> Result<T> error (T data) {
|
||||||
|
return restResult(data, FAIL, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> Result<T> error (T data, String msg) {
|
||||||
|
return restResult(data, FAIL, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> Result<T> error (int code, String msg) {
|
||||||
|
return restResult(null, code, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static <T> Result<T> warn () {
|
||||||
|
return restResult(null, WARN, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> Result<T> warn (String msg) {
|
||||||
|
return restResult(null, WARN, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> Result<T> warn (T data) {
|
||||||
|
return restResult(data, WARN, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> Result<T> warn (T data, String msg) {
|
||||||
|
return restResult(data, WARN, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> Result<T> warn (int code, String msg) {
|
||||||
|
return restResult(null, code, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <T> Result<T> restResult (T data, int code, String msg) {
|
||||||
|
return Result.<T>builder()
|
||||||
|
.code(code)
|
||||||
|
.data(data)
|
||||||
|
.msg(msg)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> Boolean isError (Result<T> ret) {
|
||||||
|
return !isSuccess(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> Boolean isSuccess (Result<T> ret) {
|
||||||
|
return Result.SUCCESS == ret.getCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
package com.muyu.eventdriven.listener;
|
||||||
|
|
||||||
|
import lombok.extern.log4j.Log4j2;
|
||||||
|
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.data.redis.connection.Message;
|
||||||
|
import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;
|
||||||
|
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RedisKeyExpirationListener
|
||||||
|
*
|
||||||
|
* @author Yangle
|
||||||
|
* Date 2024/6/21 14:12
|
||||||
|
*/
|
||||||
|
@Log4j2
|
||||||
|
@Configuration
|
||||||
|
public class RedisExpirationListener extends KeyExpirationEventMessageListener {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RabbitTemplate rabbitTemplate;
|
||||||
|
|
||||||
|
|
||||||
|
public RedisExpirationListener(RedisMessageListenerContainer listenerContainer) {
|
||||||
|
super ( listenerContainer );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 针对redis数据失效事件,进行数据处理
|
||||||
|
* @param message 失效的key
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void onMessage(Message message, byte[] pattern) {
|
||||||
|
log.info("过期redis数据:" + message.toString());
|
||||||
|
try {
|
||||||
|
String key = message.toString();
|
||||||
|
log.info("过期redis数据:" + key);
|
||||||
|
rabbitTemplate.convertAndSend("disconnect_connect","resolve_time",key);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
log.error("【修改支付订单过期状态异常】:" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,111 @@
|
||||||
|
//package com.mobai.kafka.listener;
|
||||||
|
//
|
||||||
|
//import com.mobai.domain.MqttServerModel;
|
||||||
|
//import com.mobai.domain.Vehicle;
|
||||||
|
//import com.mobai.domain.VehicleEvent;
|
||||||
|
//import com.mobai.forest.ForestGet;
|
||||||
|
//import com.mobai.utils.RedisService;
|
||||||
|
//import com.mobai.vehicle.event.service.EventsService;
|
||||||
|
//import com.mobai.vehicle.ownModel.HandlerHelper;
|
||||||
|
//import lombok.extern.log4j.Log4j2;
|
||||||
|
//import org.apache.kafka.clients.consumer.ConsumerRecord;
|
||||||
|
//import org.apache.kafka.clients.consumer.ConsumerRecords;
|
||||||
|
//import org.apache.kafka.clients.consumer.KafkaConsumer;
|
||||||
|
//import org.apache.kafka.common.TopicPartition;
|
||||||
|
//import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
//import org.springframework.boot.ApplicationArguments;
|
||||||
|
//import org.springframework.boot.ApplicationRunner;
|
||||||
|
//import org.springframework.stereotype.Component;
|
||||||
|
//
|
||||||
|
//import java.time.Duration;
|
||||||
|
//import java.util.ArrayList;
|
||||||
|
//import java.util.List;
|
||||||
|
//import java.util.Properties;
|
||||||
|
//import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
//
|
||||||
|
///**
|
||||||
|
// * @author Saisai
|
||||||
|
// * @className VinConsumerRunner
|
||||||
|
// * @description 描述
|
||||||
|
// * @date 2024/6/18 17:18
|
||||||
|
// */
|
||||||
|
//
|
||||||
|
//@Log4j2
|
||||||
|
//@Component
|
||||||
|
//public class VinConsumerRunner implements ApplicationRunner {
|
||||||
|
//
|
||||||
|
// @Autowired
|
||||||
|
// private ForestGet forestGet;
|
||||||
|
//
|
||||||
|
// @Autowired
|
||||||
|
// private KafkaConsumerListenerExample kafkaConsumerListenerExample;
|
||||||
|
//
|
||||||
|
// @Autowired
|
||||||
|
// private RedisService redisService;
|
||||||
|
//
|
||||||
|
// @Autowired
|
||||||
|
// private EventsService eventsService;
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// private final AtomicInteger start = new AtomicInteger();
|
||||||
|
// @Override
|
||||||
|
// public void run(ApplicationArguments args) throws Exception {
|
||||||
|
// if (start.get() != 0) {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// synchronized (this) {
|
||||||
|
// if (start.get() != 0) {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// start.set(1);
|
||||||
|
//
|
||||||
|
// // kafka分区监听器
|
||||||
|
// new Thread(() -> {
|
||||||
|
// ArrayList<TopicPartition> topicPartitions = new ArrayList<>();
|
||||||
|
// List<String> topics = forestGet.getIps().getData().stream().map(MqttServerModel::getTopic).toList();
|
||||||
|
// for (String topic : topics) {
|
||||||
|
// for (int i = 0; i < 8; i++) {
|
||||||
|
// TopicPartition topicPartition = new TopicPartition(topic, i);
|
||||||
|
// topicPartitions.add(topicPartition);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// Properties props = new Properties(){{
|
||||||
|
// put("bootstrap.servers", "localhost:9092");
|
||||||
|
// put("auto.commit.interval.ms", "1000");
|
||||||
|
// put("group.id", "test");
|
||||||
|
// put("enable.auto.commit", "true");
|
||||||
|
// put("session.timeout.ms", "30000");
|
||||||
|
// put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
|
||||||
|
// put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
|
||||||
|
// }};
|
||||||
|
// KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props);
|
||||||
|
// consumer.assign(topicPartitions);
|
||||||
|
// try {
|
||||||
|
// while (true) {
|
||||||
|
// ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(100));
|
||||||
|
// if (!records.isEmpty()) {
|
||||||
|
// new Thread(() -> {
|
||||||
|
// for (TopicPartition partition : records.partitions()) {
|
||||||
|
// List<ConsumerRecord<String, String>> partitionRecords = records.records(partition);
|
||||||
|
// for (ConsumerRecord<String, String> record : partitionRecords) {
|
||||||
|
// log.info("Offset = {}, Key = {}, Value = {}", record.offset(), record.key(), record.value());
|
||||||
|
// Vehicle vehicle = kafkaConsumerListenerExample.getVehicle(record.value());
|
||||||
|
// VehicleEvent events = eventsService.getEvents(vehicle.getVin());
|
||||||
|
// HandlerHelper.doHandler(events, vehicle, redisService);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }).start();
|
||||||
|
// } else {
|
||||||
|
// Thread.sleep(10);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// } catch (InterruptedException e) {
|
||||||
|
// Thread.currentThread().interrupt();
|
||||||
|
// log.error("Consumer was interrupted.", e);
|
||||||
|
// } finally {
|
||||||
|
// consumer.close();
|
||||||
|
// }
|
||||||
|
// }).start();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package com.muyu.eventdriven.mapper;
|
||||||
|
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName EventDrivenMapper
|
||||||
|
* @Description 事件系统DAO层
|
||||||
|
* @Author Yunfei.Du
|
||||||
|
* @Date 2024/6/16 下午3:47
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface EventDrivenMapper {
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
package com.muyu.eventdriven.model.param;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
/**
|
||||||
|
* @ClassName AsVehicleEvent
|
||||||
|
* @Description iotdb控制层入参
|
||||||
|
* @Author Yunfei.Du
|
||||||
|
* @Date 2024/6/16 下午3:29
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class IotDbParam {
|
||||||
|
/***
|
||||||
|
* 产品PK
|
||||||
|
*/
|
||||||
|
private String pk;
|
||||||
|
/***
|
||||||
|
* 设备号
|
||||||
|
*/
|
||||||
|
private String sn;
|
||||||
|
/***
|
||||||
|
* 时间
|
||||||
|
*/
|
||||||
|
private Long time;
|
||||||
|
/***
|
||||||
|
* 实时呼吸
|
||||||
|
*/
|
||||||
|
private String breath;
|
||||||
|
/***
|
||||||
|
* 实时心率
|
||||||
|
*/
|
||||||
|
private String heart;
|
||||||
|
/***
|
||||||
|
* 查询开始时间
|
||||||
|
*/
|
||||||
|
private String startTime;
|
||||||
|
/***
|
||||||
|
* 查询结束时间
|
||||||
|
*/
|
||||||
|
private String endTime;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
package com.muyu.eventdriven.model.result;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName AsVehicleEvent
|
||||||
|
* @Description iotdb控制层返回结果
|
||||||
|
* @Author Yunfei.Du
|
||||||
|
* @Date 2024/6/16 下午3:29
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class IotDbResult {
|
||||||
|
/***
|
||||||
|
* 时间
|
||||||
|
*/
|
||||||
|
private String time;
|
||||||
|
/***
|
||||||
|
* 产品PK
|
||||||
|
*/
|
||||||
|
private String pk;
|
||||||
|
/***
|
||||||
|
* 设备号
|
||||||
|
*/
|
||||||
|
private String sn;
|
||||||
|
/***
|
||||||
|
* 实时呼吸
|
||||||
|
*/
|
||||||
|
private String breath;
|
||||||
|
/***
|
||||||
|
* 实时心率
|
||||||
|
*/
|
||||||
|
private String heart;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,78 @@
|
||||||
|
package com.muyu.eventdriven.response;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName AsVehicleEvent
|
||||||
|
* @Description 错误返回封装
|
||||||
|
* @Author Yunfei.Du
|
||||||
|
* @Date 2024/6/16 下午3:29
|
||||||
|
*/
|
||||||
|
public class ErrorResponseData extends ResponseData {
|
||||||
|
private String exceptionClazz;
|
||||||
|
|
||||||
|
ErrorResponseData(String message) {
|
||||||
|
super(false, DEFAULT_ERROR_CODE, message, message, (Object)null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ErrorResponseData(Integer code, String message) {
|
||||||
|
super(false, code, message, message, (Object)null);
|
||||||
|
}
|
||||||
|
|
||||||
|
ErrorResponseData(Integer code, String message, Object object) {
|
||||||
|
super(false, code, message, object);
|
||||||
|
}
|
||||||
|
|
||||||
|
ErrorResponseData(Integer code, String message, String localizedMsg, Object object) {
|
||||||
|
super(false, code, message, localizedMsg, object);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(final Object o) {
|
||||||
|
if (o == this) {
|
||||||
|
return true;
|
||||||
|
} else if (!(o instanceof ErrorResponseData)) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
ErrorResponseData other = (ErrorResponseData)o;
|
||||||
|
if (!other.canEqual(this)) {
|
||||||
|
return false;
|
||||||
|
} else if (!super.equals(o)) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
Object this$exceptionClazz = this.getExceptionClazz();
|
||||||
|
Object other$exceptionClazz = other.getExceptionClazz();
|
||||||
|
if (this$exceptionClazz == null) {
|
||||||
|
if (other$exceptionClazz != null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (!this$exceptionClazz.equals(other$exceptionClazz)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean canEqual(final Object other) {
|
||||||
|
return other instanceof ErrorResponseData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int hashCode() {
|
||||||
|
int result = super.hashCode();
|
||||||
|
Object $exceptionClazz = this.getExceptionClazz();
|
||||||
|
result = result * 59 + ($exceptionClazz == null ? 43 : $exceptionClazz.hashCode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getExceptionClazz() {
|
||||||
|
return this.exceptionClazz;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExceptionClazz(final String exceptionClazz) {
|
||||||
|
this.exceptionClazz = exceptionClazz;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "ErrorResponseData(exceptionClazz=" + this.getExceptionClazz() + ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,215 @@
|
||||||
|
package com.muyu.eventdriven.response;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName AsVehicleEvent
|
||||||
|
* @Description 返回结果封装
|
||||||
|
* @Author Yunfei.Du
|
||||||
|
* @Date 2024/6/16 下午3:29
|
||||||
|
*/
|
||||||
|
public class ResponseData {
|
||||||
|
public static final String DEFAULT_SUCCESS_MESSAGE = "请求成功";
|
||||||
|
public static final String DEFAULT_ERROR_MESSAGE = "网络异常";
|
||||||
|
public static final Integer DEFAULT_SUCCESS_CODE = 200;
|
||||||
|
public static final Integer DEFAULT_ERROR_CODE = 500;
|
||||||
|
private Boolean success;
|
||||||
|
private Integer code;
|
||||||
|
private String message;
|
||||||
|
private String localizedMsg;
|
||||||
|
private Object data;
|
||||||
|
|
||||||
|
public ResponseData() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResponseData(Boolean success, Integer code, String message, Object data) {
|
||||||
|
this.success = success;
|
||||||
|
this.code = code;
|
||||||
|
this.message = message;
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResponseData(Boolean success, Integer code, String message, String localizedMsg, Object data) {
|
||||||
|
this.success = success;
|
||||||
|
this.code = code;
|
||||||
|
this.message = message;
|
||||||
|
this.localizedMsg = localizedMsg;
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResponseData(Boolean success, Integer code, String message) {
|
||||||
|
this.success = success;
|
||||||
|
this.code = code;
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SuccessResponseData success() {
|
||||||
|
return new SuccessResponseData();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SuccessResponseData success(Object object) {
|
||||||
|
return new SuccessResponseData(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SuccessResponseData success(Integer code, String message, Object object) {
|
||||||
|
return new SuccessResponseData(code, message, object);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SuccessResponseData success(Integer code, String message) {
|
||||||
|
return new SuccessResponseData(code, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SuccessResponseData success(Integer code, String message, String localizedMsg, Object object) {
|
||||||
|
return new SuccessResponseData(code, message, localizedMsg, object);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ErrorResponseData error(String message) {
|
||||||
|
return new ErrorResponseData(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ErrorResponseData error(Integer code, String message) {
|
||||||
|
return new ErrorResponseData(code, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ErrorResponseData error(Integer code, String message, Object object) {
|
||||||
|
return new ErrorResponseData(code, message, object);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ErrorResponseData error(Integer code, String message, String localizedMsg, Object object) {
|
||||||
|
return new ErrorResponseData(code, message, localizedMsg, object);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getSuccess() {
|
||||||
|
return this.success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getCode() {
|
||||||
|
return this.code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMessage() {
|
||||||
|
return this.message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLocalizedMsg() {
|
||||||
|
return this.localizedMsg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getData() {
|
||||||
|
return this.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSuccess(final Boolean success) {
|
||||||
|
this.success = success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCode(final Integer code) {
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMessage(final String message) {
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLocalizedMsg(final String localizedMsg) {
|
||||||
|
this.localizedMsg = localizedMsg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setData(final Object data) {
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(final Object o) {
|
||||||
|
if (o == this) {
|
||||||
|
return true;
|
||||||
|
} else if (!(o instanceof ResponseData)) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
ResponseData other = (ResponseData)o;
|
||||||
|
if (!other.canEqual(this)) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
label71: {
|
||||||
|
Object this$success = this.getSuccess();
|
||||||
|
Object other$success = other.getSuccess();
|
||||||
|
if (this$success == null) {
|
||||||
|
if (other$success == null) {
|
||||||
|
break label71;
|
||||||
|
}
|
||||||
|
} else if (this$success.equals(other$success)) {
|
||||||
|
break label71;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object this$code = this.getCode();
|
||||||
|
Object other$code = other.getCode();
|
||||||
|
if (this$code == null) {
|
||||||
|
if (other$code != null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (!this$code.equals(other$code)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
label57: {
|
||||||
|
Object this$message = this.getMessage();
|
||||||
|
Object other$message = other.getMessage();
|
||||||
|
if (this$message == null) {
|
||||||
|
if (other$message == null) {
|
||||||
|
break label57;
|
||||||
|
}
|
||||||
|
} else if (this$message.equals(other$message)) {
|
||||||
|
break label57;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object this$localizedMsg = this.getLocalizedMsg();
|
||||||
|
Object other$localizedMsg = other.getLocalizedMsg();
|
||||||
|
if (this$localizedMsg == null) {
|
||||||
|
if (other$localizedMsg != null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (!this$localizedMsg.equals(other$localizedMsg)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object this$data = this.getData();
|
||||||
|
Object other$data = other.getData();
|
||||||
|
if (this$data == null) {
|
||||||
|
if (other$data == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else if (this$data.equals(other$data)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean canEqual(final Object other) {
|
||||||
|
return other instanceof ResponseData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int hashCode() {
|
||||||
|
int result1 = 1;
|
||||||
|
Object $success = this.getSuccess();
|
||||||
|
int result = result1 * 59 + ($success == null ? 43 : $success.hashCode());
|
||||||
|
Object $code = this.getCode();
|
||||||
|
result = result * 59 + ($code == null ? 43 : $code.hashCode());
|
||||||
|
Object $message = this.getMessage();
|
||||||
|
result = result * 59 + ($message == null ? 43 : $message.hashCode());
|
||||||
|
Object $localizedMsg = this.getLocalizedMsg();
|
||||||
|
result = result * 59 + ($localizedMsg == null ? 43 : $localizedMsg.hashCode());
|
||||||
|
Object $data = this.getData();
|
||||||
|
result = result * 59 + ($data == null ? 43 : $data.hashCode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "ResponseData(success=" + this.getSuccess() + ", code=" + this.getCode() + ", message=" + this.getMessage() + ", localizedMsg=" + this.getLocalizedMsg() + ", data=" + this.getData() + ")";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package com.muyu.eventdriven.response;
|
||||||
|
/**
|
||||||
|
* @ClassName AsVehicleEvent
|
||||||
|
* @Description 正确返回结果封装
|
||||||
|
* @Author Yunfei.Du
|
||||||
|
* @Date 2024/6/16 下午3:29
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class SuccessResponseData extends ResponseData {
|
||||||
|
public SuccessResponseData() {
|
||||||
|
super(true, DEFAULT_SUCCESS_CODE, "请求成功", "请求成功", (Object)null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SuccessResponseData(Object object) {
|
||||||
|
super(true, DEFAULT_SUCCESS_CODE, "请求成功", "请求成功", object);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SuccessResponseData(Integer code, String message, Object object) {
|
||||||
|
super(true, code, message, message, object);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SuccessResponseData(Integer code, String message, String localizedMsg, Object object) {
|
||||||
|
super(true, code, message, localizedMsg, object);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SuccessResponseData(Integer code, String message) {
|
||||||
|
super(true, code, message);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package com.muyu.eventdriven.server;
|
||||||
|
|
||||||
|
import com.muyu.eventdriven.domain.rest.Result;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName EventInfo
|
||||||
|
* @Description 事件接口
|
||||||
|
* @Author Yunfei.Du
|
||||||
|
* @Date 2024/6/18 上午9:34
|
||||||
|
*/
|
||||||
|
public interface EventInfoService {
|
||||||
|
void creatKafkaConsumer(String vin);
|
||||||
|
|
||||||
|
Result closeKafkaConsumer(String vin);
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
package com.muyu.eventdriven.server;
|
||||||
|
|
||||||
|
|
||||||
|
import com.muyu.eventdriven.domain.VehicleData;
|
||||||
|
import com.muyu.eventdriven.model.param.IotDbParam;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName AsVehicleEvent
|
||||||
|
* @Description iotdb接口类
|
||||||
|
* @Author Yunfei.Du
|
||||||
|
* @Date 2024/6/16 下午3:29
|
||||||
|
*/
|
||||||
|
|
||||||
|
public interface IotDbServer {
|
||||||
|
/**
|
||||||
|
* 添加数据
|
||||||
|
*/
|
||||||
|
void insertData(VehicleData vehicleData);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询数据
|
||||||
|
*/
|
||||||
|
Object queryDataFromIotDb(IotDbParam iotDbParam) throws Exception;
|
||||||
|
}
|
|
@ -0,0 +1,127 @@
|
||||||
|
package com.muyu.eventdriven.server.impl;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import com.muyu.eventdriven.consumer.KafkaConsumers;
|
||||||
|
import com.muyu.eventdriven.domain.EventTacticsManage;
|
||||||
|
import com.muyu.eventdriven.domain.VehicleData;
|
||||||
|
import com.muyu.eventdriven.domain.VehicleKafka;
|
||||||
|
import com.muyu.eventdriven.domain.rest.Result;
|
||||||
|
import com.muyu.eventdriven.server.EventInfoService;
|
||||||
|
import com.muyu.eventdriven.tactics.EventTactics;
|
||||||
|
import lombok.extern.log4j.Log4j2;
|
||||||
|
import org.apache.kafka.clients.consumer.ConsumerRecord;
|
||||||
|
import org.apache.kafka.clients.consumer.ConsumerRecords;
|
||||||
|
import org.apache.kafka.clients.consumer.KafkaConsumer;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName EventInfoServiceImpl
|
||||||
|
* @Description 事件实现层
|
||||||
|
* @Author Yunfei.Du
|
||||||
|
* @Date 2024/6/18 上午9:35
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@Log4j2
|
||||||
|
public class EventInfoServiceImpl implements EventInfoService {
|
||||||
|
private static Map<String,KafkaConsumer> kafkaConsumerMap = new HashMap<>();
|
||||||
|
|
||||||
|
private static List<String> classNameList = new ArrayList<>((Arrays.asList(
|
||||||
|
"StorageEvent",
|
||||||
|
"ElectronicFenceEvent",
|
||||||
|
"FaultAlarmEvent",
|
||||||
|
"RealTimeDataEvent",
|
||||||
|
"IndexWarningEvent")));
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private KafkaConsumers kafkaConsumers;
|
||||||
|
@Autowired
|
||||||
|
private RedisTemplate<String,String> redisTemplate;
|
||||||
|
@Autowired
|
||||||
|
private EventTacticsManage eventTacticsManage;
|
||||||
|
@Autowired
|
||||||
|
private ApplicationContext applicationContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建 Kafka 消费者实例,用于消费与特定车辆 VIN 相关联的 Kafka 主题。
|
||||||
|
*
|
||||||
|
* @param vehicleVin 车辆的唯一识别码(VIN),用于确定要消费的主题。
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void creatKafkaConsumer(String vehicleVin) {
|
||||||
|
// 从 Redis 中获取车辆 Kafka 配置信息
|
||||||
|
Object o = redisTemplate.opsForHash().get("vehicleKafka", vehicleVin);
|
||||||
|
VehicleKafka vehicleKafka = JSON.parseObject ( o.toString (), VehicleKafka.class );
|
||||||
|
|
||||||
|
// 将车辆 VIN 添加到 Redis 列表中,标记该 VIN 有活跃的消费者
|
||||||
|
redisTemplate.opsForList().rightPush(vehicleVin,"");
|
||||||
|
// 设置 VIN 在 Redis 中的过期时间,避免消费者长时间不活跃但仍被保留
|
||||||
|
redisTemplate.expire(vehicleVin, 10, TimeUnit.HOURS);
|
||||||
|
// 检查是否存在已为当前车辆配置的 Kafka 消费者
|
||||||
|
if (!kafkaConsumerMap.containsKey(vehicleKafka.getConsumerName() + "-" + vehicleKafka.getPartitions())) {
|
||||||
|
// 根据车辆 Kafka 配置创建一个新的 Kafka 分区消费者
|
||||||
|
KafkaConsumer kafkaConsumer = kafkaConsumers.kafkaConsumer(vehicleKafka);
|
||||||
|
// 将新创建的消费者添加到映射中,键为消费者名称和分区组合
|
||||||
|
new Thread ( () -> {
|
||||||
|
kafkaConsumerMap.put(vehicleKafka.getConsumerName()+"-"+vehicleKafka.getPartitions(),kafkaConsumer);
|
||||||
|
// 持续检查消费者映射中是否存在当前车辆的消费者,存在则处理消息
|
||||||
|
while (true){
|
||||||
|
// 使用 ConcurrentHashMap 来保证线程安全
|
||||||
|
ConcurrentHashMap<String, ArrayList<VehicleData>> stringListHashMap = new ConcurrentHashMap<>();
|
||||||
|
// 从 Kafka 拉取消息
|
||||||
|
// 拉取消息
|
||||||
|
ConsumerRecords<String, String> msg = kafkaConsumer.poll(Duration.ofSeconds(100));
|
||||||
|
// 处理拉取到的消息,将消息按车辆事件类型分类
|
||||||
|
stringListHashMap = getVehicleData(msg, stringListHashMap);
|
||||||
|
// 对于每种车辆事件类型,异步处理相关消息
|
||||||
|
stringListHashMap.forEach((key,value) -> {
|
||||||
|
// 从 Redis 中获取车辆事件处理类的列表
|
||||||
|
// String vehicleEventString = redisTemplate.opsForHash().get(RedisConstants.VEHICLE_EVENT, key).toString();
|
||||||
|
String vehicleEventString = "1,2,3,4,5";
|
||||||
|
for (String str : vehicleEventString.split(",")) {
|
||||||
|
CompletableFuture.runAsync(() -> {
|
||||||
|
if (vehicleEventString.contains ( str )){
|
||||||
|
applicationContext.getBean(classNameList.get(Integer.parseInt(str)), EventTactics.class).eventManage(key,value);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}).start ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConcurrentHashMap<String, ArrayList<VehicleData>> getVehicleData(ConsumerRecords<String, String> msg,ConcurrentHashMap<String, ArrayList<VehicleData>> stringListHashMap) {
|
||||||
|
for (ConsumerRecord<String, String> consumerRecord : msg) {
|
||||||
|
try {
|
||||||
|
VehicleData vehicleData = JSON.parseObject(consumerRecord.value(), VehicleData.class);
|
||||||
|
// 使用 compute 方法简化数据添加逻辑
|
||||||
|
stringListHashMap.compute(vehicleData.getVin(), (vin, list) -> {
|
||||||
|
if (list == null) {
|
||||||
|
list = new ArrayList<>();
|
||||||
|
}
|
||||||
|
list.add(vehicleData);
|
||||||
|
return list;
|
||||||
|
});
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return stringListHashMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Result closeKafkaConsumer(String vin) {
|
||||||
|
redisTemplate.delete(vin);
|
||||||
|
return Result.success("释放消费者");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,111 @@
|
||||||
|
package com.muyu.eventdriven.server.impl;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.muyu.eventdriven.config.iotdb.IotDBSessionConfig;
|
||||||
|
import com.muyu.eventdriven.domain.VehicleData;
|
||||||
|
import com.muyu.eventdriven.model.param.IotDbParam;
|
||||||
|
import com.muyu.eventdriven.model.result.IotDbResult;
|
||||||
|
import com.muyu.eventdriven.server.IotDbServer;
|
||||||
|
import lombok.extern.log4j.Log4j2;
|
||||||
|
import org.apache.iotdb.rpc.IoTDBConnectionException;
|
||||||
|
import org.apache.iotdb.rpc.StatementExecutionException;
|
||||||
|
import org.apache.iotdb.session.SessionDataSet;
|
||||||
|
import org.apache.iotdb.tsfile.read.common.Field;
|
||||||
|
import org.apache.iotdb.tsfile.read.common.RowRecord;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName AsVehicleEvent
|
||||||
|
* @Description iotdb实现层
|
||||||
|
* @Author Yunfei.Du
|
||||||
|
* @Date 2024/6/16 下午3:29
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Log4j2
|
||||||
|
@Service
|
||||||
|
public class IotDbServerImpl implements IotDbServer {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private IotDBSessionConfig iotDBSessionConfig;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void insertData(VehicleData vehicleData){
|
||||||
|
|
||||||
|
try {
|
||||||
|
// iotDbParam: 模拟设备上报消息
|
||||||
|
String deviceId = "root.vehicle."+ vehicleData.getVin();
|
||||||
|
// 将设备上报的数据存入数据库(时序数据库)
|
||||||
|
List<String> measurementsList = new ArrayList<>();
|
||||||
|
measurementsList.add("data");
|
||||||
|
List<String> valuesList = new ArrayList<>();
|
||||||
|
valuesList.add(String.valueOf(JSON.toJSON(vehicleData)));
|
||||||
|
iotDBSessionConfig.insertRecord(deviceId, Long.valueOf(vehicleData.getDrivingRoute()), measurementsList, valuesList);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<IotDbResult> queryDataFromIotDb(IotDbParam iotDbParam) throws Exception {
|
||||||
|
List<IotDbResult> iotDbResultList = new ArrayList<>();
|
||||||
|
|
||||||
|
if (null != iotDbParam.getPk() && null != iotDbParam.getSn()) {
|
||||||
|
String sql = "select * from root.bizkey."+ iotDbParam.getPk() +"." + iotDbParam.getSn() + " where time >= "
|
||||||
|
+ iotDbParam.getStartTime() + " and time < " + iotDbParam.getEndTime();
|
||||||
|
SessionDataSet sessionDataSet = iotDBSessionConfig.query(sql);
|
||||||
|
List<String> columnNames = sessionDataSet.getColumnNames();
|
||||||
|
List<String> titleList = new ArrayList<>();
|
||||||
|
// 排除Time字段 -- 方便后面后面拼装数据
|
||||||
|
for (int i = 1; i < columnNames.size(); i++) {
|
||||||
|
String[] temp = columnNames.get(i).split("\\.");
|
||||||
|
titleList.add(temp[temp.length - 1]);
|
||||||
|
}
|
||||||
|
// 封装处理数据
|
||||||
|
packagingData(iotDbParam, iotDbResultList, sessionDataSet, titleList);
|
||||||
|
} else {
|
||||||
|
log.info("PK或者SN不能为空!!");
|
||||||
|
}
|
||||||
|
return iotDbResultList;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 封装处理数据
|
||||||
|
* @param iotDbParam
|
||||||
|
* @param iotDbResultList
|
||||||
|
* @param sessionDataSet
|
||||||
|
* @param titleList
|
||||||
|
* @throws StatementExecutionException
|
||||||
|
* @throws IoTDBConnectionException
|
||||||
|
*/
|
||||||
|
private void packagingData(IotDbParam iotDbParam, List<IotDbResult> iotDbResultList, SessionDataSet sessionDataSet, List<String> titleList)
|
||||||
|
throws StatementExecutionException, IoTDBConnectionException {
|
||||||
|
int fetchSize = sessionDataSet.getFetchSize();
|
||||||
|
if (fetchSize > 0) {
|
||||||
|
while (sessionDataSet.hasNext()) {
|
||||||
|
IotDbResult iotDbResult = new IotDbResult();
|
||||||
|
RowRecord next = sessionDataSet.next();
|
||||||
|
List<Field> fields = next.getFields();
|
||||||
|
String timeString = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(next.getTimestamp());
|
||||||
|
iotDbResult.setTime(timeString);
|
||||||
|
Map<String, String> map = new HashMap<>();
|
||||||
|
|
||||||
|
for (int i = 0; i < fields.size(); i++) {
|
||||||
|
Field field = fields.get(i);
|
||||||
|
// 这里的需要按照类型获取
|
||||||
|
map.put(titleList.get(i), field.getObjectValue(field.getDataType()).toString());
|
||||||
|
}
|
||||||
|
iotDbResult.setTime(timeString);
|
||||||
|
iotDbResult.setPk(iotDbParam.getPk());
|
||||||
|
iotDbResult.setSn(iotDbParam.getSn());
|
||||||
|
iotDbResult.setHeart(map.get("heart"));
|
||||||
|
iotDbResult.setBreath(map.get("breath"));
|
||||||
|
iotDbResultList.add(iotDbResult);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
package com.muyu.eventdriven.tactics;
|
||||||
|
|
||||||
|
import com.muyu.eventdriven.domain.VehicleData;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName EventTactics
|
||||||
|
* @Description 事件处理系统策略模式接口
|
||||||
|
* @Author Yunfei.Du
|
||||||
|
* @Date 2024/6/20 上午10:33
|
||||||
|
*/
|
||||||
|
public interface EventTactics {
|
||||||
|
void eventManage(VehicleData vehicleData);
|
||||||
|
void eventManage(String vin,List<VehicleData> vehicleDataList);
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
package com.muyu.eventdriven.tactics.basics;
|
||||||
|
|
||||||
|
import com.muyu.eventdriven.domain.VehicleData;
|
||||||
|
import com.muyu.eventdriven.server.IotDbServer;
|
||||||
|
import com.muyu.eventdriven.tactics.EventTactics;
|
||||||
|
import lombok.extern.log4j.Log4j2;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.Primary;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName StorageEvent
|
||||||
|
* @Description 存储事件
|
||||||
|
* @Author Yunfei.Du
|
||||||
|
* @Date 2024/6/20 上午10:38
|
||||||
|
*/
|
||||||
|
@Service("StorageEvent")
|
||||||
|
@Log4j2
|
||||||
|
@Primary
|
||||||
|
public class StorageEvent implements EventTactics {
|
||||||
|
@Autowired
|
||||||
|
private IotDbServer iotDbServer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单条数据的处理
|
||||||
|
* @param vehicleData
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void eventManage(VehicleData vehicleData) {
|
||||||
|
iotDbServer.insertData(vehicleData);
|
||||||
|
log.info("车辆{}执行存储事件",vehicleData.getVin());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 多条数据的处理
|
||||||
|
* @param vin
|
||||||
|
* @param vehicleDataList
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void eventManage(String vin, List<VehicleData> vehicleDataList) {
|
||||||
|
log.info("车辆{}执行存储事件",vin);
|
||||||
|
vehicleDataList.forEach(vehicleData -> {
|
||||||
|
iotDbServer.insertData(vehicleData);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
package com.muyu.eventdriven.tactics.system;
|
||||||
|
|
||||||
|
import com.muyu.eventdriven.domain.VehicleData;
|
||||||
|
import com.muyu.eventdriven.tactics.EventTactics;
|
||||||
|
import lombok.extern.log4j.Log4j2;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName ElectronicFenceEvent
|
||||||
|
* @Description 电子围栏
|
||||||
|
* @Author Yunfei.Du
|
||||||
|
* @Date 2024/6/20 上午10:42
|
||||||
|
*/
|
||||||
|
@Service("ElectronicFenceEvent")
|
||||||
|
@Log4j2
|
||||||
|
public class ElectronicFenceEvent implements EventTactics {
|
||||||
|
/**
|
||||||
|
* 单条数据的处理
|
||||||
|
* @param vehicleData
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void eventManage(VehicleData vehicleData) {
|
||||||
|
log.info("车辆{}执行电子围栏事件",vehicleData.getVin());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 多条数据的处理
|
||||||
|
* @param vin
|
||||||
|
* @param vehicleDataList
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void eventManage(String vin, List<VehicleData> vehicleDataList) {
|
||||||
|
log.info("车辆{}执行电子围栏事件",vin);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,149 @@
|
||||||
|
package com.muyu.eventdriven.tactics.system;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.github.benmanes.caffeine.cache.Cache;
|
||||||
|
import com.muyu.eventdriven.constants.FaultCodeConstants;
|
||||||
|
import com.muyu.eventdriven.constants.RabbitConstants;
|
||||||
|
import com.muyu.eventdriven.constants.RedisConstants;
|
||||||
|
import com.muyu.eventdriven.domain.RabbitFalut;
|
||||||
|
import com.muyu.eventdriven.domain.VehicleData;
|
||||||
|
import com.muyu.eventdriven.domain.VehicleFaultStatus;
|
||||||
|
import com.muyu.eventdriven.tactics.EventTactics;
|
||||||
|
import lombok.extern.log4j.Log4j2;
|
||||||
|
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName FaultAlarmEvent
|
||||||
|
* @Description 故障报警
|
||||||
|
* @Author Yunfei.Du
|
||||||
|
* @Date 2024/6/20 上午10:58
|
||||||
|
*/
|
||||||
|
@Service("FaultAlarmEvent")
|
||||||
|
@Log4j2
|
||||||
|
//@RequiredArgsConstructor
|
||||||
|
public class FaultAlarmEvent implements EventTactics {
|
||||||
|
@Autowired
|
||||||
|
private Cache<String, Object> caffeineCache;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RedisTemplate<String,String> redisTemplate;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RabbitTemplate rabbitTemplate;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void eventManage(VehicleData vehicleData) {
|
||||||
|
log.info("车辆{}执行故障报警事件",vehicleData.getVin());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void eventManage(String vin, List<VehicleData> vehicleDataList) {
|
||||||
|
vehicleDataList.stream().forEach(vehicleData -> {
|
||||||
|
//车辆状态
|
||||||
|
if (vehicleData.getVehicleStatus() == 0){
|
||||||
|
hasLocalCache(vehicleData, FaultCodeConstants.VEHICLESTATUS);
|
||||||
|
}
|
||||||
|
//充电状态
|
||||||
|
if (vehicleData.getChargingStatus() == 0){
|
||||||
|
hasLocalCache(vehicleData, FaultCodeConstants.CHARGINGSTATUS);
|
||||||
|
}
|
||||||
|
//运行状态
|
||||||
|
if (vehicleData.getOperatingStatus() == 0){
|
||||||
|
hasLocalCache(vehicleData, FaultCodeConstants.OPERATINGSTATUS);
|
||||||
|
}
|
||||||
|
//SOC
|
||||||
|
if (vehicleData.getSocStatus() == 0){
|
||||||
|
hasLocalCache(vehicleData, FaultCodeConstants.SOCSTATUS);
|
||||||
|
}
|
||||||
|
//可充电储能装置工作状态
|
||||||
|
if (vehicleData.getChargingEnergyStorageStatus() == 0){
|
||||||
|
hasLocalCache(vehicleData, FaultCodeConstants.CHARGINGENERGYSTORAGESTATUS);
|
||||||
|
}
|
||||||
|
//驱动电机状态
|
||||||
|
if (vehicleData.getDriveMotorStatus() == 0){
|
||||||
|
hasLocalCache(vehicleData, FaultCodeConstants.DRIVEMOTORSTATUS);
|
||||||
|
}
|
||||||
|
//定位是否有效
|
||||||
|
if (vehicleData.getPositionStatus() == 0){
|
||||||
|
hasLocalCache(vehicleData, FaultCodeConstants.POSITIONSTATUS);
|
||||||
|
}
|
||||||
|
//EAS(汽车防盗系统)状态
|
||||||
|
if (vehicleData.getEasStatus() == 0){
|
||||||
|
hasLocalCache(vehicleData, FaultCodeConstants.EASSTATUS);
|
||||||
|
}
|
||||||
|
//PTC(电动加热器)状态
|
||||||
|
if (vehicleData.getPtcStatus() == 0){
|
||||||
|
hasLocalCache(vehicleData, FaultCodeConstants.PTCSTATUS);
|
||||||
|
}
|
||||||
|
//EPS(电动助力系统)状态
|
||||||
|
if (vehicleData.getEpsStatus() == 0){
|
||||||
|
hasLocalCache(vehicleData, FaultCodeConstants.EPSSTATUS);
|
||||||
|
}
|
||||||
|
//ABS(防抱死)状态
|
||||||
|
if (vehicleData.getAbsStatus() == 0){
|
||||||
|
hasLocalCache(vehicleData, FaultCodeConstants.ABSSTATUS);
|
||||||
|
}
|
||||||
|
//MCU(电机/逆变器)状态
|
||||||
|
if (vehicleData.getMcuStatus() == 0){
|
||||||
|
hasLocalCache(vehicleData, FaultCodeConstants.MCUSTATUS);
|
||||||
|
}
|
||||||
|
//动力电池加热状态
|
||||||
|
if (vehicleData.getHeatingStatus() == 0){
|
||||||
|
hasLocalCache(vehicleData, FaultCodeConstants.HEATINGSTATUS);
|
||||||
|
}
|
||||||
|
//动力电池当前状态
|
||||||
|
if (vehicleData.getBatteryStatus() == 0){
|
||||||
|
hasLocalCache(vehicleData, FaultCodeConstants.BATTERYSTATUS);
|
||||||
|
}
|
||||||
|
//动力电池保温状态
|
||||||
|
if (vehicleData.getBatteryInsulationStatus() == 0){
|
||||||
|
hasLocalCache(vehicleData, FaultCodeConstants.BATTERYINSULATIONSTATUS);
|
||||||
|
}
|
||||||
|
//DCDC(电力交换系统)状态
|
||||||
|
if (vehicleData.getDcdcStatus() == 0){
|
||||||
|
hasLocalCache(vehicleData, FaultCodeConstants.DCDCSTATUS);
|
||||||
|
}
|
||||||
|
//CHG(充电机)状态
|
||||||
|
if (vehicleData.getChgStatus() == 0){
|
||||||
|
hasLocalCache(vehicleData, FaultCodeConstants.CHGSTATUS);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
log.info("车辆{}执行故障报警事件",vin);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查车辆故障数据是否已在本地缓存中,并根据情况更新缓存和发送故障状态消息。
|
||||||
|
* 如果缓存中已存在车辆的故障数据,则不进行任何操作。
|
||||||
|
* 如果缓存中不存在车辆的故障数据,则将数据存入缓存,并发送车辆故障状态消息。
|
||||||
|
*
|
||||||
|
* @param vehicleData 车辆数据,包含车辆vin和行驶路线等信息。
|
||||||
|
* @param faultCode 故障代码,用于标识具体的故障类型。
|
||||||
|
*/
|
||||||
|
public void hasLocalCache(VehicleData vehicleData,String faultCode){
|
||||||
|
Object o = caffeineCache.get(RedisConstants.VEHICLE_FAULT_KEY+vehicleData.getVin()+":" + faultCode, key -> vehicleData.getDrivingRoute());
|
||||||
|
if (o.toString().equals(vehicleData.getDrivingRoute())){
|
||||||
|
RabbitFalut rabbitFalut = new RabbitFalut();
|
||||||
|
rabbitFalut.setStartTime(new Date());
|
||||||
|
rabbitFalut.setVin(vehicleData.getVin());
|
||||||
|
rabbitFalut.setFaultCode(faultCode);
|
||||||
|
rabbitTemplate.convertAndSend(RabbitConstants.EXCHANGE_STATUS,RabbitConstants.QUEUE_STATUS_NORMAL, JSON.toJSONString(rabbitFalut),message ->{
|
||||||
|
message.getMessageProperties().setMessageId( UUID.randomUUID().toString());
|
||||||
|
//设置消息延迟时间为5秒
|
||||||
|
message.getMessageProperties().setDelay(5000);
|
||||||
|
log.info ( "消息发送成功" );
|
||||||
|
return message;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
redisTemplate.opsForValue().set(RedisConstants.VEHICLE_FAULT_KEY+vehicleData.getVin()+":" + faultCode,vehicleData.getDrivingRoute(),10, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.muyu.eventdriven.tactics.system;
|
||||||
|
|
||||||
|
import com.muyu.eventdriven.domain.VehicleData;
|
||||||
|
import com.muyu.eventdriven.tactics.EventTactics;
|
||||||
|
import lombok.extern.log4j.Log4j2;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName IndexWarningEvent
|
||||||
|
* @Description 指标预警
|
||||||
|
* @Author Yunfei.Du
|
||||||
|
* @Date 2024/6/20 上午11:00
|
||||||
|
*/
|
||||||
|
@Service("IndexWarningEvent")
|
||||||
|
@Log4j2
|
||||||
|
public class IndexWarningEvent implements EventTactics {
|
||||||
|
@Override
|
||||||
|
public void eventManage(VehicleData vehicleData) {
|
||||||
|
log.info("车辆{}执行指标预警事件",vehicleData.getVin());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void eventManage(String vin, List<VehicleData> vehicleDataList) {
|
||||||
|
log.info("车辆{}执行指标预警事件",vin);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
package com.muyu.eventdriven.tactics.system;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.muyu.eventdriven.domain.VehicleData;
|
||||||
|
import com.muyu.eventdriven.tactics.EventTactics;
|
||||||
|
import lombok.extern.log4j.Log4j2;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName RealTimeDataEvent
|
||||||
|
* @Description 实时数据
|
||||||
|
* @Author Yunfei.Du
|
||||||
|
* @Date 2024/6/20 上午10:47
|
||||||
|
*/
|
||||||
|
@Service("RealTimeDataEvent")
|
||||||
|
@Log4j2
|
||||||
|
public class RealTimeDataEvent implements EventTactics {
|
||||||
|
@Autowired
|
||||||
|
private RedisTemplate<String,String> redisTemplate;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void eventManage(VehicleData vehicleData) {
|
||||||
|
if (redisTemplate.hasKey(vehicleData.getVin())){
|
||||||
|
log.info("{}监听到的消息内容: {}", vehicleData.getVin(),vehicleData);
|
||||||
|
redisTemplate.opsForList().rightPush(vehicleData.getVin(), JSON.toJSONString(vehicleData));
|
||||||
|
}
|
||||||
|
log.info("车辆{}执行实时数据事件",vehicleData.getVin());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void eventManage(String vin, List<VehicleData> vehicleDataList) {
|
||||||
|
log.info("车辆{}执行实时数据事件",vin);
|
||||||
|
if (redisTemplate.hasKey(vin)){
|
||||||
|
log.info("{}监听到的消息内容: {}", vin,vehicleDataList);
|
||||||
|
vehicleDataList.forEach(vehicleData -> {
|
||||||
|
redisTemplate.opsForList().rightPush(vin, JSON.toJSONString(vehicleData));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
server:
|
||||||
|
port: 9006
|
||||||
|
|
||||||
|
spring:
|
||||||
|
rabbitmq:
|
||||||
|
username: guest
|
||||||
|
password: guest
|
||||||
|
virtualHost: /
|
||||||
|
port: 5672
|
||||||
|
host: 43.142.12.243
|
||||||
|
kafka:
|
||||||
|
#config/consumer.properties配置的bootstrap.servers
|
||||||
|
bootstrap-servers: 43.142.12.243:9092
|
||||||
|
producer:
|
||||||
|
key-serializer: org.apache.kafka.common.serialization.StringSerializer
|
||||||
|
value-serializer: org.apache.kafka.common.serialization.StringSerializer
|
||||||
|
consumer:
|
||||||
|
key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
|
||||||
|
value-deserializer: org.apache.kafka.common.serialization.StringDeserializer
|
||||||
|
#这个可以和config/consumer.properties里的group.id不同
|
||||||
|
group-id: test-consumer-group
|
||||||
|
redis:
|
||||||
|
host: 127.0.0.1
|
||||||
|
port: 6379
|
||||||
|
password: dyf@123
|
||||||
|
datasource:
|
||||||
|
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||||
|
url: jdbc:mysql://127.0.0.1:3306/event-driven?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
||||||
|
username: root
|
||||||
|
password: 1234
|
||||||
|
|
||||||
|
# mybatis配置
|
||||||
|
mybatis:
|
||||||
|
# 搜索指定包别名
|
||||||
|
typeAliasesPackage: com.muyu.eventdriven.domain
|
||||||
|
# 配置mapper的扫描,找到所有的mapper.xml映射文件
|
||||||
|
mapperLocations: classpath:mapper/**/*.xml
|
||||||
|
configuration:
|
||||||
|
map-underscore-to-camel-case: true
|
||||||
|
# 将mapper接口所在包的日志级别改成debug,可以在控制台打印sql
|
||||||
|
logging:
|
||||||
|
level:
|
||||||
|
com.bwie.**: debug
|
||||||
|
application:
|
||||||
|
name: event-driven
|
||||||
|
iotdb:
|
||||||
|
username: root
|
||||||
|
password: root
|
||||||
|
ip: 43.142.12.243
|
||||||
|
port: 6667
|
||||||
|
fetchSize: 10000
|
|
@ -0,0 +1,5 @@
|
||||||
|
<?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="com.muyu.eventdriven.mapper.EventDrivenMapper">
|
||||||
|
|
||||||
|
</mapper>
|
Loading…
Reference in New Issue