diff --git a/cloud-auth/pom.xml b/cloud-auth/pom.xml
index 4cd0756..c38fc2b 100644
--- a/cloud-auth/pom.xml
+++ b/cloud-auth/pom.xml
@@ -17,6 +17,11 @@
+
+ com.baomidou
+ mybatis-plus-boot-starter
+ 3.5.5
+
@@ -36,6 +41,11 @@
spring-cloud-starter-alibaba-sentinel
+
+ com.muyu
+ cloud-common-saas
+
+
org.springframework.boot
diff --git a/cloud-modules/cloud-modules-template/pom.xml b/cloud-modules/cloud-modules-template/pom.xml
index fa19206..12015f9 100644
--- a/cloud-modules/cloud-modules-template/pom.xml
+++ b/cloud-modules/cloud-modules-template/pom.xml
@@ -89,6 +89,15 @@
com.muyu
cloud-common-xxl
+
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+
+
+ redis.clients
+ jedis
+
diff --git a/cloud-modules/cloud-modules-template/src/main/java/com/muyu/template/CloudTemplateApplication.java b/cloud-modules/cloud-modules-template/src/main/java/com/muyu/template/CloudTemplateApplication.java
index 80804e6..359305f 100644
--- a/cloud-modules/cloud-modules-template/src/main/java/com/muyu/template/CloudTemplateApplication.java
+++ b/cloud-modules/cloud-modules-template/src/main/java/com/muyu/template/CloudTemplateApplication.java
@@ -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);
-
}
-
}
diff --git a/cloud-modules/cloud-modules-template/src/main/java/com/muyu/template/config/MqttConfigure.java b/cloud-modules/cloud-modules-template/src/main/java/com/muyu/template/config/MqttConfigure.java
index 065aa80..48bb64c 100644
--- a/cloud-modules/cloud-modules-template/src/main/java/com/muyu/template/config/MqttConfigure.java
+++ b/cloud-modules/cloud-modules-template/src/main/java/com/muyu/template/config/MqttConfigure.java
@@ -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 carList = redisService.getCacheList("carList");
- for (SysCar sysCar : carList) {
- if(sysCar.getCarVin().equals(carVin)){
- carByVin=sysCar;
- }
+ List carList = service.get("carList");
+ if(carList==null){
+ throw new RuntimeException("Redis未获取到车辆数据!!!");
+ }else{
+ // 使用 HashMap 存储车信息,以 VIN 作为键
+ Map 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 templateTypeList;
- //key
- String redisKey = "messageTemplateType" + templateId;
+ List 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 templateTypeList1=null;
- List templateTypeList2 = redisService.getCacheList("templateTypeList");
- for (MessageTemplateType messageTemplateType : templateTypeList2) {
- if(messageTemplateType.getTemplateId()==templateId){
- templateTypeList1.add(messageTemplateType);
- }
- }
-// List 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 stringStringProducerRecord = new ProducerRecord<>("four_car", jsonObject.toString());
-// kafkaProducer.send(stringStringProducerRecord);
-// log.info("kafka发送成功");
-// }
+ //kafka发送消息
+ public void sendKafka(JSONObject jsonObject){
+ ProducerRecord stringStringProducerRecord = new ProducerRecord<>("four_car", jsonObject.toString());
+ kafkaProducer.send(stringStringProducerRecord);
+ log.info("kafka发送成功");
+ }
}
diff --git a/cloud-modules/cloud-modules-template/src/main/java/com/muyu/template/controller/KafkaController.java b/cloud-modules/cloud-modules-template/src/main/java/com/muyu/template/controller/KafkaController.java
deleted file mode 100644
index 34e4ccd..0000000
--- a/cloud-modules/cloud-modules-template/src/main/java/com/muyu/template/controller/KafkaController.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.muyu.template.controller;
-
-/**
- * @author liuxinyue
- * @Package:com.muyu.template.controller
- * @name:KafkaController
- * @Date:2024/10/4 16:11
- */
-public class KafkaController {
-}
diff --git a/cloud-modules/cloud-modules-template/src/main/java/com/muyu/template/controller/TemplateController.java b/cloud-modules/cloud-modules-template/src/main/java/com/muyu/template/controller/TemplateController.java
new file mode 100644
index 0000000..1e55cda
--- /dev/null
+++ b/cloud-modules/cloud-modules-template/src/main/java/com/muyu/template/controller/TemplateController.java
@@ -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
+ * @Package:com.muyu.template.controller
+ * @name:TemplateController
+ * @Date:2024/10/7 10:28
+ */
+@RestController
+@RequestMapping("/template")
+@AllArgsConstructor
+@Tag(name = "协议解析管理",description = "协议解析管理")
+@Log4j2
+public class TemplateController {
+}
diff --git a/cloud-modules/cloud-modules-template/src/main/java/com/muyu/template/test.java b/cloud-modules/cloud-modules-template/src/main/java/com/muyu/template/test.java
index e602a8d..e7d8821 100644
--- a/cloud-modules/cloud-modules-template/src/main/java/com/muyu/template/test.java
+++ b/cloud-modules/cloud-modules-template/src/main/java/com/muyu/template/test.java
@@ -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
* @Package:com.muyu.template
* @name:test
* @Date:2024/10/4 9:42
*/
+@Log4j2
public class test {
+ private static int DURATION_SECONDS = 60;
+ private static List 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 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 templateList = redisService.getCacheList("template");
+ //报文模版 根据templateId取出对应的模版
+ List templateTypeList1=null;
+ List templateTypeList = redisService.getCacheList("templateTypeList");
+ for (MessageTemplateType messageTemplateType : templateTypeList) {
+ if(messageTemplateType.getTemplateId().equals(templateId)){
+ templateTypeList1.add(messageTemplateType);
+ }
+ }
//获取策略对应的规则列表
List warnRule = redisService.getCacheList("warnRule");
-
+ //车辆对应的规则
List 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 messageTemplateTypes=null;
+ for (String s : templateIdSplit) {
+ for (MessageTemplateType messageTemplateType : templateTypeList1) {
+ if(s.equals(messageTemplateType.getTemplateId())){
+ messageTemplateTypes.add(messageTemplateType);
+ }
+ }
+ }
+ JSONObject entries = messageParsing(message);
+ //将解析后的数据添加到List 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 carList = redisService.getCacheList("carList");
+ for (SysCar sysCar : carList) {
+ if(sysCar.getCarVin().equals(carVin)){
+ carByVin=sysCar;
+ }
+ }
+ log.info("车辆信息为:" + carByVin);
+ //对应车辆所对应的报文模版
+ Integer templateId = carByVin.getTemplateId();
+ List 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 templateTypeList1=null;
+ List 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;
+ }
}
diff --git a/cloud-modules/cloud-modules-template/src/main/java/com/muyu/template/test2.java b/cloud-modules/cloud-modules-template/src/main/java/com/muyu/template/test2.java
new file mode 100644
index 0000000..32f1447
--- /dev/null
+++ b/cloud-modules/cloud-modules-template/src/main/java/com/muyu/template/test2.java
@@ -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
+ * @Package:com.muyu.template
+ * @name:test2
+ * @Date:2024/10/6 10:34
+ */
+@Log4j2
+public class test2 {
+
+ private static final int DURATION_SECONDS = 5;
+ private static List 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("出错啦,出错啦,车子超速啦!!!");
+ }
+ }
+ }
+
+
+}
diff --git a/cloud-modules/saas/saas-common/src/main/java/com/muyu/common/domain/resp/SysCarVo.java b/cloud-modules/saas/saas-common/src/main/java/com/muyu/common/domain/resp/SysCarVo.java
index c798859..966d328 100644
--- a/cloud-modules/saas/saas-common/src/main/java/com/muyu/common/domain/resp/SysCarVo.java
+++ b/cloud-modules/saas/saas-common/src/main/java/com/muyu/common/domain/resp/SysCarVo.java
@@ -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 = "车辆类型名称")