Merge remote-tracking branch 'origin/dev.template' into dev

dev.vehiclegateway
刘武 2024-10-07 20:39:38 +08:00
commit f45e6865d9
9 changed files with 330 additions and 76 deletions

View File

@ -17,6 +17,11 @@
<dependencies>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.5</version>
</dependency>
<!-- SpringCloud Alibaba Nacos -->
<dependency>
@ -36,6 +41,11 @@
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>com.muyu</groupId>
<artifactId>cloud-common-saas</artifactId>
</dependency>
<!-- SpringBoot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>

View File

@ -89,6 +89,15 @@
<groupId>com.muyu</groupId>
<artifactId>cloud-common-xxl</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId> <!-- or lettuce -->
</dependency>
</dependencies>
<properties>

View File

@ -13,11 +13,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
@EnableMyFeignClients
@SpringBootApplication
public class CloudTemplateApplication {
public static void main(String[] args) {
SpringApplication.run(CloudTemplateApplication.class, args);
}
}

View File

@ -1,11 +1,19 @@
package com.muyu.template.config;
import cn.hutool.json.JSONObject;
import com.alibaba.fastjson2.JSON;
import com.muyu.cache.MessageTemplateCacheService;
import com.muyu.cache.MessageTemplateTypeCacheService;
import com.muyu.cache.SysCarCacheService;
import com.muyu.cache.TemplateCacheService;
import com.muyu.common.domain.MessageTemplate;
import com.muyu.common.domain.MessageTemplateType;
import com.muyu.common.domain.SysCar;
import com.muyu.common.domain.Template;
import com.muyu.common.domain.resp.SysCarVo;
import com.muyu.common.redis.service.RedisService;
import lombok.extern.log4j.Log4j2;
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.eclipse.paho.client.mqttv3.*;
import org.springframework.beans.factory.annotation.Autowired;
@ -17,6 +25,12 @@ import org.springframework.web.bind.annotation.RequestParam;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
*
* @author liuxinyue
@ -33,10 +47,16 @@ public class MqttConfigure {
private RedisService redisService;
@Autowired
private RedisTemplate redisTemplate;
private SysCarCacheService service;
// @Autowired
// private KafkaProducer kafkaProducer;
@Autowired
private MessageTemplateCacheService messageTemplateCacheService;
@Autowired
private MessageTemplateTypeCacheService messageTemplateTypeCacheService;
@Autowired
private KafkaProducer kafkaProducer;
@PostConstruct
public void MQTTMonitoring(){
@ -69,8 +89,8 @@ public class MqttConfigure {
JSONObject jsonObject = new JSONObject(messageContent);
// 从JSON对象中获取"msg"字段的值
String msgValue = jsonObject.getStr("msg");
log.info("接收到的报文为:"+msgValue);
messageParsing(msgValue);
log.info("接收到的值为:"+msgValue);
}
//交付完成
@Override
@ -103,49 +123,34 @@ public class MqttConfigure {
result.append((char) decimal);
}
//取出VIN码
String carVin = result.substring(0, 18 - 1);
String carVin = result.substring(1, 18 );
log.info("carVin码为:" + carVin);
//根据VIN码获取车辆信息
SysCar carByVin = null;
List<SysCar> carList = redisService.getCacheList("carList");
for (SysCar sysCar : carList) {
if(sysCar.getCarVin().equals(carVin)){
carByVin=sysCar;
}
List<SysCarVo> carList = service.get("carList");
if(carList==null){
throw new RuntimeException("Redis未获取到车辆数据!!!");
}else{
// 使用 HashMap 存储车信息,以 VIN 作为键
Map<String, SysCarVo> carMap = carList.stream()
.collect(Collectors.toMap(SysCarVo::getCarVin, Function.identity()));
carByVin = carMap.get(carVin);
}
// SysCar carByVin = service.findCarByVin(carVin);
log.info("车辆信息为:" + carByVin);
//对应车辆所对应的报文模版
Integer templateId = carByVin.getTemplateId();
List<MessageTemplateType> templateTypeList;
//key
String redisKey = "messageTemplateType" + templateId;
List<MessageTemplateType> messageTemplateTypes=null;
String redisKey = "messageTemplateTypeList";
//key存在
if (redisTemplate.hasKey(redisKey)) {
List list = redisTemplate.opsForList().range(redisKey, 0, -1);
templateTypeList = list.stream().map(o -> JSON.parseObject(o.toString(), MessageTemplateType.class))
.toList();
} else {
List<MessageTemplateType> templateTypeList1=null;
List<MessageTemplateType> templateTypeList2 = redisService.getCacheList("templateTypeList");
for (MessageTemplateType messageTemplateType : templateTypeList2) {
if(messageTemplateType.getTemplateId()==templateId){
templateTypeList1.add(messageTemplateType);
}
}
// List<MessageTemplateType> templateTypeList1 = messageTemplateTypeService.findTemplateById(templateId);
templateTypeList = templateTypeList1;
templateTypeList.forEach(
templateType ->
redisTemplate.opsForList().rightPush(
redisKey, JSON.toJSONString(templateType)
)
);
Boolean b = redisService.hasKey(redisKey);
if (b) {
messageTemplateTypes = messageTemplateTypeCacheService.get(redisKey);
}else{
throw new RuntimeException("请先将配置存入Redis!!!");
}
//将模版里面有的配置进行循环
for (MessageTemplateType messageTemplateType : templateTypeList) {
for (MessageTemplateType messageTemplateType : messageTemplateTypes) {
//开始位置
Integer startIndex = messageTemplateType.getStartIndex() - 1;
//结束位置
@ -154,17 +159,16 @@ public class MqttConfigure {
jsonObject.put(messageTemplateType.getMessageField(), result.substring(startIndex, endIndex));
}
log.info("解析后的报文是:" + jsonObject);
// sendKafka(jsonObject);
sendKafka(jsonObject);
log.info("发送kafka成功");
return jsonObject;
}
// //kafka发送消息
// public void sendKafka(JSONObject jsonObject){
// ProducerRecord<String, String> stringStringProducerRecord = new ProducerRecord<>("four_car", jsonObject.toString());
// kafkaProducer.send(stringStringProducerRecord);
// log.info("kafka发送成功");
// }
//kafka发送消息
public void sendKafka(JSONObject jsonObject){
ProducerRecord<String, String> stringStringProducerRecord = new ProducerRecord<>("four_car", jsonObject.toString());
kafkaProducer.send(stringStringProducerRecord);
log.info("kafka发送成功");
}
}

View File

@ -1,10 +0,0 @@
package com.muyu.template.controller;
/**
* @author liuxinyue
* @Packagecom.muyu.template.controller
* @nameKafkaController
* @Date2024/10/4 16:11
*/
public class KafkaController {
}

View File

@ -0,0 +1,21 @@
package com.muyu.template.controller;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author liuxinyue
* @Packagecom.muyu.template.controller
* @nameTemplateController
* @Date2024/10/7 10:28
*/
@RestController
@RequestMapping("/template")
@AllArgsConstructor
@Tag(name = "协议解析管理",description = "协议解析管理")
@Log4j2
public class TemplateController {
}

View File

@ -1,34 +1,44 @@
package com.muyu.template;
import com.muyu.common.domain.SysCar;
import com.muyu.common.domain.Template;
import com.muyu.common.domain.WarnRule;
import com.muyu.common.domain.WarnStrategy;
import cn.hutool.json.JSONObject;
import com.alibaba.fastjson2.JSON;
import com.muyu.common.domain.*;
import com.muyu.common.redis.service.RedisService;
import org.springframework.beans.factory.annotation.Autowired;
import lombok.extern.log4j.Log4j2;
import org.springframework.data.redis.core.RedisTemplate;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* @author liuxinyue
* @Packagecom.muyu.template
* @nametest
* @Date2024/10/4 9:42
*/
@Log4j2
public class test {
private static int DURATION_SECONDS = 60;
private static List<JSONObject> receivedStrings = new ArrayList<>();
private static int elapsedSeconds = 0;
private static ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
private static String file="elapsed";
@Resource
private RedisTemplate redisTemplate;
@Resource
private RedisService redisService;
public void main(String[] args) {
String message="7E 36 33 59 43 5a 44 59 36 33 33 36 43 38 48 34 43 41 31 37 32 37 36 36 38 35 39 37 37 38 39 31 32 31 2e 34 37 34 30 30 30 30 33 31 2e 32 33 30 30 30 31 30 31 38 2e 30 30 30 31 38 38 31 2e 37 39 30 30 30 30 35 36 31 30 30 30 33 31 30 30 30 36 38 39 39 30 30 30 30 30 50 31 30 39 30 39 2e 35 30 30 32 34 30 30 30 30 31 33 32 36 35 37 33 39 30 36 37 30 30 30 30 32 31 31 30 30 31 33 32 35 30 30 30 30 36 37 30 30 30 2e 32 32 30 30 30 30 37 35 30 30 30 30 31 33 31 30 30 30 30 35 37 30 30 30 30 33 30 30 30 34 30 30 30 37 39 30 30 30 30 32 30 30 30 30 30 31 37 30 30 30 30 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 55 7E";
//车类型
Long carTypeId=null;
//查找车对应的类型
List<SysCar> carList = redisService.getCacheList("car");
for (SysCar sysCar : carList) {
if(sysCar.getCarVin().equals("")){
if(sysCar.getCarVin().equals("1HGCM82633A123456")){
//获取到车的类型ID
carTypeId = sysCar.getCarTypeId();
}
@ -47,16 +57,147 @@ public class test {
}
}
//根据ID取出对应的报文模版
List<Template> templateList = redisService.getCacheList("template");
//报文模版 根据templateId取出对应的模版
List<MessageTemplateType> templateTypeList1=null;
List<MessageTemplateType> templateTypeList = redisService.getCacheList("templateTypeList");
for (MessageTemplateType messageTemplateType : templateTypeList) {
if(messageTemplateType.getTemplateId().equals(templateId)){
templateTypeList1.add(messageTemplateType);
}
}
//获取策略对应的规则列表
List<WarnRule> warnRule = redisService.getCacheList("warnRule");
//车辆对应的规则
List<WarnRule> warnRuleList = null;
for (WarnRule rule : warnRule) {
for (WarnStrategy strategy : warnStrategyList) {
if(rule.getStrategyId()==strategy.getId()){
warnRuleList.add(rule);
}
}
}
String templateIds=null;
for (WarnRule rule : warnRuleList) {
//滑窗时间
Long slideTime = rule.getSlideTime();
if(slideTime!=null){
DURATION_SECONDS= Math.toIntExact(slideTime);
}
templateIds+=","+rule.getMsgTypeId();
}
String[] templateIdSplit = templateIds.split(",");
//最终获取到的报文模版 使用他进行比较
List<MessageTemplateType> messageTemplateTypes=null;
for (String s : templateIdSplit) {
for (MessageTemplateType messageTemplateType : templateTypeList1) {
if(s.equals(messageTemplateType.getTemplateId())){
messageTemplateTypes.add(messageTemplateType);
}
}
}
JSONObject entries = messageParsing(message);
//将解析后的数据添加到List<JSONObject> receivedStrings中
receivedStrings.add(entries);
cleanUpOldStrings();
checkForSpeeding();
}
// 清理超过指定秒数内的数据
private static void cleanUpOldStrings() {
long currentTime = System.currentTimeMillis();
receivedStrings.removeIf(jsonObject ->
currentTime - jsonObject.getLong("time") > TimeUnit.SECONDS.toMillis(DURATION_SECONDS)
);
}
// 检查是否有超速情况
private static void checkForSpeeding() {
if (receivedStrings.size() < 2) return; // 如果数据不足,直接返回
for (int i = 0; i < receivedStrings.size() - 1; i++) {
JSONObject current = receivedStrings.get(i);
JSONObject next = receivedStrings.get(i + 1);
Short currentElapsed = current.getShort(file);
Short nextElapsed = next.getShort(file);
// 检查条件如果相差大于12则记录错误
if (nextElapsed > currentElapsed + 12) {
System.out.println("出错啦,出错啦,车子超速啦!!!");
}
}
}
//解析报文的方法
public JSONObject messageParsing(String templateMessage) {
//给一个JSON对象
JSONObject jsonObject = new JSONObject();
//先截取出VIN码 然后根据VIN码查询这个车属于什么类型
if (templateMessage.length() < 18) {
throw new RuntimeException("The vehicle message is incorrect");
}
//将报文进行切割
String[] hexArray = templateMessage.split(" ");
StringBuilder result = new StringBuilder();
for (String hex : hexArray) {
int decimal = Integer.parseInt(hex, 16);
result.append((char) decimal);
}
//取出VIN码
String carVin = result.substring(0, 18 - 1);
log.info("carVin码为:" + carVin);
//根据VIN码获取车辆信息
SysCar carByVin = null;
List<SysCar> carList = redisService.getCacheList("carList");
for (SysCar sysCar : carList) {
if(sysCar.getCarVin().equals(carVin)){
carByVin=sysCar;
}
}
log.info("车辆信息为:" + carByVin);
//对应车辆所对应的报文模版
Integer templateId = carByVin.getTemplateId();
List<MessageTemplateType> templateTypeList;
//key
String redisKey = "messageTemplateType" + templateId;
//key存在
if (redisTemplate.hasKey(redisKey)) {
List list = redisTemplate.opsForList().range(redisKey, 0, -1);
templateTypeList = list.stream().map(o -> JSON.parseObject(o.toString(), MessageTemplateType.class))
.toList();
} else {
List<MessageTemplateType> templateTypeList1=null;
List<MessageTemplateType> templateTypeList2 = redisService.getCacheList("templateTypeList");
for (MessageTemplateType messageTemplateType : templateTypeList2) {
if(messageTemplateType.getTemplateId()==templateId){
templateTypeList1.add(messageTemplateType);
}
}
templateTypeList = templateTypeList1;
templateTypeList.forEach(
templateType ->
redisTemplate.opsForList().rightPush(
redisKey, JSON.toJSONString(templateType)
)
);
}
//将模版里面有的配置进行循环
for (MessageTemplateType messageTemplateType : templateTypeList) {
//开始位置
Integer startIndex = messageTemplateType.getStartIndex() - 1;
//结束位置
Integer endIndex = messageTemplateType.getEndIndex();
//将每个解析后的字段都存入到JSON对象中
jsonObject.put(messageTemplateType.getMessageField(),result.substring(startIndex, endIndex));
}
log.info("解析后的报文是:" + jsonObject);
return jsonObject;
}
}

View File

@ -0,0 +1,85 @@
package com.muyu.template;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.log4j.Log4j2;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* @author liuxinyue
* @Packagecom.muyu.template
* @nametest2
* @Date2024/10/6 10:34
*/
@Log4j2
public class test2 {
private static final int DURATION_SECONDS = 5;
private static List<JSONObject> receivedStrings = new ArrayList<>();
private static ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
private static int elapsedSeconds = 0;
private static String file="elapsed";
public static void main(String[] args) {
// 定义一个任务,每秒执行一次
Runnable task = new Runnable() {
@Override
public void run() {
JSONObject stringFromSource = getStringFromSource(); // 模拟获取字符串
receivedStrings.add(stringFromSource);
System.out.println("Received: " + stringFromSource);
// 清理超过的数据
cleanUpOldStrings();
// 检查超速条件
checkForSpeeding();
}
};
// 每隔1秒执行一次任务
scheduler.scheduleAtFixedRate(task, 0, 1, TimeUnit.SECONDS);
}
// 模拟从某个源获取字符串的方法
private static JSONObject getStringFromSource() {
JSONObject jsonObject = new JSONObject();
jsonObject.put("message", "Hello World");
jsonObject.put("time", System.currentTimeMillis());
jsonObject.put("elapsed", elapsedSeconds);
return jsonObject;
}
// 清理超过60秒的数据
private static void cleanUpOldStrings() {
long currentTime = System.currentTimeMillis();
receivedStrings.removeIf(jsonObject ->
currentTime - jsonObject.getLong("time") > TimeUnit.SECONDS.toMillis(DURATION_SECONDS)
);
}
// 检查是否有超速情况
private static void checkForSpeeding() {
if (receivedStrings.size() < 2) return; // 如果数据不足,直接返回
JSONObject jsonObject = new JSONObject();
jsonObject.put("message", "Hello World");
jsonObject.put("time", System.currentTimeMillis());
jsonObject.put("elapsed", 100);
for (int i = 0; i < receivedStrings.size() - 1; i++) {
JSONObject current = receivedStrings.get(i);
JSONObject next = receivedStrings.get(i + 1);
Short currentElapsed = current.getShort(file);
Short nextElapsed = next.getShort(file);
receivedStrings.add(jsonObject);
// 检查条件如果相差大于12则记录错误
if (nextElapsed > currentElapsed + 12) {
System.out.println("出错啦,出错啦,车子超速啦!!!");
}
}
}
}

View File

@ -2,10 +2,7 @@ package com.muyu.common.domain.resp;
import com.muyu.common.core.annotation.Excel;
import com.muyu.common.domain.SysCar;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.*;
/**
*
@ -18,6 +15,7 @@ import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class SysCarVo extends SysCar {
@Excel(name = "车辆类型名称")