diff --git a/.gitignore b/.gitignore
index 9e20bc1..78302f1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,6 @@
.idea/
**/target/**
logs/
+*.log
+*.log.*
*.iml
diff --git a/.gitignore b/.gitignore
index 9e20bc1..78302f1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,6 @@
.idea/
**/target/**
logs/
+*.log
+*.log.*
*.iml
diff --git a/casic-iot-web/src/main/resources/config/application-dev.yml b/casic-iot-web/src/main/resources/config/application-dev.yml
index 487fc70..c5c99b7 100644
--- a/casic-iot-web/src/main/resources/config/application-dev.yml
+++ b/casic-iot-web/src/main/resources/config/application-dev.yml
@@ -37,7 +37,7 @@
invalid-time: 86400
config-prefix: 'Casic:'
#kaptcha-open: false #是否开启登录时验证码 (true/false)
- no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/push/data,/push/test
+ no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/aep/**
#flowable数据源和多数据源配置
db:
init:
diff --git a/.gitignore b/.gitignore
index 9e20bc1..78302f1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,6 @@
.idea/
**/target/**
logs/
+*.log
+*.log.*
*.iml
diff --git a/casic-iot-web/src/main/resources/config/application-dev.yml b/casic-iot-web/src/main/resources/config/application-dev.yml
index 487fc70..c5c99b7 100644
--- a/casic-iot-web/src/main/resources/config/application-dev.yml
+++ b/casic-iot-web/src/main/resources/config/application-dev.yml
@@ -37,7 +37,7 @@
invalid-time: 86400
config-prefix: 'Casic:'
#kaptcha-open: false #是否开启登录时验证码 (true/false)
- no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/push/data,/push/test
+ no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/aep/**
#flowable数据源和多数据源配置
db:
init:
diff --git a/casic-iot-web/src/main/resources/config/logback-spring.xml b/casic-iot-web/src/main/resources/config/logback-spring.xml
index c0c7ac9..2d308a8 100644
--- a/casic-iot-web/src/main/resources/config/logback-spring.xml
+++ b/casic-iot-web/src/main/resources/config/logback-spring.xml
@@ -5,7 +5,7 @@
-
+
diff --git a/.gitignore b/.gitignore
index 9e20bc1..78302f1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,6 @@
.idea/
**/target/**
logs/
+*.log
+*.log.*
*.iml
diff --git a/casic-iot-web/src/main/resources/config/application-dev.yml b/casic-iot-web/src/main/resources/config/application-dev.yml
index 487fc70..c5c99b7 100644
--- a/casic-iot-web/src/main/resources/config/application-dev.yml
+++ b/casic-iot-web/src/main/resources/config/application-dev.yml
@@ -37,7 +37,7 @@
invalid-time: 86400
config-prefix: 'Casic:'
#kaptcha-open: false #是否开启登录时验证码 (true/false)
- no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/push/data,/push/test
+ no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/aep/**
#flowable数据源和多数据源配置
db:
init:
diff --git a/casic-iot-web/src/main/resources/config/logback-spring.xml b/casic-iot-web/src/main/resources/config/logback-spring.xml
index c0c7ac9..2d308a8 100644
--- a/casic-iot-web/src/main/resources/config/logback-spring.xml
+++ b/casic-iot-web/src/main/resources/config/logback-spring.xml
@@ -5,7 +5,7 @@
-
+
diff --git a/pom.xml b/pom.xml
index 3ad2470..a194074 100644
--- a/pom.xml
+++ b/pom.xml
@@ -49,6 +49,7 @@
2.0.0.alpha
2.5.4
2.5.6
+ 1.2.62
2.0.0.alpha
@@ -56,7 +57,11 @@
-
+
+ com.casic
+ casic-core
+ ${core.version}
+
com.baomidou
dynamic-datasource-spring-boot-starter
@@ -69,11 +74,11 @@
${fastjson.version}
-
- cn.hutool
- hutool-core
- 5.7.2
-
+
+
+
+
+
org.projectlombok
diff --git a/.gitignore b/.gitignore
index 9e20bc1..78302f1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,6 @@
.idea/
**/target/**
logs/
+*.log
+*.log.*
*.iml
diff --git a/casic-iot-web/src/main/resources/config/application-dev.yml b/casic-iot-web/src/main/resources/config/application-dev.yml
index 487fc70..c5c99b7 100644
--- a/casic-iot-web/src/main/resources/config/application-dev.yml
+++ b/casic-iot-web/src/main/resources/config/application-dev.yml
@@ -37,7 +37,7 @@
invalid-time: 86400
config-prefix: 'Casic:'
#kaptcha-open: false #是否开启登录时验证码 (true/false)
- no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/push/data,/push/test
+ no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/aep/**
#flowable数据源和多数据源配置
db:
init:
diff --git a/casic-iot-web/src/main/resources/config/logback-spring.xml b/casic-iot-web/src/main/resources/config/logback-spring.xml
index c0c7ac9..2d308a8 100644
--- a/casic-iot-web/src/main/resources/config/logback-spring.xml
+++ b/casic-iot-web/src/main/resources/config/logback-spring.xml
@@ -5,7 +5,7 @@
-
+
diff --git a/pom.xml b/pom.xml
index 3ad2470..a194074 100644
--- a/pom.xml
+++ b/pom.xml
@@ -49,6 +49,7 @@
2.0.0.alpha
2.5.4
2.5.6
+ 1.2.62
2.0.0.alpha
@@ -56,7 +57,11 @@
-
+
+ com.casic
+ casic-core
+ ${core.version}
+
com.baomidou
dynamic-datasource-spring-boot-starter
@@ -69,11 +74,11 @@
${fastjson.version}
-
- cn.hutool
- hutool-core
- 5.7.2
-
+
+
+
+
+
org.projectlombok
diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml
index d5118b4..8dcc497 100644
--- a/sensorhub-core/pom.xml
+++ b/sensorhub-core/pom.xml
@@ -35,17 +35,17 @@
com.ctg.ag
ctg-ag-sdk-core
-
2.8.0-SNAPSHOT
-
+ system
+ ${pom.basedir}\lib\ctg-ag-sdk-core-2.8.0.jar
com.ctg.ag
ag-sdk-biz
2.8.0-SNAPSHOT
-
-
+ system
+ ${pom.basedir}\lib\ag-sdk-biz.jar
diff --git a/.gitignore b/.gitignore
index 9e20bc1..78302f1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,6 @@
.idea/
**/target/**
logs/
+*.log
+*.log.*
*.iml
diff --git a/casic-iot-web/src/main/resources/config/application-dev.yml b/casic-iot-web/src/main/resources/config/application-dev.yml
index 487fc70..c5c99b7 100644
--- a/casic-iot-web/src/main/resources/config/application-dev.yml
+++ b/casic-iot-web/src/main/resources/config/application-dev.yml
@@ -37,7 +37,7 @@
invalid-time: 86400
config-prefix: 'Casic:'
#kaptcha-open: false #是否开启登录时验证码 (true/false)
- no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/push/data,/push/test
+ no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/aep/**
#flowable数据源和多数据源配置
db:
init:
diff --git a/casic-iot-web/src/main/resources/config/logback-spring.xml b/casic-iot-web/src/main/resources/config/logback-spring.xml
index c0c7ac9..2d308a8 100644
--- a/casic-iot-web/src/main/resources/config/logback-spring.xml
+++ b/casic-iot-web/src/main/resources/config/logback-spring.xml
@@ -5,7 +5,7 @@
-
+
diff --git a/pom.xml b/pom.xml
index 3ad2470..a194074 100644
--- a/pom.xml
+++ b/pom.xml
@@ -49,6 +49,7 @@
2.0.0.alpha
2.5.4
2.5.6
+ 1.2.62
2.0.0.alpha
@@ -56,7 +57,11 @@
-
+
+ com.casic
+ casic-core
+ ${core.version}
+
com.baomidou
dynamic-datasource-spring-boot-starter
@@ -69,11 +74,11 @@
${fastjson.version}
-
- cn.hutool
- hutool-core
- 5.7.2
-
+
+
+
+
+
org.projectlombok
diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml
index d5118b4..8dcc497 100644
--- a/sensorhub-core/pom.xml
+++ b/sensorhub-core/pom.xml
@@ -35,17 +35,17 @@
com.ctg.ag
ctg-ag-sdk-core
-
2.8.0-SNAPSHOT
-
+ system
+ ${pom.basedir}\lib\ctg-ag-sdk-core-2.8.0.jar
com.ctg.ag
ag-sdk-biz
2.8.0-SNAPSHOT
-
-
+ system
+ ${pom.basedir}\lib\ag-sdk-biz.jar
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java
deleted file mode 100644
index 40c55e8..0000000
--- a/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java
+++ /dev/null
@@ -1,30 +0,0 @@
-//package com.casic.missiles;
-//
-//import com.casic.missiles.netty.SensorhubServer;
-//import lombok.extern.slf4j.Slf4j;
-//import org.mybatis.spring.annotation.MapperScan;
-//import org.springframework.beans.factory.annotation.Autowired;
-//import org.springframework.boot.CommandLineRunner;
-//import org.springframework.boot.SpringApplication;
-//import org.springframework.boot.autoconfigure.SpringBootApplication;
-//import org.springframework.cache.annotation.EnableCaching;
-//
-//
-//@SpringBootApplication(scanBasePackages = "com.casic.missiles")
-//@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"})
-//@EnableCaching //开启缓存
-//@Slf4j
-//public class ServerApplication implements CommandLineRunner {
-//
-// @Autowired
-// private SensorhubServer nettyServer;
-// public static void main(String[] args) {
-// SpringApplication.run(ServerApplication.class, args);
-// }
-//
-// @Override
-// public void run(String... args) {
-// this.nettyServer.startServer();
-// }
-//
-//}
diff --git a/.gitignore b/.gitignore
index 9e20bc1..78302f1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,6 @@
.idea/
**/target/**
logs/
+*.log
+*.log.*
*.iml
diff --git a/casic-iot-web/src/main/resources/config/application-dev.yml b/casic-iot-web/src/main/resources/config/application-dev.yml
index 487fc70..c5c99b7 100644
--- a/casic-iot-web/src/main/resources/config/application-dev.yml
+++ b/casic-iot-web/src/main/resources/config/application-dev.yml
@@ -37,7 +37,7 @@
invalid-time: 86400
config-prefix: 'Casic:'
#kaptcha-open: false #是否开启登录时验证码 (true/false)
- no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/push/data,/push/test
+ no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/aep/**
#flowable数据源和多数据源配置
db:
init:
diff --git a/casic-iot-web/src/main/resources/config/logback-spring.xml b/casic-iot-web/src/main/resources/config/logback-spring.xml
index c0c7ac9..2d308a8 100644
--- a/casic-iot-web/src/main/resources/config/logback-spring.xml
+++ b/casic-iot-web/src/main/resources/config/logback-spring.xml
@@ -5,7 +5,7 @@
-
+
diff --git a/pom.xml b/pom.xml
index 3ad2470..a194074 100644
--- a/pom.xml
+++ b/pom.xml
@@ -49,6 +49,7 @@
2.0.0.alpha
2.5.4
2.5.6
+ 1.2.62
2.0.0.alpha
@@ -56,7 +57,11 @@
-
+
+ com.casic
+ casic-core
+ ${core.version}
+
com.baomidou
dynamic-datasource-spring-boot-starter
@@ -69,11 +74,11 @@
${fastjson.version}
-
- cn.hutool
- hutool-core
- 5.7.2
-
+
+
+
+
+
org.projectlombok
diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml
index d5118b4..8dcc497 100644
--- a/sensorhub-core/pom.xml
+++ b/sensorhub-core/pom.xml
@@ -35,17 +35,17 @@
com.ctg.ag
ctg-ag-sdk-core
-
2.8.0-SNAPSHOT
-
+ system
+ ${pom.basedir}\lib\ctg-ag-sdk-core-2.8.0.jar
com.ctg.ag
ag-sdk-biz
2.8.0-SNAPSHOT
-
-
+ system
+ ${pom.basedir}\lib\ag-sdk-biz.jar
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java
deleted file mode 100644
index 40c55e8..0000000
--- a/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java
+++ /dev/null
@@ -1,30 +0,0 @@
-//package com.casic.missiles;
-//
-//import com.casic.missiles.netty.SensorhubServer;
-//import lombok.extern.slf4j.Slf4j;
-//import org.mybatis.spring.annotation.MapperScan;
-//import org.springframework.beans.factory.annotation.Autowired;
-//import org.springframework.boot.CommandLineRunner;
-//import org.springframework.boot.SpringApplication;
-//import org.springframework.boot.autoconfigure.SpringBootApplication;
-//import org.springframework.cache.annotation.EnableCaching;
-//
-//
-//@SpringBootApplication(scanBasePackages = "com.casic.missiles")
-//@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"})
-//@EnableCaching //开启缓存
-//@Slf4j
-//public class ServerApplication implements CommandLineRunner {
-//
-// @Autowired
-// private SensorhubServer nettyServer;
-// public static void main(String[] args) {
-// SpringApplication.run(ServerApplication.class, args);
-// }
-//
-// @Override
-// public void run(String... args) {
-// this.nettyServer.startServer();
-// }
-//
-//}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java b/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java
new file mode 100644
index 0000000..8f90fd9
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java
@@ -0,0 +1,96 @@
+package com.casic.missiles.controller;
+
+import com.alibaba.fastjson.JSONObject;
+import com.casic.missiles.frame.BirmmBaseFrame;
+import com.casic.missiles.model.response.ResponseData;
+import com.casic.missiles.service.IGeneralService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.tomcat.util.buf.HexUtils;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.util.Base64;
+import java.util.Map;
+
+@RestController
+@Slf4j
+public class GeneralDataReceiver {
+
+ @Resource
+ IGeneralService defaultService;
+
+ @RequestMapping("/aep/data/string")
+ public Object aepDataString(@RequestBody Map dataMap) {
+ log.info("收到AEP平台推送消息:{}", JSONObject.toJSONString(dataMap));
+ log.debug("deviceId: {}, productId: {}, IMEI: {}, timestamp: {}", dataMap.get("deviceId"), dataMap.get("productId"), dataMap.get("IMEI"), dataMap.get("timestamp"));
+
+ // 从推送的数据中获取消息帧
+ String frameStr = new String(getFrameStringFromData(dataMap));
+ log.info("字符串消息帧:{}", frameStr);
+
+ return ResponseData.success();
+ }
+
+ @RequestMapping("/aep/data/hex")
+ public Object aepDataHex(@RequestBody Map dataMap) {
+ log.info("收到AEP平台推送消息:{}", JSONObject.toJSONString(dataMap));
+ log.debug("deviceId: {}, productId: {}, IMEI: {}, timestamp: {}", dataMap.get("deviceId"), dataMap.get("productId"), dataMap.get("IMEI"), dataMap.get("timestamp"));
+
+ // 从推送的数据中获取消息帧
+ byte[] frameBytes = getFrameStringFromData(dataMap);
+ log.info("HEX字节消息帧:{}", HexUtils.toHexString(frameBytes).toUpperCase());
+
+ BirmmBaseFrame birmmFrame = defaultService.dataParse(frameBytes);
+ if (birmmFrame != null) {
+ log.info("HEX字节消息解析成功:{}", birmmFrame);
+ }
+
+ // 返回给电信AEP平台
+ return ResponseData.success();
+ }
+
+ private byte[] getFrameStringFromData(Map dataMap) {
+ byte[] frameStr = new byte[]{};
+
+ if (!dataMap.containsKey("payload")) {
+ log.error("消息帧不含payload字段");
+ return frameStr;
+ }
+
+ // 判断是否有profile
+ boolean hasProfile = false;
+ if (dataMap.containsKey("profile")) {
+ hasProfile = (Boolean) dataMap.get("profile");
+ }
+
+ JSONObject payload = (JSONObject) dataMap.get("payload");
+ // base64格式的消息 电信平台推送的内容
+ String dataBase64 = "";
+ if (hasProfile) {
+ if (!payload.containsKey("serviceData")) {
+ log.error("payload字段中不含serviceData字段");
+ } else {
+ JSONObject serviceData = payload.getJSONObject("serviceData");
+ if (!serviceData.containsKey("Value")) {
+ log.error("serviceData字段中不含Value字段");
+ } else {
+ dataBase64 = serviceData.getString("Value");
+ }
+ }
+ } else {
+ if (payload.containsKey("APPdata")) {
+ dataBase64 = payload.getString("APPdata");
+ } else {
+ log.error("payload字段中不含APPdata字段");
+ }
+ }
+
+ if (!dataBase64.isEmpty()) {
+ frameStr = Base64.getDecoder().decode(dataBase64); // base64解码
+ }
+
+ return frameStr;
+ }
+}
diff --git a/.gitignore b/.gitignore
index 9e20bc1..78302f1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,6 @@
.idea/
**/target/**
logs/
+*.log
+*.log.*
*.iml
diff --git a/casic-iot-web/src/main/resources/config/application-dev.yml b/casic-iot-web/src/main/resources/config/application-dev.yml
index 487fc70..c5c99b7 100644
--- a/casic-iot-web/src/main/resources/config/application-dev.yml
+++ b/casic-iot-web/src/main/resources/config/application-dev.yml
@@ -37,7 +37,7 @@
invalid-time: 86400
config-prefix: 'Casic:'
#kaptcha-open: false #是否开启登录时验证码 (true/false)
- no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/push/data,/push/test
+ no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/aep/**
#flowable数据源和多数据源配置
db:
init:
diff --git a/casic-iot-web/src/main/resources/config/logback-spring.xml b/casic-iot-web/src/main/resources/config/logback-spring.xml
index c0c7ac9..2d308a8 100644
--- a/casic-iot-web/src/main/resources/config/logback-spring.xml
+++ b/casic-iot-web/src/main/resources/config/logback-spring.xml
@@ -5,7 +5,7 @@
-
+
diff --git a/pom.xml b/pom.xml
index 3ad2470..a194074 100644
--- a/pom.xml
+++ b/pom.xml
@@ -49,6 +49,7 @@
2.0.0.alpha
2.5.4
2.5.6
+ 1.2.62
2.0.0.alpha
@@ -56,7 +57,11 @@
-
+
+ com.casic
+ casic-core
+ ${core.version}
+
com.baomidou
dynamic-datasource-spring-boot-starter
@@ -69,11 +74,11 @@
${fastjson.version}
-
- cn.hutool
- hutool-core
- 5.7.2
-
+
+
+
+
+
org.projectlombok
diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml
index d5118b4..8dcc497 100644
--- a/sensorhub-core/pom.xml
+++ b/sensorhub-core/pom.xml
@@ -35,17 +35,17 @@
com.ctg.ag
ctg-ag-sdk-core
-
2.8.0-SNAPSHOT
-
+ system
+ ${pom.basedir}\lib\ctg-ag-sdk-core-2.8.0.jar
com.ctg.ag
ag-sdk-biz
2.8.0-SNAPSHOT
-
-
+ system
+ ${pom.basedir}\lib\ag-sdk-biz.jar
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java
deleted file mode 100644
index 40c55e8..0000000
--- a/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java
+++ /dev/null
@@ -1,30 +0,0 @@
-//package com.casic.missiles;
-//
-//import com.casic.missiles.netty.SensorhubServer;
-//import lombok.extern.slf4j.Slf4j;
-//import org.mybatis.spring.annotation.MapperScan;
-//import org.springframework.beans.factory.annotation.Autowired;
-//import org.springframework.boot.CommandLineRunner;
-//import org.springframework.boot.SpringApplication;
-//import org.springframework.boot.autoconfigure.SpringBootApplication;
-//import org.springframework.cache.annotation.EnableCaching;
-//
-//
-//@SpringBootApplication(scanBasePackages = "com.casic.missiles")
-//@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"})
-//@EnableCaching //开启缓存
-//@Slf4j
-//public class ServerApplication implements CommandLineRunner {
-//
-// @Autowired
-// private SensorhubServer nettyServer;
-// public static void main(String[] args) {
-// SpringApplication.run(ServerApplication.class, args);
-// }
-//
-// @Override
-// public void run(String... args) {
-// this.nettyServer.startServer();
-// }
-//
-//}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java b/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java
new file mode 100644
index 0000000..8f90fd9
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java
@@ -0,0 +1,96 @@
+package com.casic.missiles.controller;
+
+import com.alibaba.fastjson.JSONObject;
+import com.casic.missiles.frame.BirmmBaseFrame;
+import com.casic.missiles.model.response.ResponseData;
+import com.casic.missiles.service.IGeneralService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.tomcat.util.buf.HexUtils;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.util.Base64;
+import java.util.Map;
+
+@RestController
+@Slf4j
+public class GeneralDataReceiver {
+
+ @Resource
+ IGeneralService defaultService;
+
+ @RequestMapping("/aep/data/string")
+ public Object aepDataString(@RequestBody Map dataMap) {
+ log.info("收到AEP平台推送消息:{}", JSONObject.toJSONString(dataMap));
+ log.debug("deviceId: {}, productId: {}, IMEI: {}, timestamp: {}", dataMap.get("deviceId"), dataMap.get("productId"), dataMap.get("IMEI"), dataMap.get("timestamp"));
+
+ // 从推送的数据中获取消息帧
+ String frameStr = new String(getFrameStringFromData(dataMap));
+ log.info("字符串消息帧:{}", frameStr);
+
+ return ResponseData.success();
+ }
+
+ @RequestMapping("/aep/data/hex")
+ public Object aepDataHex(@RequestBody Map dataMap) {
+ log.info("收到AEP平台推送消息:{}", JSONObject.toJSONString(dataMap));
+ log.debug("deviceId: {}, productId: {}, IMEI: {}, timestamp: {}", dataMap.get("deviceId"), dataMap.get("productId"), dataMap.get("IMEI"), dataMap.get("timestamp"));
+
+ // 从推送的数据中获取消息帧
+ byte[] frameBytes = getFrameStringFromData(dataMap);
+ log.info("HEX字节消息帧:{}", HexUtils.toHexString(frameBytes).toUpperCase());
+
+ BirmmBaseFrame birmmFrame = defaultService.dataParse(frameBytes);
+ if (birmmFrame != null) {
+ log.info("HEX字节消息解析成功:{}", birmmFrame);
+ }
+
+ // 返回给电信AEP平台
+ return ResponseData.success();
+ }
+
+ private byte[] getFrameStringFromData(Map dataMap) {
+ byte[] frameStr = new byte[]{};
+
+ if (!dataMap.containsKey("payload")) {
+ log.error("消息帧不含payload字段");
+ return frameStr;
+ }
+
+ // 判断是否有profile
+ boolean hasProfile = false;
+ if (dataMap.containsKey("profile")) {
+ hasProfile = (Boolean) dataMap.get("profile");
+ }
+
+ JSONObject payload = (JSONObject) dataMap.get("payload");
+ // base64格式的消息 电信平台推送的内容
+ String dataBase64 = "";
+ if (hasProfile) {
+ if (!payload.containsKey("serviceData")) {
+ log.error("payload字段中不含serviceData字段");
+ } else {
+ JSONObject serviceData = payload.getJSONObject("serviceData");
+ if (!serviceData.containsKey("Value")) {
+ log.error("serviceData字段中不含Value字段");
+ } else {
+ dataBase64 = serviceData.getString("Value");
+ }
+ }
+ } else {
+ if (payload.containsKey("APPdata")) {
+ dataBase64 = payload.getString("APPdata");
+ } else {
+ log.error("payload字段中不含APPdata字段");
+ }
+ }
+
+ if (!dataBase64.isEmpty()) {
+ frameStr = Base64.getDecoder().decode(dataBase64); // base64解码
+ }
+
+ return frameStr;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java
new file mode 100644
index 0000000..ae6706a
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java
@@ -0,0 +1,40 @@
+package com.casic.missiles.frame;
+
+import lombok.Data;
+import java.util.List;
+
+@Data
+public class BirmmBaseFrame {
+
+ // 前导码 固定为A3
+ final String PRE_CODE = "A3";
+
+ // 协议版本 固定为20
+ final String VERSION = "20";
+
+ // 帧长度 后续到CRC字段前的字节总长度 不包括长度字段和CRC字段
+ int length;
+
+ // 设备编号
+ String devCode;
+
+ // 通信方式
+ String communicationType;
+
+ // 目标节点地址
+ String destinationAddr;
+
+ // PDU类型
+ String pduType;
+
+ // 序号
+ String sequence;
+
+ // 业务字段List
+ String tagListString;
+
+ List tagList;
+
+ // CRC
+ String crc;
+}
diff --git a/.gitignore b/.gitignore
index 9e20bc1..78302f1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,6 @@
.idea/
**/target/**
logs/
+*.log
+*.log.*
*.iml
diff --git a/casic-iot-web/src/main/resources/config/application-dev.yml b/casic-iot-web/src/main/resources/config/application-dev.yml
index 487fc70..c5c99b7 100644
--- a/casic-iot-web/src/main/resources/config/application-dev.yml
+++ b/casic-iot-web/src/main/resources/config/application-dev.yml
@@ -37,7 +37,7 @@
invalid-time: 86400
config-prefix: 'Casic:'
#kaptcha-open: false #是否开启登录时验证码 (true/false)
- no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/push/data,/push/test
+ no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/aep/**
#flowable数据源和多数据源配置
db:
init:
diff --git a/casic-iot-web/src/main/resources/config/logback-spring.xml b/casic-iot-web/src/main/resources/config/logback-spring.xml
index c0c7ac9..2d308a8 100644
--- a/casic-iot-web/src/main/resources/config/logback-spring.xml
+++ b/casic-iot-web/src/main/resources/config/logback-spring.xml
@@ -5,7 +5,7 @@
-
+
diff --git a/pom.xml b/pom.xml
index 3ad2470..a194074 100644
--- a/pom.xml
+++ b/pom.xml
@@ -49,6 +49,7 @@
2.0.0.alpha
2.5.4
2.5.6
+ 1.2.62
2.0.0.alpha
@@ -56,7 +57,11 @@
-
+
+ com.casic
+ casic-core
+ ${core.version}
+
com.baomidou
dynamic-datasource-spring-boot-starter
@@ -69,11 +74,11 @@
${fastjson.version}
-
- cn.hutool
- hutool-core
- 5.7.2
-
+
+
+
+
+
org.projectlombok
diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml
index d5118b4..8dcc497 100644
--- a/sensorhub-core/pom.xml
+++ b/sensorhub-core/pom.xml
@@ -35,17 +35,17 @@
com.ctg.ag
ctg-ag-sdk-core
-
2.8.0-SNAPSHOT
-
+ system
+ ${pom.basedir}\lib\ctg-ag-sdk-core-2.8.0.jar
com.ctg.ag
ag-sdk-biz
2.8.0-SNAPSHOT
-
-
+ system
+ ${pom.basedir}\lib\ag-sdk-biz.jar
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java
deleted file mode 100644
index 40c55e8..0000000
--- a/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java
+++ /dev/null
@@ -1,30 +0,0 @@
-//package com.casic.missiles;
-//
-//import com.casic.missiles.netty.SensorhubServer;
-//import lombok.extern.slf4j.Slf4j;
-//import org.mybatis.spring.annotation.MapperScan;
-//import org.springframework.beans.factory.annotation.Autowired;
-//import org.springframework.boot.CommandLineRunner;
-//import org.springframework.boot.SpringApplication;
-//import org.springframework.boot.autoconfigure.SpringBootApplication;
-//import org.springframework.cache.annotation.EnableCaching;
-//
-//
-//@SpringBootApplication(scanBasePackages = "com.casic.missiles")
-//@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"})
-//@EnableCaching //开启缓存
-//@Slf4j
-//public class ServerApplication implements CommandLineRunner {
-//
-// @Autowired
-// private SensorhubServer nettyServer;
-// public static void main(String[] args) {
-// SpringApplication.run(ServerApplication.class, args);
-// }
-//
-// @Override
-// public void run(String... args) {
-// this.nettyServer.startServer();
-// }
-//
-//}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java b/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java
new file mode 100644
index 0000000..8f90fd9
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java
@@ -0,0 +1,96 @@
+package com.casic.missiles.controller;
+
+import com.alibaba.fastjson.JSONObject;
+import com.casic.missiles.frame.BirmmBaseFrame;
+import com.casic.missiles.model.response.ResponseData;
+import com.casic.missiles.service.IGeneralService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.tomcat.util.buf.HexUtils;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.util.Base64;
+import java.util.Map;
+
+@RestController
+@Slf4j
+public class GeneralDataReceiver {
+
+ @Resource
+ IGeneralService defaultService;
+
+ @RequestMapping("/aep/data/string")
+ public Object aepDataString(@RequestBody Map dataMap) {
+ log.info("收到AEP平台推送消息:{}", JSONObject.toJSONString(dataMap));
+ log.debug("deviceId: {}, productId: {}, IMEI: {}, timestamp: {}", dataMap.get("deviceId"), dataMap.get("productId"), dataMap.get("IMEI"), dataMap.get("timestamp"));
+
+ // 从推送的数据中获取消息帧
+ String frameStr = new String(getFrameStringFromData(dataMap));
+ log.info("字符串消息帧:{}", frameStr);
+
+ return ResponseData.success();
+ }
+
+ @RequestMapping("/aep/data/hex")
+ public Object aepDataHex(@RequestBody Map dataMap) {
+ log.info("收到AEP平台推送消息:{}", JSONObject.toJSONString(dataMap));
+ log.debug("deviceId: {}, productId: {}, IMEI: {}, timestamp: {}", dataMap.get("deviceId"), dataMap.get("productId"), dataMap.get("IMEI"), dataMap.get("timestamp"));
+
+ // 从推送的数据中获取消息帧
+ byte[] frameBytes = getFrameStringFromData(dataMap);
+ log.info("HEX字节消息帧:{}", HexUtils.toHexString(frameBytes).toUpperCase());
+
+ BirmmBaseFrame birmmFrame = defaultService.dataParse(frameBytes);
+ if (birmmFrame != null) {
+ log.info("HEX字节消息解析成功:{}", birmmFrame);
+ }
+
+ // 返回给电信AEP平台
+ return ResponseData.success();
+ }
+
+ private byte[] getFrameStringFromData(Map dataMap) {
+ byte[] frameStr = new byte[]{};
+
+ if (!dataMap.containsKey("payload")) {
+ log.error("消息帧不含payload字段");
+ return frameStr;
+ }
+
+ // 判断是否有profile
+ boolean hasProfile = false;
+ if (dataMap.containsKey("profile")) {
+ hasProfile = (Boolean) dataMap.get("profile");
+ }
+
+ JSONObject payload = (JSONObject) dataMap.get("payload");
+ // base64格式的消息 电信平台推送的内容
+ String dataBase64 = "";
+ if (hasProfile) {
+ if (!payload.containsKey("serviceData")) {
+ log.error("payload字段中不含serviceData字段");
+ } else {
+ JSONObject serviceData = payload.getJSONObject("serviceData");
+ if (!serviceData.containsKey("Value")) {
+ log.error("serviceData字段中不含Value字段");
+ } else {
+ dataBase64 = serviceData.getString("Value");
+ }
+ }
+ } else {
+ if (payload.containsKey("APPdata")) {
+ dataBase64 = payload.getString("APPdata");
+ } else {
+ log.error("payload字段中不含APPdata字段");
+ }
+ }
+
+ if (!dataBase64.isEmpty()) {
+ frameStr = Base64.getDecoder().decode(dataBase64); // base64解码
+ }
+
+ return frameStr;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java
new file mode 100644
index 0000000..ae6706a
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java
@@ -0,0 +1,40 @@
+package com.casic.missiles.frame;
+
+import lombok.Data;
+import java.util.List;
+
+@Data
+public class BirmmBaseFrame {
+
+ // 前导码 固定为A3
+ final String PRE_CODE = "A3";
+
+ // 协议版本 固定为20
+ final String VERSION = "20";
+
+ // 帧长度 后续到CRC字段前的字节总长度 不包括长度字段和CRC字段
+ int length;
+
+ // 设备编号
+ String devCode;
+
+ // 通信方式
+ String communicationType;
+
+ // 目标节点地址
+ String destinationAddr;
+
+ // PDU类型
+ String pduType;
+
+ // 序号
+ String sequence;
+
+ // 业务字段List
+ String tagListString;
+
+ List tagList;
+
+ // CRC
+ String crc;
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java
new file mode 100644
index 0000000..2285f9a
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java
@@ -0,0 +1,11 @@
+package com.casic.missiles.frame;
+
+import lombok.Data;
+
+@Data
+public class BirmmBaseTag {
+
+ private String oid;
+ private int tagLen;
+ private String valueStr;
+}
diff --git a/.gitignore b/.gitignore
index 9e20bc1..78302f1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,6 @@
.idea/
**/target/**
logs/
+*.log
+*.log.*
*.iml
diff --git a/casic-iot-web/src/main/resources/config/application-dev.yml b/casic-iot-web/src/main/resources/config/application-dev.yml
index 487fc70..c5c99b7 100644
--- a/casic-iot-web/src/main/resources/config/application-dev.yml
+++ b/casic-iot-web/src/main/resources/config/application-dev.yml
@@ -37,7 +37,7 @@
invalid-time: 86400
config-prefix: 'Casic:'
#kaptcha-open: false #是否开启登录时验证码 (true/false)
- no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/push/data,/push/test
+ no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/aep/**
#flowable数据源和多数据源配置
db:
init:
diff --git a/casic-iot-web/src/main/resources/config/logback-spring.xml b/casic-iot-web/src/main/resources/config/logback-spring.xml
index c0c7ac9..2d308a8 100644
--- a/casic-iot-web/src/main/resources/config/logback-spring.xml
+++ b/casic-iot-web/src/main/resources/config/logback-spring.xml
@@ -5,7 +5,7 @@
-
+
diff --git a/pom.xml b/pom.xml
index 3ad2470..a194074 100644
--- a/pom.xml
+++ b/pom.xml
@@ -49,6 +49,7 @@
2.0.0.alpha
2.5.4
2.5.6
+ 1.2.62
2.0.0.alpha
@@ -56,7 +57,11 @@
-
+
+ com.casic
+ casic-core
+ ${core.version}
+
com.baomidou
dynamic-datasource-spring-boot-starter
@@ -69,11 +74,11 @@
${fastjson.version}
-
- cn.hutool
- hutool-core
- 5.7.2
-
+
+
+
+
+
org.projectlombok
diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml
index d5118b4..8dcc497 100644
--- a/sensorhub-core/pom.xml
+++ b/sensorhub-core/pom.xml
@@ -35,17 +35,17 @@
com.ctg.ag
ctg-ag-sdk-core
-
2.8.0-SNAPSHOT
-
+ system
+ ${pom.basedir}\lib\ctg-ag-sdk-core-2.8.0.jar
com.ctg.ag
ag-sdk-biz
2.8.0-SNAPSHOT
-
-
+ system
+ ${pom.basedir}\lib\ag-sdk-biz.jar
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java
deleted file mode 100644
index 40c55e8..0000000
--- a/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java
+++ /dev/null
@@ -1,30 +0,0 @@
-//package com.casic.missiles;
-//
-//import com.casic.missiles.netty.SensorhubServer;
-//import lombok.extern.slf4j.Slf4j;
-//import org.mybatis.spring.annotation.MapperScan;
-//import org.springframework.beans.factory.annotation.Autowired;
-//import org.springframework.boot.CommandLineRunner;
-//import org.springframework.boot.SpringApplication;
-//import org.springframework.boot.autoconfigure.SpringBootApplication;
-//import org.springframework.cache.annotation.EnableCaching;
-//
-//
-//@SpringBootApplication(scanBasePackages = "com.casic.missiles")
-//@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"})
-//@EnableCaching //开启缓存
-//@Slf4j
-//public class ServerApplication implements CommandLineRunner {
-//
-// @Autowired
-// private SensorhubServer nettyServer;
-// public static void main(String[] args) {
-// SpringApplication.run(ServerApplication.class, args);
-// }
-//
-// @Override
-// public void run(String... args) {
-// this.nettyServer.startServer();
-// }
-//
-//}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java b/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java
new file mode 100644
index 0000000..8f90fd9
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java
@@ -0,0 +1,96 @@
+package com.casic.missiles.controller;
+
+import com.alibaba.fastjson.JSONObject;
+import com.casic.missiles.frame.BirmmBaseFrame;
+import com.casic.missiles.model.response.ResponseData;
+import com.casic.missiles.service.IGeneralService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.tomcat.util.buf.HexUtils;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.util.Base64;
+import java.util.Map;
+
+@RestController
+@Slf4j
+public class GeneralDataReceiver {
+
+ @Resource
+ IGeneralService defaultService;
+
+ @RequestMapping("/aep/data/string")
+ public Object aepDataString(@RequestBody Map dataMap) {
+ log.info("收到AEP平台推送消息:{}", JSONObject.toJSONString(dataMap));
+ log.debug("deviceId: {}, productId: {}, IMEI: {}, timestamp: {}", dataMap.get("deviceId"), dataMap.get("productId"), dataMap.get("IMEI"), dataMap.get("timestamp"));
+
+ // 从推送的数据中获取消息帧
+ String frameStr = new String(getFrameStringFromData(dataMap));
+ log.info("字符串消息帧:{}", frameStr);
+
+ return ResponseData.success();
+ }
+
+ @RequestMapping("/aep/data/hex")
+ public Object aepDataHex(@RequestBody Map dataMap) {
+ log.info("收到AEP平台推送消息:{}", JSONObject.toJSONString(dataMap));
+ log.debug("deviceId: {}, productId: {}, IMEI: {}, timestamp: {}", dataMap.get("deviceId"), dataMap.get("productId"), dataMap.get("IMEI"), dataMap.get("timestamp"));
+
+ // 从推送的数据中获取消息帧
+ byte[] frameBytes = getFrameStringFromData(dataMap);
+ log.info("HEX字节消息帧:{}", HexUtils.toHexString(frameBytes).toUpperCase());
+
+ BirmmBaseFrame birmmFrame = defaultService.dataParse(frameBytes);
+ if (birmmFrame != null) {
+ log.info("HEX字节消息解析成功:{}", birmmFrame);
+ }
+
+ // 返回给电信AEP平台
+ return ResponseData.success();
+ }
+
+ private byte[] getFrameStringFromData(Map dataMap) {
+ byte[] frameStr = new byte[]{};
+
+ if (!dataMap.containsKey("payload")) {
+ log.error("消息帧不含payload字段");
+ return frameStr;
+ }
+
+ // 判断是否有profile
+ boolean hasProfile = false;
+ if (dataMap.containsKey("profile")) {
+ hasProfile = (Boolean) dataMap.get("profile");
+ }
+
+ JSONObject payload = (JSONObject) dataMap.get("payload");
+ // base64格式的消息 电信平台推送的内容
+ String dataBase64 = "";
+ if (hasProfile) {
+ if (!payload.containsKey("serviceData")) {
+ log.error("payload字段中不含serviceData字段");
+ } else {
+ JSONObject serviceData = payload.getJSONObject("serviceData");
+ if (!serviceData.containsKey("Value")) {
+ log.error("serviceData字段中不含Value字段");
+ } else {
+ dataBase64 = serviceData.getString("Value");
+ }
+ }
+ } else {
+ if (payload.containsKey("APPdata")) {
+ dataBase64 = payload.getString("APPdata");
+ } else {
+ log.error("payload字段中不含APPdata字段");
+ }
+ }
+
+ if (!dataBase64.isEmpty()) {
+ frameStr = Base64.getDecoder().decode(dataBase64); // base64解码
+ }
+
+ return frameStr;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java
new file mode 100644
index 0000000..ae6706a
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java
@@ -0,0 +1,40 @@
+package com.casic.missiles.frame;
+
+import lombok.Data;
+import java.util.List;
+
+@Data
+public class BirmmBaseFrame {
+
+ // 前导码 固定为A3
+ final String PRE_CODE = "A3";
+
+ // 协议版本 固定为20
+ final String VERSION = "20";
+
+ // 帧长度 后续到CRC字段前的字节总长度 不包括长度字段和CRC字段
+ int length;
+
+ // 设备编号
+ String devCode;
+
+ // 通信方式
+ String communicationType;
+
+ // 目标节点地址
+ String destinationAddr;
+
+ // PDU类型
+ String pduType;
+
+ // 序号
+ String sequence;
+
+ // 业务字段List
+ String tagListString;
+
+ List tagList;
+
+ // CRC
+ String crc;
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java
new file mode 100644
index 0000000..2285f9a
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java
@@ -0,0 +1,11 @@
+package com.casic.missiles.frame;
+
+import lombok.Data;
+
+@Data
+public class BirmmBaseTag {
+
+ private String oid;
+ private int tagLen;
+ private String valueStr;
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java
new file mode 100644
index 0000000..b1fd65c
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java
@@ -0,0 +1,9 @@
+package com.casic.missiles.frame;
+
+public class BirmmFrameBuilderFactory {
+
+ public static BirmmBaseFrame createBirmmFrame(String pduType) {
+
+ return null;
+ }
+}
diff --git a/.gitignore b/.gitignore
index 9e20bc1..78302f1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,6 @@
.idea/
**/target/**
logs/
+*.log
+*.log.*
*.iml
diff --git a/casic-iot-web/src/main/resources/config/application-dev.yml b/casic-iot-web/src/main/resources/config/application-dev.yml
index 487fc70..c5c99b7 100644
--- a/casic-iot-web/src/main/resources/config/application-dev.yml
+++ b/casic-iot-web/src/main/resources/config/application-dev.yml
@@ -37,7 +37,7 @@
invalid-time: 86400
config-prefix: 'Casic:'
#kaptcha-open: false #是否开启登录时验证码 (true/false)
- no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/push/data,/push/test
+ no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/aep/**
#flowable数据源和多数据源配置
db:
init:
diff --git a/casic-iot-web/src/main/resources/config/logback-spring.xml b/casic-iot-web/src/main/resources/config/logback-spring.xml
index c0c7ac9..2d308a8 100644
--- a/casic-iot-web/src/main/resources/config/logback-spring.xml
+++ b/casic-iot-web/src/main/resources/config/logback-spring.xml
@@ -5,7 +5,7 @@
-
+
diff --git a/pom.xml b/pom.xml
index 3ad2470..a194074 100644
--- a/pom.xml
+++ b/pom.xml
@@ -49,6 +49,7 @@
2.0.0.alpha
2.5.4
2.5.6
+ 1.2.62
2.0.0.alpha
@@ -56,7 +57,11 @@
-
+
+ com.casic
+ casic-core
+ ${core.version}
+
com.baomidou
dynamic-datasource-spring-boot-starter
@@ -69,11 +74,11 @@
${fastjson.version}
-
- cn.hutool
- hutool-core
- 5.7.2
-
+
+
+
+
+
org.projectlombok
diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml
index d5118b4..8dcc497 100644
--- a/sensorhub-core/pom.xml
+++ b/sensorhub-core/pom.xml
@@ -35,17 +35,17 @@
com.ctg.ag
ctg-ag-sdk-core
-
2.8.0-SNAPSHOT
-
+ system
+ ${pom.basedir}\lib\ctg-ag-sdk-core-2.8.0.jar
com.ctg.ag
ag-sdk-biz
2.8.0-SNAPSHOT
-
-
+ system
+ ${pom.basedir}\lib\ag-sdk-biz.jar
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java
deleted file mode 100644
index 40c55e8..0000000
--- a/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java
+++ /dev/null
@@ -1,30 +0,0 @@
-//package com.casic.missiles;
-//
-//import com.casic.missiles.netty.SensorhubServer;
-//import lombok.extern.slf4j.Slf4j;
-//import org.mybatis.spring.annotation.MapperScan;
-//import org.springframework.beans.factory.annotation.Autowired;
-//import org.springframework.boot.CommandLineRunner;
-//import org.springframework.boot.SpringApplication;
-//import org.springframework.boot.autoconfigure.SpringBootApplication;
-//import org.springframework.cache.annotation.EnableCaching;
-//
-//
-//@SpringBootApplication(scanBasePackages = "com.casic.missiles")
-//@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"})
-//@EnableCaching //开启缓存
-//@Slf4j
-//public class ServerApplication implements CommandLineRunner {
-//
-// @Autowired
-// private SensorhubServer nettyServer;
-// public static void main(String[] args) {
-// SpringApplication.run(ServerApplication.class, args);
-// }
-//
-// @Override
-// public void run(String... args) {
-// this.nettyServer.startServer();
-// }
-//
-//}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java b/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java
new file mode 100644
index 0000000..8f90fd9
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java
@@ -0,0 +1,96 @@
+package com.casic.missiles.controller;
+
+import com.alibaba.fastjson.JSONObject;
+import com.casic.missiles.frame.BirmmBaseFrame;
+import com.casic.missiles.model.response.ResponseData;
+import com.casic.missiles.service.IGeneralService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.tomcat.util.buf.HexUtils;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.util.Base64;
+import java.util.Map;
+
+@RestController
+@Slf4j
+public class GeneralDataReceiver {
+
+ @Resource
+ IGeneralService defaultService;
+
+ @RequestMapping("/aep/data/string")
+ public Object aepDataString(@RequestBody Map dataMap) {
+ log.info("收到AEP平台推送消息:{}", JSONObject.toJSONString(dataMap));
+ log.debug("deviceId: {}, productId: {}, IMEI: {}, timestamp: {}", dataMap.get("deviceId"), dataMap.get("productId"), dataMap.get("IMEI"), dataMap.get("timestamp"));
+
+ // 从推送的数据中获取消息帧
+ String frameStr = new String(getFrameStringFromData(dataMap));
+ log.info("字符串消息帧:{}", frameStr);
+
+ return ResponseData.success();
+ }
+
+ @RequestMapping("/aep/data/hex")
+ public Object aepDataHex(@RequestBody Map dataMap) {
+ log.info("收到AEP平台推送消息:{}", JSONObject.toJSONString(dataMap));
+ log.debug("deviceId: {}, productId: {}, IMEI: {}, timestamp: {}", dataMap.get("deviceId"), dataMap.get("productId"), dataMap.get("IMEI"), dataMap.get("timestamp"));
+
+ // 从推送的数据中获取消息帧
+ byte[] frameBytes = getFrameStringFromData(dataMap);
+ log.info("HEX字节消息帧:{}", HexUtils.toHexString(frameBytes).toUpperCase());
+
+ BirmmBaseFrame birmmFrame = defaultService.dataParse(frameBytes);
+ if (birmmFrame != null) {
+ log.info("HEX字节消息解析成功:{}", birmmFrame);
+ }
+
+ // 返回给电信AEP平台
+ return ResponseData.success();
+ }
+
+ private byte[] getFrameStringFromData(Map dataMap) {
+ byte[] frameStr = new byte[]{};
+
+ if (!dataMap.containsKey("payload")) {
+ log.error("消息帧不含payload字段");
+ return frameStr;
+ }
+
+ // 判断是否有profile
+ boolean hasProfile = false;
+ if (dataMap.containsKey("profile")) {
+ hasProfile = (Boolean) dataMap.get("profile");
+ }
+
+ JSONObject payload = (JSONObject) dataMap.get("payload");
+ // base64格式的消息 电信平台推送的内容
+ String dataBase64 = "";
+ if (hasProfile) {
+ if (!payload.containsKey("serviceData")) {
+ log.error("payload字段中不含serviceData字段");
+ } else {
+ JSONObject serviceData = payload.getJSONObject("serviceData");
+ if (!serviceData.containsKey("Value")) {
+ log.error("serviceData字段中不含Value字段");
+ } else {
+ dataBase64 = serviceData.getString("Value");
+ }
+ }
+ } else {
+ if (payload.containsKey("APPdata")) {
+ dataBase64 = payload.getString("APPdata");
+ } else {
+ log.error("payload字段中不含APPdata字段");
+ }
+ }
+
+ if (!dataBase64.isEmpty()) {
+ frameStr = Base64.getDecoder().decode(dataBase64); // base64解码
+ }
+
+ return frameStr;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java
new file mode 100644
index 0000000..ae6706a
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java
@@ -0,0 +1,40 @@
+package com.casic.missiles.frame;
+
+import lombok.Data;
+import java.util.List;
+
+@Data
+public class BirmmBaseFrame {
+
+ // 前导码 固定为A3
+ final String PRE_CODE = "A3";
+
+ // 协议版本 固定为20
+ final String VERSION = "20";
+
+ // 帧长度 后续到CRC字段前的字节总长度 不包括长度字段和CRC字段
+ int length;
+
+ // 设备编号
+ String devCode;
+
+ // 通信方式
+ String communicationType;
+
+ // 目标节点地址
+ String destinationAddr;
+
+ // PDU类型
+ String pduType;
+
+ // 序号
+ String sequence;
+
+ // 业务字段List
+ String tagListString;
+
+ List tagList;
+
+ // CRC
+ String crc;
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java
new file mode 100644
index 0000000..2285f9a
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java
@@ -0,0 +1,11 @@
+package com.casic.missiles.frame;
+
+import lombok.Data;
+
+@Data
+public class BirmmBaseTag {
+
+ private String oid;
+ private int tagLen;
+ private String valueStr;
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java
new file mode 100644
index 0000000..b1fd65c
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java
@@ -0,0 +1,9 @@
+package com.casic.missiles.frame;
+
+public class BirmmFrameBuilderFactory {
+
+ public static BirmmBaseFrame createBirmmFrame(String pduType) {
+
+ return null;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmTagBuilderFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmTagBuilderFactory.java
new file mode 100644
index 0000000..95ebdab
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmTagBuilderFactory.java
@@ -0,0 +1,33 @@
+package com.casic.missiles.frame;
+
+import com.casic.missiles.enums.BirmmTagAttributeEnums;
+import com.casic.missiles.frame.commanTag.*;
+
+public class BirmmTagBuilderFactory {
+
+ public static BirmmBaseTag createTagByOid(String oid) {
+ BirmmTagAttributeEnums tag = BirmmTagAttributeEnums.toType(oid);
+ if (null != tag) {
+ switch (tag) {
+ case CELL_TAG:
+ return new CellTag();
+
+ case DATE_TAG:
+ return new DateTag();
+
+ case PIC_TAG:
+ return new PCITag();
+
+ case SNR_TAG:
+ return new SNRTag();
+
+ case RSRP_TAG:
+ return new RSRPTag();
+
+ default:
+ return null;
+ }
+ }
+ return null;
+ }
+}
diff --git a/.gitignore b/.gitignore
index 9e20bc1..78302f1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,6 @@
.idea/
**/target/**
logs/
+*.log
+*.log.*
*.iml
diff --git a/casic-iot-web/src/main/resources/config/application-dev.yml b/casic-iot-web/src/main/resources/config/application-dev.yml
index 487fc70..c5c99b7 100644
--- a/casic-iot-web/src/main/resources/config/application-dev.yml
+++ b/casic-iot-web/src/main/resources/config/application-dev.yml
@@ -37,7 +37,7 @@
invalid-time: 86400
config-prefix: 'Casic:'
#kaptcha-open: false #是否开启登录时验证码 (true/false)
- no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/push/data,/push/test
+ no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/aep/**
#flowable数据源和多数据源配置
db:
init:
diff --git a/casic-iot-web/src/main/resources/config/logback-spring.xml b/casic-iot-web/src/main/resources/config/logback-spring.xml
index c0c7ac9..2d308a8 100644
--- a/casic-iot-web/src/main/resources/config/logback-spring.xml
+++ b/casic-iot-web/src/main/resources/config/logback-spring.xml
@@ -5,7 +5,7 @@
-
+
diff --git a/pom.xml b/pom.xml
index 3ad2470..a194074 100644
--- a/pom.xml
+++ b/pom.xml
@@ -49,6 +49,7 @@
2.0.0.alpha
2.5.4
2.5.6
+ 1.2.62
2.0.0.alpha
@@ -56,7 +57,11 @@
-
+
+ com.casic
+ casic-core
+ ${core.version}
+
com.baomidou
dynamic-datasource-spring-boot-starter
@@ -69,11 +74,11 @@
${fastjson.version}
-
- cn.hutool
- hutool-core
- 5.7.2
-
+
+
+
+
+
org.projectlombok
diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml
index d5118b4..8dcc497 100644
--- a/sensorhub-core/pom.xml
+++ b/sensorhub-core/pom.xml
@@ -35,17 +35,17 @@
com.ctg.ag
ctg-ag-sdk-core
-
2.8.0-SNAPSHOT
-
+ system
+ ${pom.basedir}\lib\ctg-ag-sdk-core-2.8.0.jar
com.ctg.ag
ag-sdk-biz
2.8.0-SNAPSHOT
-
-
+ system
+ ${pom.basedir}\lib\ag-sdk-biz.jar
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java
deleted file mode 100644
index 40c55e8..0000000
--- a/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java
+++ /dev/null
@@ -1,30 +0,0 @@
-//package com.casic.missiles;
-//
-//import com.casic.missiles.netty.SensorhubServer;
-//import lombok.extern.slf4j.Slf4j;
-//import org.mybatis.spring.annotation.MapperScan;
-//import org.springframework.beans.factory.annotation.Autowired;
-//import org.springframework.boot.CommandLineRunner;
-//import org.springframework.boot.SpringApplication;
-//import org.springframework.boot.autoconfigure.SpringBootApplication;
-//import org.springframework.cache.annotation.EnableCaching;
-//
-//
-//@SpringBootApplication(scanBasePackages = "com.casic.missiles")
-//@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"})
-//@EnableCaching //开启缓存
-//@Slf4j
-//public class ServerApplication implements CommandLineRunner {
-//
-// @Autowired
-// private SensorhubServer nettyServer;
-// public static void main(String[] args) {
-// SpringApplication.run(ServerApplication.class, args);
-// }
-//
-// @Override
-// public void run(String... args) {
-// this.nettyServer.startServer();
-// }
-//
-//}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java b/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java
new file mode 100644
index 0000000..8f90fd9
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java
@@ -0,0 +1,96 @@
+package com.casic.missiles.controller;
+
+import com.alibaba.fastjson.JSONObject;
+import com.casic.missiles.frame.BirmmBaseFrame;
+import com.casic.missiles.model.response.ResponseData;
+import com.casic.missiles.service.IGeneralService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.tomcat.util.buf.HexUtils;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.util.Base64;
+import java.util.Map;
+
+@RestController
+@Slf4j
+public class GeneralDataReceiver {
+
+ @Resource
+ IGeneralService defaultService;
+
+ @RequestMapping("/aep/data/string")
+ public Object aepDataString(@RequestBody Map dataMap) {
+ log.info("收到AEP平台推送消息:{}", JSONObject.toJSONString(dataMap));
+ log.debug("deviceId: {}, productId: {}, IMEI: {}, timestamp: {}", dataMap.get("deviceId"), dataMap.get("productId"), dataMap.get("IMEI"), dataMap.get("timestamp"));
+
+ // 从推送的数据中获取消息帧
+ String frameStr = new String(getFrameStringFromData(dataMap));
+ log.info("字符串消息帧:{}", frameStr);
+
+ return ResponseData.success();
+ }
+
+ @RequestMapping("/aep/data/hex")
+ public Object aepDataHex(@RequestBody Map dataMap) {
+ log.info("收到AEP平台推送消息:{}", JSONObject.toJSONString(dataMap));
+ log.debug("deviceId: {}, productId: {}, IMEI: {}, timestamp: {}", dataMap.get("deviceId"), dataMap.get("productId"), dataMap.get("IMEI"), dataMap.get("timestamp"));
+
+ // 从推送的数据中获取消息帧
+ byte[] frameBytes = getFrameStringFromData(dataMap);
+ log.info("HEX字节消息帧:{}", HexUtils.toHexString(frameBytes).toUpperCase());
+
+ BirmmBaseFrame birmmFrame = defaultService.dataParse(frameBytes);
+ if (birmmFrame != null) {
+ log.info("HEX字节消息解析成功:{}", birmmFrame);
+ }
+
+ // 返回给电信AEP平台
+ return ResponseData.success();
+ }
+
+ private byte[] getFrameStringFromData(Map dataMap) {
+ byte[] frameStr = new byte[]{};
+
+ if (!dataMap.containsKey("payload")) {
+ log.error("消息帧不含payload字段");
+ return frameStr;
+ }
+
+ // 判断是否有profile
+ boolean hasProfile = false;
+ if (dataMap.containsKey("profile")) {
+ hasProfile = (Boolean) dataMap.get("profile");
+ }
+
+ JSONObject payload = (JSONObject) dataMap.get("payload");
+ // base64格式的消息 电信平台推送的内容
+ String dataBase64 = "";
+ if (hasProfile) {
+ if (!payload.containsKey("serviceData")) {
+ log.error("payload字段中不含serviceData字段");
+ } else {
+ JSONObject serviceData = payload.getJSONObject("serviceData");
+ if (!serviceData.containsKey("Value")) {
+ log.error("serviceData字段中不含Value字段");
+ } else {
+ dataBase64 = serviceData.getString("Value");
+ }
+ }
+ } else {
+ if (payload.containsKey("APPdata")) {
+ dataBase64 = payload.getString("APPdata");
+ } else {
+ log.error("payload字段中不含APPdata字段");
+ }
+ }
+
+ if (!dataBase64.isEmpty()) {
+ frameStr = Base64.getDecoder().decode(dataBase64); // base64解码
+ }
+
+ return frameStr;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java
new file mode 100644
index 0000000..ae6706a
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java
@@ -0,0 +1,40 @@
+package com.casic.missiles.frame;
+
+import lombok.Data;
+import java.util.List;
+
+@Data
+public class BirmmBaseFrame {
+
+ // 前导码 固定为A3
+ final String PRE_CODE = "A3";
+
+ // 协议版本 固定为20
+ final String VERSION = "20";
+
+ // 帧长度 后续到CRC字段前的字节总长度 不包括长度字段和CRC字段
+ int length;
+
+ // 设备编号
+ String devCode;
+
+ // 通信方式
+ String communicationType;
+
+ // 目标节点地址
+ String destinationAddr;
+
+ // PDU类型
+ String pduType;
+
+ // 序号
+ String sequence;
+
+ // 业务字段List
+ String tagListString;
+
+ List tagList;
+
+ // CRC
+ String crc;
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java
new file mode 100644
index 0000000..2285f9a
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java
@@ -0,0 +1,11 @@
+package com.casic.missiles.frame;
+
+import lombok.Data;
+
+@Data
+public class BirmmBaseTag {
+
+ private String oid;
+ private int tagLen;
+ private String valueStr;
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java
new file mode 100644
index 0000000..b1fd65c
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java
@@ -0,0 +1,9 @@
+package com.casic.missiles.frame;
+
+public class BirmmFrameBuilderFactory {
+
+ public static BirmmBaseFrame createBirmmFrame(String pduType) {
+
+ return null;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmTagBuilderFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmTagBuilderFactory.java
new file mode 100644
index 0000000..95ebdab
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmTagBuilderFactory.java
@@ -0,0 +1,33 @@
+package com.casic.missiles.frame;
+
+import com.casic.missiles.enums.BirmmTagAttributeEnums;
+import com.casic.missiles.frame.commanTag.*;
+
+public class BirmmTagBuilderFactory {
+
+ public static BirmmBaseTag createTagByOid(String oid) {
+ BirmmTagAttributeEnums tag = BirmmTagAttributeEnums.toType(oid);
+ if (null != tag) {
+ switch (tag) {
+ case CELL_TAG:
+ return new CellTag();
+
+ case DATE_TAG:
+ return new DateTag();
+
+ case PIC_TAG:
+ return new PCITag();
+
+ case SNR_TAG:
+ return new SNRTag();
+
+ case RSRP_TAG:
+ return new RSRPTag();
+
+ default:
+ return null;
+ }
+ }
+ return null;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/CellTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/CellTag.java
new file mode 100644
index 0000000..b0e0360
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/CellTag.java
@@ -0,0 +1,20 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class CellTag extends BirmmBaseTag {
+
+ final String CELL_TAG_OID = "60000020";
+
+ int cellVal;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ cellVal = Integer.parseInt(valueStr, 16);
+ }
+}
diff --git a/.gitignore b/.gitignore
index 9e20bc1..78302f1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,6 @@
.idea/
**/target/**
logs/
+*.log
+*.log.*
*.iml
diff --git a/casic-iot-web/src/main/resources/config/application-dev.yml b/casic-iot-web/src/main/resources/config/application-dev.yml
index 487fc70..c5c99b7 100644
--- a/casic-iot-web/src/main/resources/config/application-dev.yml
+++ b/casic-iot-web/src/main/resources/config/application-dev.yml
@@ -37,7 +37,7 @@
invalid-time: 86400
config-prefix: 'Casic:'
#kaptcha-open: false #是否开启登录时验证码 (true/false)
- no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/push/data,/push/test
+ no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/aep/**
#flowable数据源和多数据源配置
db:
init:
diff --git a/casic-iot-web/src/main/resources/config/logback-spring.xml b/casic-iot-web/src/main/resources/config/logback-spring.xml
index c0c7ac9..2d308a8 100644
--- a/casic-iot-web/src/main/resources/config/logback-spring.xml
+++ b/casic-iot-web/src/main/resources/config/logback-spring.xml
@@ -5,7 +5,7 @@
-
+
diff --git a/pom.xml b/pom.xml
index 3ad2470..a194074 100644
--- a/pom.xml
+++ b/pom.xml
@@ -49,6 +49,7 @@
2.0.0.alpha
2.5.4
2.5.6
+ 1.2.62
2.0.0.alpha
@@ -56,7 +57,11 @@
-
+
+ com.casic
+ casic-core
+ ${core.version}
+
com.baomidou
dynamic-datasource-spring-boot-starter
@@ -69,11 +74,11 @@
${fastjson.version}
-
- cn.hutool
- hutool-core
- 5.7.2
-
+
+
+
+
+
org.projectlombok
diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml
index d5118b4..8dcc497 100644
--- a/sensorhub-core/pom.xml
+++ b/sensorhub-core/pom.xml
@@ -35,17 +35,17 @@
com.ctg.ag
ctg-ag-sdk-core
-
2.8.0-SNAPSHOT
-
+ system
+ ${pom.basedir}\lib\ctg-ag-sdk-core-2.8.0.jar
com.ctg.ag
ag-sdk-biz
2.8.0-SNAPSHOT
-
-
+ system
+ ${pom.basedir}\lib\ag-sdk-biz.jar
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java
deleted file mode 100644
index 40c55e8..0000000
--- a/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java
+++ /dev/null
@@ -1,30 +0,0 @@
-//package com.casic.missiles;
-//
-//import com.casic.missiles.netty.SensorhubServer;
-//import lombok.extern.slf4j.Slf4j;
-//import org.mybatis.spring.annotation.MapperScan;
-//import org.springframework.beans.factory.annotation.Autowired;
-//import org.springframework.boot.CommandLineRunner;
-//import org.springframework.boot.SpringApplication;
-//import org.springframework.boot.autoconfigure.SpringBootApplication;
-//import org.springframework.cache.annotation.EnableCaching;
-//
-//
-//@SpringBootApplication(scanBasePackages = "com.casic.missiles")
-//@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"})
-//@EnableCaching //开启缓存
-//@Slf4j
-//public class ServerApplication implements CommandLineRunner {
-//
-// @Autowired
-// private SensorhubServer nettyServer;
-// public static void main(String[] args) {
-// SpringApplication.run(ServerApplication.class, args);
-// }
-//
-// @Override
-// public void run(String... args) {
-// this.nettyServer.startServer();
-// }
-//
-//}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java b/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java
new file mode 100644
index 0000000..8f90fd9
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java
@@ -0,0 +1,96 @@
+package com.casic.missiles.controller;
+
+import com.alibaba.fastjson.JSONObject;
+import com.casic.missiles.frame.BirmmBaseFrame;
+import com.casic.missiles.model.response.ResponseData;
+import com.casic.missiles.service.IGeneralService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.tomcat.util.buf.HexUtils;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.util.Base64;
+import java.util.Map;
+
+@RestController
+@Slf4j
+public class GeneralDataReceiver {
+
+ @Resource
+ IGeneralService defaultService;
+
+ @RequestMapping("/aep/data/string")
+ public Object aepDataString(@RequestBody Map dataMap) {
+ log.info("收到AEP平台推送消息:{}", JSONObject.toJSONString(dataMap));
+ log.debug("deviceId: {}, productId: {}, IMEI: {}, timestamp: {}", dataMap.get("deviceId"), dataMap.get("productId"), dataMap.get("IMEI"), dataMap.get("timestamp"));
+
+ // 从推送的数据中获取消息帧
+ String frameStr = new String(getFrameStringFromData(dataMap));
+ log.info("字符串消息帧:{}", frameStr);
+
+ return ResponseData.success();
+ }
+
+ @RequestMapping("/aep/data/hex")
+ public Object aepDataHex(@RequestBody Map dataMap) {
+ log.info("收到AEP平台推送消息:{}", JSONObject.toJSONString(dataMap));
+ log.debug("deviceId: {}, productId: {}, IMEI: {}, timestamp: {}", dataMap.get("deviceId"), dataMap.get("productId"), dataMap.get("IMEI"), dataMap.get("timestamp"));
+
+ // 从推送的数据中获取消息帧
+ byte[] frameBytes = getFrameStringFromData(dataMap);
+ log.info("HEX字节消息帧:{}", HexUtils.toHexString(frameBytes).toUpperCase());
+
+ BirmmBaseFrame birmmFrame = defaultService.dataParse(frameBytes);
+ if (birmmFrame != null) {
+ log.info("HEX字节消息解析成功:{}", birmmFrame);
+ }
+
+ // 返回给电信AEP平台
+ return ResponseData.success();
+ }
+
+ private byte[] getFrameStringFromData(Map dataMap) {
+ byte[] frameStr = new byte[]{};
+
+ if (!dataMap.containsKey("payload")) {
+ log.error("消息帧不含payload字段");
+ return frameStr;
+ }
+
+ // 判断是否有profile
+ boolean hasProfile = false;
+ if (dataMap.containsKey("profile")) {
+ hasProfile = (Boolean) dataMap.get("profile");
+ }
+
+ JSONObject payload = (JSONObject) dataMap.get("payload");
+ // base64格式的消息 电信平台推送的内容
+ String dataBase64 = "";
+ if (hasProfile) {
+ if (!payload.containsKey("serviceData")) {
+ log.error("payload字段中不含serviceData字段");
+ } else {
+ JSONObject serviceData = payload.getJSONObject("serviceData");
+ if (!serviceData.containsKey("Value")) {
+ log.error("serviceData字段中不含Value字段");
+ } else {
+ dataBase64 = serviceData.getString("Value");
+ }
+ }
+ } else {
+ if (payload.containsKey("APPdata")) {
+ dataBase64 = payload.getString("APPdata");
+ } else {
+ log.error("payload字段中不含APPdata字段");
+ }
+ }
+
+ if (!dataBase64.isEmpty()) {
+ frameStr = Base64.getDecoder().decode(dataBase64); // base64解码
+ }
+
+ return frameStr;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java
new file mode 100644
index 0000000..ae6706a
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java
@@ -0,0 +1,40 @@
+package com.casic.missiles.frame;
+
+import lombok.Data;
+import java.util.List;
+
+@Data
+public class BirmmBaseFrame {
+
+ // 前导码 固定为A3
+ final String PRE_CODE = "A3";
+
+ // 协议版本 固定为20
+ final String VERSION = "20";
+
+ // 帧长度 后续到CRC字段前的字节总长度 不包括长度字段和CRC字段
+ int length;
+
+ // 设备编号
+ String devCode;
+
+ // 通信方式
+ String communicationType;
+
+ // 目标节点地址
+ String destinationAddr;
+
+ // PDU类型
+ String pduType;
+
+ // 序号
+ String sequence;
+
+ // 业务字段List
+ String tagListString;
+
+ List tagList;
+
+ // CRC
+ String crc;
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java
new file mode 100644
index 0000000..2285f9a
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java
@@ -0,0 +1,11 @@
+package com.casic.missiles.frame;
+
+import lombok.Data;
+
+@Data
+public class BirmmBaseTag {
+
+ private String oid;
+ private int tagLen;
+ private String valueStr;
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java
new file mode 100644
index 0000000..b1fd65c
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java
@@ -0,0 +1,9 @@
+package com.casic.missiles.frame;
+
+public class BirmmFrameBuilderFactory {
+
+ public static BirmmBaseFrame createBirmmFrame(String pduType) {
+
+ return null;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmTagBuilderFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmTagBuilderFactory.java
new file mode 100644
index 0000000..95ebdab
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmTagBuilderFactory.java
@@ -0,0 +1,33 @@
+package com.casic.missiles.frame;
+
+import com.casic.missiles.enums.BirmmTagAttributeEnums;
+import com.casic.missiles.frame.commanTag.*;
+
+public class BirmmTagBuilderFactory {
+
+ public static BirmmBaseTag createTagByOid(String oid) {
+ BirmmTagAttributeEnums tag = BirmmTagAttributeEnums.toType(oid);
+ if (null != tag) {
+ switch (tag) {
+ case CELL_TAG:
+ return new CellTag();
+
+ case DATE_TAG:
+ return new DateTag();
+
+ case PIC_TAG:
+ return new PCITag();
+
+ case SNR_TAG:
+ return new SNRTag();
+
+ case RSRP_TAG:
+ return new RSRPTag();
+
+ default:
+ return null;
+ }
+ }
+ return null;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/CellTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/CellTag.java
new file mode 100644
index 0000000..b0e0360
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/CellTag.java
@@ -0,0 +1,20 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class CellTag extends BirmmBaseTag {
+
+ final String CELL_TAG_OID = "60000020";
+
+ int cellVal;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ cellVal = Integer.parseInt(valueStr, 16);
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/DateTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/DateTag.java
new file mode 100644
index 0000000..e8c5db4
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/DateTag.java
@@ -0,0 +1,30 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.time.LocalDate;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class DateTag extends BirmmBaseTag {
+
+ final String DATE_TAG_OID = "10000050";
+
+ LocalDate date;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ String hexY = valueStr.substring(0, 2);
+ String hexM = valueStr.substring(2, 4);
+ String hexD = valueStr.substring(4, 6);
+
+ date = LocalDate.now();
+ date = date.withYear(BytesUtil.hexStringToUInt(hexY) + 2000);
+ date = date.withMonth(BytesUtil.hexStringToUInt(hexM));
+ date = date.withDayOfMonth(BytesUtil.hexStringToUInt(hexD));
+ }
+}
diff --git a/.gitignore b/.gitignore
index 9e20bc1..78302f1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,6 @@
.idea/
**/target/**
logs/
+*.log
+*.log.*
*.iml
diff --git a/casic-iot-web/src/main/resources/config/application-dev.yml b/casic-iot-web/src/main/resources/config/application-dev.yml
index 487fc70..c5c99b7 100644
--- a/casic-iot-web/src/main/resources/config/application-dev.yml
+++ b/casic-iot-web/src/main/resources/config/application-dev.yml
@@ -37,7 +37,7 @@
invalid-time: 86400
config-prefix: 'Casic:'
#kaptcha-open: false #是否开启登录时验证码 (true/false)
- no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/push/data,/push/test
+ no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/aep/**
#flowable数据源和多数据源配置
db:
init:
diff --git a/casic-iot-web/src/main/resources/config/logback-spring.xml b/casic-iot-web/src/main/resources/config/logback-spring.xml
index c0c7ac9..2d308a8 100644
--- a/casic-iot-web/src/main/resources/config/logback-spring.xml
+++ b/casic-iot-web/src/main/resources/config/logback-spring.xml
@@ -5,7 +5,7 @@
-
+
diff --git a/pom.xml b/pom.xml
index 3ad2470..a194074 100644
--- a/pom.xml
+++ b/pom.xml
@@ -49,6 +49,7 @@
2.0.0.alpha
2.5.4
2.5.6
+ 1.2.62
2.0.0.alpha
@@ -56,7 +57,11 @@
-
+
+ com.casic
+ casic-core
+ ${core.version}
+
com.baomidou
dynamic-datasource-spring-boot-starter
@@ -69,11 +74,11 @@
${fastjson.version}
-
- cn.hutool
- hutool-core
- 5.7.2
-
+
+
+
+
+
org.projectlombok
diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml
index d5118b4..8dcc497 100644
--- a/sensorhub-core/pom.xml
+++ b/sensorhub-core/pom.xml
@@ -35,17 +35,17 @@
com.ctg.ag
ctg-ag-sdk-core
-
2.8.0-SNAPSHOT
-
+ system
+ ${pom.basedir}\lib\ctg-ag-sdk-core-2.8.0.jar
com.ctg.ag
ag-sdk-biz
2.8.0-SNAPSHOT
-
-
+ system
+ ${pom.basedir}\lib\ag-sdk-biz.jar
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java
deleted file mode 100644
index 40c55e8..0000000
--- a/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java
+++ /dev/null
@@ -1,30 +0,0 @@
-//package com.casic.missiles;
-//
-//import com.casic.missiles.netty.SensorhubServer;
-//import lombok.extern.slf4j.Slf4j;
-//import org.mybatis.spring.annotation.MapperScan;
-//import org.springframework.beans.factory.annotation.Autowired;
-//import org.springframework.boot.CommandLineRunner;
-//import org.springframework.boot.SpringApplication;
-//import org.springframework.boot.autoconfigure.SpringBootApplication;
-//import org.springframework.cache.annotation.EnableCaching;
-//
-//
-//@SpringBootApplication(scanBasePackages = "com.casic.missiles")
-//@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"})
-//@EnableCaching //开启缓存
-//@Slf4j
-//public class ServerApplication implements CommandLineRunner {
-//
-// @Autowired
-// private SensorhubServer nettyServer;
-// public static void main(String[] args) {
-// SpringApplication.run(ServerApplication.class, args);
-// }
-//
-// @Override
-// public void run(String... args) {
-// this.nettyServer.startServer();
-// }
-//
-//}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java b/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java
new file mode 100644
index 0000000..8f90fd9
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java
@@ -0,0 +1,96 @@
+package com.casic.missiles.controller;
+
+import com.alibaba.fastjson.JSONObject;
+import com.casic.missiles.frame.BirmmBaseFrame;
+import com.casic.missiles.model.response.ResponseData;
+import com.casic.missiles.service.IGeneralService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.tomcat.util.buf.HexUtils;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.util.Base64;
+import java.util.Map;
+
+@RestController
+@Slf4j
+public class GeneralDataReceiver {
+
+ @Resource
+ IGeneralService defaultService;
+
+ @RequestMapping("/aep/data/string")
+ public Object aepDataString(@RequestBody Map dataMap) {
+ log.info("收到AEP平台推送消息:{}", JSONObject.toJSONString(dataMap));
+ log.debug("deviceId: {}, productId: {}, IMEI: {}, timestamp: {}", dataMap.get("deviceId"), dataMap.get("productId"), dataMap.get("IMEI"), dataMap.get("timestamp"));
+
+ // 从推送的数据中获取消息帧
+ String frameStr = new String(getFrameStringFromData(dataMap));
+ log.info("字符串消息帧:{}", frameStr);
+
+ return ResponseData.success();
+ }
+
+ @RequestMapping("/aep/data/hex")
+ public Object aepDataHex(@RequestBody Map dataMap) {
+ log.info("收到AEP平台推送消息:{}", JSONObject.toJSONString(dataMap));
+ log.debug("deviceId: {}, productId: {}, IMEI: {}, timestamp: {}", dataMap.get("deviceId"), dataMap.get("productId"), dataMap.get("IMEI"), dataMap.get("timestamp"));
+
+ // 从推送的数据中获取消息帧
+ byte[] frameBytes = getFrameStringFromData(dataMap);
+ log.info("HEX字节消息帧:{}", HexUtils.toHexString(frameBytes).toUpperCase());
+
+ BirmmBaseFrame birmmFrame = defaultService.dataParse(frameBytes);
+ if (birmmFrame != null) {
+ log.info("HEX字节消息解析成功:{}", birmmFrame);
+ }
+
+ // 返回给电信AEP平台
+ return ResponseData.success();
+ }
+
+ private byte[] getFrameStringFromData(Map dataMap) {
+ byte[] frameStr = new byte[]{};
+
+ if (!dataMap.containsKey("payload")) {
+ log.error("消息帧不含payload字段");
+ return frameStr;
+ }
+
+ // 判断是否有profile
+ boolean hasProfile = false;
+ if (dataMap.containsKey("profile")) {
+ hasProfile = (Boolean) dataMap.get("profile");
+ }
+
+ JSONObject payload = (JSONObject) dataMap.get("payload");
+ // base64格式的消息 电信平台推送的内容
+ String dataBase64 = "";
+ if (hasProfile) {
+ if (!payload.containsKey("serviceData")) {
+ log.error("payload字段中不含serviceData字段");
+ } else {
+ JSONObject serviceData = payload.getJSONObject("serviceData");
+ if (!serviceData.containsKey("Value")) {
+ log.error("serviceData字段中不含Value字段");
+ } else {
+ dataBase64 = serviceData.getString("Value");
+ }
+ }
+ } else {
+ if (payload.containsKey("APPdata")) {
+ dataBase64 = payload.getString("APPdata");
+ } else {
+ log.error("payload字段中不含APPdata字段");
+ }
+ }
+
+ if (!dataBase64.isEmpty()) {
+ frameStr = Base64.getDecoder().decode(dataBase64); // base64解码
+ }
+
+ return frameStr;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java
new file mode 100644
index 0000000..ae6706a
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java
@@ -0,0 +1,40 @@
+package com.casic.missiles.frame;
+
+import lombok.Data;
+import java.util.List;
+
+@Data
+public class BirmmBaseFrame {
+
+ // 前导码 固定为A3
+ final String PRE_CODE = "A3";
+
+ // 协议版本 固定为20
+ final String VERSION = "20";
+
+ // 帧长度 后续到CRC字段前的字节总长度 不包括长度字段和CRC字段
+ int length;
+
+ // 设备编号
+ String devCode;
+
+ // 通信方式
+ String communicationType;
+
+ // 目标节点地址
+ String destinationAddr;
+
+ // PDU类型
+ String pduType;
+
+ // 序号
+ String sequence;
+
+ // 业务字段List
+ String tagListString;
+
+ List tagList;
+
+ // CRC
+ String crc;
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java
new file mode 100644
index 0000000..2285f9a
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java
@@ -0,0 +1,11 @@
+package com.casic.missiles.frame;
+
+import lombok.Data;
+
+@Data
+public class BirmmBaseTag {
+
+ private String oid;
+ private int tagLen;
+ private String valueStr;
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java
new file mode 100644
index 0000000..b1fd65c
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java
@@ -0,0 +1,9 @@
+package com.casic.missiles.frame;
+
+public class BirmmFrameBuilderFactory {
+
+ public static BirmmBaseFrame createBirmmFrame(String pduType) {
+
+ return null;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmTagBuilderFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmTagBuilderFactory.java
new file mode 100644
index 0000000..95ebdab
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmTagBuilderFactory.java
@@ -0,0 +1,33 @@
+package com.casic.missiles.frame;
+
+import com.casic.missiles.enums.BirmmTagAttributeEnums;
+import com.casic.missiles.frame.commanTag.*;
+
+public class BirmmTagBuilderFactory {
+
+ public static BirmmBaseTag createTagByOid(String oid) {
+ BirmmTagAttributeEnums tag = BirmmTagAttributeEnums.toType(oid);
+ if (null != tag) {
+ switch (tag) {
+ case CELL_TAG:
+ return new CellTag();
+
+ case DATE_TAG:
+ return new DateTag();
+
+ case PIC_TAG:
+ return new PCITag();
+
+ case SNR_TAG:
+ return new SNRTag();
+
+ case RSRP_TAG:
+ return new RSRPTag();
+
+ default:
+ return null;
+ }
+ }
+ return null;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/CellTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/CellTag.java
new file mode 100644
index 0000000..b0e0360
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/CellTag.java
@@ -0,0 +1,20 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class CellTag extends BirmmBaseTag {
+
+ final String CELL_TAG_OID = "60000020";
+
+ int cellVal;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ cellVal = Integer.parseInt(valueStr, 16);
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/DateTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/DateTag.java
new file mode 100644
index 0000000..e8c5db4
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/DateTag.java
@@ -0,0 +1,30 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.time.LocalDate;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class DateTag extends BirmmBaseTag {
+
+ final String DATE_TAG_OID = "10000050";
+
+ LocalDate date;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ String hexY = valueStr.substring(0, 2);
+ String hexM = valueStr.substring(2, 4);
+ String hexD = valueStr.substring(4, 6);
+
+ date = LocalDate.now();
+ date = date.withYear(BytesUtil.hexStringToUInt(hexY) + 2000);
+ date = date.withMonth(BytesUtil.hexStringToUInt(hexM));
+ date = date.withDayOfMonth(BytesUtil.hexStringToUInt(hexD));
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/PCITag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/PCITag.java
new file mode 100644
index 0000000..4433cea
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/PCITag.java
@@ -0,0 +1,22 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class PCITag extends BirmmBaseTag {
+
+ final String PCI_TAG_OID = "60000511";
+
+ // TYPE_U16整型,主小区物理小区号PCI,范围: 0 – 503
+ int pci;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ pci = BytesUtil.hexStringToUInt(valueStr);
+ }
+}
diff --git a/.gitignore b/.gitignore
index 9e20bc1..78302f1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,6 @@
.idea/
**/target/**
logs/
+*.log
+*.log.*
*.iml
diff --git a/casic-iot-web/src/main/resources/config/application-dev.yml b/casic-iot-web/src/main/resources/config/application-dev.yml
index 487fc70..c5c99b7 100644
--- a/casic-iot-web/src/main/resources/config/application-dev.yml
+++ b/casic-iot-web/src/main/resources/config/application-dev.yml
@@ -37,7 +37,7 @@
invalid-time: 86400
config-prefix: 'Casic:'
#kaptcha-open: false #是否开启登录时验证码 (true/false)
- no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/push/data,/push/test
+ no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/aep/**
#flowable数据源和多数据源配置
db:
init:
diff --git a/casic-iot-web/src/main/resources/config/logback-spring.xml b/casic-iot-web/src/main/resources/config/logback-spring.xml
index c0c7ac9..2d308a8 100644
--- a/casic-iot-web/src/main/resources/config/logback-spring.xml
+++ b/casic-iot-web/src/main/resources/config/logback-spring.xml
@@ -5,7 +5,7 @@
-
+
diff --git a/pom.xml b/pom.xml
index 3ad2470..a194074 100644
--- a/pom.xml
+++ b/pom.xml
@@ -49,6 +49,7 @@
2.0.0.alpha
2.5.4
2.5.6
+ 1.2.62
2.0.0.alpha
@@ -56,7 +57,11 @@
-
+
+ com.casic
+ casic-core
+ ${core.version}
+
com.baomidou
dynamic-datasource-spring-boot-starter
@@ -69,11 +74,11 @@
${fastjson.version}
-
- cn.hutool
- hutool-core
- 5.7.2
-
+
+
+
+
+
org.projectlombok
diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml
index d5118b4..8dcc497 100644
--- a/sensorhub-core/pom.xml
+++ b/sensorhub-core/pom.xml
@@ -35,17 +35,17 @@
com.ctg.ag
ctg-ag-sdk-core
-
2.8.0-SNAPSHOT
-
+ system
+ ${pom.basedir}\lib\ctg-ag-sdk-core-2.8.0.jar
com.ctg.ag
ag-sdk-biz
2.8.0-SNAPSHOT
-
-
+ system
+ ${pom.basedir}\lib\ag-sdk-biz.jar
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java
deleted file mode 100644
index 40c55e8..0000000
--- a/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java
+++ /dev/null
@@ -1,30 +0,0 @@
-//package com.casic.missiles;
-//
-//import com.casic.missiles.netty.SensorhubServer;
-//import lombok.extern.slf4j.Slf4j;
-//import org.mybatis.spring.annotation.MapperScan;
-//import org.springframework.beans.factory.annotation.Autowired;
-//import org.springframework.boot.CommandLineRunner;
-//import org.springframework.boot.SpringApplication;
-//import org.springframework.boot.autoconfigure.SpringBootApplication;
-//import org.springframework.cache.annotation.EnableCaching;
-//
-//
-//@SpringBootApplication(scanBasePackages = "com.casic.missiles")
-//@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"})
-//@EnableCaching //开启缓存
-//@Slf4j
-//public class ServerApplication implements CommandLineRunner {
-//
-// @Autowired
-// private SensorhubServer nettyServer;
-// public static void main(String[] args) {
-// SpringApplication.run(ServerApplication.class, args);
-// }
-//
-// @Override
-// public void run(String... args) {
-// this.nettyServer.startServer();
-// }
-//
-//}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java b/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java
new file mode 100644
index 0000000..8f90fd9
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java
@@ -0,0 +1,96 @@
+package com.casic.missiles.controller;
+
+import com.alibaba.fastjson.JSONObject;
+import com.casic.missiles.frame.BirmmBaseFrame;
+import com.casic.missiles.model.response.ResponseData;
+import com.casic.missiles.service.IGeneralService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.tomcat.util.buf.HexUtils;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.util.Base64;
+import java.util.Map;
+
+@RestController
+@Slf4j
+public class GeneralDataReceiver {
+
+ @Resource
+ IGeneralService defaultService;
+
+ @RequestMapping("/aep/data/string")
+ public Object aepDataString(@RequestBody Map dataMap) {
+ log.info("收到AEP平台推送消息:{}", JSONObject.toJSONString(dataMap));
+ log.debug("deviceId: {}, productId: {}, IMEI: {}, timestamp: {}", dataMap.get("deviceId"), dataMap.get("productId"), dataMap.get("IMEI"), dataMap.get("timestamp"));
+
+ // 从推送的数据中获取消息帧
+ String frameStr = new String(getFrameStringFromData(dataMap));
+ log.info("字符串消息帧:{}", frameStr);
+
+ return ResponseData.success();
+ }
+
+ @RequestMapping("/aep/data/hex")
+ public Object aepDataHex(@RequestBody Map dataMap) {
+ log.info("收到AEP平台推送消息:{}", JSONObject.toJSONString(dataMap));
+ log.debug("deviceId: {}, productId: {}, IMEI: {}, timestamp: {}", dataMap.get("deviceId"), dataMap.get("productId"), dataMap.get("IMEI"), dataMap.get("timestamp"));
+
+ // 从推送的数据中获取消息帧
+ byte[] frameBytes = getFrameStringFromData(dataMap);
+ log.info("HEX字节消息帧:{}", HexUtils.toHexString(frameBytes).toUpperCase());
+
+ BirmmBaseFrame birmmFrame = defaultService.dataParse(frameBytes);
+ if (birmmFrame != null) {
+ log.info("HEX字节消息解析成功:{}", birmmFrame);
+ }
+
+ // 返回给电信AEP平台
+ return ResponseData.success();
+ }
+
+ private byte[] getFrameStringFromData(Map dataMap) {
+ byte[] frameStr = new byte[]{};
+
+ if (!dataMap.containsKey("payload")) {
+ log.error("消息帧不含payload字段");
+ return frameStr;
+ }
+
+ // 判断是否有profile
+ boolean hasProfile = false;
+ if (dataMap.containsKey("profile")) {
+ hasProfile = (Boolean) dataMap.get("profile");
+ }
+
+ JSONObject payload = (JSONObject) dataMap.get("payload");
+ // base64格式的消息 电信平台推送的内容
+ String dataBase64 = "";
+ if (hasProfile) {
+ if (!payload.containsKey("serviceData")) {
+ log.error("payload字段中不含serviceData字段");
+ } else {
+ JSONObject serviceData = payload.getJSONObject("serviceData");
+ if (!serviceData.containsKey("Value")) {
+ log.error("serviceData字段中不含Value字段");
+ } else {
+ dataBase64 = serviceData.getString("Value");
+ }
+ }
+ } else {
+ if (payload.containsKey("APPdata")) {
+ dataBase64 = payload.getString("APPdata");
+ } else {
+ log.error("payload字段中不含APPdata字段");
+ }
+ }
+
+ if (!dataBase64.isEmpty()) {
+ frameStr = Base64.getDecoder().decode(dataBase64); // base64解码
+ }
+
+ return frameStr;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java
new file mode 100644
index 0000000..ae6706a
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java
@@ -0,0 +1,40 @@
+package com.casic.missiles.frame;
+
+import lombok.Data;
+import java.util.List;
+
+@Data
+public class BirmmBaseFrame {
+
+ // 前导码 固定为A3
+ final String PRE_CODE = "A3";
+
+ // 协议版本 固定为20
+ final String VERSION = "20";
+
+ // 帧长度 后续到CRC字段前的字节总长度 不包括长度字段和CRC字段
+ int length;
+
+ // 设备编号
+ String devCode;
+
+ // 通信方式
+ String communicationType;
+
+ // 目标节点地址
+ String destinationAddr;
+
+ // PDU类型
+ String pduType;
+
+ // 序号
+ String sequence;
+
+ // 业务字段List
+ String tagListString;
+
+ List tagList;
+
+ // CRC
+ String crc;
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java
new file mode 100644
index 0000000..2285f9a
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java
@@ -0,0 +1,11 @@
+package com.casic.missiles.frame;
+
+import lombok.Data;
+
+@Data
+public class BirmmBaseTag {
+
+ private String oid;
+ private int tagLen;
+ private String valueStr;
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java
new file mode 100644
index 0000000..b1fd65c
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java
@@ -0,0 +1,9 @@
+package com.casic.missiles.frame;
+
+public class BirmmFrameBuilderFactory {
+
+ public static BirmmBaseFrame createBirmmFrame(String pduType) {
+
+ return null;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmTagBuilderFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmTagBuilderFactory.java
new file mode 100644
index 0000000..95ebdab
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmTagBuilderFactory.java
@@ -0,0 +1,33 @@
+package com.casic.missiles.frame;
+
+import com.casic.missiles.enums.BirmmTagAttributeEnums;
+import com.casic.missiles.frame.commanTag.*;
+
+public class BirmmTagBuilderFactory {
+
+ public static BirmmBaseTag createTagByOid(String oid) {
+ BirmmTagAttributeEnums tag = BirmmTagAttributeEnums.toType(oid);
+ if (null != tag) {
+ switch (tag) {
+ case CELL_TAG:
+ return new CellTag();
+
+ case DATE_TAG:
+ return new DateTag();
+
+ case PIC_TAG:
+ return new PCITag();
+
+ case SNR_TAG:
+ return new SNRTag();
+
+ case RSRP_TAG:
+ return new RSRPTag();
+
+ default:
+ return null;
+ }
+ }
+ return null;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/CellTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/CellTag.java
new file mode 100644
index 0000000..b0e0360
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/CellTag.java
@@ -0,0 +1,20 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class CellTag extends BirmmBaseTag {
+
+ final String CELL_TAG_OID = "60000020";
+
+ int cellVal;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ cellVal = Integer.parseInt(valueStr, 16);
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/DateTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/DateTag.java
new file mode 100644
index 0000000..e8c5db4
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/DateTag.java
@@ -0,0 +1,30 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.time.LocalDate;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class DateTag extends BirmmBaseTag {
+
+ final String DATE_TAG_OID = "10000050";
+
+ LocalDate date;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ String hexY = valueStr.substring(0, 2);
+ String hexM = valueStr.substring(2, 4);
+ String hexD = valueStr.substring(4, 6);
+
+ date = LocalDate.now();
+ date = date.withYear(BytesUtil.hexStringToUInt(hexY) + 2000);
+ date = date.withMonth(BytesUtil.hexStringToUInt(hexM));
+ date = date.withDayOfMonth(BytesUtil.hexStringToUInt(hexD));
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/PCITag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/PCITag.java
new file mode 100644
index 0000000..4433cea
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/PCITag.java
@@ -0,0 +1,22 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class PCITag extends BirmmBaseTag {
+
+ final String PCI_TAG_OID = "60000511";
+
+ // TYPE_U16整型,主小区物理小区号PCI,范围: 0 – 503
+ int pci;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ pci = BytesUtil.hexStringToUInt(valueStr);
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/RSRPTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/RSRPTag.java
new file mode 100644
index 0000000..d1bb0a8
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/RSRPTag.java
@@ -0,0 +1,22 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class RSRPTag extends BirmmBaseTag {
+
+ final String RSRP_TAG_OID = "60000513";
+
+ //带符号整型,主小区RSRP值,单位dBm。仅在RRC-IDLE状态时可用 -140 ~ -40 越大越好
+ int rsrp;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ rsrp = BytesUtil.hexStringToSInt(valueStr);
+ }
+}
diff --git a/.gitignore b/.gitignore
index 9e20bc1..78302f1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,6 @@
.idea/
**/target/**
logs/
+*.log
+*.log.*
*.iml
diff --git a/casic-iot-web/src/main/resources/config/application-dev.yml b/casic-iot-web/src/main/resources/config/application-dev.yml
index 487fc70..c5c99b7 100644
--- a/casic-iot-web/src/main/resources/config/application-dev.yml
+++ b/casic-iot-web/src/main/resources/config/application-dev.yml
@@ -37,7 +37,7 @@
invalid-time: 86400
config-prefix: 'Casic:'
#kaptcha-open: false #是否开启登录时验证码 (true/false)
- no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/push/data,/push/test
+ no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/aep/**
#flowable数据源和多数据源配置
db:
init:
diff --git a/casic-iot-web/src/main/resources/config/logback-spring.xml b/casic-iot-web/src/main/resources/config/logback-spring.xml
index c0c7ac9..2d308a8 100644
--- a/casic-iot-web/src/main/resources/config/logback-spring.xml
+++ b/casic-iot-web/src/main/resources/config/logback-spring.xml
@@ -5,7 +5,7 @@
-
+
diff --git a/pom.xml b/pom.xml
index 3ad2470..a194074 100644
--- a/pom.xml
+++ b/pom.xml
@@ -49,6 +49,7 @@
2.0.0.alpha
2.5.4
2.5.6
+ 1.2.62
2.0.0.alpha
@@ -56,7 +57,11 @@
-
+
+ com.casic
+ casic-core
+ ${core.version}
+
com.baomidou
dynamic-datasource-spring-boot-starter
@@ -69,11 +74,11 @@
${fastjson.version}
-
- cn.hutool
- hutool-core
- 5.7.2
-
+
+
+
+
+
org.projectlombok
diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml
index d5118b4..8dcc497 100644
--- a/sensorhub-core/pom.xml
+++ b/sensorhub-core/pom.xml
@@ -35,17 +35,17 @@
com.ctg.ag
ctg-ag-sdk-core
-
2.8.0-SNAPSHOT
-
+ system
+ ${pom.basedir}\lib\ctg-ag-sdk-core-2.8.0.jar
com.ctg.ag
ag-sdk-biz
2.8.0-SNAPSHOT
-
-
+ system
+ ${pom.basedir}\lib\ag-sdk-biz.jar
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java
deleted file mode 100644
index 40c55e8..0000000
--- a/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java
+++ /dev/null
@@ -1,30 +0,0 @@
-//package com.casic.missiles;
-//
-//import com.casic.missiles.netty.SensorhubServer;
-//import lombok.extern.slf4j.Slf4j;
-//import org.mybatis.spring.annotation.MapperScan;
-//import org.springframework.beans.factory.annotation.Autowired;
-//import org.springframework.boot.CommandLineRunner;
-//import org.springframework.boot.SpringApplication;
-//import org.springframework.boot.autoconfigure.SpringBootApplication;
-//import org.springframework.cache.annotation.EnableCaching;
-//
-//
-//@SpringBootApplication(scanBasePackages = "com.casic.missiles")
-//@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"})
-//@EnableCaching //开启缓存
-//@Slf4j
-//public class ServerApplication implements CommandLineRunner {
-//
-// @Autowired
-// private SensorhubServer nettyServer;
-// public static void main(String[] args) {
-// SpringApplication.run(ServerApplication.class, args);
-// }
-//
-// @Override
-// public void run(String... args) {
-// this.nettyServer.startServer();
-// }
-//
-//}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java b/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java
new file mode 100644
index 0000000..8f90fd9
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java
@@ -0,0 +1,96 @@
+package com.casic.missiles.controller;
+
+import com.alibaba.fastjson.JSONObject;
+import com.casic.missiles.frame.BirmmBaseFrame;
+import com.casic.missiles.model.response.ResponseData;
+import com.casic.missiles.service.IGeneralService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.tomcat.util.buf.HexUtils;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.util.Base64;
+import java.util.Map;
+
+@RestController
+@Slf4j
+public class GeneralDataReceiver {
+
+ @Resource
+ IGeneralService defaultService;
+
+ @RequestMapping("/aep/data/string")
+ public Object aepDataString(@RequestBody Map dataMap) {
+ log.info("收到AEP平台推送消息:{}", JSONObject.toJSONString(dataMap));
+ log.debug("deviceId: {}, productId: {}, IMEI: {}, timestamp: {}", dataMap.get("deviceId"), dataMap.get("productId"), dataMap.get("IMEI"), dataMap.get("timestamp"));
+
+ // 从推送的数据中获取消息帧
+ String frameStr = new String(getFrameStringFromData(dataMap));
+ log.info("字符串消息帧:{}", frameStr);
+
+ return ResponseData.success();
+ }
+
+ @RequestMapping("/aep/data/hex")
+ public Object aepDataHex(@RequestBody Map dataMap) {
+ log.info("收到AEP平台推送消息:{}", JSONObject.toJSONString(dataMap));
+ log.debug("deviceId: {}, productId: {}, IMEI: {}, timestamp: {}", dataMap.get("deviceId"), dataMap.get("productId"), dataMap.get("IMEI"), dataMap.get("timestamp"));
+
+ // 从推送的数据中获取消息帧
+ byte[] frameBytes = getFrameStringFromData(dataMap);
+ log.info("HEX字节消息帧:{}", HexUtils.toHexString(frameBytes).toUpperCase());
+
+ BirmmBaseFrame birmmFrame = defaultService.dataParse(frameBytes);
+ if (birmmFrame != null) {
+ log.info("HEX字节消息解析成功:{}", birmmFrame);
+ }
+
+ // 返回给电信AEP平台
+ return ResponseData.success();
+ }
+
+ private byte[] getFrameStringFromData(Map dataMap) {
+ byte[] frameStr = new byte[]{};
+
+ if (!dataMap.containsKey("payload")) {
+ log.error("消息帧不含payload字段");
+ return frameStr;
+ }
+
+ // 判断是否有profile
+ boolean hasProfile = false;
+ if (dataMap.containsKey("profile")) {
+ hasProfile = (Boolean) dataMap.get("profile");
+ }
+
+ JSONObject payload = (JSONObject) dataMap.get("payload");
+ // base64格式的消息 电信平台推送的内容
+ String dataBase64 = "";
+ if (hasProfile) {
+ if (!payload.containsKey("serviceData")) {
+ log.error("payload字段中不含serviceData字段");
+ } else {
+ JSONObject serviceData = payload.getJSONObject("serviceData");
+ if (!serviceData.containsKey("Value")) {
+ log.error("serviceData字段中不含Value字段");
+ } else {
+ dataBase64 = serviceData.getString("Value");
+ }
+ }
+ } else {
+ if (payload.containsKey("APPdata")) {
+ dataBase64 = payload.getString("APPdata");
+ } else {
+ log.error("payload字段中不含APPdata字段");
+ }
+ }
+
+ if (!dataBase64.isEmpty()) {
+ frameStr = Base64.getDecoder().decode(dataBase64); // base64解码
+ }
+
+ return frameStr;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java
new file mode 100644
index 0000000..ae6706a
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java
@@ -0,0 +1,40 @@
+package com.casic.missiles.frame;
+
+import lombok.Data;
+import java.util.List;
+
+@Data
+public class BirmmBaseFrame {
+
+ // 前导码 固定为A3
+ final String PRE_CODE = "A3";
+
+ // 协议版本 固定为20
+ final String VERSION = "20";
+
+ // 帧长度 后续到CRC字段前的字节总长度 不包括长度字段和CRC字段
+ int length;
+
+ // 设备编号
+ String devCode;
+
+ // 通信方式
+ String communicationType;
+
+ // 目标节点地址
+ String destinationAddr;
+
+ // PDU类型
+ String pduType;
+
+ // 序号
+ String sequence;
+
+ // 业务字段List
+ String tagListString;
+
+ List tagList;
+
+ // CRC
+ String crc;
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java
new file mode 100644
index 0000000..2285f9a
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java
@@ -0,0 +1,11 @@
+package com.casic.missiles.frame;
+
+import lombok.Data;
+
+@Data
+public class BirmmBaseTag {
+
+ private String oid;
+ private int tagLen;
+ private String valueStr;
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java
new file mode 100644
index 0000000..b1fd65c
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java
@@ -0,0 +1,9 @@
+package com.casic.missiles.frame;
+
+public class BirmmFrameBuilderFactory {
+
+ public static BirmmBaseFrame createBirmmFrame(String pduType) {
+
+ return null;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmTagBuilderFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmTagBuilderFactory.java
new file mode 100644
index 0000000..95ebdab
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmTagBuilderFactory.java
@@ -0,0 +1,33 @@
+package com.casic.missiles.frame;
+
+import com.casic.missiles.enums.BirmmTagAttributeEnums;
+import com.casic.missiles.frame.commanTag.*;
+
+public class BirmmTagBuilderFactory {
+
+ public static BirmmBaseTag createTagByOid(String oid) {
+ BirmmTagAttributeEnums tag = BirmmTagAttributeEnums.toType(oid);
+ if (null != tag) {
+ switch (tag) {
+ case CELL_TAG:
+ return new CellTag();
+
+ case DATE_TAG:
+ return new DateTag();
+
+ case PIC_TAG:
+ return new PCITag();
+
+ case SNR_TAG:
+ return new SNRTag();
+
+ case RSRP_TAG:
+ return new RSRPTag();
+
+ default:
+ return null;
+ }
+ }
+ return null;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/CellTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/CellTag.java
new file mode 100644
index 0000000..b0e0360
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/CellTag.java
@@ -0,0 +1,20 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class CellTag extends BirmmBaseTag {
+
+ final String CELL_TAG_OID = "60000020";
+
+ int cellVal;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ cellVal = Integer.parseInt(valueStr, 16);
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/DateTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/DateTag.java
new file mode 100644
index 0000000..e8c5db4
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/DateTag.java
@@ -0,0 +1,30 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.time.LocalDate;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class DateTag extends BirmmBaseTag {
+
+ final String DATE_TAG_OID = "10000050";
+
+ LocalDate date;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ String hexY = valueStr.substring(0, 2);
+ String hexM = valueStr.substring(2, 4);
+ String hexD = valueStr.substring(4, 6);
+
+ date = LocalDate.now();
+ date = date.withYear(BytesUtil.hexStringToUInt(hexY) + 2000);
+ date = date.withMonth(BytesUtil.hexStringToUInt(hexM));
+ date = date.withDayOfMonth(BytesUtil.hexStringToUInt(hexD));
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/PCITag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/PCITag.java
new file mode 100644
index 0000000..4433cea
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/PCITag.java
@@ -0,0 +1,22 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class PCITag extends BirmmBaseTag {
+
+ final String PCI_TAG_OID = "60000511";
+
+ // TYPE_U16整型,主小区物理小区号PCI,范围: 0 – 503
+ int pci;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ pci = BytesUtil.hexStringToUInt(valueStr);
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/RSRPTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/RSRPTag.java
new file mode 100644
index 0000000..d1bb0a8
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/RSRPTag.java
@@ -0,0 +1,22 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class RSRPTag extends BirmmBaseTag {
+
+ final String RSRP_TAG_OID = "60000513";
+
+ //带符号整型,主小区RSRP值,单位dBm。仅在RRC-IDLE状态时可用 -140 ~ -40 越大越好
+ int rsrp;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ rsrp = BytesUtil.hexStringToSInt(valueStr);
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/SNRTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/SNRTag.java
new file mode 100644
index 0000000..3040799
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/SNRTag.java
@@ -0,0 +1,22 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class SNRTag extends BirmmBaseTag {
+
+ final String SNR_TAG_OID = "60000516";
+
+ //带符号整型,主小区lart SNR值,单位dB。仅在RRC-IDLE状态时可用 -20 ~ 50 越大越好
+ int snr;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ snr = BytesUtil.hexStringToSInt(valueStr);
+ }
+}
diff --git a/.gitignore b/.gitignore
index 9e20bc1..78302f1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,6 @@
.idea/
**/target/**
logs/
+*.log
+*.log.*
*.iml
diff --git a/casic-iot-web/src/main/resources/config/application-dev.yml b/casic-iot-web/src/main/resources/config/application-dev.yml
index 487fc70..c5c99b7 100644
--- a/casic-iot-web/src/main/resources/config/application-dev.yml
+++ b/casic-iot-web/src/main/resources/config/application-dev.yml
@@ -37,7 +37,7 @@
invalid-time: 86400
config-prefix: 'Casic:'
#kaptcha-open: false #是否开启登录时验证码 (true/false)
- no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/push/data,/push/test
+ no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/aep/**
#flowable数据源和多数据源配置
db:
init:
diff --git a/casic-iot-web/src/main/resources/config/logback-spring.xml b/casic-iot-web/src/main/resources/config/logback-spring.xml
index c0c7ac9..2d308a8 100644
--- a/casic-iot-web/src/main/resources/config/logback-spring.xml
+++ b/casic-iot-web/src/main/resources/config/logback-spring.xml
@@ -5,7 +5,7 @@
-
+
diff --git a/pom.xml b/pom.xml
index 3ad2470..a194074 100644
--- a/pom.xml
+++ b/pom.xml
@@ -49,6 +49,7 @@
2.0.0.alpha
2.5.4
2.5.6
+ 1.2.62
2.0.0.alpha
@@ -56,7 +57,11 @@
-
+
+ com.casic
+ casic-core
+ ${core.version}
+
com.baomidou
dynamic-datasource-spring-boot-starter
@@ -69,11 +74,11 @@
${fastjson.version}
-
- cn.hutool
- hutool-core
- 5.7.2
-
+
+
+
+
+
org.projectlombok
diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml
index d5118b4..8dcc497 100644
--- a/sensorhub-core/pom.xml
+++ b/sensorhub-core/pom.xml
@@ -35,17 +35,17 @@
com.ctg.ag
ctg-ag-sdk-core
-
2.8.0-SNAPSHOT
-
+ system
+ ${pom.basedir}\lib\ctg-ag-sdk-core-2.8.0.jar
com.ctg.ag
ag-sdk-biz
2.8.0-SNAPSHOT
-
-
+ system
+ ${pom.basedir}\lib\ag-sdk-biz.jar
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java
deleted file mode 100644
index 40c55e8..0000000
--- a/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java
+++ /dev/null
@@ -1,30 +0,0 @@
-//package com.casic.missiles;
-//
-//import com.casic.missiles.netty.SensorhubServer;
-//import lombok.extern.slf4j.Slf4j;
-//import org.mybatis.spring.annotation.MapperScan;
-//import org.springframework.beans.factory.annotation.Autowired;
-//import org.springframework.boot.CommandLineRunner;
-//import org.springframework.boot.SpringApplication;
-//import org.springframework.boot.autoconfigure.SpringBootApplication;
-//import org.springframework.cache.annotation.EnableCaching;
-//
-//
-//@SpringBootApplication(scanBasePackages = "com.casic.missiles")
-//@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"})
-//@EnableCaching //开启缓存
-//@Slf4j
-//public class ServerApplication implements CommandLineRunner {
-//
-// @Autowired
-// private SensorhubServer nettyServer;
-// public static void main(String[] args) {
-// SpringApplication.run(ServerApplication.class, args);
-// }
-//
-// @Override
-// public void run(String... args) {
-// this.nettyServer.startServer();
-// }
-//
-//}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java b/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java
new file mode 100644
index 0000000..8f90fd9
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java
@@ -0,0 +1,96 @@
+package com.casic.missiles.controller;
+
+import com.alibaba.fastjson.JSONObject;
+import com.casic.missiles.frame.BirmmBaseFrame;
+import com.casic.missiles.model.response.ResponseData;
+import com.casic.missiles.service.IGeneralService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.tomcat.util.buf.HexUtils;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.util.Base64;
+import java.util.Map;
+
+@RestController
+@Slf4j
+public class GeneralDataReceiver {
+
+ @Resource
+ IGeneralService defaultService;
+
+ @RequestMapping("/aep/data/string")
+ public Object aepDataString(@RequestBody Map dataMap) {
+ log.info("收到AEP平台推送消息:{}", JSONObject.toJSONString(dataMap));
+ log.debug("deviceId: {}, productId: {}, IMEI: {}, timestamp: {}", dataMap.get("deviceId"), dataMap.get("productId"), dataMap.get("IMEI"), dataMap.get("timestamp"));
+
+ // 从推送的数据中获取消息帧
+ String frameStr = new String(getFrameStringFromData(dataMap));
+ log.info("字符串消息帧:{}", frameStr);
+
+ return ResponseData.success();
+ }
+
+ @RequestMapping("/aep/data/hex")
+ public Object aepDataHex(@RequestBody Map dataMap) {
+ log.info("收到AEP平台推送消息:{}", JSONObject.toJSONString(dataMap));
+ log.debug("deviceId: {}, productId: {}, IMEI: {}, timestamp: {}", dataMap.get("deviceId"), dataMap.get("productId"), dataMap.get("IMEI"), dataMap.get("timestamp"));
+
+ // 从推送的数据中获取消息帧
+ byte[] frameBytes = getFrameStringFromData(dataMap);
+ log.info("HEX字节消息帧:{}", HexUtils.toHexString(frameBytes).toUpperCase());
+
+ BirmmBaseFrame birmmFrame = defaultService.dataParse(frameBytes);
+ if (birmmFrame != null) {
+ log.info("HEX字节消息解析成功:{}", birmmFrame);
+ }
+
+ // 返回给电信AEP平台
+ return ResponseData.success();
+ }
+
+ private byte[] getFrameStringFromData(Map dataMap) {
+ byte[] frameStr = new byte[]{};
+
+ if (!dataMap.containsKey("payload")) {
+ log.error("消息帧不含payload字段");
+ return frameStr;
+ }
+
+ // 判断是否有profile
+ boolean hasProfile = false;
+ if (dataMap.containsKey("profile")) {
+ hasProfile = (Boolean) dataMap.get("profile");
+ }
+
+ JSONObject payload = (JSONObject) dataMap.get("payload");
+ // base64格式的消息 电信平台推送的内容
+ String dataBase64 = "";
+ if (hasProfile) {
+ if (!payload.containsKey("serviceData")) {
+ log.error("payload字段中不含serviceData字段");
+ } else {
+ JSONObject serviceData = payload.getJSONObject("serviceData");
+ if (!serviceData.containsKey("Value")) {
+ log.error("serviceData字段中不含Value字段");
+ } else {
+ dataBase64 = serviceData.getString("Value");
+ }
+ }
+ } else {
+ if (payload.containsKey("APPdata")) {
+ dataBase64 = payload.getString("APPdata");
+ } else {
+ log.error("payload字段中不含APPdata字段");
+ }
+ }
+
+ if (!dataBase64.isEmpty()) {
+ frameStr = Base64.getDecoder().decode(dataBase64); // base64解码
+ }
+
+ return frameStr;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java
new file mode 100644
index 0000000..ae6706a
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java
@@ -0,0 +1,40 @@
+package com.casic.missiles.frame;
+
+import lombok.Data;
+import java.util.List;
+
+@Data
+public class BirmmBaseFrame {
+
+ // 前导码 固定为A3
+ final String PRE_CODE = "A3";
+
+ // 协议版本 固定为20
+ final String VERSION = "20";
+
+ // 帧长度 后续到CRC字段前的字节总长度 不包括长度字段和CRC字段
+ int length;
+
+ // 设备编号
+ String devCode;
+
+ // 通信方式
+ String communicationType;
+
+ // 目标节点地址
+ String destinationAddr;
+
+ // PDU类型
+ String pduType;
+
+ // 序号
+ String sequence;
+
+ // 业务字段List
+ String tagListString;
+
+ List tagList;
+
+ // CRC
+ String crc;
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java
new file mode 100644
index 0000000..2285f9a
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java
@@ -0,0 +1,11 @@
+package com.casic.missiles.frame;
+
+import lombok.Data;
+
+@Data
+public class BirmmBaseTag {
+
+ private String oid;
+ private int tagLen;
+ private String valueStr;
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java
new file mode 100644
index 0000000..b1fd65c
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java
@@ -0,0 +1,9 @@
+package com.casic.missiles.frame;
+
+public class BirmmFrameBuilderFactory {
+
+ public static BirmmBaseFrame createBirmmFrame(String pduType) {
+
+ return null;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmTagBuilderFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmTagBuilderFactory.java
new file mode 100644
index 0000000..95ebdab
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmTagBuilderFactory.java
@@ -0,0 +1,33 @@
+package com.casic.missiles.frame;
+
+import com.casic.missiles.enums.BirmmTagAttributeEnums;
+import com.casic.missiles.frame.commanTag.*;
+
+public class BirmmTagBuilderFactory {
+
+ public static BirmmBaseTag createTagByOid(String oid) {
+ BirmmTagAttributeEnums tag = BirmmTagAttributeEnums.toType(oid);
+ if (null != tag) {
+ switch (tag) {
+ case CELL_TAG:
+ return new CellTag();
+
+ case DATE_TAG:
+ return new DateTag();
+
+ case PIC_TAG:
+ return new PCITag();
+
+ case SNR_TAG:
+ return new SNRTag();
+
+ case RSRP_TAG:
+ return new RSRPTag();
+
+ default:
+ return null;
+ }
+ }
+ return null;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/CellTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/CellTag.java
new file mode 100644
index 0000000..b0e0360
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/CellTag.java
@@ -0,0 +1,20 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class CellTag extends BirmmBaseTag {
+
+ final String CELL_TAG_OID = "60000020";
+
+ int cellVal;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ cellVal = Integer.parseInt(valueStr, 16);
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/DateTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/DateTag.java
new file mode 100644
index 0000000..e8c5db4
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/DateTag.java
@@ -0,0 +1,30 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.time.LocalDate;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class DateTag extends BirmmBaseTag {
+
+ final String DATE_TAG_OID = "10000050";
+
+ LocalDate date;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ String hexY = valueStr.substring(0, 2);
+ String hexM = valueStr.substring(2, 4);
+ String hexD = valueStr.substring(4, 6);
+
+ date = LocalDate.now();
+ date = date.withYear(BytesUtil.hexStringToUInt(hexY) + 2000);
+ date = date.withMonth(BytesUtil.hexStringToUInt(hexM));
+ date = date.withDayOfMonth(BytesUtil.hexStringToUInt(hexD));
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/PCITag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/PCITag.java
new file mode 100644
index 0000000..4433cea
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/PCITag.java
@@ -0,0 +1,22 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class PCITag extends BirmmBaseTag {
+
+ final String PCI_TAG_OID = "60000511";
+
+ // TYPE_U16整型,主小区物理小区号PCI,范围: 0 – 503
+ int pci;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ pci = BytesUtil.hexStringToUInt(valueStr);
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/RSRPTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/RSRPTag.java
new file mode 100644
index 0000000..d1bb0a8
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/RSRPTag.java
@@ -0,0 +1,22 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class RSRPTag extends BirmmBaseTag {
+
+ final String RSRP_TAG_OID = "60000513";
+
+ //带符号整型,主小区RSRP值,单位dBm。仅在RRC-IDLE状态时可用 -140 ~ -40 越大越好
+ int rsrp;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ rsrp = BytesUtil.hexStringToSInt(valueStr);
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/SNRTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/SNRTag.java
new file mode 100644
index 0000000..3040799
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/SNRTag.java
@@ -0,0 +1,22 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class SNRTag extends BirmmBaseTag {
+
+ final String SNR_TAG_OID = "60000516";
+
+ //带符号整型,主小区lart SNR值,单位dB。仅在RRC-IDLE状态时可用 -20 ~ 50 越大越好
+ int snr;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ snr = BytesUtil.hexStringToSInt(valueStr);
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/BirmmProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/BirmmProtocolParser.java
new file mode 100644
index 0000000..d29e372
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/BirmmProtocolParser.java
@@ -0,0 +1,38 @@
+package com.casic.missiles.parser;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+
+import java.util.List;
+
+/**
+ * BIRMM系列设备
+ * 一般设备协议解析
+ */
+public interface BirmmProtocolParser {
+
+ boolean preCheckFrame(byte[] frameBytes);
+
+ boolean validateCRC(byte[] frameBytes);
+
+ boolean validateLength(byte[] tagBytes, int length);
+
+ String getFrameHeader(byte[] frameBytes);
+
+ int getLength(byte[] frameBytes);
+
+ String getDevCode(byte[] frameBytes);
+
+ String getCommunicationType(byte[] frameBytes);
+
+ String getDestinationAddr(byte[] frameBytes);
+
+ String getPDUType(byte[] frameBytes);
+
+ String getSequence(byte[] frameBytes);
+
+ String getTagListString(byte[] frameBytes);
+ List getTagList(byte[] tagBytes);
+
+ String getCRC(byte[] frameBytes);
+ String getToBeVerifiedCRCBytes(byte[] frameBytes);
+}
diff --git a/.gitignore b/.gitignore
index 9e20bc1..78302f1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,6 @@
.idea/
**/target/**
logs/
+*.log
+*.log.*
*.iml
diff --git a/casic-iot-web/src/main/resources/config/application-dev.yml b/casic-iot-web/src/main/resources/config/application-dev.yml
index 487fc70..c5c99b7 100644
--- a/casic-iot-web/src/main/resources/config/application-dev.yml
+++ b/casic-iot-web/src/main/resources/config/application-dev.yml
@@ -37,7 +37,7 @@
invalid-time: 86400
config-prefix: 'Casic:'
#kaptcha-open: false #是否开启登录时验证码 (true/false)
- no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/push/data,/push/test
+ no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/aep/**
#flowable数据源和多数据源配置
db:
init:
diff --git a/casic-iot-web/src/main/resources/config/logback-spring.xml b/casic-iot-web/src/main/resources/config/logback-spring.xml
index c0c7ac9..2d308a8 100644
--- a/casic-iot-web/src/main/resources/config/logback-spring.xml
+++ b/casic-iot-web/src/main/resources/config/logback-spring.xml
@@ -5,7 +5,7 @@
-
+
diff --git a/pom.xml b/pom.xml
index 3ad2470..a194074 100644
--- a/pom.xml
+++ b/pom.xml
@@ -49,6 +49,7 @@
2.0.0.alpha
2.5.4
2.5.6
+ 1.2.62
2.0.0.alpha
@@ -56,7 +57,11 @@
-
+
+ com.casic
+ casic-core
+ ${core.version}
+
com.baomidou
dynamic-datasource-spring-boot-starter
@@ -69,11 +74,11 @@
${fastjson.version}
-
- cn.hutool
- hutool-core
- 5.7.2
-
+
+
+
+
+
org.projectlombok
diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml
index d5118b4..8dcc497 100644
--- a/sensorhub-core/pom.xml
+++ b/sensorhub-core/pom.xml
@@ -35,17 +35,17 @@
com.ctg.ag
ctg-ag-sdk-core
-
2.8.0-SNAPSHOT
-
+ system
+ ${pom.basedir}\lib\ctg-ag-sdk-core-2.8.0.jar
com.ctg.ag
ag-sdk-biz
2.8.0-SNAPSHOT
-
-
+ system
+ ${pom.basedir}\lib\ag-sdk-biz.jar
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java
deleted file mode 100644
index 40c55e8..0000000
--- a/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java
+++ /dev/null
@@ -1,30 +0,0 @@
-//package com.casic.missiles;
-//
-//import com.casic.missiles.netty.SensorhubServer;
-//import lombok.extern.slf4j.Slf4j;
-//import org.mybatis.spring.annotation.MapperScan;
-//import org.springframework.beans.factory.annotation.Autowired;
-//import org.springframework.boot.CommandLineRunner;
-//import org.springframework.boot.SpringApplication;
-//import org.springframework.boot.autoconfigure.SpringBootApplication;
-//import org.springframework.cache.annotation.EnableCaching;
-//
-//
-//@SpringBootApplication(scanBasePackages = "com.casic.missiles")
-//@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"})
-//@EnableCaching //开启缓存
-//@Slf4j
-//public class ServerApplication implements CommandLineRunner {
-//
-// @Autowired
-// private SensorhubServer nettyServer;
-// public static void main(String[] args) {
-// SpringApplication.run(ServerApplication.class, args);
-// }
-//
-// @Override
-// public void run(String... args) {
-// this.nettyServer.startServer();
-// }
-//
-//}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java b/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java
new file mode 100644
index 0000000..8f90fd9
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java
@@ -0,0 +1,96 @@
+package com.casic.missiles.controller;
+
+import com.alibaba.fastjson.JSONObject;
+import com.casic.missiles.frame.BirmmBaseFrame;
+import com.casic.missiles.model.response.ResponseData;
+import com.casic.missiles.service.IGeneralService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.tomcat.util.buf.HexUtils;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.util.Base64;
+import java.util.Map;
+
+@RestController
+@Slf4j
+public class GeneralDataReceiver {
+
+ @Resource
+ IGeneralService defaultService;
+
+ @RequestMapping("/aep/data/string")
+ public Object aepDataString(@RequestBody Map dataMap) {
+ log.info("收到AEP平台推送消息:{}", JSONObject.toJSONString(dataMap));
+ log.debug("deviceId: {}, productId: {}, IMEI: {}, timestamp: {}", dataMap.get("deviceId"), dataMap.get("productId"), dataMap.get("IMEI"), dataMap.get("timestamp"));
+
+ // 从推送的数据中获取消息帧
+ String frameStr = new String(getFrameStringFromData(dataMap));
+ log.info("字符串消息帧:{}", frameStr);
+
+ return ResponseData.success();
+ }
+
+ @RequestMapping("/aep/data/hex")
+ public Object aepDataHex(@RequestBody Map dataMap) {
+ log.info("收到AEP平台推送消息:{}", JSONObject.toJSONString(dataMap));
+ log.debug("deviceId: {}, productId: {}, IMEI: {}, timestamp: {}", dataMap.get("deviceId"), dataMap.get("productId"), dataMap.get("IMEI"), dataMap.get("timestamp"));
+
+ // 从推送的数据中获取消息帧
+ byte[] frameBytes = getFrameStringFromData(dataMap);
+ log.info("HEX字节消息帧:{}", HexUtils.toHexString(frameBytes).toUpperCase());
+
+ BirmmBaseFrame birmmFrame = defaultService.dataParse(frameBytes);
+ if (birmmFrame != null) {
+ log.info("HEX字节消息解析成功:{}", birmmFrame);
+ }
+
+ // 返回给电信AEP平台
+ return ResponseData.success();
+ }
+
+ private byte[] getFrameStringFromData(Map dataMap) {
+ byte[] frameStr = new byte[]{};
+
+ if (!dataMap.containsKey("payload")) {
+ log.error("消息帧不含payload字段");
+ return frameStr;
+ }
+
+ // 判断是否有profile
+ boolean hasProfile = false;
+ if (dataMap.containsKey("profile")) {
+ hasProfile = (Boolean) dataMap.get("profile");
+ }
+
+ JSONObject payload = (JSONObject) dataMap.get("payload");
+ // base64格式的消息 电信平台推送的内容
+ String dataBase64 = "";
+ if (hasProfile) {
+ if (!payload.containsKey("serviceData")) {
+ log.error("payload字段中不含serviceData字段");
+ } else {
+ JSONObject serviceData = payload.getJSONObject("serviceData");
+ if (!serviceData.containsKey("Value")) {
+ log.error("serviceData字段中不含Value字段");
+ } else {
+ dataBase64 = serviceData.getString("Value");
+ }
+ }
+ } else {
+ if (payload.containsKey("APPdata")) {
+ dataBase64 = payload.getString("APPdata");
+ } else {
+ log.error("payload字段中不含APPdata字段");
+ }
+ }
+
+ if (!dataBase64.isEmpty()) {
+ frameStr = Base64.getDecoder().decode(dataBase64); // base64解码
+ }
+
+ return frameStr;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java
new file mode 100644
index 0000000..ae6706a
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java
@@ -0,0 +1,40 @@
+package com.casic.missiles.frame;
+
+import lombok.Data;
+import java.util.List;
+
+@Data
+public class BirmmBaseFrame {
+
+ // 前导码 固定为A3
+ final String PRE_CODE = "A3";
+
+ // 协议版本 固定为20
+ final String VERSION = "20";
+
+ // 帧长度 后续到CRC字段前的字节总长度 不包括长度字段和CRC字段
+ int length;
+
+ // 设备编号
+ String devCode;
+
+ // 通信方式
+ String communicationType;
+
+ // 目标节点地址
+ String destinationAddr;
+
+ // PDU类型
+ String pduType;
+
+ // 序号
+ String sequence;
+
+ // 业务字段List
+ String tagListString;
+
+ List tagList;
+
+ // CRC
+ String crc;
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java
new file mode 100644
index 0000000..2285f9a
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java
@@ -0,0 +1,11 @@
+package com.casic.missiles.frame;
+
+import lombok.Data;
+
+@Data
+public class BirmmBaseTag {
+
+ private String oid;
+ private int tagLen;
+ private String valueStr;
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java
new file mode 100644
index 0000000..b1fd65c
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java
@@ -0,0 +1,9 @@
+package com.casic.missiles.frame;
+
+public class BirmmFrameBuilderFactory {
+
+ public static BirmmBaseFrame createBirmmFrame(String pduType) {
+
+ return null;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmTagBuilderFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmTagBuilderFactory.java
new file mode 100644
index 0000000..95ebdab
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmTagBuilderFactory.java
@@ -0,0 +1,33 @@
+package com.casic.missiles.frame;
+
+import com.casic.missiles.enums.BirmmTagAttributeEnums;
+import com.casic.missiles.frame.commanTag.*;
+
+public class BirmmTagBuilderFactory {
+
+ public static BirmmBaseTag createTagByOid(String oid) {
+ BirmmTagAttributeEnums tag = BirmmTagAttributeEnums.toType(oid);
+ if (null != tag) {
+ switch (tag) {
+ case CELL_TAG:
+ return new CellTag();
+
+ case DATE_TAG:
+ return new DateTag();
+
+ case PIC_TAG:
+ return new PCITag();
+
+ case SNR_TAG:
+ return new SNRTag();
+
+ case RSRP_TAG:
+ return new RSRPTag();
+
+ default:
+ return null;
+ }
+ }
+ return null;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/CellTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/CellTag.java
new file mode 100644
index 0000000..b0e0360
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/CellTag.java
@@ -0,0 +1,20 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class CellTag extends BirmmBaseTag {
+
+ final String CELL_TAG_OID = "60000020";
+
+ int cellVal;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ cellVal = Integer.parseInt(valueStr, 16);
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/DateTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/DateTag.java
new file mode 100644
index 0000000..e8c5db4
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/DateTag.java
@@ -0,0 +1,30 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.time.LocalDate;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class DateTag extends BirmmBaseTag {
+
+ final String DATE_TAG_OID = "10000050";
+
+ LocalDate date;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ String hexY = valueStr.substring(0, 2);
+ String hexM = valueStr.substring(2, 4);
+ String hexD = valueStr.substring(4, 6);
+
+ date = LocalDate.now();
+ date = date.withYear(BytesUtil.hexStringToUInt(hexY) + 2000);
+ date = date.withMonth(BytesUtil.hexStringToUInt(hexM));
+ date = date.withDayOfMonth(BytesUtil.hexStringToUInt(hexD));
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/PCITag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/PCITag.java
new file mode 100644
index 0000000..4433cea
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/PCITag.java
@@ -0,0 +1,22 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class PCITag extends BirmmBaseTag {
+
+ final String PCI_TAG_OID = "60000511";
+
+ // TYPE_U16整型,主小区物理小区号PCI,范围: 0 – 503
+ int pci;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ pci = BytesUtil.hexStringToUInt(valueStr);
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/RSRPTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/RSRPTag.java
new file mode 100644
index 0000000..d1bb0a8
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/RSRPTag.java
@@ -0,0 +1,22 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class RSRPTag extends BirmmBaseTag {
+
+ final String RSRP_TAG_OID = "60000513";
+
+ //带符号整型,主小区RSRP值,单位dBm。仅在RRC-IDLE状态时可用 -140 ~ -40 越大越好
+ int rsrp;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ rsrp = BytesUtil.hexStringToSInt(valueStr);
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/SNRTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/SNRTag.java
new file mode 100644
index 0000000..3040799
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/SNRTag.java
@@ -0,0 +1,22 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class SNRTag extends BirmmBaseTag {
+
+ final String SNR_TAG_OID = "60000516";
+
+ //带符号整型,主小区lart SNR值,单位dB。仅在RRC-IDLE状态时可用 -20 ~ 50 越大越好
+ int snr;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ snr = BytesUtil.hexStringToSInt(valueStr);
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/BirmmProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/BirmmProtocolParser.java
new file mode 100644
index 0000000..d29e372
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/BirmmProtocolParser.java
@@ -0,0 +1,38 @@
+package com.casic.missiles.parser;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+
+import java.util.List;
+
+/**
+ * BIRMM系列设备
+ * 一般设备协议解析
+ */
+public interface BirmmProtocolParser {
+
+ boolean preCheckFrame(byte[] frameBytes);
+
+ boolean validateCRC(byte[] frameBytes);
+
+ boolean validateLength(byte[] tagBytes, int length);
+
+ String getFrameHeader(byte[] frameBytes);
+
+ int getLength(byte[] frameBytes);
+
+ String getDevCode(byte[] frameBytes);
+
+ String getCommunicationType(byte[] frameBytes);
+
+ String getDestinationAddr(byte[] frameBytes);
+
+ String getPDUType(byte[] frameBytes);
+
+ String getSequence(byte[] frameBytes);
+
+ String getTagListString(byte[] frameBytes);
+ List getTagList(byte[] tagBytes);
+
+ String getCRC(byte[] frameBytes);
+ String getToBeVerifiedCRCBytes(byte[] frameBytes);
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/impl/BirmmProtocolParserImpl.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/impl/BirmmProtocolParserImpl.java
new file mode 100644
index 0000000..11c542d
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/impl/BirmmProtocolParserImpl.java
@@ -0,0 +1,145 @@
+package com.casic.missiles.parser.impl;
+
+import com.casic.missiles.enums.BirmmFrameAttributeEnums;
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.frame.BirmmTagBuilderFactory;
+import com.casic.missiles.parser.BirmmProtocolParser;
+import com.casic.missiles.parser.crc.CRCUtil;
+import com.casic.missiles.util.BytesUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Component
+@Slf4j
+public class BirmmProtocolParserImpl implements BirmmProtocolParser {
+ @Override
+ public boolean preCheckFrame(byte[] frameBytes) {
+ if (!checkPreCodeAndVersion(frameBytes)) {
+ log.error("帧头不符合协议:{}", getFrameHeader(frameBytes));
+ return false;
+ }
+
+ if (!preCheckLength(frameBytes)) {
+ log.error("帧长度不满足最低长度要求:{}", frameBytes.length);
+ return false;
+ }
+
+ if (!validateCRC(frameBytes)) {
+ log.error("CRC校验不通过:{}", getCRC(frameBytes));
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public boolean validateCRC(byte[] frameBytes) {
+ byte[] toBeVerifiedBytes = new byte[frameBytes.length - BirmmFrameAttributeEnums.CRC.getLength()];
+ System.arraycopy(frameBytes, 0, toBeVerifiedBytes, 0, toBeVerifiedBytes.length);
+
+ // 计算CRC值
+ CRCUtil crcUtil = new CRCUtil(CRCUtil.Parameters.CRC16MODBUS);
+ long crcVal = crcUtil.calculateCRC(toBeVerifiedBytes);
+ // 格式化输出
+ String crcStr = String.format("%0" + BirmmFrameAttributeEnums.CRC.getLength() * 2 + "X", crcVal);
+
+ return getCRC(frameBytes).equalsIgnoreCase(crcStr);
+ }
+
+ @Override
+ public boolean validateLength(byte[] tagBytes, int length) {
+ return false;
+ }
+
+ @Override
+ public String getFrameHeader(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.HEADER.getOffset(), BirmmFrameAttributeEnums.HEADER.getLength()); // byte[0] ~ byte[1] 表示A320
+ }
+
+ @Override
+ public int getLength(byte[] frameBytes) {
+ byte[] lengthBytes = new byte[BirmmFrameAttributeEnums.LENGTH.getLength()];
+ System.arraycopy(frameBytes, BirmmFrameAttributeEnums.LENGTH.getOffset(), lengthBytes, 0, lengthBytes.length); // byte[2] ~ byte[3] 表示长度
+
+ return BytesUtil.hexStringToUInt(lengthBytes);
+ }
+
+ @Override
+ public String getDevCode(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.DEVICE_CODE.getOffset(), BirmmFrameAttributeEnums.DEVICE_CODE.getLength()); // byte[4] ~ byte[10] 表示设备编号
+ }
+
+ @Override
+ public String getCommunicationType(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.COMM_TYPE.getOffset(), BirmmFrameAttributeEnums.COMM_TYPE.getLength()); // byte[11] 表示通信方式
+ }
+
+ @Override
+ public String getDestinationAddr(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.DEST_ADDR.getOffset(), BirmmFrameAttributeEnums.DEST_ADDR.getLength()); // byte[12] ~ byte[13] 表示目标节点地址
+ }
+
+ @Override
+ public String getPDUType(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.PDU_TYPE.getOffset(), BirmmFrameAttributeEnums.PDU_TYPE.getLength()); // byte[14] ~ byte[15] 表示PDUType
+ }
+
+ @Override
+ public String getSequence(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.SEQ.getOffset(), BirmmFrameAttributeEnums.SEQ.getLength()); // byte[16] 表示序号
+ }
+
+ @Override
+ public String getTagListString(byte[] frameBytes) {
+ // 帧结构其余字节长度为 18 = 1+1+2+6+1+2+2+1+2
+ return BytesUtil.extractHexString(frameBytes, 16, frameBytes.length - 18); // 从byte[16]开始
+ }
+
+ @Override
+ public List getTagList(byte[] tagBytes) {
+ // 必须包含OID和长度 4 + 2
+ if (tagBytes.length < 6) {
+ return null;
+ }
+ List tagList = new ArrayList<>();
+ int idx = 0;
+ while (idx + 6 < tagBytes.length) {
+ String oid = BytesUtil.extractHexString(tagBytes, idx, 4);
+ int tagLen = BytesUtil.hexStringToUInt(new byte[] {tagBytes[idx + 4], tagBytes[idx + 5]});
+ idx += 6;
+ if (tagLen + idx < tagBytes.length) {
+ BirmmBaseTag tagBase = BirmmTagBuilderFactory.createTagByOid(oid);
+ if (null != tagBase) {
+ String valStr = BytesUtil.extractHexString(tagBytes, idx, tagLen);
+ tagBase.setValueStr(valStr);
+
+ tagList.add(tagBase);
+ }
+ }
+ idx += tagLen;
+ }
+
+ return tagList;
+ }
+
+ private boolean checkPreCodeAndVersion(byte[] frameBytes) {
+ String headerStr = getFrameHeader(frameBytes);
+ return headerStr.equalsIgnoreCase(BirmmFrameAttributeEnums.HEADER.getDefaultStr());
+ }
+
+ private boolean preCheckLength(byte[] frameBytes) {
+ return frameBytes.length >= 18;
+ }
+
+ @Override
+ public String getCRC(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, frameBytes.length - 2, BirmmFrameAttributeEnums.CRC.getLength()); // 最后两个字节表示CRC校验码
+ }
+
+ @Override
+ public String getToBeVerifiedCRCBytes(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, 0, frameBytes.length - 2); // 所有字节都用于生成CRC校验码
+ }
+}
diff --git a/.gitignore b/.gitignore
index 9e20bc1..78302f1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,6 @@
.idea/
**/target/**
logs/
+*.log
+*.log.*
*.iml
diff --git a/casic-iot-web/src/main/resources/config/application-dev.yml b/casic-iot-web/src/main/resources/config/application-dev.yml
index 487fc70..c5c99b7 100644
--- a/casic-iot-web/src/main/resources/config/application-dev.yml
+++ b/casic-iot-web/src/main/resources/config/application-dev.yml
@@ -37,7 +37,7 @@
invalid-time: 86400
config-prefix: 'Casic:'
#kaptcha-open: false #是否开启登录时验证码 (true/false)
- no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/push/data,/push/test
+ no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/aep/**
#flowable数据源和多数据源配置
db:
init:
diff --git a/casic-iot-web/src/main/resources/config/logback-spring.xml b/casic-iot-web/src/main/resources/config/logback-spring.xml
index c0c7ac9..2d308a8 100644
--- a/casic-iot-web/src/main/resources/config/logback-spring.xml
+++ b/casic-iot-web/src/main/resources/config/logback-spring.xml
@@ -5,7 +5,7 @@
-
+
diff --git a/pom.xml b/pom.xml
index 3ad2470..a194074 100644
--- a/pom.xml
+++ b/pom.xml
@@ -49,6 +49,7 @@
2.0.0.alpha
2.5.4
2.5.6
+ 1.2.62
2.0.0.alpha
@@ -56,7 +57,11 @@
-
+
+ com.casic
+ casic-core
+ ${core.version}
+
com.baomidou
dynamic-datasource-spring-boot-starter
@@ -69,11 +74,11 @@
${fastjson.version}
-
- cn.hutool
- hutool-core
- 5.7.2
-
+
+
+
+
+
org.projectlombok
diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml
index d5118b4..8dcc497 100644
--- a/sensorhub-core/pom.xml
+++ b/sensorhub-core/pom.xml
@@ -35,17 +35,17 @@
com.ctg.ag
ctg-ag-sdk-core
-
2.8.0-SNAPSHOT
-
+ system
+ ${pom.basedir}\lib\ctg-ag-sdk-core-2.8.0.jar
com.ctg.ag
ag-sdk-biz
2.8.0-SNAPSHOT
-
-
+ system
+ ${pom.basedir}\lib\ag-sdk-biz.jar
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java
deleted file mode 100644
index 40c55e8..0000000
--- a/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java
+++ /dev/null
@@ -1,30 +0,0 @@
-//package com.casic.missiles;
-//
-//import com.casic.missiles.netty.SensorhubServer;
-//import lombok.extern.slf4j.Slf4j;
-//import org.mybatis.spring.annotation.MapperScan;
-//import org.springframework.beans.factory.annotation.Autowired;
-//import org.springframework.boot.CommandLineRunner;
-//import org.springframework.boot.SpringApplication;
-//import org.springframework.boot.autoconfigure.SpringBootApplication;
-//import org.springframework.cache.annotation.EnableCaching;
-//
-//
-//@SpringBootApplication(scanBasePackages = "com.casic.missiles")
-//@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"})
-//@EnableCaching //开启缓存
-//@Slf4j
-//public class ServerApplication implements CommandLineRunner {
-//
-// @Autowired
-// private SensorhubServer nettyServer;
-// public static void main(String[] args) {
-// SpringApplication.run(ServerApplication.class, args);
-// }
-//
-// @Override
-// public void run(String... args) {
-// this.nettyServer.startServer();
-// }
-//
-//}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java b/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java
new file mode 100644
index 0000000..8f90fd9
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java
@@ -0,0 +1,96 @@
+package com.casic.missiles.controller;
+
+import com.alibaba.fastjson.JSONObject;
+import com.casic.missiles.frame.BirmmBaseFrame;
+import com.casic.missiles.model.response.ResponseData;
+import com.casic.missiles.service.IGeneralService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.tomcat.util.buf.HexUtils;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.util.Base64;
+import java.util.Map;
+
+@RestController
+@Slf4j
+public class GeneralDataReceiver {
+
+ @Resource
+ IGeneralService defaultService;
+
+ @RequestMapping("/aep/data/string")
+ public Object aepDataString(@RequestBody Map dataMap) {
+ log.info("收到AEP平台推送消息:{}", JSONObject.toJSONString(dataMap));
+ log.debug("deviceId: {}, productId: {}, IMEI: {}, timestamp: {}", dataMap.get("deviceId"), dataMap.get("productId"), dataMap.get("IMEI"), dataMap.get("timestamp"));
+
+ // 从推送的数据中获取消息帧
+ String frameStr = new String(getFrameStringFromData(dataMap));
+ log.info("字符串消息帧:{}", frameStr);
+
+ return ResponseData.success();
+ }
+
+ @RequestMapping("/aep/data/hex")
+ public Object aepDataHex(@RequestBody Map dataMap) {
+ log.info("收到AEP平台推送消息:{}", JSONObject.toJSONString(dataMap));
+ log.debug("deviceId: {}, productId: {}, IMEI: {}, timestamp: {}", dataMap.get("deviceId"), dataMap.get("productId"), dataMap.get("IMEI"), dataMap.get("timestamp"));
+
+ // 从推送的数据中获取消息帧
+ byte[] frameBytes = getFrameStringFromData(dataMap);
+ log.info("HEX字节消息帧:{}", HexUtils.toHexString(frameBytes).toUpperCase());
+
+ BirmmBaseFrame birmmFrame = defaultService.dataParse(frameBytes);
+ if (birmmFrame != null) {
+ log.info("HEX字节消息解析成功:{}", birmmFrame);
+ }
+
+ // 返回给电信AEP平台
+ return ResponseData.success();
+ }
+
+ private byte[] getFrameStringFromData(Map dataMap) {
+ byte[] frameStr = new byte[]{};
+
+ if (!dataMap.containsKey("payload")) {
+ log.error("消息帧不含payload字段");
+ return frameStr;
+ }
+
+ // 判断是否有profile
+ boolean hasProfile = false;
+ if (dataMap.containsKey("profile")) {
+ hasProfile = (Boolean) dataMap.get("profile");
+ }
+
+ JSONObject payload = (JSONObject) dataMap.get("payload");
+ // base64格式的消息 电信平台推送的内容
+ String dataBase64 = "";
+ if (hasProfile) {
+ if (!payload.containsKey("serviceData")) {
+ log.error("payload字段中不含serviceData字段");
+ } else {
+ JSONObject serviceData = payload.getJSONObject("serviceData");
+ if (!serviceData.containsKey("Value")) {
+ log.error("serviceData字段中不含Value字段");
+ } else {
+ dataBase64 = serviceData.getString("Value");
+ }
+ }
+ } else {
+ if (payload.containsKey("APPdata")) {
+ dataBase64 = payload.getString("APPdata");
+ } else {
+ log.error("payload字段中不含APPdata字段");
+ }
+ }
+
+ if (!dataBase64.isEmpty()) {
+ frameStr = Base64.getDecoder().decode(dataBase64); // base64解码
+ }
+
+ return frameStr;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java
new file mode 100644
index 0000000..ae6706a
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java
@@ -0,0 +1,40 @@
+package com.casic.missiles.frame;
+
+import lombok.Data;
+import java.util.List;
+
+@Data
+public class BirmmBaseFrame {
+
+ // 前导码 固定为A3
+ final String PRE_CODE = "A3";
+
+ // 协议版本 固定为20
+ final String VERSION = "20";
+
+ // 帧长度 后续到CRC字段前的字节总长度 不包括长度字段和CRC字段
+ int length;
+
+ // 设备编号
+ String devCode;
+
+ // 通信方式
+ String communicationType;
+
+ // 目标节点地址
+ String destinationAddr;
+
+ // PDU类型
+ String pduType;
+
+ // 序号
+ String sequence;
+
+ // 业务字段List
+ String tagListString;
+
+ List tagList;
+
+ // CRC
+ String crc;
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java
new file mode 100644
index 0000000..2285f9a
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java
@@ -0,0 +1,11 @@
+package com.casic.missiles.frame;
+
+import lombok.Data;
+
+@Data
+public class BirmmBaseTag {
+
+ private String oid;
+ private int tagLen;
+ private String valueStr;
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java
new file mode 100644
index 0000000..b1fd65c
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java
@@ -0,0 +1,9 @@
+package com.casic.missiles.frame;
+
+public class BirmmFrameBuilderFactory {
+
+ public static BirmmBaseFrame createBirmmFrame(String pduType) {
+
+ return null;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmTagBuilderFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmTagBuilderFactory.java
new file mode 100644
index 0000000..95ebdab
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmTagBuilderFactory.java
@@ -0,0 +1,33 @@
+package com.casic.missiles.frame;
+
+import com.casic.missiles.enums.BirmmTagAttributeEnums;
+import com.casic.missiles.frame.commanTag.*;
+
+public class BirmmTagBuilderFactory {
+
+ public static BirmmBaseTag createTagByOid(String oid) {
+ BirmmTagAttributeEnums tag = BirmmTagAttributeEnums.toType(oid);
+ if (null != tag) {
+ switch (tag) {
+ case CELL_TAG:
+ return new CellTag();
+
+ case DATE_TAG:
+ return new DateTag();
+
+ case PIC_TAG:
+ return new PCITag();
+
+ case SNR_TAG:
+ return new SNRTag();
+
+ case RSRP_TAG:
+ return new RSRPTag();
+
+ default:
+ return null;
+ }
+ }
+ return null;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/CellTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/CellTag.java
new file mode 100644
index 0000000..b0e0360
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/CellTag.java
@@ -0,0 +1,20 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class CellTag extends BirmmBaseTag {
+
+ final String CELL_TAG_OID = "60000020";
+
+ int cellVal;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ cellVal = Integer.parseInt(valueStr, 16);
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/DateTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/DateTag.java
new file mode 100644
index 0000000..e8c5db4
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/DateTag.java
@@ -0,0 +1,30 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.time.LocalDate;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class DateTag extends BirmmBaseTag {
+
+ final String DATE_TAG_OID = "10000050";
+
+ LocalDate date;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ String hexY = valueStr.substring(0, 2);
+ String hexM = valueStr.substring(2, 4);
+ String hexD = valueStr.substring(4, 6);
+
+ date = LocalDate.now();
+ date = date.withYear(BytesUtil.hexStringToUInt(hexY) + 2000);
+ date = date.withMonth(BytesUtil.hexStringToUInt(hexM));
+ date = date.withDayOfMonth(BytesUtil.hexStringToUInt(hexD));
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/PCITag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/PCITag.java
new file mode 100644
index 0000000..4433cea
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/PCITag.java
@@ -0,0 +1,22 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class PCITag extends BirmmBaseTag {
+
+ final String PCI_TAG_OID = "60000511";
+
+ // TYPE_U16整型,主小区物理小区号PCI,范围: 0 – 503
+ int pci;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ pci = BytesUtil.hexStringToUInt(valueStr);
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/RSRPTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/RSRPTag.java
new file mode 100644
index 0000000..d1bb0a8
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/RSRPTag.java
@@ -0,0 +1,22 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class RSRPTag extends BirmmBaseTag {
+
+ final String RSRP_TAG_OID = "60000513";
+
+ //带符号整型,主小区RSRP值,单位dBm。仅在RRC-IDLE状态时可用 -140 ~ -40 越大越好
+ int rsrp;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ rsrp = BytesUtil.hexStringToSInt(valueStr);
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/SNRTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/SNRTag.java
new file mode 100644
index 0000000..3040799
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/SNRTag.java
@@ -0,0 +1,22 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class SNRTag extends BirmmBaseTag {
+
+ final String SNR_TAG_OID = "60000516";
+
+ //带符号整型,主小区lart SNR值,单位dB。仅在RRC-IDLE状态时可用 -20 ~ 50 越大越好
+ int snr;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ snr = BytesUtil.hexStringToSInt(valueStr);
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/BirmmProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/BirmmProtocolParser.java
new file mode 100644
index 0000000..d29e372
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/BirmmProtocolParser.java
@@ -0,0 +1,38 @@
+package com.casic.missiles.parser;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+
+import java.util.List;
+
+/**
+ * BIRMM系列设备
+ * 一般设备协议解析
+ */
+public interface BirmmProtocolParser {
+
+ boolean preCheckFrame(byte[] frameBytes);
+
+ boolean validateCRC(byte[] frameBytes);
+
+ boolean validateLength(byte[] tagBytes, int length);
+
+ String getFrameHeader(byte[] frameBytes);
+
+ int getLength(byte[] frameBytes);
+
+ String getDevCode(byte[] frameBytes);
+
+ String getCommunicationType(byte[] frameBytes);
+
+ String getDestinationAddr(byte[] frameBytes);
+
+ String getPDUType(byte[] frameBytes);
+
+ String getSequence(byte[] frameBytes);
+
+ String getTagListString(byte[] frameBytes);
+ List getTagList(byte[] tagBytes);
+
+ String getCRC(byte[] frameBytes);
+ String getToBeVerifiedCRCBytes(byte[] frameBytes);
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/impl/BirmmProtocolParserImpl.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/impl/BirmmProtocolParserImpl.java
new file mode 100644
index 0000000..11c542d
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/impl/BirmmProtocolParserImpl.java
@@ -0,0 +1,145 @@
+package com.casic.missiles.parser.impl;
+
+import com.casic.missiles.enums.BirmmFrameAttributeEnums;
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.frame.BirmmTagBuilderFactory;
+import com.casic.missiles.parser.BirmmProtocolParser;
+import com.casic.missiles.parser.crc.CRCUtil;
+import com.casic.missiles.util.BytesUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Component
+@Slf4j
+public class BirmmProtocolParserImpl implements BirmmProtocolParser {
+ @Override
+ public boolean preCheckFrame(byte[] frameBytes) {
+ if (!checkPreCodeAndVersion(frameBytes)) {
+ log.error("帧头不符合协议:{}", getFrameHeader(frameBytes));
+ return false;
+ }
+
+ if (!preCheckLength(frameBytes)) {
+ log.error("帧长度不满足最低长度要求:{}", frameBytes.length);
+ return false;
+ }
+
+ if (!validateCRC(frameBytes)) {
+ log.error("CRC校验不通过:{}", getCRC(frameBytes));
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public boolean validateCRC(byte[] frameBytes) {
+ byte[] toBeVerifiedBytes = new byte[frameBytes.length - BirmmFrameAttributeEnums.CRC.getLength()];
+ System.arraycopy(frameBytes, 0, toBeVerifiedBytes, 0, toBeVerifiedBytes.length);
+
+ // 计算CRC值
+ CRCUtil crcUtil = new CRCUtil(CRCUtil.Parameters.CRC16MODBUS);
+ long crcVal = crcUtil.calculateCRC(toBeVerifiedBytes);
+ // 格式化输出
+ String crcStr = String.format("%0" + BirmmFrameAttributeEnums.CRC.getLength() * 2 + "X", crcVal);
+
+ return getCRC(frameBytes).equalsIgnoreCase(crcStr);
+ }
+
+ @Override
+ public boolean validateLength(byte[] tagBytes, int length) {
+ return false;
+ }
+
+ @Override
+ public String getFrameHeader(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.HEADER.getOffset(), BirmmFrameAttributeEnums.HEADER.getLength()); // byte[0] ~ byte[1] 表示A320
+ }
+
+ @Override
+ public int getLength(byte[] frameBytes) {
+ byte[] lengthBytes = new byte[BirmmFrameAttributeEnums.LENGTH.getLength()];
+ System.arraycopy(frameBytes, BirmmFrameAttributeEnums.LENGTH.getOffset(), lengthBytes, 0, lengthBytes.length); // byte[2] ~ byte[3] 表示长度
+
+ return BytesUtil.hexStringToUInt(lengthBytes);
+ }
+
+ @Override
+ public String getDevCode(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.DEVICE_CODE.getOffset(), BirmmFrameAttributeEnums.DEVICE_CODE.getLength()); // byte[4] ~ byte[10] 表示设备编号
+ }
+
+ @Override
+ public String getCommunicationType(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.COMM_TYPE.getOffset(), BirmmFrameAttributeEnums.COMM_TYPE.getLength()); // byte[11] 表示通信方式
+ }
+
+ @Override
+ public String getDestinationAddr(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.DEST_ADDR.getOffset(), BirmmFrameAttributeEnums.DEST_ADDR.getLength()); // byte[12] ~ byte[13] 表示目标节点地址
+ }
+
+ @Override
+ public String getPDUType(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.PDU_TYPE.getOffset(), BirmmFrameAttributeEnums.PDU_TYPE.getLength()); // byte[14] ~ byte[15] 表示PDUType
+ }
+
+ @Override
+ public String getSequence(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.SEQ.getOffset(), BirmmFrameAttributeEnums.SEQ.getLength()); // byte[16] 表示序号
+ }
+
+ @Override
+ public String getTagListString(byte[] frameBytes) {
+ // 帧结构其余字节长度为 18 = 1+1+2+6+1+2+2+1+2
+ return BytesUtil.extractHexString(frameBytes, 16, frameBytes.length - 18); // 从byte[16]开始
+ }
+
+ @Override
+ public List getTagList(byte[] tagBytes) {
+ // 必须包含OID和长度 4 + 2
+ if (tagBytes.length < 6) {
+ return null;
+ }
+ List tagList = new ArrayList<>();
+ int idx = 0;
+ while (idx + 6 < tagBytes.length) {
+ String oid = BytesUtil.extractHexString(tagBytes, idx, 4);
+ int tagLen = BytesUtil.hexStringToUInt(new byte[] {tagBytes[idx + 4], tagBytes[idx + 5]});
+ idx += 6;
+ if (tagLen + idx < tagBytes.length) {
+ BirmmBaseTag tagBase = BirmmTagBuilderFactory.createTagByOid(oid);
+ if (null != tagBase) {
+ String valStr = BytesUtil.extractHexString(tagBytes, idx, tagLen);
+ tagBase.setValueStr(valStr);
+
+ tagList.add(tagBase);
+ }
+ }
+ idx += tagLen;
+ }
+
+ return tagList;
+ }
+
+ private boolean checkPreCodeAndVersion(byte[] frameBytes) {
+ String headerStr = getFrameHeader(frameBytes);
+ return headerStr.equalsIgnoreCase(BirmmFrameAttributeEnums.HEADER.getDefaultStr());
+ }
+
+ private boolean preCheckLength(byte[] frameBytes) {
+ return frameBytes.length >= 18;
+ }
+
+ @Override
+ public String getCRC(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, frameBytes.length - 2, BirmmFrameAttributeEnums.CRC.getLength()); // 最后两个字节表示CRC校验码
+ }
+
+ @Override
+ public String getToBeVerifiedCRCBytes(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, 0, frameBytes.length - 2); // 所有字节都用于生成CRC校验码
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/service/GeneralServiceImpl.java b/sensorhub-core/src/main/java/com/casic/missiles/service/GeneralServiceImpl.java
new file mode 100644
index 0000000..118a8de
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/service/GeneralServiceImpl.java
@@ -0,0 +1,65 @@
+package com.casic.missiles.service;
+
+import com.casic.missiles.frame.BirmmBaseFrame;
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.frame.BirmmFrameBuilderFactory;
+import com.casic.missiles.parser.BirmmProtocolParser;
+import com.casic.missiles.parser.safe.SafeStrategy;
+import com.casic.missiles.parser.safe.impl.Sm4;
+import com.casic.missiles.util.SpringContextUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.tomcat.util.buf.HexUtils;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import javax.annotation.Resource;
+
+@Service
+@Slf4j
+public class GeneralServiceImpl implements IGeneralService {
+
+ @Resource
+ BirmmProtocolParser protocol;
+
+ @Override
+ public BirmmBaseFrame dataParse(byte[] frame) {
+ boolean frameValid = protocol.preCheckFrame(frame);
+ if (frameValid) {
+ // 解析长度
+ int length = protocol.getLength(frame);
+
+ // 解析得到设备编号
+ String devCode = protocol.getDevCode(frame);
+
+ // 解析通信方式
+ String commType = protocol.getCommunicationType(frame);
+
+ // 解析目标节点地址
+ String destAddr = protocol.getDestinationAddr(frame);
+
+ // 解析得到PDUType
+ String pduType = protocol.getPDUType(frame);
+
+ // 解析序号
+ String seq = protocol.getSequence(frame);
+
+ // 加密后的业务字段
+ String tagListStr = protocol.getTagListString(frame);
+
+ log.info("帧结构字段解析结果:[长度:{}],[设备编号:{}],[通信方式:{}],[目标节点地址:{}],[PDUType:{}],[序号:{}]", length, devCode, commType, destAddr, pduType, seq);
+
+ // 解密
+ SafeStrategy safeStrategy = SpringContextUtil.getBean(Sm4.class);
+ byte[] plainBytes = safeStrategy.decryption(tagListStr);
+ String plainTagListStr = HexUtils.toHexString(plainBytes).toUpperCase();
+
+ log.info("业务字段:{}", plainTagListStr);
+
+ // 获得业务字段tagList
+ List tagList = protocol.getTagList(plainBytes);
+ System.out.println(tagList.size());
+ }
+
+ return null;
+ }
+}
diff --git a/.gitignore b/.gitignore
index 9e20bc1..78302f1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,6 @@
.idea/
**/target/**
logs/
+*.log
+*.log.*
*.iml
diff --git a/casic-iot-web/src/main/resources/config/application-dev.yml b/casic-iot-web/src/main/resources/config/application-dev.yml
index 487fc70..c5c99b7 100644
--- a/casic-iot-web/src/main/resources/config/application-dev.yml
+++ b/casic-iot-web/src/main/resources/config/application-dev.yml
@@ -37,7 +37,7 @@
invalid-time: 86400
config-prefix: 'Casic:'
#kaptcha-open: false #是否开启登录时验证码 (true/false)
- no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/push/data,/push/test
+ no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/aep/**
#flowable数据源和多数据源配置
db:
init:
diff --git a/casic-iot-web/src/main/resources/config/logback-spring.xml b/casic-iot-web/src/main/resources/config/logback-spring.xml
index c0c7ac9..2d308a8 100644
--- a/casic-iot-web/src/main/resources/config/logback-spring.xml
+++ b/casic-iot-web/src/main/resources/config/logback-spring.xml
@@ -5,7 +5,7 @@
-
+
diff --git a/pom.xml b/pom.xml
index 3ad2470..a194074 100644
--- a/pom.xml
+++ b/pom.xml
@@ -49,6 +49,7 @@
2.0.0.alpha
2.5.4
2.5.6
+ 1.2.62
2.0.0.alpha
@@ -56,7 +57,11 @@
-
+
+ com.casic
+ casic-core
+ ${core.version}
+
com.baomidou
dynamic-datasource-spring-boot-starter
@@ -69,11 +74,11 @@
${fastjson.version}
-
- cn.hutool
- hutool-core
- 5.7.2
-
+
+
+
+
+
org.projectlombok
diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml
index d5118b4..8dcc497 100644
--- a/sensorhub-core/pom.xml
+++ b/sensorhub-core/pom.xml
@@ -35,17 +35,17 @@
com.ctg.ag
ctg-ag-sdk-core
-
2.8.0-SNAPSHOT
-
+ system
+ ${pom.basedir}\lib\ctg-ag-sdk-core-2.8.0.jar
com.ctg.ag
ag-sdk-biz
2.8.0-SNAPSHOT
-
-
+ system
+ ${pom.basedir}\lib\ag-sdk-biz.jar
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java
deleted file mode 100644
index 40c55e8..0000000
--- a/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java
+++ /dev/null
@@ -1,30 +0,0 @@
-//package com.casic.missiles;
-//
-//import com.casic.missiles.netty.SensorhubServer;
-//import lombok.extern.slf4j.Slf4j;
-//import org.mybatis.spring.annotation.MapperScan;
-//import org.springframework.beans.factory.annotation.Autowired;
-//import org.springframework.boot.CommandLineRunner;
-//import org.springframework.boot.SpringApplication;
-//import org.springframework.boot.autoconfigure.SpringBootApplication;
-//import org.springframework.cache.annotation.EnableCaching;
-//
-//
-//@SpringBootApplication(scanBasePackages = "com.casic.missiles")
-//@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"})
-//@EnableCaching //开启缓存
-//@Slf4j
-//public class ServerApplication implements CommandLineRunner {
-//
-// @Autowired
-// private SensorhubServer nettyServer;
-// public static void main(String[] args) {
-// SpringApplication.run(ServerApplication.class, args);
-// }
-//
-// @Override
-// public void run(String... args) {
-// this.nettyServer.startServer();
-// }
-//
-//}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java b/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java
new file mode 100644
index 0000000..8f90fd9
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java
@@ -0,0 +1,96 @@
+package com.casic.missiles.controller;
+
+import com.alibaba.fastjson.JSONObject;
+import com.casic.missiles.frame.BirmmBaseFrame;
+import com.casic.missiles.model.response.ResponseData;
+import com.casic.missiles.service.IGeneralService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.tomcat.util.buf.HexUtils;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.util.Base64;
+import java.util.Map;
+
+@RestController
+@Slf4j
+public class GeneralDataReceiver {
+
+ @Resource
+ IGeneralService defaultService;
+
+ @RequestMapping("/aep/data/string")
+ public Object aepDataString(@RequestBody Map dataMap) {
+ log.info("收到AEP平台推送消息:{}", JSONObject.toJSONString(dataMap));
+ log.debug("deviceId: {}, productId: {}, IMEI: {}, timestamp: {}", dataMap.get("deviceId"), dataMap.get("productId"), dataMap.get("IMEI"), dataMap.get("timestamp"));
+
+ // 从推送的数据中获取消息帧
+ String frameStr = new String(getFrameStringFromData(dataMap));
+ log.info("字符串消息帧:{}", frameStr);
+
+ return ResponseData.success();
+ }
+
+ @RequestMapping("/aep/data/hex")
+ public Object aepDataHex(@RequestBody Map dataMap) {
+ log.info("收到AEP平台推送消息:{}", JSONObject.toJSONString(dataMap));
+ log.debug("deviceId: {}, productId: {}, IMEI: {}, timestamp: {}", dataMap.get("deviceId"), dataMap.get("productId"), dataMap.get("IMEI"), dataMap.get("timestamp"));
+
+ // 从推送的数据中获取消息帧
+ byte[] frameBytes = getFrameStringFromData(dataMap);
+ log.info("HEX字节消息帧:{}", HexUtils.toHexString(frameBytes).toUpperCase());
+
+ BirmmBaseFrame birmmFrame = defaultService.dataParse(frameBytes);
+ if (birmmFrame != null) {
+ log.info("HEX字节消息解析成功:{}", birmmFrame);
+ }
+
+ // 返回给电信AEP平台
+ return ResponseData.success();
+ }
+
+ private byte[] getFrameStringFromData(Map dataMap) {
+ byte[] frameStr = new byte[]{};
+
+ if (!dataMap.containsKey("payload")) {
+ log.error("消息帧不含payload字段");
+ return frameStr;
+ }
+
+ // 判断是否有profile
+ boolean hasProfile = false;
+ if (dataMap.containsKey("profile")) {
+ hasProfile = (Boolean) dataMap.get("profile");
+ }
+
+ JSONObject payload = (JSONObject) dataMap.get("payload");
+ // base64格式的消息 电信平台推送的内容
+ String dataBase64 = "";
+ if (hasProfile) {
+ if (!payload.containsKey("serviceData")) {
+ log.error("payload字段中不含serviceData字段");
+ } else {
+ JSONObject serviceData = payload.getJSONObject("serviceData");
+ if (!serviceData.containsKey("Value")) {
+ log.error("serviceData字段中不含Value字段");
+ } else {
+ dataBase64 = serviceData.getString("Value");
+ }
+ }
+ } else {
+ if (payload.containsKey("APPdata")) {
+ dataBase64 = payload.getString("APPdata");
+ } else {
+ log.error("payload字段中不含APPdata字段");
+ }
+ }
+
+ if (!dataBase64.isEmpty()) {
+ frameStr = Base64.getDecoder().decode(dataBase64); // base64解码
+ }
+
+ return frameStr;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java
new file mode 100644
index 0000000..ae6706a
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java
@@ -0,0 +1,40 @@
+package com.casic.missiles.frame;
+
+import lombok.Data;
+import java.util.List;
+
+@Data
+public class BirmmBaseFrame {
+
+ // 前导码 固定为A3
+ final String PRE_CODE = "A3";
+
+ // 协议版本 固定为20
+ final String VERSION = "20";
+
+ // 帧长度 后续到CRC字段前的字节总长度 不包括长度字段和CRC字段
+ int length;
+
+ // 设备编号
+ String devCode;
+
+ // 通信方式
+ String communicationType;
+
+ // 目标节点地址
+ String destinationAddr;
+
+ // PDU类型
+ String pduType;
+
+ // 序号
+ String sequence;
+
+ // 业务字段List
+ String tagListString;
+
+ List tagList;
+
+ // CRC
+ String crc;
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java
new file mode 100644
index 0000000..2285f9a
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java
@@ -0,0 +1,11 @@
+package com.casic.missiles.frame;
+
+import lombok.Data;
+
+@Data
+public class BirmmBaseTag {
+
+ private String oid;
+ private int tagLen;
+ private String valueStr;
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java
new file mode 100644
index 0000000..b1fd65c
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java
@@ -0,0 +1,9 @@
+package com.casic.missiles.frame;
+
+public class BirmmFrameBuilderFactory {
+
+ public static BirmmBaseFrame createBirmmFrame(String pduType) {
+
+ return null;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmTagBuilderFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmTagBuilderFactory.java
new file mode 100644
index 0000000..95ebdab
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmTagBuilderFactory.java
@@ -0,0 +1,33 @@
+package com.casic.missiles.frame;
+
+import com.casic.missiles.enums.BirmmTagAttributeEnums;
+import com.casic.missiles.frame.commanTag.*;
+
+public class BirmmTagBuilderFactory {
+
+ public static BirmmBaseTag createTagByOid(String oid) {
+ BirmmTagAttributeEnums tag = BirmmTagAttributeEnums.toType(oid);
+ if (null != tag) {
+ switch (tag) {
+ case CELL_TAG:
+ return new CellTag();
+
+ case DATE_TAG:
+ return new DateTag();
+
+ case PIC_TAG:
+ return new PCITag();
+
+ case SNR_TAG:
+ return new SNRTag();
+
+ case RSRP_TAG:
+ return new RSRPTag();
+
+ default:
+ return null;
+ }
+ }
+ return null;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/CellTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/CellTag.java
new file mode 100644
index 0000000..b0e0360
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/CellTag.java
@@ -0,0 +1,20 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class CellTag extends BirmmBaseTag {
+
+ final String CELL_TAG_OID = "60000020";
+
+ int cellVal;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ cellVal = Integer.parseInt(valueStr, 16);
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/DateTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/DateTag.java
new file mode 100644
index 0000000..e8c5db4
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/DateTag.java
@@ -0,0 +1,30 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.time.LocalDate;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class DateTag extends BirmmBaseTag {
+
+ final String DATE_TAG_OID = "10000050";
+
+ LocalDate date;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ String hexY = valueStr.substring(0, 2);
+ String hexM = valueStr.substring(2, 4);
+ String hexD = valueStr.substring(4, 6);
+
+ date = LocalDate.now();
+ date = date.withYear(BytesUtil.hexStringToUInt(hexY) + 2000);
+ date = date.withMonth(BytesUtil.hexStringToUInt(hexM));
+ date = date.withDayOfMonth(BytesUtil.hexStringToUInt(hexD));
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/PCITag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/PCITag.java
new file mode 100644
index 0000000..4433cea
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/PCITag.java
@@ -0,0 +1,22 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class PCITag extends BirmmBaseTag {
+
+ final String PCI_TAG_OID = "60000511";
+
+ // TYPE_U16整型,主小区物理小区号PCI,范围: 0 – 503
+ int pci;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ pci = BytesUtil.hexStringToUInt(valueStr);
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/RSRPTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/RSRPTag.java
new file mode 100644
index 0000000..d1bb0a8
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/RSRPTag.java
@@ -0,0 +1,22 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class RSRPTag extends BirmmBaseTag {
+
+ final String RSRP_TAG_OID = "60000513";
+
+ //带符号整型,主小区RSRP值,单位dBm。仅在RRC-IDLE状态时可用 -140 ~ -40 越大越好
+ int rsrp;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ rsrp = BytesUtil.hexStringToSInt(valueStr);
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/SNRTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/SNRTag.java
new file mode 100644
index 0000000..3040799
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/SNRTag.java
@@ -0,0 +1,22 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class SNRTag extends BirmmBaseTag {
+
+ final String SNR_TAG_OID = "60000516";
+
+ //带符号整型,主小区lart SNR值,单位dB。仅在RRC-IDLE状态时可用 -20 ~ 50 越大越好
+ int snr;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ snr = BytesUtil.hexStringToSInt(valueStr);
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/BirmmProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/BirmmProtocolParser.java
new file mode 100644
index 0000000..d29e372
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/BirmmProtocolParser.java
@@ -0,0 +1,38 @@
+package com.casic.missiles.parser;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+
+import java.util.List;
+
+/**
+ * BIRMM系列设备
+ * 一般设备协议解析
+ */
+public interface BirmmProtocolParser {
+
+ boolean preCheckFrame(byte[] frameBytes);
+
+ boolean validateCRC(byte[] frameBytes);
+
+ boolean validateLength(byte[] tagBytes, int length);
+
+ String getFrameHeader(byte[] frameBytes);
+
+ int getLength(byte[] frameBytes);
+
+ String getDevCode(byte[] frameBytes);
+
+ String getCommunicationType(byte[] frameBytes);
+
+ String getDestinationAddr(byte[] frameBytes);
+
+ String getPDUType(byte[] frameBytes);
+
+ String getSequence(byte[] frameBytes);
+
+ String getTagListString(byte[] frameBytes);
+ List getTagList(byte[] tagBytes);
+
+ String getCRC(byte[] frameBytes);
+ String getToBeVerifiedCRCBytes(byte[] frameBytes);
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/impl/BirmmProtocolParserImpl.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/impl/BirmmProtocolParserImpl.java
new file mode 100644
index 0000000..11c542d
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/impl/BirmmProtocolParserImpl.java
@@ -0,0 +1,145 @@
+package com.casic.missiles.parser.impl;
+
+import com.casic.missiles.enums.BirmmFrameAttributeEnums;
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.frame.BirmmTagBuilderFactory;
+import com.casic.missiles.parser.BirmmProtocolParser;
+import com.casic.missiles.parser.crc.CRCUtil;
+import com.casic.missiles.util.BytesUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Component
+@Slf4j
+public class BirmmProtocolParserImpl implements BirmmProtocolParser {
+ @Override
+ public boolean preCheckFrame(byte[] frameBytes) {
+ if (!checkPreCodeAndVersion(frameBytes)) {
+ log.error("帧头不符合协议:{}", getFrameHeader(frameBytes));
+ return false;
+ }
+
+ if (!preCheckLength(frameBytes)) {
+ log.error("帧长度不满足最低长度要求:{}", frameBytes.length);
+ return false;
+ }
+
+ if (!validateCRC(frameBytes)) {
+ log.error("CRC校验不通过:{}", getCRC(frameBytes));
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public boolean validateCRC(byte[] frameBytes) {
+ byte[] toBeVerifiedBytes = new byte[frameBytes.length - BirmmFrameAttributeEnums.CRC.getLength()];
+ System.arraycopy(frameBytes, 0, toBeVerifiedBytes, 0, toBeVerifiedBytes.length);
+
+ // 计算CRC值
+ CRCUtil crcUtil = new CRCUtil(CRCUtil.Parameters.CRC16MODBUS);
+ long crcVal = crcUtil.calculateCRC(toBeVerifiedBytes);
+ // 格式化输出
+ String crcStr = String.format("%0" + BirmmFrameAttributeEnums.CRC.getLength() * 2 + "X", crcVal);
+
+ return getCRC(frameBytes).equalsIgnoreCase(crcStr);
+ }
+
+ @Override
+ public boolean validateLength(byte[] tagBytes, int length) {
+ return false;
+ }
+
+ @Override
+ public String getFrameHeader(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.HEADER.getOffset(), BirmmFrameAttributeEnums.HEADER.getLength()); // byte[0] ~ byte[1] 表示A320
+ }
+
+ @Override
+ public int getLength(byte[] frameBytes) {
+ byte[] lengthBytes = new byte[BirmmFrameAttributeEnums.LENGTH.getLength()];
+ System.arraycopy(frameBytes, BirmmFrameAttributeEnums.LENGTH.getOffset(), lengthBytes, 0, lengthBytes.length); // byte[2] ~ byte[3] 表示长度
+
+ return BytesUtil.hexStringToUInt(lengthBytes);
+ }
+
+ @Override
+ public String getDevCode(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.DEVICE_CODE.getOffset(), BirmmFrameAttributeEnums.DEVICE_CODE.getLength()); // byte[4] ~ byte[10] 表示设备编号
+ }
+
+ @Override
+ public String getCommunicationType(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.COMM_TYPE.getOffset(), BirmmFrameAttributeEnums.COMM_TYPE.getLength()); // byte[11] 表示通信方式
+ }
+
+ @Override
+ public String getDestinationAddr(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.DEST_ADDR.getOffset(), BirmmFrameAttributeEnums.DEST_ADDR.getLength()); // byte[12] ~ byte[13] 表示目标节点地址
+ }
+
+ @Override
+ public String getPDUType(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.PDU_TYPE.getOffset(), BirmmFrameAttributeEnums.PDU_TYPE.getLength()); // byte[14] ~ byte[15] 表示PDUType
+ }
+
+ @Override
+ public String getSequence(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.SEQ.getOffset(), BirmmFrameAttributeEnums.SEQ.getLength()); // byte[16] 表示序号
+ }
+
+ @Override
+ public String getTagListString(byte[] frameBytes) {
+ // 帧结构其余字节长度为 18 = 1+1+2+6+1+2+2+1+2
+ return BytesUtil.extractHexString(frameBytes, 16, frameBytes.length - 18); // 从byte[16]开始
+ }
+
+ @Override
+ public List getTagList(byte[] tagBytes) {
+ // 必须包含OID和长度 4 + 2
+ if (tagBytes.length < 6) {
+ return null;
+ }
+ List tagList = new ArrayList<>();
+ int idx = 0;
+ while (idx + 6 < tagBytes.length) {
+ String oid = BytesUtil.extractHexString(tagBytes, idx, 4);
+ int tagLen = BytesUtil.hexStringToUInt(new byte[] {tagBytes[idx + 4], tagBytes[idx + 5]});
+ idx += 6;
+ if (tagLen + idx < tagBytes.length) {
+ BirmmBaseTag tagBase = BirmmTagBuilderFactory.createTagByOid(oid);
+ if (null != tagBase) {
+ String valStr = BytesUtil.extractHexString(tagBytes, idx, tagLen);
+ tagBase.setValueStr(valStr);
+
+ tagList.add(tagBase);
+ }
+ }
+ idx += tagLen;
+ }
+
+ return tagList;
+ }
+
+ private boolean checkPreCodeAndVersion(byte[] frameBytes) {
+ String headerStr = getFrameHeader(frameBytes);
+ return headerStr.equalsIgnoreCase(BirmmFrameAttributeEnums.HEADER.getDefaultStr());
+ }
+
+ private boolean preCheckLength(byte[] frameBytes) {
+ return frameBytes.length >= 18;
+ }
+
+ @Override
+ public String getCRC(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, frameBytes.length - 2, BirmmFrameAttributeEnums.CRC.getLength()); // 最后两个字节表示CRC校验码
+ }
+
+ @Override
+ public String getToBeVerifiedCRCBytes(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, 0, frameBytes.length - 2); // 所有字节都用于生成CRC校验码
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/service/GeneralServiceImpl.java b/sensorhub-core/src/main/java/com/casic/missiles/service/GeneralServiceImpl.java
new file mode 100644
index 0000000..118a8de
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/service/GeneralServiceImpl.java
@@ -0,0 +1,65 @@
+package com.casic.missiles.service;
+
+import com.casic.missiles.frame.BirmmBaseFrame;
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.frame.BirmmFrameBuilderFactory;
+import com.casic.missiles.parser.BirmmProtocolParser;
+import com.casic.missiles.parser.safe.SafeStrategy;
+import com.casic.missiles.parser.safe.impl.Sm4;
+import com.casic.missiles.util.SpringContextUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.tomcat.util.buf.HexUtils;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import javax.annotation.Resource;
+
+@Service
+@Slf4j
+public class GeneralServiceImpl implements IGeneralService {
+
+ @Resource
+ BirmmProtocolParser protocol;
+
+ @Override
+ public BirmmBaseFrame dataParse(byte[] frame) {
+ boolean frameValid = protocol.preCheckFrame(frame);
+ if (frameValid) {
+ // 解析长度
+ int length = protocol.getLength(frame);
+
+ // 解析得到设备编号
+ String devCode = protocol.getDevCode(frame);
+
+ // 解析通信方式
+ String commType = protocol.getCommunicationType(frame);
+
+ // 解析目标节点地址
+ String destAddr = protocol.getDestinationAddr(frame);
+
+ // 解析得到PDUType
+ String pduType = protocol.getPDUType(frame);
+
+ // 解析序号
+ String seq = protocol.getSequence(frame);
+
+ // 加密后的业务字段
+ String tagListStr = protocol.getTagListString(frame);
+
+ log.info("帧结构字段解析结果:[长度:{}],[设备编号:{}],[通信方式:{}],[目标节点地址:{}],[PDUType:{}],[序号:{}]", length, devCode, commType, destAddr, pduType, seq);
+
+ // 解密
+ SafeStrategy safeStrategy = SpringContextUtil.getBean(Sm4.class);
+ byte[] plainBytes = safeStrategy.decryption(tagListStr);
+ String plainTagListStr = HexUtils.toHexString(plainBytes).toUpperCase();
+
+ log.info("业务字段:{}", plainTagListStr);
+
+ // 获得业务字段tagList
+ List tagList = protocol.getTagList(plainBytes);
+ System.out.println(tagList.size());
+ }
+
+ return null;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/service/IGeneralService.java b/sensorhub-core/src/main/java/com/casic/missiles/service/IGeneralService.java
new file mode 100644
index 0000000..5e27b33
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/service/IGeneralService.java
@@ -0,0 +1,8 @@
+package com.casic.missiles.service;
+
+import com.casic.missiles.frame.BirmmBaseFrame;
+
+public interface IGeneralService {
+
+ BirmmBaseFrame dataParse(byte[] frame);
+}
diff --git a/.gitignore b/.gitignore
index 9e20bc1..78302f1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,6 @@
.idea/
**/target/**
logs/
+*.log
+*.log.*
*.iml
diff --git a/casic-iot-web/src/main/resources/config/application-dev.yml b/casic-iot-web/src/main/resources/config/application-dev.yml
index 487fc70..c5c99b7 100644
--- a/casic-iot-web/src/main/resources/config/application-dev.yml
+++ b/casic-iot-web/src/main/resources/config/application-dev.yml
@@ -37,7 +37,7 @@
invalid-time: 86400
config-prefix: 'Casic:'
#kaptcha-open: false #是否开启登录时验证码 (true/false)
- no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/push/data,/push/test
+ no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/aep/**
#flowable数据源和多数据源配置
db:
init:
diff --git a/casic-iot-web/src/main/resources/config/logback-spring.xml b/casic-iot-web/src/main/resources/config/logback-spring.xml
index c0c7ac9..2d308a8 100644
--- a/casic-iot-web/src/main/resources/config/logback-spring.xml
+++ b/casic-iot-web/src/main/resources/config/logback-spring.xml
@@ -5,7 +5,7 @@
-
+
diff --git a/pom.xml b/pom.xml
index 3ad2470..a194074 100644
--- a/pom.xml
+++ b/pom.xml
@@ -49,6 +49,7 @@
2.0.0.alpha
2.5.4
2.5.6
+ 1.2.62
2.0.0.alpha
@@ -56,7 +57,11 @@
-
+
+ com.casic
+ casic-core
+ ${core.version}
+
com.baomidou
dynamic-datasource-spring-boot-starter
@@ -69,11 +74,11 @@
${fastjson.version}
-
- cn.hutool
- hutool-core
- 5.7.2
-
+
+
+
+
+
org.projectlombok
diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml
index d5118b4..8dcc497 100644
--- a/sensorhub-core/pom.xml
+++ b/sensorhub-core/pom.xml
@@ -35,17 +35,17 @@
com.ctg.ag
ctg-ag-sdk-core
-
2.8.0-SNAPSHOT
-
+ system
+ ${pom.basedir}\lib\ctg-ag-sdk-core-2.8.0.jar
com.ctg.ag
ag-sdk-biz
2.8.0-SNAPSHOT
-
-
+ system
+ ${pom.basedir}\lib\ag-sdk-biz.jar
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java
deleted file mode 100644
index 40c55e8..0000000
--- a/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java
+++ /dev/null
@@ -1,30 +0,0 @@
-//package com.casic.missiles;
-//
-//import com.casic.missiles.netty.SensorhubServer;
-//import lombok.extern.slf4j.Slf4j;
-//import org.mybatis.spring.annotation.MapperScan;
-//import org.springframework.beans.factory.annotation.Autowired;
-//import org.springframework.boot.CommandLineRunner;
-//import org.springframework.boot.SpringApplication;
-//import org.springframework.boot.autoconfigure.SpringBootApplication;
-//import org.springframework.cache.annotation.EnableCaching;
-//
-//
-//@SpringBootApplication(scanBasePackages = "com.casic.missiles")
-//@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"})
-//@EnableCaching //开启缓存
-//@Slf4j
-//public class ServerApplication implements CommandLineRunner {
-//
-// @Autowired
-// private SensorhubServer nettyServer;
-// public static void main(String[] args) {
-// SpringApplication.run(ServerApplication.class, args);
-// }
-//
-// @Override
-// public void run(String... args) {
-// this.nettyServer.startServer();
-// }
-//
-//}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java b/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java
new file mode 100644
index 0000000..8f90fd9
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java
@@ -0,0 +1,96 @@
+package com.casic.missiles.controller;
+
+import com.alibaba.fastjson.JSONObject;
+import com.casic.missiles.frame.BirmmBaseFrame;
+import com.casic.missiles.model.response.ResponseData;
+import com.casic.missiles.service.IGeneralService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.tomcat.util.buf.HexUtils;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.util.Base64;
+import java.util.Map;
+
+@RestController
+@Slf4j
+public class GeneralDataReceiver {
+
+ @Resource
+ IGeneralService defaultService;
+
+ @RequestMapping("/aep/data/string")
+ public Object aepDataString(@RequestBody Map dataMap) {
+ log.info("收到AEP平台推送消息:{}", JSONObject.toJSONString(dataMap));
+ log.debug("deviceId: {}, productId: {}, IMEI: {}, timestamp: {}", dataMap.get("deviceId"), dataMap.get("productId"), dataMap.get("IMEI"), dataMap.get("timestamp"));
+
+ // 从推送的数据中获取消息帧
+ String frameStr = new String(getFrameStringFromData(dataMap));
+ log.info("字符串消息帧:{}", frameStr);
+
+ return ResponseData.success();
+ }
+
+ @RequestMapping("/aep/data/hex")
+ public Object aepDataHex(@RequestBody Map dataMap) {
+ log.info("收到AEP平台推送消息:{}", JSONObject.toJSONString(dataMap));
+ log.debug("deviceId: {}, productId: {}, IMEI: {}, timestamp: {}", dataMap.get("deviceId"), dataMap.get("productId"), dataMap.get("IMEI"), dataMap.get("timestamp"));
+
+ // 从推送的数据中获取消息帧
+ byte[] frameBytes = getFrameStringFromData(dataMap);
+ log.info("HEX字节消息帧:{}", HexUtils.toHexString(frameBytes).toUpperCase());
+
+ BirmmBaseFrame birmmFrame = defaultService.dataParse(frameBytes);
+ if (birmmFrame != null) {
+ log.info("HEX字节消息解析成功:{}", birmmFrame);
+ }
+
+ // 返回给电信AEP平台
+ return ResponseData.success();
+ }
+
+ private byte[] getFrameStringFromData(Map dataMap) {
+ byte[] frameStr = new byte[]{};
+
+ if (!dataMap.containsKey("payload")) {
+ log.error("消息帧不含payload字段");
+ return frameStr;
+ }
+
+ // 判断是否有profile
+ boolean hasProfile = false;
+ if (dataMap.containsKey("profile")) {
+ hasProfile = (Boolean) dataMap.get("profile");
+ }
+
+ JSONObject payload = (JSONObject) dataMap.get("payload");
+ // base64格式的消息 电信平台推送的内容
+ String dataBase64 = "";
+ if (hasProfile) {
+ if (!payload.containsKey("serviceData")) {
+ log.error("payload字段中不含serviceData字段");
+ } else {
+ JSONObject serviceData = payload.getJSONObject("serviceData");
+ if (!serviceData.containsKey("Value")) {
+ log.error("serviceData字段中不含Value字段");
+ } else {
+ dataBase64 = serviceData.getString("Value");
+ }
+ }
+ } else {
+ if (payload.containsKey("APPdata")) {
+ dataBase64 = payload.getString("APPdata");
+ } else {
+ log.error("payload字段中不含APPdata字段");
+ }
+ }
+
+ if (!dataBase64.isEmpty()) {
+ frameStr = Base64.getDecoder().decode(dataBase64); // base64解码
+ }
+
+ return frameStr;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java
new file mode 100644
index 0000000..ae6706a
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java
@@ -0,0 +1,40 @@
+package com.casic.missiles.frame;
+
+import lombok.Data;
+import java.util.List;
+
+@Data
+public class BirmmBaseFrame {
+
+ // 前导码 固定为A3
+ final String PRE_CODE = "A3";
+
+ // 协议版本 固定为20
+ final String VERSION = "20";
+
+ // 帧长度 后续到CRC字段前的字节总长度 不包括长度字段和CRC字段
+ int length;
+
+ // 设备编号
+ String devCode;
+
+ // 通信方式
+ String communicationType;
+
+ // 目标节点地址
+ String destinationAddr;
+
+ // PDU类型
+ String pduType;
+
+ // 序号
+ String sequence;
+
+ // 业务字段List
+ String tagListString;
+
+ List tagList;
+
+ // CRC
+ String crc;
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java
new file mode 100644
index 0000000..2285f9a
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java
@@ -0,0 +1,11 @@
+package com.casic.missiles.frame;
+
+import lombok.Data;
+
+@Data
+public class BirmmBaseTag {
+
+ private String oid;
+ private int tagLen;
+ private String valueStr;
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java
new file mode 100644
index 0000000..b1fd65c
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java
@@ -0,0 +1,9 @@
+package com.casic.missiles.frame;
+
+public class BirmmFrameBuilderFactory {
+
+ public static BirmmBaseFrame createBirmmFrame(String pduType) {
+
+ return null;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmTagBuilderFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmTagBuilderFactory.java
new file mode 100644
index 0000000..95ebdab
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmTagBuilderFactory.java
@@ -0,0 +1,33 @@
+package com.casic.missiles.frame;
+
+import com.casic.missiles.enums.BirmmTagAttributeEnums;
+import com.casic.missiles.frame.commanTag.*;
+
+public class BirmmTagBuilderFactory {
+
+ public static BirmmBaseTag createTagByOid(String oid) {
+ BirmmTagAttributeEnums tag = BirmmTagAttributeEnums.toType(oid);
+ if (null != tag) {
+ switch (tag) {
+ case CELL_TAG:
+ return new CellTag();
+
+ case DATE_TAG:
+ return new DateTag();
+
+ case PIC_TAG:
+ return new PCITag();
+
+ case SNR_TAG:
+ return new SNRTag();
+
+ case RSRP_TAG:
+ return new RSRPTag();
+
+ default:
+ return null;
+ }
+ }
+ return null;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/CellTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/CellTag.java
new file mode 100644
index 0000000..b0e0360
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/CellTag.java
@@ -0,0 +1,20 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class CellTag extends BirmmBaseTag {
+
+ final String CELL_TAG_OID = "60000020";
+
+ int cellVal;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ cellVal = Integer.parseInt(valueStr, 16);
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/DateTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/DateTag.java
new file mode 100644
index 0000000..e8c5db4
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/DateTag.java
@@ -0,0 +1,30 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.time.LocalDate;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class DateTag extends BirmmBaseTag {
+
+ final String DATE_TAG_OID = "10000050";
+
+ LocalDate date;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ String hexY = valueStr.substring(0, 2);
+ String hexM = valueStr.substring(2, 4);
+ String hexD = valueStr.substring(4, 6);
+
+ date = LocalDate.now();
+ date = date.withYear(BytesUtil.hexStringToUInt(hexY) + 2000);
+ date = date.withMonth(BytesUtil.hexStringToUInt(hexM));
+ date = date.withDayOfMonth(BytesUtil.hexStringToUInt(hexD));
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/PCITag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/PCITag.java
new file mode 100644
index 0000000..4433cea
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/PCITag.java
@@ -0,0 +1,22 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class PCITag extends BirmmBaseTag {
+
+ final String PCI_TAG_OID = "60000511";
+
+ // TYPE_U16整型,主小区物理小区号PCI,范围: 0 – 503
+ int pci;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ pci = BytesUtil.hexStringToUInt(valueStr);
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/RSRPTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/RSRPTag.java
new file mode 100644
index 0000000..d1bb0a8
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/RSRPTag.java
@@ -0,0 +1,22 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class RSRPTag extends BirmmBaseTag {
+
+ final String RSRP_TAG_OID = "60000513";
+
+ //带符号整型,主小区RSRP值,单位dBm。仅在RRC-IDLE状态时可用 -140 ~ -40 越大越好
+ int rsrp;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ rsrp = BytesUtil.hexStringToSInt(valueStr);
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/SNRTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/SNRTag.java
new file mode 100644
index 0000000..3040799
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/SNRTag.java
@@ -0,0 +1,22 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class SNRTag extends BirmmBaseTag {
+
+ final String SNR_TAG_OID = "60000516";
+
+ //带符号整型,主小区lart SNR值,单位dB。仅在RRC-IDLE状态时可用 -20 ~ 50 越大越好
+ int snr;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ snr = BytesUtil.hexStringToSInt(valueStr);
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/BirmmProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/BirmmProtocolParser.java
new file mode 100644
index 0000000..d29e372
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/BirmmProtocolParser.java
@@ -0,0 +1,38 @@
+package com.casic.missiles.parser;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+
+import java.util.List;
+
+/**
+ * BIRMM系列设备
+ * 一般设备协议解析
+ */
+public interface BirmmProtocolParser {
+
+ boolean preCheckFrame(byte[] frameBytes);
+
+ boolean validateCRC(byte[] frameBytes);
+
+ boolean validateLength(byte[] tagBytes, int length);
+
+ String getFrameHeader(byte[] frameBytes);
+
+ int getLength(byte[] frameBytes);
+
+ String getDevCode(byte[] frameBytes);
+
+ String getCommunicationType(byte[] frameBytes);
+
+ String getDestinationAddr(byte[] frameBytes);
+
+ String getPDUType(byte[] frameBytes);
+
+ String getSequence(byte[] frameBytes);
+
+ String getTagListString(byte[] frameBytes);
+ List getTagList(byte[] tagBytes);
+
+ String getCRC(byte[] frameBytes);
+ String getToBeVerifiedCRCBytes(byte[] frameBytes);
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/impl/BirmmProtocolParserImpl.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/impl/BirmmProtocolParserImpl.java
new file mode 100644
index 0000000..11c542d
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/impl/BirmmProtocolParserImpl.java
@@ -0,0 +1,145 @@
+package com.casic.missiles.parser.impl;
+
+import com.casic.missiles.enums.BirmmFrameAttributeEnums;
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.frame.BirmmTagBuilderFactory;
+import com.casic.missiles.parser.BirmmProtocolParser;
+import com.casic.missiles.parser.crc.CRCUtil;
+import com.casic.missiles.util.BytesUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Component
+@Slf4j
+public class BirmmProtocolParserImpl implements BirmmProtocolParser {
+ @Override
+ public boolean preCheckFrame(byte[] frameBytes) {
+ if (!checkPreCodeAndVersion(frameBytes)) {
+ log.error("帧头不符合协议:{}", getFrameHeader(frameBytes));
+ return false;
+ }
+
+ if (!preCheckLength(frameBytes)) {
+ log.error("帧长度不满足最低长度要求:{}", frameBytes.length);
+ return false;
+ }
+
+ if (!validateCRC(frameBytes)) {
+ log.error("CRC校验不通过:{}", getCRC(frameBytes));
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public boolean validateCRC(byte[] frameBytes) {
+ byte[] toBeVerifiedBytes = new byte[frameBytes.length - BirmmFrameAttributeEnums.CRC.getLength()];
+ System.arraycopy(frameBytes, 0, toBeVerifiedBytes, 0, toBeVerifiedBytes.length);
+
+ // 计算CRC值
+ CRCUtil crcUtil = new CRCUtil(CRCUtil.Parameters.CRC16MODBUS);
+ long crcVal = crcUtil.calculateCRC(toBeVerifiedBytes);
+ // 格式化输出
+ String crcStr = String.format("%0" + BirmmFrameAttributeEnums.CRC.getLength() * 2 + "X", crcVal);
+
+ return getCRC(frameBytes).equalsIgnoreCase(crcStr);
+ }
+
+ @Override
+ public boolean validateLength(byte[] tagBytes, int length) {
+ return false;
+ }
+
+ @Override
+ public String getFrameHeader(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.HEADER.getOffset(), BirmmFrameAttributeEnums.HEADER.getLength()); // byte[0] ~ byte[1] 表示A320
+ }
+
+ @Override
+ public int getLength(byte[] frameBytes) {
+ byte[] lengthBytes = new byte[BirmmFrameAttributeEnums.LENGTH.getLength()];
+ System.arraycopy(frameBytes, BirmmFrameAttributeEnums.LENGTH.getOffset(), lengthBytes, 0, lengthBytes.length); // byte[2] ~ byte[3] 表示长度
+
+ return BytesUtil.hexStringToUInt(lengthBytes);
+ }
+
+ @Override
+ public String getDevCode(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.DEVICE_CODE.getOffset(), BirmmFrameAttributeEnums.DEVICE_CODE.getLength()); // byte[4] ~ byte[10] 表示设备编号
+ }
+
+ @Override
+ public String getCommunicationType(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.COMM_TYPE.getOffset(), BirmmFrameAttributeEnums.COMM_TYPE.getLength()); // byte[11] 表示通信方式
+ }
+
+ @Override
+ public String getDestinationAddr(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.DEST_ADDR.getOffset(), BirmmFrameAttributeEnums.DEST_ADDR.getLength()); // byte[12] ~ byte[13] 表示目标节点地址
+ }
+
+ @Override
+ public String getPDUType(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.PDU_TYPE.getOffset(), BirmmFrameAttributeEnums.PDU_TYPE.getLength()); // byte[14] ~ byte[15] 表示PDUType
+ }
+
+ @Override
+ public String getSequence(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.SEQ.getOffset(), BirmmFrameAttributeEnums.SEQ.getLength()); // byte[16] 表示序号
+ }
+
+ @Override
+ public String getTagListString(byte[] frameBytes) {
+ // 帧结构其余字节长度为 18 = 1+1+2+6+1+2+2+1+2
+ return BytesUtil.extractHexString(frameBytes, 16, frameBytes.length - 18); // 从byte[16]开始
+ }
+
+ @Override
+ public List getTagList(byte[] tagBytes) {
+ // 必须包含OID和长度 4 + 2
+ if (tagBytes.length < 6) {
+ return null;
+ }
+ List tagList = new ArrayList<>();
+ int idx = 0;
+ while (idx + 6 < tagBytes.length) {
+ String oid = BytesUtil.extractHexString(tagBytes, idx, 4);
+ int tagLen = BytesUtil.hexStringToUInt(new byte[] {tagBytes[idx + 4], tagBytes[idx + 5]});
+ idx += 6;
+ if (tagLen + idx < tagBytes.length) {
+ BirmmBaseTag tagBase = BirmmTagBuilderFactory.createTagByOid(oid);
+ if (null != tagBase) {
+ String valStr = BytesUtil.extractHexString(tagBytes, idx, tagLen);
+ tagBase.setValueStr(valStr);
+
+ tagList.add(tagBase);
+ }
+ }
+ idx += tagLen;
+ }
+
+ return tagList;
+ }
+
+ private boolean checkPreCodeAndVersion(byte[] frameBytes) {
+ String headerStr = getFrameHeader(frameBytes);
+ return headerStr.equalsIgnoreCase(BirmmFrameAttributeEnums.HEADER.getDefaultStr());
+ }
+
+ private boolean preCheckLength(byte[] frameBytes) {
+ return frameBytes.length >= 18;
+ }
+
+ @Override
+ public String getCRC(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, frameBytes.length - 2, BirmmFrameAttributeEnums.CRC.getLength()); // 最后两个字节表示CRC校验码
+ }
+
+ @Override
+ public String getToBeVerifiedCRCBytes(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, 0, frameBytes.length - 2); // 所有字节都用于生成CRC校验码
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/service/GeneralServiceImpl.java b/sensorhub-core/src/main/java/com/casic/missiles/service/GeneralServiceImpl.java
new file mode 100644
index 0000000..118a8de
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/service/GeneralServiceImpl.java
@@ -0,0 +1,65 @@
+package com.casic.missiles.service;
+
+import com.casic.missiles.frame.BirmmBaseFrame;
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.frame.BirmmFrameBuilderFactory;
+import com.casic.missiles.parser.BirmmProtocolParser;
+import com.casic.missiles.parser.safe.SafeStrategy;
+import com.casic.missiles.parser.safe.impl.Sm4;
+import com.casic.missiles.util.SpringContextUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.tomcat.util.buf.HexUtils;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import javax.annotation.Resource;
+
+@Service
+@Slf4j
+public class GeneralServiceImpl implements IGeneralService {
+
+ @Resource
+ BirmmProtocolParser protocol;
+
+ @Override
+ public BirmmBaseFrame dataParse(byte[] frame) {
+ boolean frameValid = protocol.preCheckFrame(frame);
+ if (frameValid) {
+ // 解析长度
+ int length = protocol.getLength(frame);
+
+ // 解析得到设备编号
+ String devCode = protocol.getDevCode(frame);
+
+ // 解析通信方式
+ String commType = protocol.getCommunicationType(frame);
+
+ // 解析目标节点地址
+ String destAddr = protocol.getDestinationAddr(frame);
+
+ // 解析得到PDUType
+ String pduType = protocol.getPDUType(frame);
+
+ // 解析序号
+ String seq = protocol.getSequence(frame);
+
+ // 加密后的业务字段
+ String tagListStr = protocol.getTagListString(frame);
+
+ log.info("帧结构字段解析结果:[长度:{}],[设备编号:{}],[通信方式:{}],[目标节点地址:{}],[PDUType:{}],[序号:{}]", length, devCode, commType, destAddr, pduType, seq);
+
+ // 解密
+ SafeStrategy safeStrategy = SpringContextUtil.getBean(Sm4.class);
+ byte[] plainBytes = safeStrategy.decryption(tagListStr);
+ String plainTagListStr = HexUtils.toHexString(plainBytes).toUpperCase();
+
+ log.info("业务字段:{}", plainTagListStr);
+
+ // 获得业务字段tagList
+ List tagList = protocol.getTagList(plainBytes);
+ System.out.println(tagList.size());
+ }
+
+ return null;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/service/IGeneralService.java b/sensorhub-core/src/main/java/com/casic/missiles/service/IGeneralService.java
new file mode 100644
index 0000000..5e27b33
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/service/IGeneralService.java
@@ -0,0 +1,8 @@
+package com.casic.missiles.service;
+
+import com.casic.missiles.frame.BirmmBaseFrame;
+
+public interface IGeneralService {
+
+ BirmmBaseFrame dataParse(byte[] frame);
+}
diff --git a/sensorhub-support/pom.xml b/sensorhub-support/pom.xml
index 56d8813..abc3dda 100644
--- a/sensorhub-support/pom.xml
+++ b/sensorhub-support/pom.xml
@@ -26,6 +26,12 @@
+ com.alibaba
+ fastjson
+ ${fastjson.version}
+
+
+
org.apache.commons
commons-lang3
3.1
diff --git a/.gitignore b/.gitignore
index 9e20bc1..78302f1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,6 @@
.idea/
**/target/**
logs/
+*.log
+*.log.*
*.iml
diff --git a/casic-iot-web/src/main/resources/config/application-dev.yml b/casic-iot-web/src/main/resources/config/application-dev.yml
index 487fc70..c5c99b7 100644
--- a/casic-iot-web/src/main/resources/config/application-dev.yml
+++ b/casic-iot-web/src/main/resources/config/application-dev.yml
@@ -37,7 +37,7 @@
invalid-time: 86400
config-prefix: 'Casic:'
#kaptcha-open: false #是否开启登录时验证码 (true/false)
- no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/push/data,/push/test
+ no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/aep/**
#flowable数据源和多数据源配置
db:
init:
diff --git a/casic-iot-web/src/main/resources/config/logback-spring.xml b/casic-iot-web/src/main/resources/config/logback-spring.xml
index c0c7ac9..2d308a8 100644
--- a/casic-iot-web/src/main/resources/config/logback-spring.xml
+++ b/casic-iot-web/src/main/resources/config/logback-spring.xml
@@ -5,7 +5,7 @@
-
+
diff --git a/pom.xml b/pom.xml
index 3ad2470..a194074 100644
--- a/pom.xml
+++ b/pom.xml
@@ -49,6 +49,7 @@
2.0.0.alpha
2.5.4
2.5.6
+ 1.2.62
2.0.0.alpha
@@ -56,7 +57,11 @@
-
+
+ com.casic
+ casic-core
+ ${core.version}
+
com.baomidou
dynamic-datasource-spring-boot-starter
@@ -69,11 +74,11 @@
${fastjson.version}
-
- cn.hutool
- hutool-core
- 5.7.2
-
+
+
+
+
+
org.projectlombok
diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml
index d5118b4..8dcc497 100644
--- a/sensorhub-core/pom.xml
+++ b/sensorhub-core/pom.xml
@@ -35,17 +35,17 @@
com.ctg.ag
ctg-ag-sdk-core
-
2.8.0-SNAPSHOT
-
+ system
+ ${pom.basedir}\lib\ctg-ag-sdk-core-2.8.0.jar
com.ctg.ag
ag-sdk-biz
2.8.0-SNAPSHOT
-
-
+ system
+ ${pom.basedir}\lib\ag-sdk-biz.jar
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java
deleted file mode 100644
index 40c55e8..0000000
--- a/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java
+++ /dev/null
@@ -1,30 +0,0 @@
-//package com.casic.missiles;
-//
-//import com.casic.missiles.netty.SensorhubServer;
-//import lombok.extern.slf4j.Slf4j;
-//import org.mybatis.spring.annotation.MapperScan;
-//import org.springframework.beans.factory.annotation.Autowired;
-//import org.springframework.boot.CommandLineRunner;
-//import org.springframework.boot.SpringApplication;
-//import org.springframework.boot.autoconfigure.SpringBootApplication;
-//import org.springframework.cache.annotation.EnableCaching;
-//
-//
-//@SpringBootApplication(scanBasePackages = "com.casic.missiles")
-//@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"})
-//@EnableCaching //开启缓存
-//@Slf4j
-//public class ServerApplication implements CommandLineRunner {
-//
-// @Autowired
-// private SensorhubServer nettyServer;
-// public static void main(String[] args) {
-// SpringApplication.run(ServerApplication.class, args);
-// }
-//
-// @Override
-// public void run(String... args) {
-// this.nettyServer.startServer();
-// }
-//
-//}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java b/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java
new file mode 100644
index 0000000..8f90fd9
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java
@@ -0,0 +1,96 @@
+package com.casic.missiles.controller;
+
+import com.alibaba.fastjson.JSONObject;
+import com.casic.missiles.frame.BirmmBaseFrame;
+import com.casic.missiles.model.response.ResponseData;
+import com.casic.missiles.service.IGeneralService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.tomcat.util.buf.HexUtils;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.util.Base64;
+import java.util.Map;
+
+@RestController
+@Slf4j
+public class GeneralDataReceiver {
+
+ @Resource
+ IGeneralService defaultService;
+
+ @RequestMapping("/aep/data/string")
+ public Object aepDataString(@RequestBody Map dataMap) {
+ log.info("收到AEP平台推送消息:{}", JSONObject.toJSONString(dataMap));
+ log.debug("deviceId: {}, productId: {}, IMEI: {}, timestamp: {}", dataMap.get("deviceId"), dataMap.get("productId"), dataMap.get("IMEI"), dataMap.get("timestamp"));
+
+ // 从推送的数据中获取消息帧
+ String frameStr = new String(getFrameStringFromData(dataMap));
+ log.info("字符串消息帧:{}", frameStr);
+
+ return ResponseData.success();
+ }
+
+ @RequestMapping("/aep/data/hex")
+ public Object aepDataHex(@RequestBody Map dataMap) {
+ log.info("收到AEP平台推送消息:{}", JSONObject.toJSONString(dataMap));
+ log.debug("deviceId: {}, productId: {}, IMEI: {}, timestamp: {}", dataMap.get("deviceId"), dataMap.get("productId"), dataMap.get("IMEI"), dataMap.get("timestamp"));
+
+ // 从推送的数据中获取消息帧
+ byte[] frameBytes = getFrameStringFromData(dataMap);
+ log.info("HEX字节消息帧:{}", HexUtils.toHexString(frameBytes).toUpperCase());
+
+ BirmmBaseFrame birmmFrame = defaultService.dataParse(frameBytes);
+ if (birmmFrame != null) {
+ log.info("HEX字节消息解析成功:{}", birmmFrame);
+ }
+
+ // 返回给电信AEP平台
+ return ResponseData.success();
+ }
+
+ private byte[] getFrameStringFromData(Map dataMap) {
+ byte[] frameStr = new byte[]{};
+
+ if (!dataMap.containsKey("payload")) {
+ log.error("消息帧不含payload字段");
+ return frameStr;
+ }
+
+ // 判断是否有profile
+ boolean hasProfile = false;
+ if (dataMap.containsKey("profile")) {
+ hasProfile = (Boolean) dataMap.get("profile");
+ }
+
+ JSONObject payload = (JSONObject) dataMap.get("payload");
+ // base64格式的消息 电信平台推送的内容
+ String dataBase64 = "";
+ if (hasProfile) {
+ if (!payload.containsKey("serviceData")) {
+ log.error("payload字段中不含serviceData字段");
+ } else {
+ JSONObject serviceData = payload.getJSONObject("serviceData");
+ if (!serviceData.containsKey("Value")) {
+ log.error("serviceData字段中不含Value字段");
+ } else {
+ dataBase64 = serviceData.getString("Value");
+ }
+ }
+ } else {
+ if (payload.containsKey("APPdata")) {
+ dataBase64 = payload.getString("APPdata");
+ } else {
+ log.error("payload字段中不含APPdata字段");
+ }
+ }
+
+ if (!dataBase64.isEmpty()) {
+ frameStr = Base64.getDecoder().decode(dataBase64); // base64解码
+ }
+
+ return frameStr;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java
new file mode 100644
index 0000000..ae6706a
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java
@@ -0,0 +1,40 @@
+package com.casic.missiles.frame;
+
+import lombok.Data;
+import java.util.List;
+
+@Data
+public class BirmmBaseFrame {
+
+ // 前导码 固定为A3
+ final String PRE_CODE = "A3";
+
+ // 协议版本 固定为20
+ final String VERSION = "20";
+
+ // 帧长度 后续到CRC字段前的字节总长度 不包括长度字段和CRC字段
+ int length;
+
+ // 设备编号
+ String devCode;
+
+ // 通信方式
+ String communicationType;
+
+ // 目标节点地址
+ String destinationAddr;
+
+ // PDU类型
+ String pduType;
+
+ // 序号
+ String sequence;
+
+ // 业务字段List
+ String tagListString;
+
+ List tagList;
+
+ // CRC
+ String crc;
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java
new file mode 100644
index 0000000..2285f9a
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java
@@ -0,0 +1,11 @@
+package com.casic.missiles.frame;
+
+import lombok.Data;
+
+@Data
+public class BirmmBaseTag {
+
+ private String oid;
+ private int tagLen;
+ private String valueStr;
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java
new file mode 100644
index 0000000..b1fd65c
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java
@@ -0,0 +1,9 @@
+package com.casic.missiles.frame;
+
+public class BirmmFrameBuilderFactory {
+
+ public static BirmmBaseFrame createBirmmFrame(String pduType) {
+
+ return null;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmTagBuilderFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmTagBuilderFactory.java
new file mode 100644
index 0000000..95ebdab
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmTagBuilderFactory.java
@@ -0,0 +1,33 @@
+package com.casic.missiles.frame;
+
+import com.casic.missiles.enums.BirmmTagAttributeEnums;
+import com.casic.missiles.frame.commanTag.*;
+
+public class BirmmTagBuilderFactory {
+
+ public static BirmmBaseTag createTagByOid(String oid) {
+ BirmmTagAttributeEnums tag = BirmmTagAttributeEnums.toType(oid);
+ if (null != tag) {
+ switch (tag) {
+ case CELL_TAG:
+ return new CellTag();
+
+ case DATE_TAG:
+ return new DateTag();
+
+ case PIC_TAG:
+ return new PCITag();
+
+ case SNR_TAG:
+ return new SNRTag();
+
+ case RSRP_TAG:
+ return new RSRPTag();
+
+ default:
+ return null;
+ }
+ }
+ return null;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/CellTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/CellTag.java
new file mode 100644
index 0000000..b0e0360
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/CellTag.java
@@ -0,0 +1,20 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class CellTag extends BirmmBaseTag {
+
+ final String CELL_TAG_OID = "60000020";
+
+ int cellVal;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ cellVal = Integer.parseInt(valueStr, 16);
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/DateTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/DateTag.java
new file mode 100644
index 0000000..e8c5db4
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/DateTag.java
@@ -0,0 +1,30 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.time.LocalDate;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class DateTag extends BirmmBaseTag {
+
+ final String DATE_TAG_OID = "10000050";
+
+ LocalDate date;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ String hexY = valueStr.substring(0, 2);
+ String hexM = valueStr.substring(2, 4);
+ String hexD = valueStr.substring(4, 6);
+
+ date = LocalDate.now();
+ date = date.withYear(BytesUtil.hexStringToUInt(hexY) + 2000);
+ date = date.withMonth(BytesUtil.hexStringToUInt(hexM));
+ date = date.withDayOfMonth(BytesUtil.hexStringToUInt(hexD));
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/PCITag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/PCITag.java
new file mode 100644
index 0000000..4433cea
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/PCITag.java
@@ -0,0 +1,22 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class PCITag extends BirmmBaseTag {
+
+ final String PCI_TAG_OID = "60000511";
+
+ // TYPE_U16整型,主小区物理小区号PCI,范围: 0 – 503
+ int pci;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ pci = BytesUtil.hexStringToUInt(valueStr);
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/RSRPTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/RSRPTag.java
new file mode 100644
index 0000000..d1bb0a8
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/RSRPTag.java
@@ -0,0 +1,22 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class RSRPTag extends BirmmBaseTag {
+
+ final String RSRP_TAG_OID = "60000513";
+
+ //带符号整型,主小区RSRP值,单位dBm。仅在RRC-IDLE状态时可用 -140 ~ -40 越大越好
+ int rsrp;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ rsrp = BytesUtil.hexStringToSInt(valueStr);
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/SNRTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/SNRTag.java
new file mode 100644
index 0000000..3040799
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/SNRTag.java
@@ -0,0 +1,22 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class SNRTag extends BirmmBaseTag {
+
+ final String SNR_TAG_OID = "60000516";
+
+ //带符号整型,主小区lart SNR值,单位dB。仅在RRC-IDLE状态时可用 -20 ~ 50 越大越好
+ int snr;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ snr = BytesUtil.hexStringToSInt(valueStr);
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/BirmmProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/BirmmProtocolParser.java
new file mode 100644
index 0000000..d29e372
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/BirmmProtocolParser.java
@@ -0,0 +1,38 @@
+package com.casic.missiles.parser;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+
+import java.util.List;
+
+/**
+ * BIRMM系列设备
+ * 一般设备协议解析
+ */
+public interface BirmmProtocolParser {
+
+ boolean preCheckFrame(byte[] frameBytes);
+
+ boolean validateCRC(byte[] frameBytes);
+
+ boolean validateLength(byte[] tagBytes, int length);
+
+ String getFrameHeader(byte[] frameBytes);
+
+ int getLength(byte[] frameBytes);
+
+ String getDevCode(byte[] frameBytes);
+
+ String getCommunicationType(byte[] frameBytes);
+
+ String getDestinationAddr(byte[] frameBytes);
+
+ String getPDUType(byte[] frameBytes);
+
+ String getSequence(byte[] frameBytes);
+
+ String getTagListString(byte[] frameBytes);
+ List getTagList(byte[] tagBytes);
+
+ String getCRC(byte[] frameBytes);
+ String getToBeVerifiedCRCBytes(byte[] frameBytes);
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/impl/BirmmProtocolParserImpl.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/impl/BirmmProtocolParserImpl.java
new file mode 100644
index 0000000..11c542d
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/impl/BirmmProtocolParserImpl.java
@@ -0,0 +1,145 @@
+package com.casic.missiles.parser.impl;
+
+import com.casic.missiles.enums.BirmmFrameAttributeEnums;
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.frame.BirmmTagBuilderFactory;
+import com.casic.missiles.parser.BirmmProtocolParser;
+import com.casic.missiles.parser.crc.CRCUtil;
+import com.casic.missiles.util.BytesUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Component
+@Slf4j
+public class BirmmProtocolParserImpl implements BirmmProtocolParser {
+ @Override
+ public boolean preCheckFrame(byte[] frameBytes) {
+ if (!checkPreCodeAndVersion(frameBytes)) {
+ log.error("帧头不符合协议:{}", getFrameHeader(frameBytes));
+ return false;
+ }
+
+ if (!preCheckLength(frameBytes)) {
+ log.error("帧长度不满足最低长度要求:{}", frameBytes.length);
+ return false;
+ }
+
+ if (!validateCRC(frameBytes)) {
+ log.error("CRC校验不通过:{}", getCRC(frameBytes));
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public boolean validateCRC(byte[] frameBytes) {
+ byte[] toBeVerifiedBytes = new byte[frameBytes.length - BirmmFrameAttributeEnums.CRC.getLength()];
+ System.arraycopy(frameBytes, 0, toBeVerifiedBytes, 0, toBeVerifiedBytes.length);
+
+ // 计算CRC值
+ CRCUtil crcUtil = new CRCUtil(CRCUtil.Parameters.CRC16MODBUS);
+ long crcVal = crcUtil.calculateCRC(toBeVerifiedBytes);
+ // 格式化输出
+ String crcStr = String.format("%0" + BirmmFrameAttributeEnums.CRC.getLength() * 2 + "X", crcVal);
+
+ return getCRC(frameBytes).equalsIgnoreCase(crcStr);
+ }
+
+ @Override
+ public boolean validateLength(byte[] tagBytes, int length) {
+ return false;
+ }
+
+ @Override
+ public String getFrameHeader(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.HEADER.getOffset(), BirmmFrameAttributeEnums.HEADER.getLength()); // byte[0] ~ byte[1] 表示A320
+ }
+
+ @Override
+ public int getLength(byte[] frameBytes) {
+ byte[] lengthBytes = new byte[BirmmFrameAttributeEnums.LENGTH.getLength()];
+ System.arraycopy(frameBytes, BirmmFrameAttributeEnums.LENGTH.getOffset(), lengthBytes, 0, lengthBytes.length); // byte[2] ~ byte[3] 表示长度
+
+ return BytesUtil.hexStringToUInt(lengthBytes);
+ }
+
+ @Override
+ public String getDevCode(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.DEVICE_CODE.getOffset(), BirmmFrameAttributeEnums.DEVICE_CODE.getLength()); // byte[4] ~ byte[10] 表示设备编号
+ }
+
+ @Override
+ public String getCommunicationType(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.COMM_TYPE.getOffset(), BirmmFrameAttributeEnums.COMM_TYPE.getLength()); // byte[11] 表示通信方式
+ }
+
+ @Override
+ public String getDestinationAddr(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.DEST_ADDR.getOffset(), BirmmFrameAttributeEnums.DEST_ADDR.getLength()); // byte[12] ~ byte[13] 表示目标节点地址
+ }
+
+ @Override
+ public String getPDUType(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.PDU_TYPE.getOffset(), BirmmFrameAttributeEnums.PDU_TYPE.getLength()); // byte[14] ~ byte[15] 表示PDUType
+ }
+
+ @Override
+ public String getSequence(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.SEQ.getOffset(), BirmmFrameAttributeEnums.SEQ.getLength()); // byte[16] 表示序号
+ }
+
+ @Override
+ public String getTagListString(byte[] frameBytes) {
+ // 帧结构其余字节长度为 18 = 1+1+2+6+1+2+2+1+2
+ return BytesUtil.extractHexString(frameBytes, 16, frameBytes.length - 18); // 从byte[16]开始
+ }
+
+ @Override
+ public List getTagList(byte[] tagBytes) {
+ // 必须包含OID和长度 4 + 2
+ if (tagBytes.length < 6) {
+ return null;
+ }
+ List tagList = new ArrayList<>();
+ int idx = 0;
+ while (idx + 6 < tagBytes.length) {
+ String oid = BytesUtil.extractHexString(tagBytes, idx, 4);
+ int tagLen = BytesUtil.hexStringToUInt(new byte[] {tagBytes[idx + 4], tagBytes[idx + 5]});
+ idx += 6;
+ if (tagLen + idx < tagBytes.length) {
+ BirmmBaseTag tagBase = BirmmTagBuilderFactory.createTagByOid(oid);
+ if (null != tagBase) {
+ String valStr = BytesUtil.extractHexString(tagBytes, idx, tagLen);
+ tagBase.setValueStr(valStr);
+
+ tagList.add(tagBase);
+ }
+ }
+ idx += tagLen;
+ }
+
+ return tagList;
+ }
+
+ private boolean checkPreCodeAndVersion(byte[] frameBytes) {
+ String headerStr = getFrameHeader(frameBytes);
+ return headerStr.equalsIgnoreCase(BirmmFrameAttributeEnums.HEADER.getDefaultStr());
+ }
+
+ private boolean preCheckLength(byte[] frameBytes) {
+ return frameBytes.length >= 18;
+ }
+
+ @Override
+ public String getCRC(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, frameBytes.length - 2, BirmmFrameAttributeEnums.CRC.getLength()); // 最后两个字节表示CRC校验码
+ }
+
+ @Override
+ public String getToBeVerifiedCRCBytes(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, 0, frameBytes.length - 2); // 所有字节都用于生成CRC校验码
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/service/GeneralServiceImpl.java b/sensorhub-core/src/main/java/com/casic/missiles/service/GeneralServiceImpl.java
new file mode 100644
index 0000000..118a8de
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/service/GeneralServiceImpl.java
@@ -0,0 +1,65 @@
+package com.casic.missiles.service;
+
+import com.casic.missiles.frame.BirmmBaseFrame;
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.frame.BirmmFrameBuilderFactory;
+import com.casic.missiles.parser.BirmmProtocolParser;
+import com.casic.missiles.parser.safe.SafeStrategy;
+import com.casic.missiles.parser.safe.impl.Sm4;
+import com.casic.missiles.util.SpringContextUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.tomcat.util.buf.HexUtils;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import javax.annotation.Resource;
+
+@Service
+@Slf4j
+public class GeneralServiceImpl implements IGeneralService {
+
+ @Resource
+ BirmmProtocolParser protocol;
+
+ @Override
+ public BirmmBaseFrame dataParse(byte[] frame) {
+ boolean frameValid = protocol.preCheckFrame(frame);
+ if (frameValid) {
+ // 解析长度
+ int length = protocol.getLength(frame);
+
+ // 解析得到设备编号
+ String devCode = protocol.getDevCode(frame);
+
+ // 解析通信方式
+ String commType = protocol.getCommunicationType(frame);
+
+ // 解析目标节点地址
+ String destAddr = protocol.getDestinationAddr(frame);
+
+ // 解析得到PDUType
+ String pduType = protocol.getPDUType(frame);
+
+ // 解析序号
+ String seq = protocol.getSequence(frame);
+
+ // 加密后的业务字段
+ String tagListStr = protocol.getTagListString(frame);
+
+ log.info("帧结构字段解析结果:[长度:{}],[设备编号:{}],[通信方式:{}],[目标节点地址:{}],[PDUType:{}],[序号:{}]", length, devCode, commType, destAddr, pduType, seq);
+
+ // 解密
+ SafeStrategy safeStrategy = SpringContextUtil.getBean(Sm4.class);
+ byte[] plainBytes = safeStrategy.decryption(tagListStr);
+ String plainTagListStr = HexUtils.toHexString(plainBytes).toUpperCase();
+
+ log.info("业务字段:{}", plainTagListStr);
+
+ // 获得业务字段tagList
+ List tagList = protocol.getTagList(plainBytes);
+ System.out.println(tagList.size());
+ }
+
+ return null;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/service/IGeneralService.java b/sensorhub-core/src/main/java/com/casic/missiles/service/IGeneralService.java
new file mode 100644
index 0000000..5e27b33
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/service/IGeneralService.java
@@ -0,0 +1,8 @@
+package com.casic.missiles.service;
+
+import com.casic.missiles.frame.BirmmBaseFrame;
+
+public interface IGeneralService {
+
+ BirmmBaseFrame dataParse(byte[] frame);
+}
diff --git a/sensorhub-support/pom.xml b/sensorhub-support/pom.xml
index 56d8813..abc3dda 100644
--- a/sensorhub-support/pom.xml
+++ b/sensorhub-support/pom.xml
@@ -26,6 +26,12 @@
+ com.alibaba
+ fastjson
+ ${fastjson.version}
+
+
+
org.apache.commons
commons-lang3
3.1
diff --git a/sensorhub-support/src/main/java/com/casic/missiles/enums/BirmmFrameAttributeEnums.java b/sensorhub-support/src/main/java/com/casic/missiles/enums/BirmmFrameAttributeEnums.java
new file mode 100644
index 0000000..626e25a
--- /dev/null
+++ b/sensorhub-support/src/main/java/com/casic/missiles/enums/BirmmFrameAttributeEnums.java
@@ -0,0 +1,43 @@
+package com.casic.missiles.enums;
+
+import lombok.Getter;
+
+/**
+ * 帧结构属性枚举
+ */
+@Getter
+public enum BirmmFrameAttributeEnums {
+ PREAMBLE("Preamble", 1, 0, "A3"),
+ VERSION("Version", 1, 1, "20"),
+ HEADER("Header", 2, 0, "A320"),
+ LENGTH("Length", 2, 2, "0000"),
+ DEVICE_CODE("DeviceCode", 6, 4, ""),
+ COMM_TYPE("CommunicationType", 1, 10, "00"),
+ DEST_ADDR("DestinationAddr", 2, 11, "0000"),
+ PDU_TYPE("PDUType", 2, 13, "0000"),
+ SEQ("Sequence", 1, 15, "00"),
+ CRC("CRC", 2, -1, "0000");
+
+ /**
+ * 名称
+ */
+ private final String name;
+
+ /**
+ * 属性字节长度
+ */
+ private final int length;
+ /**
+ * 属性的偏移量
+ */
+ private final int offset;
+
+ private final String defaultStr;
+
+ BirmmFrameAttributeEnums(String name, int length, int offset, String defaultStr) {
+ this.name = name;
+ this.length = length;
+ this.offset = offset;
+ this.defaultStr = defaultStr;
+ }
+}
diff --git a/.gitignore b/.gitignore
index 9e20bc1..78302f1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,6 @@
.idea/
**/target/**
logs/
+*.log
+*.log.*
*.iml
diff --git a/casic-iot-web/src/main/resources/config/application-dev.yml b/casic-iot-web/src/main/resources/config/application-dev.yml
index 487fc70..c5c99b7 100644
--- a/casic-iot-web/src/main/resources/config/application-dev.yml
+++ b/casic-iot-web/src/main/resources/config/application-dev.yml
@@ -37,7 +37,7 @@
invalid-time: 86400
config-prefix: 'Casic:'
#kaptcha-open: false #是否开启登录时验证码 (true/false)
- no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/push/data,/push/test
+ no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/aep/**
#flowable数据源和多数据源配置
db:
init:
diff --git a/casic-iot-web/src/main/resources/config/logback-spring.xml b/casic-iot-web/src/main/resources/config/logback-spring.xml
index c0c7ac9..2d308a8 100644
--- a/casic-iot-web/src/main/resources/config/logback-spring.xml
+++ b/casic-iot-web/src/main/resources/config/logback-spring.xml
@@ -5,7 +5,7 @@
-
+
diff --git a/pom.xml b/pom.xml
index 3ad2470..a194074 100644
--- a/pom.xml
+++ b/pom.xml
@@ -49,6 +49,7 @@
2.0.0.alpha
2.5.4
2.5.6
+ 1.2.62
2.0.0.alpha
@@ -56,7 +57,11 @@
-
+
+ com.casic
+ casic-core
+ ${core.version}
+
com.baomidou
dynamic-datasource-spring-boot-starter
@@ -69,11 +74,11 @@
${fastjson.version}
-
- cn.hutool
- hutool-core
- 5.7.2
-
+
+
+
+
+
org.projectlombok
diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml
index d5118b4..8dcc497 100644
--- a/sensorhub-core/pom.xml
+++ b/sensorhub-core/pom.xml
@@ -35,17 +35,17 @@
com.ctg.ag
ctg-ag-sdk-core
-
2.8.0-SNAPSHOT
-
+ system
+ ${pom.basedir}\lib\ctg-ag-sdk-core-2.8.0.jar
com.ctg.ag
ag-sdk-biz
2.8.0-SNAPSHOT
-
-
+ system
+ ${pom.basedir}\lib\ag-sdk-biz.jar
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java
deleted file mode 100644
index 40c55e8..0000000
--- a/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java
+++ /dev/null
@@ -1,30 +0,0 @@
-//package com.casic.missiles;
-//
-//import com.casic.missiles.netty.SensorhubServer;
-//import lombok.extern.slf4j.Slf4j;
-//import org.mybatis.spring.annotation.MapperScan;
-//import org.springframework.beans.factory.annotation.Autowired;
-//import org.springframework.boot.CommandLineRunner;
-//import org.springframework.boot.SpringApplication;
-//import org.springframework.boot.autoconfigure.SpringBootApplication;
-//import org.springframework.cache.annotation.EnableCaching;
-//
-//
-//@SpringBootApplication(scanBasePackages = "com.casic.missiles")
-//@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"})
-//@EnableCaching //开启缓存
-//@Slf4j
-//public class ServerApplication implements CommandLineRunner {
-//
-// @Autowired
-// private SensorhubServer nettyServer;
-// public static void main(String[] args) {
-// SpringApplication.run(ServerApplication.class, args);
-// }
-//
-// @Override
-// public void run(String... args) {
-// this.nettyServer.startServer();
-// }
-//
-//}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java b/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java
new file mode 100644
index 0000000..8f90fd9
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java
@@ -0,0 +1,96 @@
+package com.casic.missiles.controller;
+
+import com.alibaba.fastjson.JSONObject;
+import com.casic.missiles.frame.BirmmBaseFrame;
+import com.casic.missiles.model.response.ResponseData;
+import com.casic.missiles.service.IGeneralService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.tomcat.util.buf.HexUtils;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.util.Base64;
+import java.util.Map;
+
+@RestController
+@Slf4j
+public class GeneralDataReceiver {
+
+ @Resource
+ IGeneralService defaultService;
+
+ @RequestMapping("/aep/data/string")
+ public Object aepDataString(@RequestBody Map dataMap) {
+ log.info("收到AEP平台推送消息:{}", JSONObject.toJSONString(dataMap));
+ log.debug("deviceId: {}, productId: {}, IMEI: {}, timestamp: {}", dataMap.get("deviceId"), dataMap.get("productId"), dataMap.get("IMEI"), dataMap.get("timestamp"));
+
+ // 从推送的数据中获取消息帧
+ String frameStr = new String(getFrameStringFromData(dataMap));
+ log.info("字符串消息帧:{}", frameStr);
+
+ return ResponseData.success();
+ }
+
+ @RequestMapping("/aep/data/hex")
+ public Object aepDataHex(@RequestBody Map dataMap) {
+ log.info("收到AEP平台推送消息:{}", JSONObject.toJSONString(dataMap));
+ log.debug("deviceId: {}, productId: {}, IMEI: {}, timestamp: {}", dataMap.get("deviceId"), dataMap.get("productId"), dataMap.get("IMEI"), dataMap.get("timestamp"));
+
+ // 从推送的数据中获取消息帧
+ byte[] frameBytes = getFrameStringFromData(dataMap);
+ log.info("HEX字节消息帧:{}", HexUtils.toHexString(frameBytes).toUpperCase());
+
+ BirmmBaseFrame birmmFrame = defaultService.dataParse(frameBytes);
+ if (birmmFrame != null) {
+ log.info("HEX字节消息解析成功:{}", birmmFrame);
+ }
+
+ // 返回给电信AEP平台
+ return ResponseData.success();
+ }
+
+ private byte[] getFrameStringFromData(Map dataMap) {
+ byte[] frameStr = new byte[]{};
+
+ if (!dataMap.containsKey("payload")) {
+ log.error("消息帧不含payload字段");
+ return frameStr;
+ }
+
+ // 判断是否有profile
+ boolean hasProfile = false;
+ if (dataMap.containsKey("profile")) {
+ hasProfile = (Boolean) dataMap.get("profile");
+ }
+
+ JSONObject payload = (JSONObject) dataMap.get("payload");
+ // base64格式的消息 电信平台推送的内容
+ String dataBase64 = "";
+ if (hasProfile) {
+ if (!payload.containsKey("serviceData")) {
+ log.error("payload字段中不含serviceData字段");
+ } else {
+ JSONObject serviceData = payload.getJSONObject("serviceData");
+ if (!serviceData.containsKey("Value")) {
+ log.error("serviceData字段中不含Value字段");
+ } else {
+ dataBase64 = serviceData.getString("Value");
+ }
+ }
+ } else {
+ if (payload.containsKey("APPdata")) {
+ dataBase64 = payload.getString("APPdata");
+ } else {
+ log.error("payload字段中不含APPdata字段");
+ }
+ }
+
+ if (!dataBase64.isEmpty()) {
+ frameStr = Base64.getDecoder().decode(dataBase64); // base64解码
+ }
+
+ return frameStr;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java
new file mode 100644
index 0000000..ae6706a
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java
@@ -0,0 +1,40 @@
+package com.casic.missiles.frame;
+
+import lombok.Data;
+import java.util.List;
+
+@Data
+public class BirmmBaseFrame {
+
+ // 前导码 固定为A3
+ final String PRE_CODE = "A3";
+
+ // 协议版本 固定为20
+ final String VERSION = "20";
+
+ // 帧长度 后续到CRC字段前的字节总长度 不包括长度字段和CRC字段
+ int length;
+
+ // 设备编号
+ String devCode;
+
+ // 通信方式
+ String communicationType;
+
+ // 目标节点地址
+ String destinationAddr;
+
+ // PDU类型
+ String pduType;
+
+ // 序号
+ String sequence;
+
+ // 业务字段List
+ String tagListString;
+
+ List tagList;
+
+ // CRC
+ String crc;
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java
new file mode 100644
index 0000000..2285f9a
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java
@@ -0,0 +1,11 @@
+package com.casic.missiles.frame;
+
+import lombok.Data;
+
+@Data
+public class BirmmBaseTag {
+
+ private String oid;
+ private int tagLen;
+ private String valueStr;
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java
new file mode 100644
index 0000000..b1fd65c
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java
@@ -0,0 +1,9 @@
+package com.casic.missiles.frame;
+
+public class BirmmFrameBuilderFactory {
+
+ public static BirmmBaseFrame createBirmmFrame(String pduType) {
+
+ return null;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmTagBuilderFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmTagBuilderFactory.java
new file mode 100644
index 0000000..95ebdab
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmTagBuilderFactory.java
@@ -0,0 +1,33 @@
+package com.casic.missiles.frame;
+
+import com.casic.missiles.enums.BirmmTagAttributeEnums;
+import com.casic.missiles.frame.commanTag.*;
+
+public class BirmmTagBuilderFactory {
+
+ public static BirmmBaseTag createTagByOid(String oid) {
+ BirmmTagAttributeEnums tag = BirmmTagAttributeEnums.toType(oid);
+ if (null != tag) {
+ switch (tag) {
+ case CELL_TAG:
+ return new CellTag();
+
+ case DATE_TAG:
+ return new DateTag();
+
+ case PIC_TAG:
+ return new PCITag();
+
+ case SNR_TAG:
+ return new SNRTag();
+
+ case RSRP_TAG:
+ return new RSRPTag();
+
+ default:
+ return null;
+ }
+ }
+ return null;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/CellTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/CellTag.java
new file mode 100644
index 0000000..b0e0360
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/CellTag.java
@@ -0,0 +1,20 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class CellTag extends BirmmBaseTag {
+
+ final String CELL_TAG_OID = "60000020";
+
+ int cellVal;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ cellVal = Integer.parseInt(valueStr, 16);
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/DateTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/DateTag.java
new file mode 100644
index 0000000..e8c5db4
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/DateTag.java
@@ -0,0 +1,30 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.time.LocalDate;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class DateTag extends BirmmBaseTag {
+
+ final String DATE_TAG_OID = "10000050";
+
+ LocalDate date;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ String hexY = valueStr.substring(0, 2);
+ String hexM = valueStr.substring(2, 4);
+ String hexD = valueStr.substring(4, 6);
+
+ date = LocalDate.now();
+ date = date.withYear(BytesUtil.hexStringToUInt(hexY) + 2000);
+ date = date.withMonth(BytesUtil.hexStringToUInt(hexM));
+ date = date.withDayOfMonth(BytesUtil.hexStringToUInt(hexD));
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/PCITag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/PCITag.java
new file mode 100644
index 0000000..4433cea
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/PCITag.java
@@ -0,0 +1,22 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class PCITag extends BirmmBaseTag {
+
+ final String PCI_TAG_OID = "60000511";
+
+ // TYPE_U16整型,主小区物理小区号PCI,范围: 0 – 503
+ int pci;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ pci = BytesUtil.hexStringToUInt(valueStr);
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/RSRPTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/RSRPTag.java
new file mode 100644
index 0000000..d1bb0a8
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/RSRPTag.java
@@ -0,0 +1,22 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class RSRPTag extends BirmmBaseTag {
+
+ final String RSRP_TAG_OID = "60000513";
+
+ //带符号整型,主小区RSRP值,单位dBm。仅在RRC-IDLE状态时可用 -140 ~ -40 越大越好
+ int rsrp;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ rsrp = BytesUtil.hexStringToSInt(valueStr);
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/SNRTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/SNRTag.java
new file mode 100644
index 0000000..3040799
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/SNRTag.java
@@ -0,0 +1,22 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class SNRTag extends BirmmBaseTag {
+
+ final String SNR_TAG_OID = "60000516";
+
+ //带符号整型,主小区lart SNR值,单位dB。仅在RRC-IDLE状态时可用 -20 ~ 50 越大越好
+ int snr;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ snr = BytesUtil.hexStringToSInt(valueStr);
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/BirmmProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/BirmmProtocolParser.java
new file mode 100644
index 0000000..d29e372
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/BirmmProtocolParser.java
@@ -0,0 +1,38 @@
+package com.casic.missiles.parser;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+
+import java.util.List;
+
+/**
+ * BIRMM系列设备
+ * 一般设备协议解析
+ */
+public interface BirmmProtocolParser {
+
+ boolean preCheckFrame(byte[] frameBytes);
+
+ boolean validateCRC(byte[] frameBytes);
+
+ boolean validateLength(byte[] tagBytes, int length);
+
+ String getFrameHeader(byte[] frameBytes);
+
+ int getLength(byte[] frameBytes);
+
+ String getDevCode(byte[] frameBytes);
+
+ String getCommunicationType(byte[] frameBytes);
+
+ String getDestinationAddr(byte[] frameBytes);
+
+ String getPDUType(byte[] frameBytes);
+
+ String getSequence(byte[] frameBytes);
+
+ String getTagListString(byte[] frameBytes);
+ List getTagList(byte[] tagBytes);
+
+ String getCRC(byte[] frameBytes);
+ String getToBeVerifiedCRCBytes(byte[] frameBytes);
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/impl/BirmmProtocolParserImpl.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/impl/BirmmProtocolParserImpl.java
new file mode 100644
index 0000000..11c542d
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/impl/BirmmProtocolParserImpl.java
@@ -0,0 +1,145 @@
+package com.casic.missiles.parser.impl;
+
+import com.casic.missiles.enums.BirmmFrameAttributeEnums;
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.frame.BirmmTagBuilderFactory;
+import com.casic.missiles.parser.BirmmProtocolParser;
+import com.casic.missiles.parser.crc.CRCUtil;
+import com.casic.missiles.util.BytesUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Component
+@Slf4j
+public class BirmmProtocolParserImpl implements BirmmProtocolParser {
+ @Override
+ public boolean preCheckFrame(byte[] frameBytes) {
+ if (!checkPreCodeAndVersion(frameBytes)) {
+ log.error("帧头不符合协议:{}", getFrameHeader(frameBytes));
+ return false;
+ }
+
+ if (!preCheckLength(frameBytes)) {
+ log.error("帧长度不满足最低长度要求:{}", frameBytes.length);
+ return false;
+ }
+
+ if (!validateCRC(frameBytes)) {
+ log.error("CRC校验不通过:{}", getCRC(frameBytes));
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public boolean validateCRC(byte[] frameBytes) {
+ byte[] toBeVerifiedBytes = new byte[frameBytes.length - BirmmFrameAttributeEnums.CRC.getLength()];
+ System.arraycopy(frameBytes, 0, toBeVerifiedBytes, 0, toBeVerifiedBytes.length);
+
+ // 计算CRC值
+ CRCUtil crcUtil = new CRCUtil(CRCUtil.Parameters.CRC16MODBUS);
+ long crcVal = crcUtil.calculateCRC(toBeVerifiedBytes);
+ // 格式化输出
+ String crcStr = String.format("%0" + BirmmFrameAttributeEnums.CRC.getLength() * 2 + "X", crcVal);
+
+ return getCRC(frameBytes).equalsIgnoreCase(crcStr);
+ }
+
+ @Override
+ public boolean validateLength(byte[] tagBytes, int length) {
+ return false;
+ }
+
+ @Override
+ public String getFrameHeader(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.HEADER.getOffset(), BirmmFrameAttributeEnums.HEADER.getLength()); // byte[0] ~ byte[1] 表示A320
+ }
+
+ @Override
+ public int getLength(byte[] frameBytes) {
+ byte[] lengthBytes = new byte[BirmmFrameAttributeEnums.LENGTH.getLength()];
+ System.arraycopy(frameBytes, BirmmFrameAttributeEnums.LENGTH.getOffset(), lengthBytes, 0, lengthBytes.length); // byte[2] ~ byte[3] 表示长度
+
+ return BytesUtil.hexStringToUInt(lengthBytes);
+ }
+
+ @Override
+ public String getDevCode(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.DEVICE_CODE.getOffset(), BirmmFrameAttributeEnums.DEVICE_CODE.getLength()); // byte[4] ~ byte[10] 表示设备编号
+ }
+
+ @Override
+ public String getCommunicationType(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.COMM_TYPE.getOffset(), BirmmFrameAttributeEnums.COMM_TYPE.getLength()); // byte[11] 表示通信方式
+ }
+
+ @Override
+ public String getDestinationAddr(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.DEST_ADDR.getOffset(), BirmmFrameAttributeEnums.DEST_ADDR.getLength()); // byte[12] ~ byte[13] 表示目标节点地址
+ }
+
+ @Override
+ public String getPDUType(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.PDU_TYPE.getOffset(), BirmmFrameAttributeEnums.PDU_TYPE.getLength()); // byte[14] ~ byte[15] 表示PDUType
+ }
+
+ @Override
+ public String getSequence(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.SEQ.getOffset(), BirmmFrameAttributeEnums.SEQ.getLength()); // byte[16] 表示序号
+ }
+
+ @Override
+ public String getTagListString(byte[] frameBytes) {
+ // 帧结构其余字节长度为 18 = 1+1+2+6+1+2+2+1+2
+ return BytesUtil.extractHexString(frameBytes, 16, frameBytes.length - 18); // 从byte[16]开始
+ }
+
+ @Override
+ public List getTagList(byte[] tagBytes) {
+ // 必须包含OID和长度 4 + 2
+ if (tagBytes.length < 6) {
+ return null;
+ }
+ List tagList = new ArrayList<>();
+ int idx = 0;
+ while (idx + 6 < tagBytes.length) {
+ String oid = BytesUtil.extractHexString(tagBytes, idx, 4);
+ int tagLen = BytesUtil.hexStringToUInt(new byte[] {tagBytes[idx + 4], tagBytes[idx + 5]});
+ idx += 6;
+ if (tagLen + idx < tagBytes.length) {
+ BirmmBaseTag tagBase = BirmmTagBuilderFactory.createTagByOid(oid);
+ if (null != tagBase) {
+ String valStr = BytesUtil.extractHexString(tagBytes, idx, tagLen);
+ tagBase.setValueStr(valStr);
+
+ tagList.add(tagBase);
+ }
+ }
+ idx += tagLen;
+ }
+
+ return tagList;
+ }
+
+ private boolean checkPreCodeAndVersion(byte[] frameBytes) {
+ String headerStr = getFrameHeader(frameBytes);
+ return headerStr.equalsIgnoreCase(BirmmFrameAttributeEnums.HEADER.getDefaultStr());
+ }
+
+ private boolean preCheckLength(byte[] frameBytes) {
+ return frameBytes.length >= 18;
+ }
+
+ @Override
+ public String getCRC(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, frameBytes.length - 2, BirmmFrameAttributeEnums.CRC.getLength()); // 最后两个字节表示CRC校验码
+ }
+
+ @Override
+ public String getToBeVerifiedCRCBytes(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, 0, frameBytes.length - 2); // 所有字节都用于生成CRC校验码
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/service/GeneralServiceImpl.java b/sensorhub-core/src/main/java/com/casic/missiles/service/GeneralServiceImpl.java
new file mode 100644
index 0000000..118a8de
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/service/GeneralServiceImpl.java
@@ -0,0 +1,65 @@
+package com.casic.missiles.service;
+
+import com.casic.missiles.frame.BirmmBaseFrame;
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.frame.BirmmFrameBuilderFactory;
+import com.casic.missiles.parser.BirmmProtocolParser;
+import com.casic.missiles.parser.safe.SafeStrategy;
+import com.casic.missiles.parser.safe.impl.Sm4;
+import com.casic.missiles.util.SpringContextUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.tomcat.util.buf.HexUtils;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import javax.annotation.Resource;
+
+@Service
+@Slf4j
+public class GeneralServiceImpl implements IGeneralService {
+
+ @Resource
+ BirmmProtocolParser protocol;
+
+ @Override
+ public BirmmBaseFrame dataParse(byte[] frame) {
+ boolean frameValid = protocol.preCheckFrame(frame);
+ if (frameValid) {
+ // 解析长度
+ int length = protocol.getLength(frame);
+
+ // 解析得到设备编号
+ String devCode = protocol.getDevCode(frame);
+
+ // 解析通信方式
+ String commType = protocol.getCommunicationType(frame);
+
+ // 解析目标节点地址
+ String destAddr = protocol.getDestinationAddr(frame);
+
+ // 解析得到PDUType
+ String pduType = protocol.getPDUType(frame);
+
+ // 解析序号
+ String seq = protocol.getSequence(frame);
+
+ // 加密后的业务字段
+ String tagListStr = protocol.getTagListString(frame);
+
+ log.info("帧结构字段解析结果:[长度:{}],[设备编号:{}],[通信方式:{}],[目标节点地址:{}],[PDUType:{}],[序号:{}]", length, devCode, commType, destAddr, pduType, seq);
+
+ // 解密
+ SafeStrategy safeStrategy = SpringContextUtil.getBean(Sm4.class);
+ byte[] plainBytes = safeStrategy.decryption(tagListStr);
+ String plainTagListStr = HexUtils.toHexString(plainBytes).toUpperCase();
+
+ log.info("业务字段:{}", plainTagListStr);
+
+ // 获得业务字段tagList
+ List tagList = protocol.getTagList(plainBytes);
+ System.out.println(tagList.size());
+ }
+
+ return null;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/service/IGeneralService.java b/sensorhub-core/src/main/java/com/casic/missiles/service/IGeneralService.java
new file mode 100644
index 0000000..5e27b33
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/service/IGeneralService.java
@@ -0,0 +1,8 @@
+package com.casic.missiles.service;
+
+import com.casic.missiles.frame.BirmmBaseFrame;
+
+public interface IGeneralService {
+
+ BirmmBaseFrame dataParse(byte[] frame);
+}
diff --git a/sensorhub-support/pom.xml b/sensorhub-support/pom.xml
index 56d8813..abc3dda 100644
--- a/sensorhub-support/pom.xml
+++ b/sensorhub-support/pom.xml
@@ -26,6 +26,12 @@
+ com.alibaba
+ fastjson
+ ${fastjson.version}
+
+
+
org.apache.commons
commons-lang3
3.1
diff --git a/sensorhub-support/src/main/java/com/casic/missiles/enums/BirmmFrameAttributeEnums.java b/sensorhub-support/src/main/java/com/casic/missiles/enums/BirmmFrameAttributeEnums.java
new file mode 100644
index 0000000..626e25a
--- /dev/null
+++ b/sensorhub-support/src/main/java/com/casic/missiles/enums/BirmmFrameAttributeEnums.java
@@ -0,0 +1,43 @@
+package com.casic.missiles.enums;
+
+import lombok.Getter;
+
+/**
+ * 帧结构属性枚举
+ */
+@Getter
+public enum BirmmFrameAttributeEnums {
+ PREAMBLE("Preamble", 1, 0, "A3"),
+ VERSION("Version", 1, 1, "20"),
+ HEADER("Header", 2, 0, "A320"),
+ LENGTH("Length", 2, 2, "0000"),
+ DEVICE_CODE("DeviceCode", 6, 4, ""),
+ COMM_TYPE("CommunicationType", 1, 10, "00"),
+ DEST_ADDR("DestinationAddr", 2, 11, "0000"),
+ PDU_TYPE("PDUType", 2, 13, "0000"),
+ SEQ("Sequence", 1, 15, "00"),
+ CRC("CRC", 2, -1, "0000");
+
+ /**
+ * 名称
+ */
+ private final String name;
+
+ /**
+ * 属性字节长度
+ */
+ private final int length;
+ /**
+ * 属性的偏移量
+ */
+ private final int offset;
+
+ private final String defaultStr;
+
+ BirmmFrameAttributeEnums(String name, int length, int offset, String defaultStr) {
+ this.name = name;
+ this.length = length;
+ this.offset = offset;
+ this.defaultStr = defaultStr;
+ }
+}
diff --git a/sensorhub-support/src/main/java/com/casic/missiles/enums/BirmmTagAttributeEnums.java b/sensorhub-support/src/main/java/com/casic/missiles/enums/BirmmTagAttributeEnums.java
new file mode 100644
index 0000000..1df2e90
--- /dev/null
+++ b/sensorhub-support/src/main/java/com/casic/missiles/enums/BirmmTagAttributeEnums.java
@@ -0,0 +1,36 @@
+package com.casic.missiles.enums;
+
+import lombok.Getter;
+
+import java.util.stream.Stream;
+
+/**
+ * 帧结构属性枚举
+ */
+@Getter
+public enum BirmmTagAttributeEnums {
+ CELL_TAG("60000020", 1),
+ DATE_TAG("10000050", 3),
+ PIC_TAG("60000511", 2),
+ RSRP_TAG("60000513", 2),
+ SNR_TAG("60000516", 2);
+
+ /**
+ * 名称
+ */
+ private final String name;
+
+ /**
+ * 属性字节长度
+ */
+ private final int length;
+
+ BirmmTagAttributeEnums(String name, int length) {
+ this.name = name;
+ this.length = length;
+ }
+
+ public static BirmmTagAttributeEnums toType(String oid) {
+ return Stream.of(BirmmTagAttributeEnums.values()).filter(p -> p.name.equalsIgnoreCase(oid)).findAny().orElse(null);
+ }
+}
diff --git a/.gitignore b/.gitignore
index 9e20bc1..78302f1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,6 @@
.idea/
**/target/**
logs/
+*.log
+*.log.*
*.iml
diff --git a/casic-iot-web/src/main/resources/config/application-dev.yml b/casic-iot-web/src/main/resources/config/application-dev.yml
index 487fc70..c5c99b7 100644
--- a/casic-iot-web/src/main/resources/config/application-dev.yml
+++ b/casic-iot-web/src/main/resources/config/application-dev.yml
@@ -37,7 +37,7 @@
invalid-time: 86400
config-prefix: 'Casic:'
#kaptcha-open: false #是否开启登录时验证码 (true/false)
- no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/push/data,/push/test
+ no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/aep/**
#flowable数据源和多数据源配置
db:
init:
diff --git a/casic-iot-web/src/main/resources/config/logback-spring.xml b/casic-iot-web/src/main/resources/config/logback-spring.xml
index c0c7ac9..2d308a8 100644
--- a/casic-iot-web/src/main/resources/config/logback-spring.xml
+++ b/casic-iot-web/src/main/resources/config/logback-spring.xml
@@ -5,7 +5,7 @@
-
+
diff --git a/pom.xml b/pom.xml
index 3ad2470..a194074 100644
--- a/pom.xml
+++ b/pom.xml
@@ -49,6 +49,7 @@
2.0.0.alpha
2.5.4
2.5.6
+ 1.2.62
2.0.0.alpha
@@ -56,7 +57,11 @@
-
+
+ com.casic
+ casic-core
+ ${core.version}
+
com.baomidou
dynamic-datasource-spring-boot-starter
@@ -69,11 +74,11 @@
${fastjson.version}
-
- cn.hutool
- hutool-core
- 5.7.2
-
+
+
+
+
+
org.projectlombok
diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml
index d5118b4..8dcc497 100644
--- a/sensorhub-core/pom.xml
+++ b/sensorhub-core/pom.xml
@@ -35,17 +35,17 @@
com.ctg.ag
ctg-ag-sdk-core
-
2.8.0-SNAPSHOT
-
+ system
+ ${pom.basedir}\lib\ctg-ag-sdk-core-2.8.0.jar
com.ctg.ag
ag-sdk-biz
2.8.0-SNAPSHOT
-
-
+ system
+ ${pom.basedir}\lib\ag-sdk-biz.jar
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java
deleted file mode 100644
index 40c55e8..0000000
--- a/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java
+++ /dev/null
@@ -1,30 +0,0 @@
-//package com.casic.missiles;
-//
-//import com.casic.missiles.netty.SensorhubServer;
-//import lombok.extern.slf4j.Slf4j;
-//import org.mybatis.spring.annotation.MapperScan;
-//import org.springframework.beans.factory.annotation.Autowired;
-//import org.springframework.boot.CommandLineRunner;
-//import org.springframework.boot.SpringApplication;
-//import org.springframework.boot.autoconfigure.SpringBootApplication;
-//import org.springframework.cache.annotation.EnableCaching;
-//
-//
-//@SpringBootApplication(scanBasePackages = "com.casic.missiles")
-//@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"})
-//@EnableCaching //开启缓存
-//@Slf4j
-//public class ServerApplication implements CommandLineRunner {
-//
-// @Autowired
-// private SensorhubServer nettyServer;
-// public static void main(String[] args) {
-// SpringApplication.run(ServerApplication.class, args);
-// }
-//
-// @Override
-// public void run(String... args) {
-// this.nettyServer.startServer();
-// }
-//
-//}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java b/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java
new file mode 100644
index 0000000..8f90fd9
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java
@@ -0,0 +1,96 @@
+package com.casic.missiles.controller;
+
+import com.alibaba.fastjson.JSONObject;
+import com.casic.missiles.frame.BirmmBaseFrame;
+import com.casic.missiles.model.response.ResponseData;
+import com.casic.missiles.service.IGeneralService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.tomcat.util.buf.HexUtils;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.util.Base64;
+import java.util.Map;
+
+@RestController
+@Slf4j
+public class GeneralDataReceiver {
+
+ @Resource
+ IGeneralService defaultService;
+
+ @RequestMapping("/aep/data/string")
+ public Object aepDataString(@RequestBody Map dataMap) {
+ log.info("收到AEP平台推送消息:{}", JSONObject.toJSONString(dataMap));
+ log.debug("deviceId: {}, productId: {}, IMEI: {}, timestamp: {}", dataMap.get("deviceId"), dataMap.get("productId"), dataMap.get("IMEI"), dataMap.get("timestamp"));
+
+ // 从推送的数据中获取消息帧
+ String frameStr = new String(getFrameStringFromData(dataMap));
+ log.info("字符串消息帧:{}", frameStr);
+
+ return ResponseData.success();
+ }
+
+ @RequestMapping("/aep/data/hex")
+ public Object aepDataHex(@RequestBody Map dataMap) {
+ log.info("收到AEP平台推送消息:{}", JSONObject.toJSONString(dataMap));
+ log.debug("deviceId: {}, productId: {}, IMEI: {}, timestamp: {}", dataMap.get("deviceId"), dataMap.get("productId"), dataMap.get("IMEI"), dataMap.get("timestamp"));
+
+ // 从推送的数据中获取消息帧
+ byte[] frameBytes = getFrameStringFromData(dataMap);
+ log.info("HEX字节消息帧:{}", HexUtils.toHexString(frameBytes).toUpperCase());
+
+ BirmmBaseFrame birmmFrame = defaultService.dataParse(frameBytes);
+ if (birmmFrame != null) {
+ log.info("HEX字节消息解析成功:{}", birmmFrame);
+ }
+
+ // 返回给电信AEP平台
+ return ResponseData.success();
+ }
+
+ private byte[] getFrameStringFromData(Map dataMap) {
+ byte[] frameStr = new byte[]{};
+
+ if (!dataMap.containsKey("payload")) {
+ log.error("消息帧不含payload字段");
+ return frameStr;
+ }
+
+ // 判断是否有profile
+ boolean hasProfile = false;
+ if (dataMap.containsKey("profile")) {
+ hasProfile = (Boolean) dataMap.get("profile");
+ }
+
+ JSONObject payload = (JSONObject) dataMap.get("payload");
+ // base64格式的消息 电信平台推送的内容
+ String dataBase64 = "";
+ if (hasProfile) {
+ if (!payload.containsKey("serviceData")) {
+ log.error("payload字段中不含serviceData字段");
+ } else {
+ JSONObject serviceData = payload.getJSONObject("serviceData");
+ if (!serviceData.containsKey("Value")) {
+ log.error("serviceData字段中不含Value字段");
+ } else {
+ dataBase64 = serviceData.getString("Value");
+ }
+ }
+ } else {
+ if (payload.containsKey("APPdata")) {
+ dataBase64 = payload.getString("APPdata");
+ } else {
+ log.error("payload字段中不含APPdata字段");
+ }
+ }
+
+ if (!dataBase64.isEmpty()) {
+ frameStr = Base64.getDecoder().decode(dataBase64); // base64解码
+ }
+
+ return frameStr;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java
new file mode 100644
index 0000000..ae6706a
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java
@@ -0,0 +1,40 @@
+package com.casic.missiles.frame;
+
+import lombok.Data;
+import java.util.List;
+
+@Data
+public class BirmmBaseFrame {
+
+ // 前导码 固定为A3
+ final String PRE_CODE = "A3";
+
+ // 协议版本 固定为20
+ final String VERSION = "20";
+
+ // 帧长度 后续到CRC字段前的字节总长度 不包括长度字段和CRC字段
+ int length;
+
+ // 设备编号
+ String devCode;
+
+ // 通信方式
+ String communicationType;
+
+ // 目标节点地址
+ String destinationAddr;
+
+ // PDU类型
+ String pduType;
+
+ // 序号
+ String sequence;
+
+ // 业务字段List
+ String tagListString;
+
+ List tagList;
+
+ // CRC
+ String crc;
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java
new file mode 100644
index 0000000..2285f9a
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java
@@ -0,0 +1,11 @@
+package com.casic.missiles.frame;
+
+import lombok.Data;
+
+@Data
+public class BirmmBaseTag {
+
+ private String oid;
+ private int tagLen;
+ private String valueStr;
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java
new file mode 100644
index 0000000..b1fd65c
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java
@@ -0,0 +1,9 @@
+package com.casic.missiles.frame;
+
+public class BirmmFrameBuilderFactory {
+
+ public static BirmmBaseFrame createBirmmFrame(String pduType) {
+
+ return null;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmTagBuilderFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmTagBuilderFactory.java
new file mode 100644
index 0000000..95ebdab
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmTagBuilderFactory.java
@@ -0,0 +1,33 @@
+package com.casic.missiles.frame;
+
+import com.casic.missiles.enums.BirmmTagAttributeEnums;
+import com.casic.missiles.frame.commanTag.*;
+
+public class BirmmTagBuilderFactory {
+
+ public static BirmmBaseTag createTagByOid(String oid) {
+ BirmmTagAttributeEnums tag = BirmmTagAttributeEnums.toType(oid);
+ if (null != tag) {
+ switch (tag) {
+ case CELL_TAG:
+ return new CellTag();
+
+ case DATE_TAG:
+ return new DateTag();
+
+ case PIC_TAG:
+ return new PCITag();
+
+ case SNR_TAG:
+ return new SNRTag();
+
+ case RSRP_TAG:
+ return new RSRPTag();
+
+ default:
+ return null;
+ }
+ }
+ return null;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/CellTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/CellTag.java
new file mode 100644
index 0000000..b0e0360
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/CellTag.java
@@ -0,0 +1,20 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class CellTag extends BirmmBaseTag {
+
+ final String CELL_TAG_OID = "60000020";
+
+ int cellVal;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ cellVal = Integer.parseInt(valueStr, 16);
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/DateTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/DateTag.java
new file mode 100644
index 0000000..e8c5db4
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/DateTag.java
@@ -0,0 +1,30 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.time.LocalDate;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class DateTag extends BirmmBaseTag {
+
+ final String DATE_TAG_OID = "10000050";
+
+ LocalDate date;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ String hexY = valueStr.substring(0, 2);
+ String hexM = valueStr.substring(2, 4);
+ String hexD = valueStr.substring(4, 6);
+
+ date = LocalDate.now();
+ date = date.withYear(BytesUtil.hexStringToUInt(hexY) + 2000);
+ date = date.withMonth(BytesUtil.hexStringToUInt(hexM));
+ date = date.withDayOfMonth(BytesUtil.hexStringToUInt(hexD));
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/PCITag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/PCITag.java
new file mode 100644
index 0000000..4433cea
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/PCITag.java
@@ -0,0 +1,22 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class PCITag extends BirmmBaseTag {
+
+ final String PCI_TAG_OID = "60000511";
+
+ // TYPE_U16整型,主小区物理小区号PCI,范围: 0 – 503
+ int pci;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ pci = BytesUtil.hexStringToUInt(valueStr);
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/RSRPTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/RSRPTag.java
new file mode 100644
index 0000000..d1bb0a8
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/RSRPTag.java
@@ -0,0 +1,22 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class RSRPTag extends BirmmBaseTag {
+
+ final String RSRP_TAG_OID = "60000513";
+
+ //带符号整型,主小区RSRP值,单位dBm。仅在RRC-IDLE状态时可用 -140 ~ -40 越大越好
+ int rsrp;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ rsrp = BytesUtil.hexStringToSInt(valueStr);
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/SNRTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/SNRTag.java
new file mode 100644
index 0000000..3040799
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/SNRTag.java
@@ -0,0 +1,22 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class SNRTag extends BirmmBaseTag {
+
+ final String SNR_TAG_OID = "60000516";
+
+ //带符号整型,主小区lart SNR值,单位dB。仅在RRC-IDLE状态时可用 -20 ~ 50 越大越好
+ int snr;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ snr = BytesUtil.hexStringToSInt(valueStr);
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/BirmmProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/BirmmProtocolParser.java
new file mode 100644
index 0000000..d29e372
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/BirmmProtocolParser.java
@@ -0,0 +1,38 @@
+package com.casic.missiles.parser;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+
+import java.util.List;
+
+/**
+ * BIRMM系列设备
+ * 一般设备协议解析
+ */
+public interface BirmmProtocolParser {
+
+ boolean preCheckFrame(byte[] frameBytes);
+
+ boolean validateCRC(byte[] frameBytes);
+
+ boolean validateLength(byte[] tagBytes, int length);
+
+ String getFrameHeader(byte[] frameBytes);
+
+ int getLength(byte[] frameBytes);
+
+ String getDevCode(byte[] frameBytes);
+
+ String getCommunicationType(byte[] frameBytes);
+
+ String getDestinationAddr(byte[] frameBytes);
+
+ String getPDUType(byte[] frameBytes);
+
+ String getSequence(byte[] frameBytes);
+
+ String getTagListString(byte[] frameBytes);
+ List getTagList(byte[] tagBytes);
+
+ String getCRC(byte[] frameBytes);
+ String getToBeVerifiedCRCBytes(byte[] frameBytes);
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/impl/BirmmProtocolParserImpl.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/impl/BirmmProtocolParserImpl.java
new file mode 100644
index 0000000..11c542d
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/impl/BirmmProtocolParserImpl.java
@@ -0,0 +1,145 @@
+package com.casic.missiles.parser.impl;
+
+import com.casic.missiles.enums.BirmmFrameAttributeEnums;
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.frame.BirmmTagBuilderFactory;
+import com.casic.missiles.parser.BirmmProtocolParser;
+import com.casic.missiles.parser.crc.CRCUtil;
+import com.casic.missiles.util.BytesUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Component
+@Slf4j
+public class BirmmProtocolParserImpl implements BirmmProtocolParser {
+ @Override
+ public boolean preCheckFrame(byte[] frameBytes) {
+ if (!checkPreCodeAndVersion(frameBytes)) {
+ log.error("帧头不符合协议:{}", getFrameHeader(frameBytes));
+ return false;
+ }
+
+ if (!preCheckLength(frameBytes)) {
+ log.error("帧长度不满足最低长度要求:{}", frameBytes.length);
+ return false;
+ }
+
+ if (!validateCRC(frameBytes)) {
+ log.error("CRC校验不通过:{}", getCRC(frameBytes));
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public boolean validateCRC(byte[] frameBytes) {
+ byte[] toBeVerifiedBytes = new byte[frameBytes.length - BirmmFrameAttributeEnums.CRC.getLength()];
+ System.arraycopy(frameBytes, 0, toBeVerifiedBytes, 0, toBeVerifiedBytes.length);
+
+ // 计算CRC值
+ CRCUtil crcUtil = new CRCUtil(CRCUtil.Parameters.CRC16MODBUS);
+ long crcVal = crcUtil.calculateCRC(toBeVerifiedBytes);
+ // 格式化输出
+ String crcStr = String.format("%0" + BirmmFrameAttributeEnums.CRC.getLength() * 2 + "X", crcVal);
+
+ return getCRC(frameBytes).equalsIgnoreCase(crcStr);
+ }
+
+ @Override
+ public boolean validateLength(byte[] tagBytes, int length) {
+ return false;
+ }
+
+ @Override
+ public String getFrameHeader(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.HEADER.getOffset(), BirmmFrameAttributeEnums.HEADER.getLength()); // byte[0] ~ byte[1] 表示A320
+ }
+
+ @Override
+ public int getLength(byte[] frameBytes) {
+ byte[] lengthBytes = new byte[BirmmFrameAttributeEnums.LENGTH.getLength()];
+ System.arraycopy(frameBytes, BirmmFrameAttributeEnums.LENGTH.getOffset(), lengthBytes, 0, lengthBytes.length); // byte[2] ~ byte[3] 表示长度
+
+ return BytesUtil.hexStringToUInt(lengthBytes);
+ }
+
+ @Override
+ public String getDevCode(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.DEVICE_CODE.getOffset(), BirmmFrameAttributeEnums.DEVICE_CODE.getLength()); // byte[4] ~ byte[10] 表示设备编号
+ }
+
+ @Override
+ public String getCommunicationType(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.COMM_TYPE.getOffset(), BirmmFrameAttributeEnums.COMM_TYPE.getLength()); // byte[11] 表示通信方式
+ }
+
+ @Override
+ public String getDestinationAddr(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.DEST_ADDR.getOffset(), BirmmFrameAttributeEnums.DEST_ADDR.getLength()); // byte[12] ~ byte[13] 表示目标节点地址
+ }
+
+ @Override
+ public String getPDUType(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.PDU_TYPE.getOffset(), BirmmFrameAttributeEnums.PDU_TYPE.getLength()); // byte[14] ~ byte[15] 表示PDUType
+ }
+
+ @Override
+ public String getSequence(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.SEQ.getOffset(), BirmmFrameAttributeEnums.SEQ.getLength()); // byte[16] 表示序号
+ }
+
+ @Override
+ public String getTagListString(byte[] frameBytes) {
+ // 帧结构其余字节长度为 18 = 1+1+2+6+1+2+2+1+2
+ return BytesUtil.extractHexString(frameBytes, 16, frameBytes.length - 18); // 从byte[16]开始
+ }
+
+ @Override
+ public List getTagList(byte[] tagBytes) {
+ // 必须包含OID和长度 4 + 2
+ if (tagBytes.length < 6) {
+ return null;
+ }
+ List tagList = new ArrayList<>();
+ int idx = 0;
+ while (idx + 6 < tagBytes.length) {
+ String oid = BytesUtil.extractHexString(tagBytes, idx, 4);
+ int tagLen = BytesUtil.hexStringToUInt(new byte[] {tagBytes[idx + 4], tagBytes[idx + 5]});
+ idx += 6;
+ if (tagLen + idx < tagBytes.length) {
+ BirmmBaseTag tagBase = BirmmTagBuilderFactory.createTagByOid(oid);
+ if (null != tagBase) {
+ String valStr = BytesUtil.extractHexString(tagBytes, idx, tagLen);
+ tagBase.setValueStr(valStr);
+
+ tagList.add(tagBase);
+ }
+ }
+ idx += tagLen;
+ }
+
+ return tagList;
+ }
+
+ private boolean checkPreCodeAndVersion(byte[] frameBytes) {
+ String headerStr = getFrameHeader(frameBytes);
+ return headerStr.equalsIgnoreCase(BirmmFrameAttributeEnums.HEADER.getDefaultStr());
+ }
+
+ private boolean preCheckLength(byte[] frameBytes) {
+ return frameBytes.length >= 18;
+ }
+
+ @Override
+ public String getCRC(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, frameBytes.length - 2, BirmmFrameAttributeEnums.CRC.getLength()); // 最后两个字节表示CRC校验码
+ }
+
+ @Override
+ public String getToBeVerifiedCRCBytes(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, 0, frameBytes.length - 2); // 所有字节都用于生成CRC校验码
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/service/GeneralServiceImpl.java b/sensorhub-core/src/main/java/com/casic/missiles/service/GeneralServiceImpl.java
new file mode 100644
index 0000000..118a8de
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/service/GeneralServiceImpl.java
@@ -0,0 +1,65 @@
+package com.casic.missiles.service;
+
+import com.casic.missiles.frame.BirmmBaseFrame;
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.frame.BirmmFrameBuilderFactory;
+import com.casic.missiles.parser.BirmmProtocolParser;
+import com.casic.missiles.parser.safe.SafeStrategy;
+import com.casic.missiles.parser.safe.impl.Sm4;
+import com.casic.missiles.util.SpringContextUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.tomcat.util.buf.HexUtils;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import javax.annotation.Resource;
+
+@Service
+@Slf4j
+public class GeneralServiceImpl implements IGeneralService {
+
+ @Resource
+ BirmmProtocolParser protocol;
+
+ @Override
+ public BirmmBaseFrame dataParse(byte[] frame) {
+ boolean frameValid = protocol.preCheckFrame(frame);
+ if (frameValid) {
+ // 解析长度
+ int length = protocol.getLength(frame);
+
+ // 解析得到设备编号
+ String devCode = protocol.getDevCode(frame);
+
+ // 解析通信方式
+ String commType = protocol.getCommunicationType(frame);
+
+ // 解析目标节点地址
+ String destAddr = protocol.getDestinationAddr(frame);
+
+ // 解析得到PDUType
+ String pduType = protocol.getPDUType(frame);
+
+ // 解析序号
+ String seq = protocol.getSequence(frame);
+
+ // 加密后的业务字段
+ String tagListStr = protocol.getTagListString(frame);
+
+ log.info("帧结构字段解析结果:[长度:{}],[设备编号:{}],[通信方式:{}],[目标节点地址:{}],[PDUType:{}],[序号:{}]", length, devCode, commType, destAddr, pduType, seq);
+
+ // 解密
+ SafeStrategy safeStrategy = SpringContextUtil.getBean(Sm4.class);
+ byte[] plainBytes = safeStrategy.decryption(tagListStr);
+ String plainTagListStr = HexUtils.toHexString(plainBytes).toUpperCase();
+
+ log.info("业务字段:{}", plainTagListStr);
+
+ // 获得业务字段tagList
+ List tagList = protocol.getTagList(plainBytes);
+ System.out.println(tagList.size());
+ }
+
+ return null;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/service/IGeneralService.java b/sensorhub-core/src/main/java/com/casic/missiles/service/IGeneralService.java
new file mode 100644
index 0000000..5e27b33
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/service/IGeneralService.java
@@ -0,0 +1,8 @@
+package com.casic.missiles.service;
+
+import com.casic.missiles.frame.BirmmBaseFrame;
+
+public interface IGeneralService {
+
+ BirmmBaseFrame dataParse(byte[] frame);
+}
diff --git a/sensorhub-support/pom.xml b/sensorhub-support/pom.xml
index 56d8813..abc3dda 100644
--- a/sensorhub-support/pom.xml
+++ b/sensorhub-support/pom.xml
@@ -26,6 +26,12 @@
+ com.alibaba
+ fastjson
+ ${fastjson.version}
+
+
+
org.apache.commons
commons-lang3
3.1
diff --git a/sensorhub-support/src/main/java/com/casic/missiles/enums/BirmmFrameAttributeEnums.java b/sensorhub-support/src/main/java/com/casic/missiles/enums/BirmmFrameAttributeEnums.java
new file mode 100644
index 0000000..626e25a
--- /dev/null
+++ b/sensorhub-support/src/main/java/com/casic/missiles/enums/BirmmFrameAttributeEnums.java
@@ -0,0 +1,43 @@
+package com.casic.missiles.enums;
+
+import lombok.Getter;
+
+/**
+ * 帧结构属性枚举
+ */
+@Getter
+public enum BirmmFrameAttributeEnums {
+ PREAMBLE("Preamble", 1, 0, "A3"),
+ VERSION("Version", 1, 1, "20"),
+ HEADER("Header", 2, 0, "A320"),
+ LENGTH("Length", 2, 2, "0000"),
+ DEVICE_CODE("DeviceCode", 6, 4, ""),
+ COMM_TYPE("CommunicationType", 1, 10, "00"),
+ DEST_ADDR("DestinationAddr", 2, 11, "0000"),
+ PDU_TYPE("PDUType", 2, 13, "0000"),
+ SEQ("Sequence", 1, 15, "00"),
+ CRC("CRC", 2, -1, "0000");
+
+ /**
+ * 名称
+ */
+ private final String name;
+
+ /**
+ * 属性字节长度
+ */
+ private final int length;
+ /**
+ * 属性的偏移量
+ */
+ private final int offset;
+
+ private final String defaultStr;
+
+ BirmmFrameAttributeEnums(String name, int length, int offset, String defaultStr) {
+ this.name = name;
+ this.length = length;
+ this.offset = offset;
+ this.defaultStr = defaultStr;
+ }
+}
diff --git a/sensorhub-support/src/main/java/com/casic/missiles/enums/BirmmTagAttributeEnums.java b/sensorhub-support/src/main/java/com/casic/missiles/enums/BirmmTagAttributeEnums.java
new file mode 100644
index 0000000..1df2e90
--- /dev/null
+++ b/sensorhub-support/src/main/java/com/casic/missiles/enums/BirmmTagAttributeEnums.java
@@ -0,0 +1,36 @@
+package com.casic.missiles.enums;
+
+import lombok.Getter;
+
+import java.util.stream.Stream;
+
+/**
+ * 帧结构属性枚举
+ */
+@Getter
+public enum BirmmTagAttributeEnums {
+ CELL_TAG("60000020", 1),
+ DATE_TAG("10000050", 3),
+ PIC_TAG("60000511", 2),
+ RSRP_TAG("60000513", 2),
+ SNR_TAG("60000516", 2);
+
+ /**
+ * 名称
+ */
+ private final String name;
+
+ /**
+ * 属性字节长度
+ */
+ private final int length;
+
+ BirmmTagAttributeEnums(String name, int length) {
+ this.name = name;
+ this.length = length;
+ }
+
+ public static BirmmTagAttributeEnums toType(String oid) {
+ return Stream.of(BirmmTagAttributeEnums.values()).filter(p -> p.name.equalsIgnoreCase(oid)).findAny().orElse(null);
+ }
+}
diff --git a/sensorhub-support/src/main/java/com/casic/missiles/enums/FrameAttributeEnums.java b/sensorhub-support/src/main/java/com/casic/missiles/enums/FrameAttributeEnums.java
deleted file mode 100644
index 1fda676..0000000
--- a/sensorhub-support/src/main/java/com/casic/missiles/enums/FrameAttributeEnums.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package com.casic.missiles.enums;
-
-/**
- * 帧结构属性枚举
- */
-public enum FrameAttributeEnums {
- PREAMBLE("preamble", 1, 0),
- VERSION("Version", 1, 1),
- LENG("Leng", 2, 2),
- DEVICE_ID("Device-Id", 6, 4),
- CONN_TYPE("通信方式", 1, 10),
- DEST_ADDR("目标节点地址", 2, 11),
- PDU_TYPE("PDUType", 2, 13),
- SEQ("Seq", 1, 15),
- CRC("CRC", 2, -1);
-// GetRequest("GetRequest", 1, "服务器GET请求", FrameStructEnum.OID_LIST_STRUCT.getValue()),
-// WakeupRequest("WakeupRequest", 10, "服务器唤醒设备", FrameStructEnum.OID_LIST_STRUCT.getValue()),
-// SetRequest("SetRequest", 3, "设置设备参数请求", FrameStructEnum.TAG_LIST_STRUCT.getValue()),
-// GetResponse("GetResponse", 2, "设备响应GET请求", FrameStructEnum.TAG_LIST_STRUCT.getValue()),
-// TrapRequest("TrapRequest", 4, "设备主动上报", FrameStructEnum.TAG_LIST_STRUCT.getValue()),
-// WakeupResponse ("WakeupResponse", 11, "设备响应服务器唤醒", FrameStructEnum.TAG_LIST_STRUCT.getValue()),
-// TrapResponse ("TrapResponse", 5, "设备主动上报响应", FrameStructEnum.TAG_STRUCT.getValue()),
-// OnlineRequest ("OnlineRequest", 6, "用于设备检查连接", FrameStructEnum.TAG_STRUCT.getValue()),
-// OnlineResponse ("OnlineResponse", 7, "用于设备检查连接", FrameStructEnum.TAG_STRUCT.getValue()),
-// StarupRequest ("StarupRequest", 8, "设备上报开机信息", FrameStructEnum.TAG_STRUCT.getValue()),
-// StarupResponse ("StarupResponse", 9, "设备上报开机信息响应", FrameStructEnum.TAG_STRUCT.getValue()),
-// SetResponse ("SetResponse", 12, "设备响应SET请求", FrameStructEnum.TAG_STRUCT.getValue());
- /**
- * 名称
- */
- private String name;
-
- /**
- * 属性字节长度
- */
- private int length;
- /**
- * 属性的偏移量
- */
- private int offset;
-
- FrameAttributeEnums(String name, int length, int offset) {
- this.name = name;
- this.length = length;
- this.offset = offset;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public int getLength() {
- return length;
- }
-
- public void setLength(int length) {
- this.length = length;
- }
-
- public int getOffset() {
- return offset;
- }
-
- public void setOffset(int offset) {
- this.offset = offset;
- }
-}
diff --git a/.gitignore b/.gitignore
index 9e20bc1..78302f1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,6 @@
.idea/
**/target/**
logs/
+*.log
+*.log.*
*.iml
diff --git a/casic-iot-web/src/main/resources/config/application-dev.yml b/casic-iot-web/src/main/resources/config/application-dev.yml
index 487fc70..c5c99b7 100644
--- a/casic-iot-web/src/main/resources/config/application-dev.yml
+++ b/casic-iot-web/src/main/resources/config/application-dev.yml
@@ -37,7 +37,7 @@
invalid-time: 86400
config-prefix: 'Casic:'
#kaptcha-open: false #是否开启登录时验证码 (true/false)
- no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/push/data,/push/test
+ no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/aep/**
#flowable数据源和多数据源配置
db:
init:
diff --git a/casic-iot-web/src/main/resources/config/logback-spring.xml b/casic-iot-web/src/main/resources/config/logback-spring.xml
index c0c7ac9..2d308a8 100644
--- a/casic-iot-web/src/main/resources/config/logback-spring.xml
+++ b/casic-iot-web/src/main/resources/config/logback-spring.xml
@@ -5,7 +5,7 @@
-
+
diff --git a/pom.xml b/pom.xml
index 3ad2470..a194074 100644
--- a/pom.xml
+++ b/pom.xml
@@ -49,6 +49,7 @@
2.0.0.alpha
2.5.4
2.5.6
+ 1.2.62
2.0.0.alpha
@@ -56,7 +57,11 @@
-
+
+ com.casic
+ casic-core
+ ${core.version}
+
com.baomidou
dynamic-datasource-spring-boot-starter
@@ -69,11 +74,11 @@
${fastjson.version}
-
- cn.hutool
- hutool-core
- 5.7.2
-
+
+
+
+
+
org.projectlombok
diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml
index d5118b4..8dcc497 100644
--- a/sensorhub-core/pom.xml
+++ b/sensorhub-core/pom.xml
@@ -35,17 +35,17 @@
com.ctg.ag
ctg-ag-sdk-core
-
2.8.0-SNAPSHOT
-
+ system
+ ${pom.basedir}\lib\ctg-ag-sdk-core-2.8.0.jar
com.ctg.ag
ag-sdk-biz
2.8.0-SNAPSHOT
-
-
+ system
+ ${pom.basedir}\lib\ag-sdk-biz.jar
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java
deleted file mode 100644
index 40c55e8..0000000
--- a/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java
+++ /dev/null
@@ -1,30 +0,0 @@
-//package com.casic.missiles;
-//
-//import com.casic.missiles.netty.SensorhubServer;
-//import lombok.extern.slf4j.Slf4j;
-//import org.mybatis.spring.annotation.MapperScan;
-//import org.springframework.beans.factory.annotation.Autowired;
-//import org.springframework.boot.CommandLineRunner;
-//import org.springframework.boot.SpringApplication;
-//import org.springframework.boot.autoconfigure.SpringBootApplication;
-//import org.springframework.cache.annotation.EnableCaching;
-//
-//
-//@SpringBootApplication(scanBasePackages = "com.casic.missiles")
-//@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"})
-//@EnableCaching //开启缓存
-//@Slf4j
-//public class ServerApplication implements CommandLineRunner {
-//
-// @Autowired
-// private SensorhubServer nettyServer;
-// public static void main(String[] args) {
-// SpringApplication.run(ServerApplication.class, args);
-// }
-//
-// @Override
-// public void run(String... args) {
-// this.nettyServer.startServer();
-// }
-//
-//}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java b/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java
new file mode 100644
index 0000000..8f90fd9
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java
@@ -0,0 +1,96 @@
+package com.casic.missiles.controller;
+
+import com.alibaba.fastjson.JSONObject;
+import com.casic.missiles.frame.BirmmBaseFrame;
+import com.casic.missiles.model.response.ResponseData;
+import com.casic.missiles.service.IGeneralService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.tomcat.util.buf.HexUtils;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.util.Base64;
+import java.util.Map;
+
+@RestController
+@Slf4j
+public class GeneralDataReceiver {
+
+ @Resource
+ IGeneralService defaultService;
+
+ @RequestMapping("/aep/data/string")
+ public Object aepDataString(@RequestBody Map dataMap) {
+ log.info("收到AEP平台推送消息:{}", JSONObject.toJSONString(dataMap));
+ log.debug("deviceId: {}, productId: {}, IMEI: {}, timestamp: {}", dataMap.get("deviceId"), dataMap.get("productId"), dataMap.get("IMEI"), dataMap.get("timestamp"));
+
+ // 从推送的数据中获取消息帧
+ String frameStr = new String(getFrameStringFromData(dataMap));
+ log.info("字符串消息帧:{}", frameStr);
+
+ return ResponseData.success();
+ }
+
+ @RequestMapping("/aep/data/hex")
+ public Object aepDataHex(@RequestBody Map dataMap) {
+ log.info("收到AEP平台推送消息:{}", JSONObject.toJSONString(dataMap));
+ log.debug("deviceId: {}, productId: {}, IMEI: {}, timestamp: {}", dataMap.get("deviceId"), dataMap.get("productId"), dataMap.get("IMEI"), dataMap.get("timestamp"));
+
+ // 从推送的数据中获取消息帧
+ byte[] frameBytes = getFrameStringFromData(dataMap);
+ log.info("HEX字节消息帧:{}", HexUtils.toHexString(frameBytes).toUpperCase());
+
+ BirmmBaseFrame birmmFrame = defaultService.dataParse(frameBytes);
+ if (birmmFrame != null) {
+ log.info("HEX字节消息解析成功:{}", birmmFrame);
+ }
+
+ // 返回给电信AEP平台
+ return ResponseData.success();
+ }
+
+ private byte[] getFrameStringFromData(Map dataMap) {
+ byte[] frameStr = new byte[]{};
+
+ if (!dataMap.containsKey("payload")) {
+ log.error("消息帧不含payload字段");
+ return frameStr;
+ }
+
+ // 判断是否有profile
+ boolean hasProfile = false;
+ if (dataMap.containsKey("profile")) {
+ hasProfile = (Boolean) dataMap.get("profile");
+ }
+
+ JSONObject payload = (JSONObject) dataMap.get("payload");
+ // base64格式的消息 电信平台推送的内容
+ String dataBase64 = "";
+ if (hasProfile) {
+ if (!payload.containsKey("serviceData")) {
+ log.error("payload字段中不含serviceData字段");
+ } else {
+ JSONObject serviceData = payload.getJSONObject("serviceData");
+ if (!serviceData.containsKey("Value")) {
+ log.error("serviceData字段中不含Value字段");
+ } else {
+ dataBase64 = serviceData.getString("Value");
+ }
+ }
+ } else {
+ if (payload.containsKey("APPdata")) {
+ dataBase64 = payload.getString("APPdata");
+ } else {
+ log.error("payload字段中不含APPdata字段");
+ }
+ }
+
+ if (!dataBase64.isEmpty()) {
+ frameStr = Base64.getDecoder().decode(dataBase64); // base64解码
+ }
+
+ return frameStr;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java
new file mode 100644
index 0000000..ae6706a
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java
@@ -0,0 +1,40 @@
+package com.casic.missiles.frame;
+
+import lombok.Data;
+import java.util.List;
+
+@Data
+public class BirmmBaseFrame {
+
+ // 前导码 固定为A3
+ final String PRE_CODE = "A3";
+
+ // 协议版本 固定为20
+ final String VERSION = "20";
+
+ // 帧长度 后续到CRC字段前的字节总长度 不包括长度字段和CRC字段
+ int length;
+
+ // 设备编号
+ String devCode;
+
+ // 通信方式
+ String communicationType;
+
+ // 目标节点地址
+ String destinationAddr;
+
+ // PDU类型
+ String pduType;
+
+ // 序号
+ String sequence;
+
+ // 业务字段List
+ String tagListString;
+
+ List tagList;
+
+ // CRC
+ String crc;
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java
new file mode 100644
index 0000000..2285f9a
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java
@@ -0,0 +1,11 @@
+package com.casic.missiles.frame;
+
+import lombok.Data;
+
+@Data
+public class BirmmBaseTag {
+
+ private String oid;
+ private int tagLen;
+ private String valueStr;
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java
new file mode 100644
index 0000000..b1fd65c
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java
@@ -0,0 +1,9 @@
+package com.casic.missiles.frame;
+
+public class BirmmFrameBuilderFactory {
+
+ public static BirmmBaseFrame createBirmmFrame(String pduType) {
+
+ return null;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmTagBuilderFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmTagBuilderFactory.java
new file mode 100644
index 0000000..95ebdab
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmTagBuilderFactory.java
@@ -0,0 +1,33 @@
+package com.casic.missiles.frame;
+
+import com.casic.missiles.enums.BirmmTagAttributeEnums;
+import com.casic.missiles.frame.commanTag.*;
+
+public class BirmmTagBuilderFactory {
+
+ public static BirmmBaseTag createTagByOid(String oid) {
+ BirmmTagAttributeEnums tag = BirmmTagAttributeEnums.toType(oid);
+ if (null != tag) {
+ switch (tag) {
+ case CELL_TAG:
+ return new CellTag();
+
+ case DATE_TAG:
+ return new DateTag();
+
+ case PIC_TAG:
+ return new PCITag();
+
+ case SNR_TAG:
+ return new SNRTag();
+
+ case RSRP_TAG:
+ return new RSRPTag();
+
+ default:
+ return null;
+ }
+ }
+ return null;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/CellTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/CellTag.java
new file mode 100644
index 0000000..b0e0360
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/CellTag.java
@@ -0,0 +1,20 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class CellTag extends BirmmBaseTag {
+
+ final String CELL_TAG_OID = "60000020";
+
+ int cellVal;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ cellVal = Integer.parseInt(valueStr, 16);
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/DateTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/DateTag.java
new file mode 100644
index 0000000..e8c5db4
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/DateTag.java
@@ -0,0 +1,30 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.time.LocalDate;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class DateTag extends BirmmBaseTag {
+
+ final String DATE_TAG_OID = "10000050";
+
+ LocalDate date;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ String hexY = valueStr.substring(0, 2);
+ String hexM = valueStr.substring(2, 4);
+ String hexD = valueStr.substring(4, 6);
+
+ date = LocalDate.now();
+ date = date.withYear(BytesUtil.hexStringToUInt(hexY) + 2000);
+ date = date.withMonth(BytesUtil.hexStringToUInt(hexM));
+ date = date.withDayOfMonth(BytesUtil.hexStringToUInt(hexD));
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/PCITag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/PCITag.java
new file mode 100644
index 0000000..4433cea
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/PCITag.java
@@ -0,0 +1,22 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class PCITag extends BirmmBaseTag {
+
+ final String PCI_TAG_OID = "60000511";
+
+ // TYPE_U16整型,主小区物理小区号PCI,范围: 0 – 503
+ int pci;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ pci = BytesUtil.hexStringToUInt(valueStr);
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/RSRPTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/RSRPTag.java
new file mode 100644
index 0000000..d1bb0a8
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/RSRPTag.java
@@ -0,0 +1,22 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class RSRPTag extends BirmmBaseTag {
+
+ final String RSRP_TAG_OID = "60000513";
+
+ //带符号整型,主小区RSRP值,单位dBm。仅在RRC-IDLE状态时可用 -140 ~ -40 越大越好
+ int rsrp;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ rsrp = BytesUtil.hexStringToSInt(valueStr);
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/SNRTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/SNRTag.java
new file mode 100644
index 0000000..3040799
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/SNRTag.java
@@ -0,0 +1,22 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class SNRTag extends BirmmBaseTag {
+
+ final String SNR_TAG_OID = "60000516";
+
+ //带符号整型,主小区lart SNR值,单位dB。仅在RRC-IDLE状态时可用 -20 ~ 50 越大越好
+ int snr;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ snr = BytesUtil.hexStringToSInt(valueStr);
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/BirmmProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/BirmmProtocolParser.java
new file mode 100644
index 0000000..d29e372
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/BirmmProtocolParser.java
@@ -0,0 +1,38 @@
+package com.casic.missiles.parser;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+
+import java.util.List;
+
+/**
+ * BIRMM系列设备
+ * 一般设备协议解析
+ */
+public interface BirmmProtocolParser {
+
+ boolean preCheckFrame(byte[] frameBytes);
+
+ boolean validateCRC(byte[] frameBytes);
+
+ boolean validateLength(byte[] tagBytes, int length);
+
+ String getFrameHeader(byte[] frameBytes);
+
+ int getLength(byte[] frameBytes);
+
+ String getDevCode(byte[] frameBytes);
+
+ String getCommunicationType(byte[] frameBytes);
+
+ String getDestinationAddr(byte[] frameBytes);
+
+ String getPDUType(byte[] frameBytes);
+
+ String getSequence(byte[] frameBytes);
+
+ String getTagListString(byte[] frameBytes);
+ List getTagList(byte[] tagBytes);
+
+ String getCRC(byte[] frameBytes);
+ String getToBeVerifiedCRCBytes(byte[] frameBytes);
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/impl/BirmmProtocolParserImpl.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/impl/BirmmProtocolParserImpl.java
new file mode 100644
index 0000000..11c542d
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/impl/BirmmProtocolParserImpl.java
@@ -0,0 +1,145 @@
+package com.casic.missiles.parser.impl;
+
+import com.casic.missiles.enums.BirmmFrameAttributeEnums;
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.frame.BirmmTagBuilderFactory;
+import com.casic.missiles.parser.BirmmProtocolParser;
+import com.casic.missiles.parser.crc.CRCUtil;
+import com.casic.missiles.util.BytesUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Component
+@Slf4j
+public class BirmmProtocolParserImpl implements BirmmProtocolParser {
+ @Override
+ public boolean preCheckFrame(byte[] frameBytes) {
+ if (!checkPreCodeAndVersion(frameBytes)) {
+ log.error("帧头不符合协议:{}", getFrameHeader(frameBytes));
+ return false;
+ }
+
+ if (!preCheckLength(frameBytes)) {
+ log.error("帧长度不满足最低长度要求:{}", frameBytes.length);
+ return false;
+ }
+
+ if (!validateCRC(frameBytes)) {
+ log.error("CRC校验不通过:{}", getCRC(frameBytes));
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public boolean validateCRC(byte[] frameBytes) {
+ byte[] toBeVerifiedBytes = new byte[frameBytes.length - BirmmFrameAttributeEnums.CRC.getLength()];
+ System.arraycopy(frameBytes, 0, toBeVerifiedBytes, 0, toBeVerifiedBytes.length);
+
+ // 计算CRC值
+ CRCUtil crcUtil = new CRCUtil(CRCUtil.Parameters.CRC16MODBUS);
+ long crcVal = crcUtil.calculateCRC(toBeVerifiedBytes);
+ // 格式化输出
+ String crcStr = String.format("%0" + BirmmFrameAttributeEnums.CRC.getLength() * 2 + "X", crcVal);
+
+ return getCRC(frameBytes).equalsIgnoreCase(crcStr);
+ }
+
+ @Override
+ public boolean validateLength(byte[] tagBytes, int length) {
+ return false;
+ }
+
+ @Override
+ public String getFrameHeader(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.HEADER.getOffset(), BirmmFrameAttributeEnums.HEADER.getLength()); // byte[0] ~ byte[1] 表示A320
+ }
+
+ @Override
+ public int getLength(byte[] frameBytes) {
+ byte[] lengthBytes = new byte[BirmmFrameAttributeEnums.LENGTH.getLength()];
+ System.arraycopy(frameBytes, BirmmFrameAttributeEnums.LENGTH.getOffset(), lengthBytes, 0, lengthBytes.length); // byte[2] ~ byte[3] 表示长度
+
+ return BytesUtil.hexStringToUInt(lengthBytes);
+ }
+
+ @Override
+ public String getDevCode(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.DEVICE_CODE.getOffset(), BirmmFrameAttributeEnums.DEVICE_CODE.getLength()); // byte[4] ~ byte[10] 表示设备编号
+ }
+
+ @Override
+ public String getCommunicationType(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.COMM_TYPE.getOffset(), BirmmFrameAttributeEnums.COMM_TYPE.getLength()); // byte[11] 表示通信方式
+ }
+
+ @Override
+ public String getDestinationAddr(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.DEST_ADDR.getOffset(), BirmmFrameAttributeEnums.DEST_ADDR.getLength()); // byte[12] ~ byte[13] 表示目标节点地址
+ }
+
+ @Override
+ public String getPDUType(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.PDU_TYPE.getOffset(), BirmmFrameAttributeEnums.PDU_TYPE.getLength()); // byte[14] ~ byte[15] 表示PDUType
+ }
+
+ @Override
+ public String getSequence(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.SEQ.getOffset(), BirmmFrameAttributeEnums.SEQ.getLength()); // byte[16] 表示序号
+ }
+
+ @Override
+ public String getTagListString(byte[] frameBytes) {
+ // 帧结构其余字节长度为 18 = 1+1+2+6+1+2+2+1+2
+ return BytesUtil.extractHexString(frameBytes, 16, frameBytes.length - 18); // 从byte[16]开始
+ }
+
+ @Override
+ public List getTagList(byte[] tagBytes) {
+ // 必须包含OID和长度 4 + 2
+ if (tagBytes.length < 6) {
+ return null;
+ }
+ List tagList = new ArrayList<>();
+ int idx = 0;
+ while (idx + 6 < tagBytes.length) {
+ String oid = BytesUtil.extractHexString(tagBytes, idx, 4);
+ int tagLen = BytesUtil.hexStringToUInt(new byte[] {tagBytes[idx + 4], tagBytes[idx + 5]});
+ idx += 6;
+ if (tagLen + idx < tagBytes.length) {
+ BirmmBaseTag tagBase = BirmmTagBuilderFactory.createTagByOid(oid);
+ if (null != tagBase) {
+ String valStr = BytesUtil.extractHexString(tagBytes, idx, tagLen);
+ tagBase.setValueStr(valStr);
+
+ tagList.add(tagBase);
+ }
+ }
+ idx += tagLen;
+ }
+
+ return tagList;
+ }
+
+ private boolean checkPreCodeAndVersion(byte[] frameBytes) {
+ String headerStr = getFrameHeader(frameBytes);
+ return headerStr.equalsIgnoreCase(BirmmFrameAttributeEnums.HEADER.getDefaultStr());
+ }
+
+ private boolean preCheckLength(byte[] frameBytes) {
+ return frameBytes.length >= 18;
+ }
+
+ @Override
+ public String getCRC(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, frameBytes.length - 2, BirmmFrameAttributeEnums.CRC.getLength()); // 最后两个字节表示CRC校验码
+ }
+
+ @Override
+ public String getToBeVerifiedCRCBytes(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, 0, frameBytes.length - 2); // 所有字节都用于生成CRC校验码
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/service/GeneralServiceImpl.java b/sensorhub-core/src/main/java/com/casic/missiles/service/GeneralServiceImpl.java
new file mode 100644
index 0000000..118a8de
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/service/GeneralServiceImpl.java
@@ -0,0 +1,65 @@
+package com.casic.missiles.service;
+
+import com.casic.missiles.frame.BirmmBaseFrame;
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.frame.BirmmFrameBuilderFactory;
+import com.casic.missiles.parser.BirmmProtocolParser;
+import com.casic.missiles.parser.safe.SafeStrategy;
+import com.casic.missiles.parser.safe.impl.Sm4;
+import com.casic.missiles.util.SpringContextUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.tomcat.util.buf.HexUtils;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import javax.annotation.Resource;
+
+@Service
+@Slf4j
+public class GeneralServiceImpl implements IGeneralService {
+
+ @Resource
+ BirmmProtocolParser protocol;
+
+ @Override
+ public BirmmBaseFrame dataParse(byte[] frame) {
+ boolean frameValid = protocol.preCheckFrame(frame);
+ if (frameValid) {
+ // 解析长度
+ int length = protocol.getLength(frame);
+
+ // 解析得到设备编号
+ String devCode = protocol.getDevCode(frame);
+
+ // 解析通信方式
+ String commType = protocol.getCommunicationType(frame);
+
+ // 解析目标节点地址
+ String destAddr = protocol.getDestinationAddr(frame);
+
+ // 解析得到PDUType
+ String pduType = protocol.getPDUType(frame);
+
+ // 解析序号
+ String seq = protocol.getSequence(frame);
+
+ // 加密后的业务字段
+ String tagListStr = protocol.getTagListString(frame);
+
+ log.info("帧结构字段解析结果:[长度:{}],[设备编号:{}],[通信方式:{}],[目标节点地址:{}],[PDUType:{}],[序号:{}]", length, devCode, commType, destAddr, pduType, seq);
+
+ // 解密
+ SafeStrategy safeStrategy = SpringContextUtil.getBean(Sm4.class);
+ byte[] plainBytes = safeStrategy.decryption(tagListStr);
+ String plainTagListStr = HexUtils.toHexString(plainBytes).toUpperCase();
+
+ log.info("业务字段:{}", plainTagListStr);
+
+ // 获得业务字段tagList
+ List tagList = protocol.getTagList(plainBytes);
+ System.out.println(tagList.size());
+ }
+
+ return null;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/service/IGeneralService.java b/sensorhub-core/src/main/java/com/casic/missiles/service/IGeneralService.java
new file mode 100644
index 0000000..5e27b33
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/service/IGeneralService.java
@@ -0,0 +1,8 @@
+package com.casic.missiles.service;
+
+import com.casic.missiles.frame.BirmmBaseFrame;
+
+public interface IGeneralService {
+
+ BirmmBaseFrame dataParse(byte[] frame);
+}
diff --git a/sensorhub-support/pom.xml b/sensorhub-support/pom.xml
index 56d8813..abc3dda 100644
--- a/sensorhub-support/pom.xml
+++ b/sensorhub-support/pom.xml
@@ -26,6 +26,12 @@
+ com.alibaba
+ fastjson
+ ${fastjson.version}
+
+
+
org.apache.commons
commons-lang3
3.1
diff --git a/sensorhub-support/src/main/java/com/casic/missiles/enums/BirmmFrameAttributeEnums.java b/sensorhub-support/src/main/java/com/casic/missiles/enums/BirmmFrameAttributeEnums.java
new file mode 100644
index 0000000..626e25a
--- /dev/null
+++ b/sensorhub-support/src/main/java/com/casic/missiles/enums/BirmmFrameAttributeEnums.java
@@ -0,0 +1,43 @@
+package com.casic.missiles.enums;
+
+import lombok.Getter;
+
+/**
+ * 帧结构属性枚举
+ */
+@Getter
+public enum BirmmFrameAttributeEnums {
+ PREAMBLE("Preamble", 1, 0, "A3"),
+ VERSION("Version", 1, 1, "20"),
+ HEADER("Header", 2, 0, "A320"),
+ LENGTH("Length", 2, 2, "0000"),
+ DEVICE_CODE("DeviceCode", 6, 4, ""),
+ COMM_TYPE("CommunicationType", 1, 10, "00"),
+ DEST_ADDR("DestinationAddr", 2, 11, "0000"),
+ PDU_TYPE("PDUType", 2, 13, "0000"),
+ SEQ("Sequence", 1, 15, "00"),
+ CRC("CRC", 2, -1, "0000");
+
+ /**
+ * 名称
+ */
+ private final String name;
+
+ /**
+ * 属性字节长度
+ */
+ private final int length;
+ /**
+ * 属性的偏移量
+ */
+ private final int offset;
+
+ private final String defaultStr;
+
+ BirmmFrameAttributeEnums(String name, int length, int offset, String defaultStr) {
+ this.name = name;
+ this.length = length;
+ this.offset = offset;
+ this.defaultStr = defaultStr;
+ }
+}
diff --git a/sensorhub-support/src/main/java/com/casic/missiles/enums/BirmmTagAttributeEnums.java b/sensorhub-support/src/main/java/com/casic/missiles/enums/BirmmTagAttributeEnums.java
new file mode 100644
index 0000000..1df2e90
--- /dev/null
+++ b/sensorhub-support/src/main/java/com/casic/missiles/enums/BirmmTagAttributeEnums.java
@@ -0,0 +1,36 @@
+package com.casic.missiles.enums;
+
+import lombok.Getter;
+
+import java.util.stream.Stream;
+
+/**
+ * 帧结构属性枚举
+ */
+@Getter
+public enum BirmmTagAttributeEnums {
+ CELL_TAG("60000020", 1),
+ DATE_TAG("10000050", 3),
+ PIC_TAG("60000511", 2),
+ RSRP_TAG("60000513", 2),
+ SNR_TAG("60000516", 2);
+
+ /**
+ * 名称
+ */
+ private final String name;
+
+ /**
+ * 属性字节长度
+ */
+ private final int length;
+
+ BirmmTagAttributeEnums(String name, int length) {
+ this.name = name;
+ this.length = length;
+ }
+
+ public static BirmmTagAttributeEnums toType(String oid) {
+ return Stream.of(BirmmTagAttributeEnums.values()).filter(p -> p.name.equalsIgnoreCase(oid)).findAny().orElse(null);
+ }
+}
diff --git a/sensorhub-support/src/main/java/com/casic/missiles/enums/FrameAttributeEnums.java b/sensorhub-support/src/main/java/com/casic/missiles/enums/FrameAttributeEnums.java
deleted file mode 100644
index 1fda676..0000000
--- a/sensorhub-support/src/main/java/com/casic/missiles/enums/FrameAttributeEnums.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package com.casic.missiles.enums;
-
-/**
- * 帧结构属性枚举
- */
-public enum FrameAttributeEnums {
- PREAMBLE("preamble", 1, 0),
- VERSION("Version", 1, 1),
- LENG("Leng", 2, 2),
- DEVICE_ID("Device-Id", 6, 4),
- CONN_TYPE("通信方式", 1, 10),
- DEST_ADDR("目标节点地址", 2, 11),
- PDU_TYPE("PDUType", 2, 13),
- SEQ("Seq", 1, 15),
- CRC("CRC", 2, -1);
-// GetRequest("GetRequest", 1, "服务器GET请求", FrameStructEnum.OID_LIST_STRUCT.getValue()),
-// WakeupRequest("WakeupRequest", 10, "服务器唤醒设备", FrameStructEnum.OID_LIST_STRUCT.getValue()),
-// SetRequest("SetRequest", 3, "设置设备参数请求", FrameStructEnum.TAG_LIST_STRUCT.getValue()),
-// GetResponse("GetResponse", 2, "设备响应GET请求", FrameStructEnum.TAG_LIST_STRUCT.getValue()),
-// TrapRequest("TrapRequest", 4, "设备主动上报", FrameStructEnum.TAG_LIST_STRUCT.getValue()),
-// WakeupResponse ("WakeupResponse", 11, "设备响应服务器唤醒", FrameStructEnum.TAG_LIST_STRUCT.getValue()),
-// TrapResponse ("TrapResponse", 5, "设备主动上报响应", FrameStructEnum.TAG_STRUCT.getValue()),
-// OnlineRequest ("OnlineRequest", 6, "用于设备检查连接", FrameStructEnum.TAG_STRUCT.getValue()),
-// OnlineResponse ("OnlineResponse", 7, "用于设备检查连接", FrameStructEnum.TAG_STRUCT.getValue()),
-// StarupRequest ("StarupRequest", 8, "设备上报开机信息", FrameStructEnum.TAG_STRUCT.getValue()),
-// StarupResponse ("StarupResponse", 9, "设备上报开机信息响应", FrameStructEnum.TAG_STRUCT.getValue()),
-// SetResponse ("SetResponse", 12, "设备响应SET请求", FrameStructEnum.TAG_STRUCT.getValue());
- /**
- * 名称
- */
- private String name;
-
- /**
- * 属性字节长度
- */
- private int length;
- /**
- * 属性的偏移量
- */
- private int offset;
-
- FrameAttributeEnums(String name, int length, int offset) {
- this.name = name;
- this.length = length;
- this.offset = offset;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public int getLength() {
- return length;
- }
-
- public void setLength(int length) {
- this.length = length;
- }
-
- public int getOffset() {
- return offset;
- }
-
- public void setOffset(int offset) {
- this.offset = offset;
- }
-}
diff --git a/sensorhub-support/src/main/java/com/casic/missiles/enums/OperatorTypeEnum.java b/sensorhub-support/src/main/java/com/casic/missiles/enums/OperatorTypeEnum.java
deleted file mode 100644
index 7dd1824..0000000
--- a/sensorhub-support/src/main/java/com/casic/missiles/enums/OperatorTypeEnum.java
+++ /dev/null
@@ -1,53 +0,0 @@
-//package com.casic.missiles.enums;
-//
-//import java.util.Arrays;
-//
-///**
-// * 操作类型
-// */
-//public enum OperatorTypeEnum {
-//
-//// GetRequest("GetRequest", 1, "服务器GET请求", FrameStructEnum.OID_LIST_STRUCT.getValue()),
-//// WakeupRequest("WakeupRequest", 10, "服务器唤醒设备", FrameStructEnum.OID_LIST_STRUCT.getValue()),
-//// SetRequest("SetRequest", 3, "设置设备参数请求", FrameStructEnum.TAG_LIST_STRUCT.getValue()),
-//// GetResponse("GetResponse", 2, "设备响应GET请求", FrameStructEnum.TAG_LIST_STRUCT.getValue()),
-//// TrapRequest("TrapRequest", 4, "设备主动上报", FrameStructEnum.TAG_LIST_STRUCT.getValue()),
-//// WakeupResponse ("WakeupResponse", 11, "设备响应服务器唤醒", FrameStructEnum.TAG_LIST_STRUCT.getValue()),
-//// TrapResponse ("TrapResponse", 5, "设备主动上报响应", FrameStructEnum.TAG_STRUCT.getValue()),
-//// OnlineRequest ("OnlineRequest", 6, "用于设备检查连接", FrameStructEnum.TAG_STRUCT.getValue()),
-//// OnlineResponse ("OnlineResponse", 7, "用于设备检查连接", FrameStructEnum.TAG_STRUCT.getValue()),
-//// StarupRequest ("StarupRequest", 8, "设备上报开机信息", FrameStructEnum.TAG_STRUCT.getValue()),
-//// StarupResponse ("StarupResponse", 9, "设备上报开机信息响应", FrameStructEnum.TAG_STRUCT.getValue()),
-//// SetResponse ("SetResponse", 12, "设备响应SET请求", FrameStructEnum.TAG_STRUCT.getValue());
-//
-// private String name;
-// private int value;
-// private String desc;
-// private int frameStuct;
-//
-// OperatorTypeEnum(String name, int value, String desc, int frameStruct) {
-// this.name = name;
-// this.value = value;
-// this.desc = desc;
-// this.frameStuct = frameStruct;
-// }
-//
-// public static OperatorTypeEnum getEnumByOperatorType (int value) {
-// return Arrays.stream(OperatorTypeEnum.values()).filter(item -> item.getValue() == value).findFirst().get();
-// }
-// public String getName() {
-// return name;
-// }
-//
-// public int getValue() {
-// return value;
-// }
-//
-// public String getDesc() {
-// return desc;
-// }
-//
-// public int getFrameStruct() {
-// return frameStuct;
-// }
-//}
diff --git a/.gitignore b/.gitignore
index 9e20bc1..78302f1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,6 @@
.idea/
**/target/**
logs/
+*.log
+*.log.*
*.iml
diff --git a/casic-iot-web/src/main/resources/config/application-dev.yml b/casic-iot-web/src/main/resources/config/application-dev.yml
index 487fc70..c5c99b7 100644
--- a/casic-iot-web/src/main/resources/config/application-dev.yml
+++ b/casic-iot-web/src/main/resources/config/application-dev.yml
@@ -37,7 +37,7 @@
invalid-time: 86400
config-prefix: 'Casic:'
#kaptcha-open: false #是否开启登录时验证码 (true/false)
- no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/push/data,/push/test
+ no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/aep/**
#flowable数据源和多数据源配置
db:
init:
diff --git a/casic-iot-web/src/main/resources/config/logback-spring.xml b/casic-iot-web/src/main/resources/config/logback-spring.xml
index c0c7ac9..2d308a8 100644
--- a/casic-iot-web/src/main/resources/config/logback-spring.xml
+++ b/casic-iot-web/src/main/resources/config/logback-spring.xml
@@ -5,7 +5,7 @@
-
+
diff --git a/pom.xml b/pom.xml
index 3ad2470..a194074 100644
--- a/pom.xml
+++ b/pom.xml
@@ -49,6 +49,7 @@
2.0.0.alpha
2.5.4
2.5.6
+ 1.2.62
2.0.0.alpha
@@ -56,7 +57,11 @@
-
+
+ com.casic
+ casic-core
+ ${core.version}
+
com.baomidou
dynamic-datasource-spring-boot-starter
@@ -69,11 +74,11 @@
${fastjson.version}
-
- cn.hutool
- hutool-core
- 5.7.2
-
+
+
+
+
+
org.projectlombok
diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml
index d5118b4..8dcc497 100644
--- a/sensorhub-core/pom.xml
+++ b/sensorhub-core/pom.xml
@@ -35,17 +35,17 @@
com.ctg.ag
ctg-ag-sdk-core
-
2.8.0-SNAPSHOT
-
+ system
+ ${pom.basedir}\lib\ctg-ag-sdk-core-2.8.0.jar
com.ctg.ag
ag-sdk-biz
2.8.0-SNAPSHOT
-
-
+ system
+ ${pom.basedir}\lib\ag-sdk-biz.jar
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java
deleted file mode 100644
index 40c55e8..0000000
--- a/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java
+++ /dev/null
@@ -1,30 +0,0 @@
-//package com.casic.missiles;
-//
-//import com.casic.missiles.netty.SensorhubServer;
-//import lombok.extern.slf4j.Slf4j;
-//import org.mybatis.spring.annotation.MapperScan;
-//import org.springframework.beans.factory.annotation.Autowired;
-//import org.springframework.boot.CommandLineRunner;
-//import org.springframework.boot.SpringApplication;
-//import org.springframework.boot.autoconfigure.SpringBootApplication;
-//import org.springframework.cache.annotation.EnableCaching;
-//
-//
-//@SpringBootApplication(scanBasePackages = "com.casic.missiles")
-//@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"})
-//@EnableCaching //开启缓存
-//@Slf4j
-//public class ServerApplication implements CommandLineRunner {
-//
-// @Autowired
-// private SensorhubServer nettyServer;
-// public static void main(String[] args) {
-// SpringApplication.run(ServerApplication.class, args);
-// }
-//
-// @Override
-// public void run(String... args) {
-// this.nettyServer.startServer();
-// }
-//
-//}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java b/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java
new file mode 100644
index 0000000..8f90fd9
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java
@@ -0,0 +1,96 @@
+package com.casic.missiles.controller;
+
+import com.alibaba.fastjson.JSONObject;
+import com.casic.missiles.frame.BirmmBaseFrame;
+import com.casic.missiles.model.response.ResponseData;
+import com.casic.missiles.service.IGeneralService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.tomcat.util.buf.HexUtils;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.util.Base64;
+import java.util.Map;
+
+@RestController
+@Slf4j
+public class GeneralDataReceiver {
+
+ @Resource
+ IGeneralService defaultService;
+
+ @RequestMapping("/aep/data/string")
+ public Object aepDataString(@RequestBody Map dataMap) {
+ log.info("收到AEP平台推送消息:{}", JSONObject.toJSONString(dataMap));
+ log.debug("deviceId: {}, productId: {}, IMEI: {}, timestamp: {}", dataMap.get("deviceId"), dataMap.get("productId"), dataMap.get("IMEI"), dataMap.get("timestamp"));
+
+ // 从推送的数据中获取消息帧
+ String frameStr = new String(getFrameStringFromData(dataMap));
+ log.info("字符串消息帧:{}", frameStr);
+
+ return ResponseData.success();
+ }
+
+ @RequestMapping("/aep/data/hex")
+ public Object aepDataHex(@RequestBody Map dataMap) {
+ log.info("收到AEP平台推送消息:{}", JSONObject.toJSONString(dataMap));
+ log.debug("deviceId: {}, productId: {}, IMEI: {}, timestamp: {}", dataMap.get("deviceId"), dataMap.get("productId"), dataMap.get("IMEI"), dataMap.get("timestamp"));
+
+ // 从推送的数据中获取消息帧
+ byte[] frameBytes = getFrameStringFromData(dataMap);
+ log.info("HEX字节消息帧:{}", HexUtils.toHexString(frameBytes).toUpperCase());
+
+ BirmmBaseFrame birmmFrame = defaultService.dataParse(frameBytes);
+ if (birmmFrame != null) {
+ log.info("HEX字节消息解析成功:{}", birmmFrame);
+ }
+
+ // 返回给电信AEP平台
+ return ResponseData.success();
+ }
+
+ private byte[] getFrameStringFromData(Map dataMap) {
+ byte[] frameStr = new byte[]{};
+
+ if (!dataMap.containsKey("payload")) {
+ log.error("消息帧不含payload字段");
+ return frameStr;
+ }
+
+ // 判断是否有profile
+ boolean hasProfile = false;
+ if (dataMap.containsKey("profile")) {
+ hasProfile = (Boolean) dataMap.get("profile");
+ }
+
+ JSONObject payload = (JSONObject) dataMap.get("payload");
+ // base64格式的消息 电信平台推送的内容
+ String dataBase64 = "";
+ if (hasProfile) {
+ if (!payload.containsKey("serviceData")) {
+ log.error("payload字段中不含serviceData字段");
+ } else {
+ JSONObject serviceData = payload.getJSONObject("serviceData");
+ if (!serviceData.containsKey("Value")) {
+ log.error("serviceData字段中不含Value字段");
+ } else {
+ dataBase64 = serviceData.getString("Value");
+ }
+ }
+ } else {
+ if (payload.containsKey("APPdata")) {
+ dataBase64 = payload.getString("APPdata");
+ } else {
+ log.error("payload字段中不含APPdata字段");
+ }
+ }
+
+ if (!dataBase64.isEmpty()) {
+ frameStr = Base64.getDecoder().decode(dataBase64); // base64解码
+ }
+
+ return frameStr;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java
new file mode 100644
index 0000000..ae6706a
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java
@@ -0,0 +1,40 @@
+package com.casic.missiles.frame;
+
+import lombok.Data;
+import java.util.List;
+
+@Data
+public class BirmmBaseFrame {
+
+ // 前导码 固定为A3
+ final String PRE_CODE = "A3";
+
+ // 协议版本 固定为20
+ final String VERSION = "20";
+
+ // 帧长度 后续到CRC字段前的字节总长度 不包括长度字段和CRC字段
+ int length;
+
+ // 设备编号
+ String devCode;
+
+ // 通信方式
+ String communicationType;
+
+ // 目标节点地址
+ String destinationAddr;
+
+ // PDU类型
+ String pduType;
+
+ // 序号
+ String sequence;
+
+ // 业务字段List
+ String tagListString;
+
+ List tagList;
+
+ // CRC
+ String crc;
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java
new file mode 100644
index 0000000..2285f9a
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java
@@ -0,0 +1,11 @@
+package com.casic.missiles.frame;
+
+import lombok.Data;
+
+@Data
+public class BirmmBaseTag {
+
+ private String oid;
+ private int tagLen;
+ private String valueStr;
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java
new file mode 100644
index 0000000..b1fd65c
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java
@@ -0,0 +1,9 @@
+package com.casic.missiles.frame;
+
+public class BirmmFrameBuilderFactory {
+
+ public static BirmmBaseFrame createBirmmFrame(String pduType) {
+
+ return null;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmTagBuilderFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmTagBuilderFactory.java
new file mode 100644
index 0000000..95ebdab
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmTagBuilderFactory.java
@@ -0,0 +1,33 @@
+package com.casic.missiles.frame;
+
+import com.casic.missiles.enums.BirmmTagAttributeEnums;
+import com.casic.missiles.frame.commanTag.*;
+
+public class BirmmTagBuilderFactory {
+
+ public static BirmmBaseTag createTagByOid(String oid) {
+ BirmmTagAttributeEnums tag = BirmmTagAttributeEnums.toType(oid);
+ if (null != tag) {
+ switch (tag) {
+ case CELL_TAG:
+ return new CellTag();
+
+ case DATE_TAG:
+ return new DateTag();
+
+ case PIC_TAG:
+ return new PCITag();
+
+ case SNR_TAG:
+ return new SNRTag();
+
+ case RSRP_TAG:
+ return new RSRPTag();
+
+ default:
+ return null;
+ }
+ }
+ return null;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/CellTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/CellTag.java
new file mode 100644
index 0000000..b0e0360
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/CellTag.java
@@ -0,0 +1,20 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class CellTag extends BirmmBaseTag {
+
+ final String CELL_TAG_OID = "60000020";
+
+ int cellVal;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ cellVal = Integer.parseInt(valueStr, 16);
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/DateTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/DateTag.java
new file mode 100644
index 0000000..e8c5db4
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/DateTag.java
@@ -0,0 +1,30 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.time.LocalDate;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class DateTag extends BirmmBaseTag {
+
+ final String DATE_TAG_OID = "10000050";
+
+ LocalDate date;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ String hexY = valueStr.substring(0, 2);
+ String hexM = valueStr.substring(2, 4);
+ String hexD = valueStr.substring(4, 6);
+
+ date = LocalDate.now();
+ date = date.withYear(BytesUtil.hexStringToUInt(hexY) + 2000);
+ date = date.withMonth(BytesUtil.hexStringToUInt(hexM));
+ date = date.withDayOfMonth(BytesUtil.hexStringToUInt(hexD));
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/PCITag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/PCITag.java
new file mode 100644
index 0000000..4433cea
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/PCITag.java
@@ -0,0 +1,22 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class PCITag extends BirmmBaseTag {
+
+ final String PCI_TAG_OID = "60000511";
+
+ // TYPE_U16整型,主小区物理小区号PCI,范围: 0 – 503
+ int pci;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ pci = BytesUtil.hexStringToUInt(valueStr);
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/RSRPTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/RSRPTag.java
new file mode 100644
index 0000000..d1bb0a8
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/RSRPTag.java
@@ -0,0 +1,22 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class RSRPTag extends BirmmBaseTag {
+
+ final String RSRP_TAG_OID = "60000513";
+
+ //带符号整型,主小区RSRP值,单位dBm。仅在RRC-IDLE状态时可用 -140 ~ -40 越大越好
+ int rsrp;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ rsrp = BytesUtil.hexStringToSInt(valueStr);
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/SNRTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/SNRTag.java
new file mode 100644
index 0000000..3040799
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/SNRTag.java
@@ -0,0 +1,22 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class SNRTag extends BirmmBaseTag {
+
+ final String SNR_TAG_OID = "60000516";
+
+ //带符号整型,主小区lart SNR值,单位dB。仅在RRC-IDLE状态时可用 -20 ~ 50 越大越好
+ int snr;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ snr = BytesUtil.hexStringToSInt(valueStr);
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/BirmmProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/BirmmProtocolParser.java
new file mode 100644
index 0000000..d29e372
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/BirmmProtocolParser.java
@@ -0,0 +1,38 @@
+package com.casic.missiles.parser;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+
+import java.util.List;
+
+/**
+ * BIRMM系列设备
+ * 一般设备协议解析
+ */
+public interface BirmmProtocolParser {
+
+ boolean preCheckFrame(byte[] frameBytes);
+
+ boolean validateCRC(byte[] frameBytes);
+
+ boolean validateLength(byte[] tagBytes, int length);
+
+ String getFrameHeader(byte[] frameBytes);
+
+ int getLength(byte[] frameBytes);
+
+ String getDevCode(byte[] frameBytes);
+
+ String getCommunicationType(byte[] frameBytes);
+
+ String getDestinationAddr(byte[] frameBytes);
+
+ String getPDUType(byte[] frameBytes);
+
+ String getSequence(byte[] frameBytes);
+
+ String getTagListString(byte[] frameBytes);
+ List getTagList(byte[] tagBytes);
+
+ String getCRC(byte[] frameBytes);
+ String getToBeVerifiedCRCBytes(byte[] frameBytes);
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/impl/BirmmProtocolParserImpl.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/impl/BirmmProtocolParserImpl.java
new file mode 100644
index 0000000..11c542d
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/impl/BirmmProtocolParserImpl.java
@@ -0,0 +1,145 @@
+package com.casic.missiles.parser.impl;
+
+import com.casic.missiles.enums.BirmmFrameAttributeEnums;
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.frame.BirmmTagBuilderFactory;
+import com.casic.missiles.parser.BirmmProtocolParser;
+import com.casic.missiles.parser.crc.CRCUtil;
+import com.casic.missiles.util.BytesUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Component
+@Slf4j
+public class BirmmProtocolParserImpl implements BirmmProtocolParser {
+ @Override
+ public boolean preCheckFrame(byte[] frameBytes) {
+ if (!checkPreCodeAndVersion(frameBytes)) {
+ log.error("帧头不符合协议:{}", getFrameHeader(frameBytes));
+ return false;
+ }
+
+ if (!preCheckLength(frameBytes)) {
+ log.error("帧长度不满足最低长度要求:{}", frameBytes.length);
+ return false;
+ }
+
+ if (!validateCRC(frameBytes)) {
+ log.error("CRC校验不通过:{}", getCRC(frameBytes));
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public boolean validateCRC(byte[] frameBytes) {
+ byte[] toBeVerifiedBytes = new byte[frameBytes.length - BirmmFrameAttributeEnums.CRC.getLength()];
+ System.arraycopy(frameBytes, 0, toBeVerifiedBytes, 0, toBeVerifiedBytes.length);
+
+ // 计算CRC值
+ CRCUtil crcUtil = new CRCUtil(CRCUtil.Parameters.CRC16MODBUS);
+ long crcVal = crcUtil.calculateCRC(toBeVerifiedBytes);
+ // 格式化输出
+ String crcStr = String.format("%0" + BirmmFrameAttributeEnums.CRC.getLength() * 2 + "X", crcVal);
+
+ return getCRC(frameBytes).equalsIgnoreCase(crcStr);
+ }
+
+ @Override
+ public boolean validateLength(byte[] tagBytes, int length) {
+ return false;
+ }
+
+ @Override
+ public String getFrameHeader(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.HEADER.getOffset(), BirmmFrameAttributeEnums.HEADER.getLength()); // byte[0] ~ byte[1] 表示A320
+ }
+
+ @Override
+ public int getLength(byte[] frameBytes) {
+ byte[] lengthBytes = new byte[BirmmFrameAttributeEnums.LENGTH.getLength()];
+ System.arraycopy(frameBytes, BirmmFrameAttributeEnums.LENGTH.getOffset(), lengthBytes, 0, lengthBytes.length); // byte[2] ~ byte[3] 表示长度
+
+ return BytesUtil.hexStringToUInt(lengthBytes);
+ }
+
+ @Override
+ public String getDevCode(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.DEVICE_CODE.getOffset(), BirmmFrameAttributeEnums.DEVICE_CODE.getLength()); // byte[4] ~ byte[10] 表示设备编号
+ }
+
+ @Override
+ public String getCommunicationType(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.COMM_TYPE.getOffset(), BirmmFrameAttributeEnums.COMM_TYPE.getLength()); // byte[11] 表示通信方式
+ }
+
+ @Override
+ public String getDestinationAddr(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.DEST_ADDR.getOffset(), BirmmFrameAttributeEnums.DEST_ADDR.getLength()); // byte[12] ~ byte[13] 表示目标节点地址
+ }
+
+ @Override
+ public String getPDUType(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.PDU_TYPE.getOffset(), BirmmFrameAttributeEnums.PDU_TYPE.getLength()); // byte[14] ~ byte[15] 表示PDUType
+ }
+
+ @Override
+ public String getSequence(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.SEQ.getOffset(), BirmmFrameAttributeEnums.SEQ.getLength()); // byte[16] 表示序号
+ }
+
+ @Override
+ public String getTagListString(byte[] frameBytes) {
+ // 帧结构其余字节长度为 18 = 1+1+2+6+1+2+2+1+2
+ return BytesUtil.extractHexString(frameBytes, 16, frameBytes.length - 18); // 从byte[16]开始
+ }
+
+ @Override
+ public List getTagList(byte[] tagBytes) {
+ // 必须包含OID和长度 4 + 2
+ if (tagBytes.length < 6) {
+ return null;
+ }
+ List tagList = new ArrayList<>();
+ int idx = 0;
+ while (idx + 6 < tagBytes.length) {
+ String oid = BytesUtil.extractHexString(tagBytes, idx, 4);
+ int tagLen = BytesUtil.hexStringToUInt(new byte[] {tagBytes[idx + 4], tagBytes[idx + 5]});
+ idx += 6;
+ if (tagLen + idx < tagBytes.length) {
+ BirmmBaseTag tagBase = BirmmTagBuilderFactory.createTagByOid(oid);
+ if (null != tagBase) {
+ String valStr = BytesUtil.extractHexString(tagBytes, idx, tagLen);
+ tagBase.setValueStr(valStr);
+
+ tagList.add(tagBase);
+ }
+ }
+ idx += tagLen;
+ }
+
+ return tagList;
+ }
+
+ private boolean checkPreCodeAndVersion(byte[] frameBytes) {
+ String headerStr = getFrameHeader(frameBytes);
+ return headerStr.equalsIgnoreCase(BirmmFrameAttributeEnums.HEADER.getDefaultStr());
+ }
+
+ private boolean preCheckLength(byte[] frameBytes) {
+ return frameBytes.length >= 18;
+ }
+
+ @Override
+ public String getCRC(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, frameBytes.length - 2, BirmmFrameAttributeEnums.CRC.getLength()); // 最后两个字节表示CRC校验码
+ }
+
+ @Override
+ public String getToBeVerifiedCRCBytes(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, 0, frameBytes.length - 2); // 所有字节都用于生成CRC校验码
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/service/GeneralServiceImpl.java b/sensorhub-core/src/main/java/com/casic/missiles/service/GeneralServiceImpl.java
new file mode 100644
index 0000000..118a8de
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/service/GeneralServiceImpl.java
@@ -0,0 +1,65 @@
+package com.casic.missiles.service;
+
+import com.casic.missiles.frame.BirmmBaseFrame;
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.frame.BirmmFrameBuilderFactory;
+import com.casic.missiles.parser.BirmmProtocolParser;
+import com.casic.missiles.parser.safe.SafeStrategy;
+import com.casic.missiles.parser.safe.impl.Sm4;
+import com.casic.missiles.util.SpringContextUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.tomcat.util.buf.HexUtils;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import javax.annotation.Resource;
+
+@Service
+@Slf4j
+public class GeneralServiceImpl implements IGeneralService {
+
+ @Resource
+ BirmmProtocolParser protocol;
+
+ @Override
+ public BirmmBaseFrame dataParse(byte[] frame) {
+ boolean frameValid = protocol.preCheckFrame(frame);
+ if (frameValid) {
+ // 解析长度
+ int length = protocol.getLength(frame);
+
+ // 解析得到设备编号
+ String devCode = protocol.getDevCode(frame);
+
+ // 解析通信方式
+ String commType = protocol.getCommunicationType(frame);
+
+ // 解析目标节点地址
+ String destAddr = protocol.getDestinationAddr(frame);
+
+ // 解析得到PDUType
+ String pduType = protocol.getPDUType(frame);
+
+ // 解析序号
+ String seq = protocol.getSequence(frame);
+
+ // 加密后的业务字段
+ String tagListStr = protocol.getTagListString(frame);
+
+ log.info("帧结构字段解析结果:[长度:{}],[设备编号:{}],[通信方式:{}],[目标节点地址:{}],[PDUType:{}],[序号:{}]", length, devCode, commType, destAddr, pduType, seq);
+
+ // 解密
+ SafeStrategy safeStrategy = SpringContextUtil.getBean(Sm4.class);
+ byte[] plainBytes = safeStrategy.decryption(tagListStr);
+ String plainTagListStr = HexUtils.toHexString(plainBytes).toUpperCase();
+
+ log.info("业务字段:{}", plainTagListStr);
+
+ // 获得业务字段tagList
+ List tagList = protocol.getTagList(plainBytes);
+ System.out.println(tagList.size());
+ }
+
+ return null;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/service/IGeneralService.java b/sensorhub-core/src/main/java/com/casic/missiles/service/IGeneralService.java
new file mode 100644
index 0000000..5e27b33
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/service/IGeneralService.java
@@ -0,0 +1,8 @@
+package com.casic.missiles.service;
+
+import com.casic.missiles.frame.BirmmBaseFrame;
+
+public interface IGeneralService {
+
+ BirmmBaseFrame dataParse(byte[] frame);
+}
diff --git a/sensorhub-support/pom.xml b/sensorhub-support/pom.xml
index 56d8813..abc3dda 100644
--- a/sensorhub-support/pom.xml
+++ b/sensorhub-support/pom.xml
@@ -26,6 +26,12 @@
+ com.alibaba
+ fastjson
+ ${fastjson.version}
+
+
+
org.apache.commons
commons-lang3
3.1
diff --git a/sensorhub-support/src/main/java/com/casic/missiles/enums/BirmmFrameAttributeEnums.java b/sensorhub-support/src/main/java/com/casic/missiles/enums/BirmmFrameAttributeEnums.java
new file mode 100644
index 0000000..626e25a
--- /dev/null
+++ b/sensorhub-support/src/main/java/com/casic/missiles/enums/BirmmFrameAttributeEnums.java
@@ -0,0 +1,43 @@
+package com.casic.missiles.enums;
+
+import lombok.Getter;
+
+/**
+ * 帧结构属性枚举
+ */
+@Getter
+public enum BirmmFrameAttributeEnums {
+ PREAMBLE("Preamble", 1, 0, "A3"),
+ VERSION("Version", 1, 1, "20"),
+ HEADER("Header", 2, 0, "A320"),
+ LENGTH("Length", 2, 2, "0000"),
+ DEVICE_CODE("DeviceCode", 6, 4, ""),
+ COMM_TYPE("CommunicationType", 1, 10, "00"),
+ DEST_ADDR("DestinationAddr", 2, 11, "0000"),
+ PDU_TYPE("PDUType", 2, 13, "0000"),
+ SEQ("Sequence", 1, 15, "00"),
+ CRC("CRC", 2, -1, "0000");
+
+ /**
+ * 名称
+ */
+ private final String name;
+
+ /**
+ * 属性字节长度
+ */
+ private final int length;
+ /**
+ * 属性的偏移量
+ */
+ private final int offset;
+
+ private final String defaultStr;
+
+ BirmmFrameAttributeEnums(String name, int length, int offset, String defaultStr) {
+ this.name = name;
+ this.length = length;
+ this.offset = offset;
+ this.defaultStr = defaultStr;
+ }
+}
diff --git a/sensorhub-support/src/main/java/com/casic/missiles/enums/BirmmTagAttributeEnums.java b/sensorhub-support/src/main/java/com/casic/missiles/enums/BirmmTagAttributeEnums.java
new file mode 100644
index 0000000..1df2e90
--- /dev/null
+++ b/sensorhub-support/src/main/java/com/casic/missiles/enums/BirmmTagAttributeEnums.java
@@ -0,0 +1,36 @@
+package com.casic.missiles.enums;
+
+import lombok.Getter;
+
+import java.util.stream.Stream;
+
+/**
+ * 帧结构属性枚举
+ */
+@Getter
+public enum BirmmTagAttributeEnums {
+ CELL_TAG("60000020", 1),
+ DATE_TAG("10000050", 3),
+ PIC_TAG("60000511", 2),
+ RSRP_TAG("60000513", 2),
+ SNR_TAG("60000516", 2);
+
+ /**
+ * 名称
+ */
+ private final String name;
+
+ /**
+ * 属性字节长度
+ */
+ private final int length;
+
+ BirmmTagAttributeEnums(String name, int length) {
+ this.name = name;
+ this.length = length;
+ }
+
+ public static BirmmTagAttributeEnums toType(String oid) {
+ return Stream.of(BirmmTagAttributeEnums.values()).filter(p -> p.name.equalsIgnoreCase(oid)).findAny().orElse(null);
+ }
+}
diff --git a/sensorhub-support/src/main/java/com/casic/missiles/enums/FrameAttributeEnums.java b/sensorhub-support/src/main/java/com/casic/missiles/enums/FrameAttributeEnums.java
deleted file mode 100644
index 1fda676..0000000
--- a/sensorhub-support/src/main/java/com/casic/missiles/enums/FrameAttributeEnums.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package com.casic.missiles.enums;
-
-/**
- * 帧结构属性枚举
- */
-public enum FrameAttributeEnums {
- PREAMBLE("preamble", 1, 0),
- VERSION("Version", 1, 1),
- LENG("Leng", 2, 2),
- DEVICE_ID("Device-Id", 6, 4),
- CONN_TYPE("通信方式", 1, 10),
- DEST_ADDR("目标节点地址", 2, 11),
- PDU_TYPE("PDUType", 2, 13),
- SEQ("Seq", 1, 15),
- CRC("CRC", 2, -1);
-// GetRequest("GetRequest", 1, "服务器GET请求", FrameStructEnum.OID_LIST_STRUCT.getValue()),
-// WakeupRequest("WakeupRequest", 10, "服务器唤醒设备", FrameStructEnum.OID_LIST_STRUCT.getValue()),
-// SetRequest("SetRequest", 3, "设置设备参数请求", FrameStructEnum.TAG_LIST_STRUCT.getValue()),
-// GetResponse("GetResponse", 2, "设备响应GET请求", FrameStructEnum.TAG_LIST_STRUCT.getValue()),
-// TrapRequest("TrapRequest", 4, "设备主动上报", FrameStructEnum.TAG_LIST_STRUCT.getValue()),
-// WakeupResponse ("WakeupResponse", 11, "设备响应服务器唤醒", FrameStructEnum.TAG_LIST_STRUCT.getValue()),
-// TrapResponse ("TrapResponse", 5, "设备主动上报响应", FrameStructEnum.TAG_STRUCT.getValue()),
-// OnlineRequest ("OnlineRequest", 6, "用于设备检查连接", FrameStructEnum.TAG_STRUCT.getValue()),
-// OnlineResponse ("OnlineResponse", 7, "用于设备检查连接", FrameStructEnum.TAG_STRUCT.getValue()),
-// StarupRequest ("StarupRequest", 8, "设备上报开机信息", FrameStructEnum.TAG_STRUCT.getValue()),
-// StarupResponse ("StarupResponse", 9, "设备上报开机信息响应", FrameStructEnum.TAG_STRUCT.getValue()),
-// SetResponse ("SetResponse", 12, "设备响应SET请求", FrameStructEnum.TAG_STRUCT.getValue());
- /**
- * 名称
- */
- private String name;
-
- /**
- * 属性字节长度
- */
- private int length;
- /**
- * 属性的偏移量
- */
- private int offset;
-
- FrameAttributeEnums(String name, int length, int offset) {
- this.name = name;
- this.length = length;
- this.offset = offset;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public int getLength() {
- return length;
- }
-
- public void setLength(int length) {
- this.length = length;
- }
-
- public int getOffset() {
- return offset;
- }
-
- public void setOffset(int offset) {
- this.offset = offset;
- }
-}
diff --git a/sensorhub-support/src/main/java/com/casic/missiles/enums/OperatorTypeEnum.java b/sensorhub-support/src/main/java/com/casic/missiles/enums/OperatorTypeEnum.java
deleted file mode 100644
index 7dd1824..0000000
--- a/sensorhub-support/src/main/java/com/casic/missiles/enums/OperatorTypeEnum.java
+++ /dev/null
@@ -1,53 +0,0 @@
-//package com.casic.missiles.enums;
-//
-//import java.util.Arrays;
-//
-///**
-// * 操作类型
-// */
-//public enum OperatorTypeEnum {
-//
-//// GetRequest("GetRequest", 1, "服务器GET请求", FrameStructEnum.OID_LIST_STRUCT.getValue()),
-//// WakeupRequest("WakeupRequest", 10, "服务器唤醒设备", FrameStructEnum.OID_LIST_STRUCT.getValue()),
-//// SetRequest("SetRequest", 3, "设置设备参数请求", FrameStructEnum.TAG_LIST_STRUCT.getValue()),
-//// GetResponse("GetResponse", 2, "设备响应GET请求", FrameStructEnum.TAG_LIST_STRUCT.getValue()),
-//// TrapRequest("TrapRequest", 4, "设备主动上报", FrameStructEnum.TAG_LIST_STRUCT.getValue()),
-//// WakeupResponse ("WakeupResponse", 11, "设备响应服务器唤醒", FrameStructEnum.TAG_LIST_STRUCT.getValue()),
-//// TrapResponse ("TrapResponse", 5, "设备主动上报响应", FrameStructEnum.TAG_STRUCT.getValue()),
-//// OnlineRequest ("OnlineRequest", 6, "用于设备检查连接", FrameStructEnum.TAG_STRUCT.getValue()),
-//// OnlineResponse ("OnlineResponse", 7, "用于设备检查连接", FrameStructEnum.TAG_STRUCT.getValue()),
-//// StarupRequest ("StarupRequest", 8, "设备上报开机信息", FrameStructEnum.TAG_STRUCT.getValue()),
-//// StarupResponse ("StarupResponse", 9, "设备上报开机信息响应", FrameStructEnum.TAG_STRUCT.getValue()),
-//// SetResponse ("SetResponse", 12, "设备响应SET请求", FrameStructEnum.TAG_STRUCT.getValue());
-//
-// private String name;
-// private int value;
-// private String desc;
-// private int frameStuct;
-//
-// OperatorTypeEnum(String name, int value, String desc, int frameStruct) {
-// this.name = name;
-// this.value = value;
-// this.desc = desc;
-// this.frameStuct = frameStruct;
-// }
-//
-// public static OperatorTypeEnum getEnumByOperatorType (int value) {
-// return Arrays.stream(OperatorTypeEnum.values()).filter(item -> item.getValue() == value).findFirst().get();
-// }
-// public String getName() {
-// return name;
-// }
-//
-// public int getValue() {
-// return value;
-// }
-//
-// public String getDesc() {
-// return desc;
-// }
-//
-// public int getFrameStruct() {
-// return frameStuct;
-// }
-//}
diff --git a/sensorhub-support/src/main/java/com/casic/missiles/util/BytesUtil.java b/sensorhub-support/src/main/java/com/casic/missiles/util/BytesUtil.java
new file mode 100644
index 0000000..c09b998
--- /dev/null
+++ b/sensorhub-support/src/main/java/com/casic/missiles/util/BytesUtil.java
@@ -0,0 +1,37 @@
+package com.casic.missiles.util;
+
+import org.apache.tomcat.util.buf.HexUtils;
+
+public class BytesUtil {
+
+ public static String extractHexString(byte[] source, int start, int length) {
+ byte[] bytes = new byte[length];
+ System.arraycopy(source, start, bytes, 0, length);
+ return HexUtils.toHexString(bytes).toUpperCase();
+ }
+
+ public static int hexStringToUInt(byte[] bytes) {
+ int result = 0;
+ for (byte b : bytes) {
+ result = result * 256 + Byte.toUnsignedInt(b);
+ }
+ return result;
+ }
+
+ public static int hexStringToSInt(byte[] bytes) {
+ int result = 0;
+ for (int i = 0; i < Math.min(bytes.length, 4); i++) {
+ result <<= 8; // 左移8位
+ result |= bytes[i]; // 保存byte值到 result 最低的8位上
+ }
+ return result;
+ }
+
+ public static int hexStringToUInt(String str) {
+ return hexStringToUInt(HexUtils.fromHexString(str));
+ }
+
+ public static int hexStringToSInt(String str) {
+ return hexStringToSInt(HexUtils.fromHexString(str));
+ }
+}
diff --git a/.gitignore b/.gitignore
index 9e20bc1..78302f1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,6 @@
.idea/
**/target/**
logs/
+*.log
+*.log.*
*.iml
diff --git a/casic-iot-web/src/main/resources/config/application-dev.yml b/casic-iot-web/src/main/resources/config/application-dev.yml
index 487fc70..c5c99b7 100644
--- a/casic-iot-web/src/main/resources/config/application-dev.yml
+++ b/casic-iot-web/src/main/resources/config/application-dev.yml
@@ -37,7 +37,7 @@
invalid-time: 86400
config-prefix: 'Casic:'
#kaptcha-open: false #是否开启登录时验证码 (true/false)
- no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/push/data,/push/test
+ no-login-urls: ${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken,/v2/api-docs,/v2/api-docs-ext,/doc.html,/cockpit/**,/websocket/**,/webjars/**,/swagger-ui.html,/swagger-resources,/aep/**
#flowable数据源和多数据源配置
db:
init:
diff --git a/casic-iot-web/src/main/resources/config/logback-spring.xml b/casic-iot-web/src/main/resources/config/logback-spring.xml
index c0c7ac9..2d308a8 100644
--- a/casic-iot-web/src/main/resources/config/logback-spring.xml
+++ b/casic-iot-web/src/main/resources/config/logback-spring.xml
@@ -5,7 +5,7 @@
-
+
diff --git a/pom.xml b/pom.xml
index 3ad2470..a194074 100644
--- a/pom.xml
+++ b/pom.xml
@@ -49,6 +49,7 @@
2.0.0.alpha
2.5.4
2.5.6
+ 1.2.62
2.0.0.alpha
@@ -56,7 +57,11 @@
-
+
+ com.casic
+ casic-core
+ ${core.version}
+
com.baomidou
dynamic-datasource-spring-boot-starter
@@ -69,11 +74,11 @@
${fastjson.version}
-
- cn.hutool
- hutool-core
- 5.7.2
-
+
+
+
+
+
org.projectlombok
diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml
index d5118b4..8dcc497 100644
--- a/sensorhub-core/pom.xml
+++ b/sensorhub-core/pom.xml
@@ -35,17 +35,17 @@
com.ctg.ag
ctg-ag-sdk-core
-
2.8.0-SNAPSHOT
-
+ system
+ ${pom.basedir}\lib\ctg-ag-sdk-core-2.8.0.jar
com.ctg.ag
ag-sdk-biz
2.8.0-SNAPSHOT
-
-
+ system
+ ${pom.basedir}\lib\ag-sdk-biz.jar
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java
deleted file mode 100644
index 40c55e8..0000000
--- a/sensorhub-core/src/main/java/com/casic/missiles/ServerApplication.java
+++ /dev/null
@@ -1,30 +0,0 @@
-//package com.casic.missiles;
-//
-//import com.casic.missiles.netty.SensorhubServer;
-//import lombok.extern.slf4j.Slf4j;
-//import org.mybatis.spring.annotation.MapperScan;
-//import org.springframework.beans.factory.annotation.Autowired;
-//import org.springframework.boot.CommandLineRunner;
-//import org.springframework.boot.SpringApplication;
-//import org.springframework.boot.autoconfigure.SpringBootApplication;
-//import org.springframework.cache.annotation.EnableCaching;
-//
-//
-//@SpringBootApplication(scanBasePackages = "com.casic.missiles")
-//@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"})
-//@EnableCaching //开启缓存
-//@Slf4j
-//public class ServerApplication implements CommandLineRunner {
-//
-// @Autowired
-// private SensorhubServer nettyServer;
-// public static void main(String[] args) {
-// SpringApplication.run(ServerApplication.class, args);
-// }
-//
-// @Override
-// public void run(String... args) {
-// this.nettyServer.startServer();
-// }
-//
-//}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java b/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java
new file mode 100644
index 0000000..8f90fd9
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/controller/GeneralDataReceiver.java
@@ -0,0 +1,96 @@
+package com.casic.missiles.controller;
+
+import com.alibaba.fastjson.JSONObject;
+import com.casic.missiles.frame.BirmmBaseFrame;
+import com.casic.missiles.model.response.ResponseData;
+import com.casic.missiles.service.IGeneralService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.tomcat.util.buf.HexUtils;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.util.Base64;
+import java.util.Map;
+
+@RestController
+@Slf4j
+public class GeneralDataReceiver {
+
+ @Resource
+ IGeneralService defaultService;
+
+ @RequestMapping("/aep/data/string")
+ public Object aepDataString(@RequestBody Map dataMap) {
+ log.info("收到AEP平台推送消息:{}", JSONObject.toJSONString(dataMap));
+ log.debug("deviceId: {}, productId: {}, IMEI: {}, timestamp: {}", dataMap.get("deviceId"), dataMap.get("productId"), dataMap.get("IMEI"), dataMap.get("timestamp"));
+
+ // 从推送的数据中获取消息帧
+ String frameStr = new String(getFrameStringFromData(dataMap));
+ log.info("字符串消息帧:{}", frameStr);
+
+ return ResponseData.success();
+ }
+
+ @RequestMapping("/aep/data/hex")
+ public Object aepDataHex(@RequestBody Map dataMap) {
+ log.info("收到AEP平台推送消息:{}", JSONObject.toJSONString(dataMap));
+ log.debug("deviceId: {}, productId: {}, IMEI: {}, timestamp: {}", dataMap.get("deviceId"), dataMap.get("productId"), dataMap.get("IMEI"), dataMap.get("timestamp"));
+
+ // 从推送的数据中获取消息帧
+ byte[] frameBytes = getFrameStringFromData(dataMap);
+ log.info("HEX字节消息帧:{}", HexUtils.toHexString(frameBytes).toUpperCase());
+
+ BirmmBaseFrame birmmFrame = defaultService.dataParse(frameBytes);
+ if (birmmFrame != null) {
+ log.info("HEX字节消息解析成功:{}", birmmFrame);
+ }
+
+ // 返回给电信AEP平台
+ return ResponseData.success();
+ }
+
+ private byte[] getFrameStringFromData(Map dataMap) {
+ byte[] frameStr = new byte[]{};
+
+ if (!dataMap.containsKey("payload")) {
+ log.error("消息帧不含payload字段");
+ return frameStr;
+ }
+
+ // 判断是否有profile
+ boolean hasProfile = false;
+ if (dataMap.containsKey("profile")) {
+ hasProfile = (Boolean) dataMap.get("profile");
+ }
+
+ JSONObject payload = (JSONObject) dataMap.get("payload");
+ // base64格式的消息 电信平台推送的内容
+ String dataBase64 = "";
+ if (hasProfile) {
+ if (!payload.containsKey("serviceData")) {
+ log.error("payload字段中不含serviceData字段");
+ } else {
+ JSONObject serviceData = payload.getJSONObject("serviceData");
+ if (!serviceData.containsKey("Value")) {
+ log.error("serviceData字段中不含Value字段");
+ } else {
+ dataBase64 = serviceData.getString("Value");
+ }
+ }
+ } else {
+ if (payload.containsKey("APPdata")) {
+ dataBase64 = payload.getString("APPdata");
+ } else {
+ log.error("payload字段中不含APPdata字段");
+ }
+ }
+
+ if (!dataBase64.isEmpty()) {
+ frameStr = Base64.getDecoder().decode(dataBase64); // base64解码
+ }
+
+ return frameStr;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java
new file mode 100644
index 0000000..ae6706a
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseFrame.java
@@ -0,0 +1,40 @@
+package com.casic.missiles.frame;
+
+import lombok.Data;
+import java.util.List;
+
+@Data
+public class BirmmBaseFrame {
+
+ // 前导码 固定为A3
+ final String PRE_CODE = "A3";
+
+ // 协议版本 固定为20
+ final String VERSION = "20";
+
+ // 帧长度 后续到CRC字段前的字节总长度 不包括长度字段和CRC字段
+ int length;
+
+ // 设备编号
+ String devCode;
+
+ // 通信方式
+ String communicationType;
+
+ // 目标节点地址
+ String destinationAddr;
+
+ // PDU类型
+ String pduType;
+
+ // 序号
+ String sequence;
+
+ // 业务字段List
+ String tagListString;
+
+ List tagList;
+
+ // CRC
+ String crc;
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java
new file mode 100644
index 0000000..2285f9a
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmBaseTag.java
@@ -0,0 +1,11 @@
+package com.casic.missiles.frame;
+
+import lombok.Data;
+
+@Data
+public class BirmmBaseTag {
+
+ private String oid;
+ private int tagLen;
+ private String valueStr;
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java
new file mode 100644
index 0000000..b1fd65c
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmFrameBuilderFactory.java
@@ -0,0 +1,9 @@
+package com.casic.missiles.frame;
+
+public class BirmmFrameBuilderFactory {
+
+ public static BirmmBaseFrame createBirmmFrame(String pduType) {
+
+ return null;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmTagBuilderFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmTagBuilderFactory.java
new file mode 100644
index 0000000..95ebdab
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/BirmmTagBuilderFactory.java
@@ -0,0 +1,33 @@
+package com.casic.missiles.frame;
+
+import com.casic.missiles.enums.BirmmTagAttributeEnums;
+import com.casic.missiles.frame.commanTag.*;
+
+public class BirmmTagBuilderFactory {
+
+ public static BirmmBaseTag createTagByOid(String oid) {
+ BirmmTagAttributeEnums tag = BirmmTagAttributeEnums.toType(oid);
+ if (null != tag) {
+ switch (tag) {
+ case CELL_TAG:
+ return new CellTag();
+
+ case DATE_TAG:
+ return new DateTag();
+
+ case PIC_TAG:
+ return new PCITag();
+
+ case SNR_TAG:
+ return new SNRTag();
+
+ case RSRP_TAG:
+ return new RSRPTag();
+
+ default:
+ return null;
+ }
+ }
+ return null;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/CellTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/CellTag.java
new file mode 100644
index 0000000..b0e0360
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/CellTag.java
@@ -0,0 +1,20 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class CellTag extends BirmmBaseTag {
+
+ final String CELL_TAG_OID = "60000020";
+
+ int cellVal;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ cellVal = Integer.parseInt(valueStr, 16);
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/DateTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/DateTag.java
new file mode 100644
index 0000000..e8c5db4
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/DateTag.java
@@ -0,0 +1,30 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.time.LocalDate;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class DateTag extends BirmmBaseTag {
+
+ final String DATE_TAG_OID = "10000050";
+
+ LocalDate date;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ String hexY = valueStr.substring(0, 2);
+ String hexM = valueStr.substring(2, 4);
+ String hexD = valueStr.substring(4, 6);
+
+ date = LocalDate.now();
+ date = date.withYear(BytesUtil.hexStringToUInt(hexY) + 2000);
+ date = date.withMonth(BytesUtil.hexStringToUInt(hexM));
+ date = date.withDayOfMonth(BytesUtil.hexStringToUInt(hexD));
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/PCITag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/PCITag.java
new file mode 100644
index 0000000..4433cea
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/PCITag.java
@@ -0,0 +1,22 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class PCITag extends BirmmBaseTag {
+
+ final String PCI_TAG_OID = "60000511";
+
+ // TYPE_U16整型,主小区物理小区号PCI,范围: 0 – 503
+ int pci;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ pci = BytesUtil.hexStringToUInt(valueStr);
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/RSRPTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/RSRPTag.java
new file mode 100644
index 0000000..d1bb0a8
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/RSRPTag.java
@@ -0,0 +1,22 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class RSRPTag extends BirmmBaseTag {
+
+ final String RSRP_TAG_OID = "60000513";
+
+ //带符号整型,主小区RSRP值,单位dBm。仅在RRC-IDLE状态时可用 -140 ~ -40 越大越好
+ int rsrp;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ rsrp = BytesUtil.hexStringToSInt(valueStr);
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/SNRTag.java b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/SNRTag.java
new file mode 100644
index 0000000..3040799
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/frame/commanTag/SNRTag.java
@@ -0,0 +1,22 @@
+package com.casic.missiles.frame.commanTag;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.util.BytesUtil;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class SNRTag extends BirmmBaseTag {
+
+ final String SNR_TAG_OID = "60000516";
+
+ //带符号整型,主小区lart SNR值,单位dB。仅在RRC-IDLE状态时可用 -20 ~ 50 越大越好
+ int snr;
+
+ @Override
+ public void setValueStr(String valueStr) {
+ super.setValueStr(valueStr);
+ snr = BytesUtil.hexStringToSInt(valueStr);
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/BirmmProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/BirmmProtocolParser.java
new file mode 100644
index 0000000..d29e372
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/BirmmProtocolParser.java
@@ -0,0 +1,38 @@
+package com.casic.missiles.parser;
+
+import com.casic.missiles.frame.BirmmBaseTag;
+
+import java.util.List;
+
+/**
+ * BIRMM系列设备
+ * 一般设备协议解析
+ */
+public interface BirmmProtocolParser {
+
+ boolean preCheckFrame(byte[] frameBytes);
+
+ boolean validateCRC(byte[] frameBytes);
+
+ boolean validateLength(byte[] tagBytes, int length);
+
+ String getFrameHeader(byte[] frameBytes);
+
+ int getLength(byte[] frameBytes);
+
+ String getDevCode(byte[] frameBytes);
+
+ String getCommunicationType(byte[] frameBytes);
+
+ String getDestinationAddr(byte[] frameBytes);
+
+ String getPDUType(byte[] frameBytes);
+
+ String getSequence(byte[] frameBytes);
+
+ String getTagListString(byte[] frameBytes);
+ List getTagList(byte[] tagBytes);
+
+ String getCRC(byte[] frameBytes);
+ String getToBeVerifiedCRCBytes(byte[] frameBytes);
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/impl/BirmmProtocolParserImpl.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/impl/BirmmProtocolParserImpl.java
new file mode 100644
index 0000000..11c542d
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/impl/BirmmProtocolParserImpl.java
@@ -0,0 +1,145 @@
+package com.casic.missiles.parser.impl;
+
+import com.casic.missiles.enums.BirmmFrameAttributeEnums;
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.frame.BirmmTagBuilderFactory;
+import com.casic.missiles.parser.BirmmProtocolParser;
+import com.casic.missiles.parser.crc.CRCUtil;
+import com.casic.missiles.util.BytesUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Component
+@Slf4j
+public class BirmmProtocolParserImpl implements BirmmProtocolParser {
+ @Override
+ public boolean preCheckFrame(byte[] frameBytes) {
+ if (!checkPreCodeAndVersion(frameBytes)) {
+ log.error("帧头不符合协议:{}", getFrameHeader(frameBytes));
+ return false;
+ }
+
+ if (!preCheckLength(frameBytes)) {
+ log.error("帧长度不满足最低长度要求:{}", frameBytes.length);
+ return false;
+ }
+
+ if (!validateCRC(frameBytes)) {
+ log.error("CRC校验不通过:{}", getCRC(frameBytes));
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public boolean validateCRC(byte[] frameBytes) {
+ byte[] toBeVerifiedBytes = new byte[frameBytes.length - BirmmFrameAttributeEnums.CRC.getLength()];
+ System.arraycopy(frameBytes, 0, toBeVerifiedBytes, 0, toBeVerifiedBytes.length);
+
+ // 计算CRC值
+ CRCUtil crcUtil = new CRCUtil(CRCUtil.Parameters.CRC16MODBUS);
+ long crcVal = crcUtil.calculateCRC(toBeVerifiedBytes);
+ // 格式化输出
+ String crcStr = String.format("%0" + BirmmFrameAttributeEnums.CRC.getLength() * 2 + "X", crcVal);
+
+ return getCRC(frameBytes).equalsIgnoreCase(crcStr);
+ }
+
+ @Override
+ public boolean validateLength(byte[] tagBytes, int length) {
+ return false;
+ }
+
+ @Override
+ public String getFrameHeader(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.HEADER.getOffset(), BirmmFrameAttributeEnums.HEADER.getLength()); // byte[0] ~ byte[1] 表示A320
+ }
+
+ @Override
+ public int getLength(byte[] frameBytes) {
+ byte[] lengthBytes = new byte[BirmmFrameAttributeEnums.LENGTH.getLength()];
+ System.arraycopy(frameBytes, BirmmFrameAttributeEnums.LENGTH.getOffset(), lengthBytes, 0, lengthBytes.length); // byte[2] ~ byte[3] 表示长度
+
+ return BytesUtil.hexStringToUInt(lengthBytes);
+ }
+
+ @Override
+ public String getDevCode(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.DEVICE_CODE.getOffset(), BirmmFrameAttributeEnums.DEVICE_CODE.getLength()); // byte[4] ~ byte[10] 表示设备编号
+ }
+
+ @Override
+ public String getCommunicationType(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.COMM_TYPE.getOffset(), BirmmFrameAttributeEnums.COMM_TYPE.getLength()); // byte[11] 表示通信方式
+ }
+
+ @Override
+ public String getDestinationAddr(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.DEST_ADDR.getOffset(), BirmmFrameAttributeEnums.DEST_ADDR.getLength()); // byte[12] ~ byte[13] 表示目标节点地址
+ }
+
+ @Override
+ public String getPDUType(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.PDU_TYPE.getOffset(), BirmmFrameAttributeEnums.PDU_TYPE.getLength()); // byte[14] ~ byte[15] 表示PDUType
+ }
+
+ @Override
+ public String getSequence(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, BirmmFrameAttributeEnums.SEQ.getOffset(), BirmmFrameAttributeEnums.SEQ.getLength()); // byte[16] 表示序号
+ }
+
+ @Override
+ public String getTagListString(byte[] frameBytes) {
+ // 帧结构其余字节长度为 18 = 1+1+2+6+1+2+2+1+2
+ return BytesUtil.extractHexString(frameBytes, 16, frameBytes.length - 18); // 从byte[16]开始
+ }
+
+ @Override
+ public List getTagList(byte[] tagBytes) {
+ // 必须包含OID和长度 4 + 2
+ if (tagBytes.length < 6) {
+ return null;
+ }
+ List tagList = new ArrayList<>();
+ int idx = 0;
+ while (idx + 6 < tagBytes.length) {
+ String oid = BytesUtil.extractHexString(tagBytes, idx, 4);
+ int tagLen = BytesUtil.hexStringToUInt(new byte[] {tagBytes[idx + 4], tagBytes[idx + 5]});
+ idx += 6;
+ if (tagLen + idx < tagBytes.length) {
+ BirmmBaseTag tagBase = BirmmTagBuilderFactory.createTagByOid(oid);
+ if (null != tagBase) {
+ String valStr = BytesUtil.extractHexString(tagBytes, idx, tagLen);
+ tagBase.setValueStr(valStr);
+
+ tagList.add(tagBase);
+ }
+ }
+ idx += tagLen;
+ }
+
+ return tagList;
+ }
+
+ private boolean checkPreCodeAndVersion(byte[] frameBytes) {
+ String headerStr = getFrameHeader(frameBytes);
+ return headerStr.equalsIgnoreCase(BirmmFrameAttributeEnums.HEADER.getDefaultStr());
+ }
+
+ private boolean preCheckLength(byte[] frameBytes) {
+ return frameBytes.length >= 18;
+ }
+
+ @Override
+ public String getCRC(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, frameBytes.length - 2, BirmmFrameAttributeEnums.CRC.getLength()); // 最后两个字节表示CRC校验码
+ }
+
+ @Override
+ public String getToBeVerifiedCRCBytes(byte[] frameBytes) {
+ return BytesUtil.extractHexString(frameBytes, 0, frameBytes.length - 2); // 所有字节都用于生成CRC校验码
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/service/GeneralServiceImpl.java b/sensorhub-core/src/main/java/com/casic/missiles/service/GeneralServiceImpl.java
new file mode 100644
index 0000000..118a8de
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/service/GeneralServiceImpl.java
@@ -0,0 +1,65 @@
+package com.casic.missiles.service;
+
+import com.casic.missiles.frame.BirmmBaseFrame;
+import com.casic.missiles.frame.BirmmBaseTag;
+import com.casic.missiles.frame.BirmmFrameBuilderFactory;
+import com.casic.missiles.parser.BirmmProtocolParser;
+import com.casic.missiles.parser.safe.SafeStrategy;
+import com.casic.missiles.parser.safe.impl.Sm4;
+import com.casic.missiles.util.SpringContextUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.tomcat.util.buf.HexUtils;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import javax.annotation.Resource;
+
+@Service
+@Slf4j
+public class GeneralServiceImpl implements IGeneralService {
+
+ @Resource
+ BirmmProtocolParser protocol;
+
+ @Override
+ public BirmmBaseFrame dataParse(byte[] frame) {
+ boolean frameValid = protocol.preCheckFrame(frame);
+ if (frameValid) {
+ // 解析长度
+ int length = protocol.getLength(frame);
+
+ // 解析得到设备编号
+ String devCode = protocol.getDevCode(frame);
+
+ // 解析通信方式
+ String commType = protocol.getCommunicationType(frame);
+
+ // 解析目标节点地址
+ String destAddr = protocol.getDestinationAddr(frame);
+
+ // 解析得到PDUType
+ String pduType = protocol.getPDUType(frame);
+
+ // 解析序号
+ String seq = protocol.getSequence(frame);
+
+ // 加密后的业务字段
+ String tagListStr = protocol.getTagListString(frame);
+
+ log.info("帧结构字段解析结果:[长度:{}],[设备编号:{}],[通信方式:{}],[目标节点地址:{}],[PDUType:{}],[序号:{}]", length, devCode, commType, destAddr, pduType, seq);
+
+ // 解密
+ SafeStrategy safeStrategy = SpringContextUtil.getBean(Sm4.class);
+ byte[] plainBytes = safeStrategy.decryption(tagListStr);
+ String plainTagListStr = HexUtils.toHexString(plainBytes).toUpperCase();
+
+ log.info("业务字段:{}", plainTagListStr);
+
+ // 获得业务字段tagList
+ List tagList = protocol.getTagList(plainBytes);
+ System.out.println(tagList.size());
+ }
+
+ return null;
+ }
+}
diff --git a/sensorhub-core/src/main/java/com/casic/missiles/service/IGeneralService.java b/sensorhub-core/src/main/java/com/casic/missiles/service/IGeneralService.java
new file mode 100644
index 0000000..5e27b33
--- /dev/null
+++ b/sensorhub-core/src/main/java/com/casic/missiles/service/IGeneralService.java
@@ -0,0 +1,8 @@
+package com.casic.missiles.service;
+
+import com.casic.missiles.frame.BirmmBaseFrame;
+
+public interface IGeneralService {
+
+ BirmmBaseFrame dataParse(byte[] frame);
+}
diff --git a/sensorhub-support/pom.xml b/sensorhub-support/pom.xml
index 56d8813..abc3dda 100644
--- a/sensorhub-support/pom.xml
+++ b/sensorhub-support/pom.xml
@@ -26,6 +26,12 @@
+ com.alibaba
+ fastjson
+ ${fastjson.version}
+
+
+
org.apache.commons
commons-lang3
3.1
diff --git a/sensorhub-support/src/main/java/com/casic/missiles/enums/BirmmFrameAttributeEnums.java b/sensorhub-support/src/main/java/com/casic/missiles/enums/BirmmFrameAttributeEnums.java
new file mode 100644
index 0000000..626e25a
--- /dev/null
+++ b/sensorhub-support/src/main/java/com/casic/missiles/enums/BirmmFrameAttributeEnums.java
@@ -0,0 +1,43 @@
+package com.casic.missiles.enums;
+
+import lombok.Getter;
+
+/**
+ * 帧结构属性枚举
+ */
+@Getter
+public enum BirmmFrameAttributeEnums {
+ PREAMBLE("Preamble", 1, 0, "A3"),
+ VERSION("Version", 1, 1, "20"),
+ HEADER("Header", 2, 0, "A320"),
+ LENGTH("Length", 2, 2, "0000"),
+ DEVICE_CODE("DeviceCode", 6, 4, ""),
+ COMM_TYPE("CommunicationType", 1, 10, "00"),
+ DEST_ADDR("DestinationAddr", 2, 11, "0000"),
+ PDU_TYPE("PDUType", 2, 13, "0000"),
+ SEQ("Sequence", 1, 15, "00"),
+ CRC("CRC", 2, -1, "0000");
+
+ /**
+ * 名称
+ */
+ private final String name;
+
+ /**
+ * 属性字节长度
+ */
+ private final int length;
+ /**
+ * 属性的偏移量
+ */
+ private final int offset;
+
+ private final String defaultStr;
+
+ BirmmFrameAttributeEnums(String name, int length, int offset, String defaultStr) {
+ this.name = name;
+ this.length = length;
+ this.offset = offset;
+ this.defaultStr = defaultStr;
+ }
+}
diff --git a/sensorhub-support/src/main/java/com/casic/missiles/enums/BirmmTagAttributeEnums.java b/sensorhub-support/src/main/java/com/casic/missiles/enums/BirmmTagAttributeEnums.java
new file mode 100644
index 0000000..1df2e90
--- /dev/null
+++ b/sensorhub-support/src/main/java/com/casic/missiles/enums/BirmmTagAttributeEnums.java
@@ -0,0 +1,36 @@
+package com.casic.missiles.enums;
+
+import lombok.Getter;
+
+import java.util.stream.Stream;
+
+/**
+ * 帧结构属性枚举
+ */
+@Getter
+public enum BirmmTagAttributeEnums {
+ CELL_TAG("60000020", 1),
+ DATE_TAG("10000050", 3),
+ PIC_TAG("60000511", 2),
+ RSRP_TAG("60000513", 2),
+ SNR_TAG("60000516", 2);
+
+ /**
+ * 名称
+ */
+ private final String name;
+
+ /**
+ * 属性字节长度
+ */
+ private final int length;
+
+ BirmmTagAttributeEnums(String name, int length) {
+ this.name = name;
+ this.length = length;
+ }
+
+ public static BirmmTagAttributeEnums toType(String oid) {
+ return Stream.of(BirmmTagAttributeEnums.values()).filter(p -> p.name.equalsIgnoreCase(oid)).findAny().orElse(null);
+ }
+}
diff --git a/sensorhub-support/src/main/java/com/casic/missiles/enums/FrameAttributeEnums.java b/sensorhub-support/src/main/java/com/casic/missiles/enums/FrameAttributeEnums.java
deleted file mode 100644
index 1fda676..0000000
--- a/sensorhub-support/src/main/java/com/casic/missiles/enums/FrameAttributeEnums.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package com.casic.missiles.enums;
-
-/**
- * 帧结构属性枚举
- */
-public enum FrameAttributeEnums {
- PREAMBLE("preamble", 1, 0),
- VERSION("Version", 1, 1),
- LENG("Leng", 2, 2),
- DEVICE_ID("Device-Id", 6, 4),
- CONN_TYPE("通信方式", 1, 10),
- DEST_ADDR("目标节点地址", 2, 11),
- PDU_TYPE("PDUType", 2, 13),
- SEQ("Seq", 1, 15),
- CRC("CRC", 2, -1);
-// GetRequest("GetRequest", 1, "服务器GET请求", FrameStructEnum.OID_LIST_STRUCT.getValue()),
-// WakeupRequest("WakeupRequest", 10, "服务器唤醒设备", FrameStructEnum.OID_LIST_STRUCT.getValue()),
-// SetRequest("SetRequest", 3, "设置设备参数请求", FrameStructEnum.TAG_LIST_STRUCT.getValue()),
-// GetResponse("GetResponse", 2, "设备响应GET请求", FrameStructEnum.TAG_LIST_STRUCT.getValue()),
-// TrapRequest("TrapRequest", 4, "设备主动上报", FrameStructEnum.TAG_LIST_STRUCT.getValue()),
-// WakeupResponse ("WakeupResponse", 11, "设备响应服务器唤醒", FrameStructEnum.TAG_LIST_STRUCT.getValue()),
-// TrapResponse ("TrapResponse", 5, "设备主动上报响应", FrameStructEnum.TAG_STRUCT.getValue()),
-// OnlineRequest ("OnlineRequest", 6, "用于设备检查连接", FrameStructEnum.TAG_STRUCT.getValue()),
-// OnlineResponse ("OnlineResponse", 7, "用于设备检查连接", FrameStructEnum.TAG_STRUCT.getValue()),
-// StarupRequest ("StarupRequest", 8, "设备上报开机信息", FrameStructEnum.TAG_STRUCT.getValue()),
-// StarupResponse ("StarupResponse", 9, "设备上报开机信息响应", FrameStructEnum.TAG_STRUCT.getValue()),
-// SetResponse ("SetResponse", 12, "设备响应SET请求", FrameStructEnum.TAG_STRUCT.getValue());
- /**
- * 名称
- */
- private String name;
-
- /**
- * 属性字节长度
- */
- private int length;
- /**
- * 属性的偏移量
- */
- private int offset;
-
- FrameAttributeEnums(String name, int length, int offset) {
- this.name = name;
- this.length = length;
- this.offset = offset;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public int getLength() {
- return length;
- }
-
- public void setLength(int length) {
- this.length = length;
- }
-
- public int getOffset() {
- return offset;
- }
-
- public void setOffset(int offset) {
- this.offset = offset;
- }
-}
diff --git a/sensorhub-support/src/main/java/com/casic/missiles/enums/OperatorTypeEnum.java b/sensorhub-support/src/main/java/com/casic/missiles/enums/OperatorTypeEnum.java
deleted file mode 100644
index 7dd1824..0000000
--- a/sensorhub-support/src/main/java/com/casic/missiles/enums/OperatorTypeEnum.java
+++ /dev/null
@@ -1,53 +0,0 @@
-//package com.casic.missiles.enums;
-//
-//import java.util.Arrays;
-//
-///**
-// * 操作类型
-// */
-//public enum OperatorTypeEnum {
-//
-//// GetRequest("GetRequest", 1, "服务器GET请求", FrameStructEnum.OID_LIST_STRUCT.getValue()),
-//// WakeupRequest("WakeupRequest", 10, "服务器唤醒设备", FrameStructEnum.OID_LIST_STRUCT.getValue()),
-//// SetRequest("SetRequest", 3, "设置设备参数请求", FrameStructEnum.TAG_LIST_STRUCT.getValue()),
-//// GetResponse("GetResponse", 2, "设备响应GET请求", FrameStructEnum.TAG_LIST_STRUCT.getValue()),
-//// TrapRequest("TrapRequest", 4, "设备主动上报", FrameStructEnum.TAG_LIST_STRUCT.getValue()),
-//// WakeupResponse ("WakeupResponse", 11, "设备响应服务器唤醒", FrameStructEnum.TAG_LIST_STRUCT.getValue()),
-//// TrapResponse ("TrapResponse", 5, "设备主动上报响应", FrameStructEnum.TAG_STRUCT.getValue()),
-//// OnlineRequest ("OnlineRequest", 6, "用于设备检查连接", FrameStructEnum.TAG_STRUCT.getValue()),
-//// OnlineResponse ("OnlineResponse", 7, "用于设备检查连接", FrameStructEnum.TAG_STRUCT.getValue()),
-//// StarupRequest ("StarupRequest", 8, "设备上报开机信息", FrameStructEnum.TAG_STRUCT.getValue()),
-//// StarupResponse ("StarupResponse", 9, "设备上报开机信息响应", FrameStructEnum.TAG_STRUCT.getValue()),
-//// SetResponse ("SetResponse", 12, "设备响应SET请求", FrameStructEnum.TAG_STRUCT.getValue());
-//
-// private String name;
-// private int value;
-// private String desc;
-// private int frameStuct;
-//
-// OperatorTypeEnum(String name, int value, String desc, int frameStruct) {
-// this.name = name;
-// this.value = value;
-// this.desc = desc;
-// this.frameStuct = frameStruct;
-// }
-//
-// public static OperatorTypeEnum getEnumByOperatorType (int value) {
-// return Arrays.stream(OperatorTypeEnum.values()).filter(item -> item.getValue() == value).findFirst().get();
-// }
-// public String getName() {
-// return name;
-// }
-//
-// public int getValue() {
-// return value;
-// }
-//
-// public String getDesc() {
-// return desc;
-// }
-//
-// public int getFrameStruct() {
-// return frameStuct;
-// }
-//}
diff --git a/sensorhub-support/src/main/java/com/casic/missiles/util/BytesUtil.java b/sensorhub-support/src/main/java/com/casic/missiles/util/BytesUtil.java
new file mode 100644
index 0000000..c09b998
--- /dev/null
+++ b/sensorhub-support/src/main/java/com/casic/missiles/util/BytesUtil.java
@@ -0,0 +1,37 @@
+package com.casic.missiles.util;
+
+import org.apache.tomcat.util.buf.HexUtils;
+
+public class BytesUtil {
+
+ public static String extractHexString(byte[] source, int start, int length) {
+ byte[] bytes = new byte[length];
+ System.arraycopy(source, start, bytes, 0, length);
+ return HexUtils.toHexString(bytes).toUpperCase();
+ }
+
+ public static int hexStringToUInt(byte[] bytes) {
+ int result = 0;
+ for (byte b : bytes) {
+ result = result * 256 + Byte.toUnsignedInt(b);
+ }
+ return result;
+ }
+
+ public static int hexStringToSInt(byte[] bytes) {
+ int result = 0;
+ for (int i = 0; i < Math.min(bytes.length, 4); i++) {
+ result <<= 8; // 左移8位
+ result |= bytes[i]; // 保存byte值到 result 最低的8位上
+ }
+ return result;
+ }
+
+ public static int hexStringToUInt(String str) {
+ return hexStringToUInt(HexUtils.fromHexString(str));
+ }
+
+ public static int hexStringToSInt(String str) {
+ return hexStringToSInt(HexUtils.fromHexString(str));
+ }
+}
diff --git a/sensorhub-support/src/main/java/com/casic/missiles/util/HttpClientUtil.java b/sensorhub-support/src/main/java/com/casic/missiles/util/HttpClientUtil.java
deleted file mode 100644
index 81a221a..0000000
--- a/sensorhub-support/src/main/java/com/casic/missiles/util/HttpClientUtil.java
+++ /dev/null
@@ -1,127 +0,0 @@
-//package com.casic.missiles.util;
-//
-//import lombok.AllArgsConstructor;
-//import org.apache.http.client.methods.CloseableHttpResponse;
-//import org.apache.http.client.methods.HttpGet;
-//import org.apache.http.client.utils.URIBuilder;
-//import org.apache.http.conn.ssl.NoopHostnameVerifier;
-//import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
-//import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
-//import org.apache.http.impl.client.CloseableHttpClient;
-//import org.apache.http.impl.client.HttpClients;
-//import org.apache.http.ssl.SSLContexts;
-//import org.apache.http.util.EntityUtils;
-//import org.springframework.stereotype.Component;
-//
-//import java.io.IOException;
-//import java.net.URI;
-//import java.util.HashMap;
-//import java.util.Map;
-//
-//@Component
-//@AllArgsConstructor
-//public class HttpClientUtil {
-//
-// public String sendHourGet() {
-// String url = "http://123";
-// Map param = new HashMap<>();
-// param.put("key", "key");
-// param.put("location", "apiloction");
-// param.put("language", "zh-Hans");
-// param.put("unit", "c");
-// param.put("start", "1");
-// param.put("hours", "24");
-// // 创建Httpclient对象
-// CloseableHttpClient httpclient = HttpClients.createDefault();
-// String resultString = "";
-// CloseableHttpResponse response = null;
-// try {
-// httpclient = HttpClients.custom()
-// .setSSLSocketFactory(new SSLConnectionSocketFactory(SSLContexts.custom()
-// //忽略掉对服务器端证书的校验
-// .loadTrustMaterial(null, new TrustSelfSignedStrategy())
-// .build(), NoopHostnameVerifier.INSTANCE))
-// .build();
-// // 创建uri
-// URIBuilder builder = new URIBuilder(url);
-// if (param != null) {
-// for (String key : param.keySet()) {
-// builder.addParameter(key, param.get(key));
-// }
-// }
-// URI uri = builder.build();
-// // 创建http GET请求
-// HttpGet httpGet = new HttpGet(uri);
-// // 执行请求
-// response = httpclient.execute(httpGet);
-// // 判断返回状态是否为200
-// if (response.getStatusLine().getStatusCode() == 200) {
-// resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
-// }
-// } catch (Exception e) {
-// e.printStackTrace();
-// } finally {
-// try {
-// if (response != null) {
-// response.close();
-// }
-// httpclient.close();
-// } catch (IOException e) {
-// e.printStackTrace();
-// }
-// }
-// return resultString;
-// }
-//
-// public String sendDayGet() {
-// String url = "http://123";
-// Map param = new HashMap<>();
-// param.put("key", "key");
-// param.put("location", "location");
-// param.put("language", "zh-Hans");
-// param.put("unit", "c");
-// param.put("start", "0");
-// param.put("hours", "24");
-// // 创建Httpclient对象
-// CloseableHttpClient httpclient = HttpClients.createDefault();
-// String resultString = "";
-// CloseableHttpResponse response = null;
-// try {
-// httpclient = HttpClients.custom()
-// .setSSLSocketFactory(new SSLConnectionSocketFactory(SSLContexts.custom()
-// //忽略掉对服务器端证书的校验
-// .loadTrustMaterial(null, new TrustSelfSignedStrategy())
-// .build(), NoopHostnameVerifier.INSTANCE))
-// .build();
-// // 创建uri
-// URIBuilder builder = new URIBuilder(url);
-// if (param != null) {
-// for (String key : param.keySet()) {
-// builder.addParameter(key, param.get(key));
-// }
-// }
-// URI uri = builder.build();
-// // 创建http GET请求
-// HttpGet httpGet = new HttpGet(uri);
-// // 执行请求
-// response = httpclient.execute(httpGet);
-// // 判断返回状态是否为200
-// if (response.getStatusLine().getStatusCode() == 200) {
-// resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
-// }
-// } catch (Exception e) {
-// e.printStackTrace();
-// } finally {
-// try {
-// if (response != null) {
-// response.close();
-// }
-// httpclient.close();
-// } catch (IOException e) {
-// e.printStackTrace();
-// }
-// }
-// return resultString;
-// }
-//
-//}