事件:实时数据+故障报警

master
Yunfei Du 2024-06-25 13:11:51 +08:00
commit 80a6fb6992
55 changed files with 2996 additions and 0 deletions

38
.gitignore vendored 100644
View File

@ -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

8
.idea/.gitignore vendored 100644
View File

@ -0,0 +1,8 @@
# 默认忽略的文件
/shelf/
/workspace.xml
# 基于编辑器的 HTTP 客户端请求
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

View File

@ -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>

View File

@ -0,0 +1,5 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
</profile>
</component>

14
.idea/misc.xml 100644
View File

@ -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>

6
.idea/vcs.xml 100644
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

162
pom.xml 100644
View File

@ -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>

View File

@ -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);
}
}

View File

@ -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();
}
}
}

View File

@ -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();
}
}

View File

@ -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 {
//}

View File

@ -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();
// }
//}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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"};
}

View 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";
}

View File

@ -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;
}

View File

@ -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";
}

View File

@ -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:";
}

View File

@ -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;
}
}

View File

@ -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;
});
}
}
}

View File

@ -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);
}
}

View File

@ -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();
}
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);
// }
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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();
}
}

View File

@ -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());
}
}
}

View File

@ -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();
// }
// }
//}

View File

@ -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 {
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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() + ")";
}
}

View File

@ -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() + ")";
}
}

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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("释放消费者");
}
}

View File

@ -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);
}
}
}
}

View File

@ -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);
}

View File

@ -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);
});
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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));
});
}
}
}

View File

@ -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

View File

@ -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>