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