diff --git a/pom.xml b/pom.xml index ea8fb2d..aa28411 100644 --- a/pom.xml +++ b/pom.xml @@ -18,7 +18,6 @@ - org.springframework.boot spring-boot-starter @@ -47,7 +46,8 @@ mysql mysql-connector-java - 8.0.28 + 5.1.44 + compile @@ -88,21 +88,10 @@ 3.9 - - 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 + cn.hutool + hutool-all + 5.8.31 @@ -110,83 +99,32 @@ - org.apache.maven.plugins - maven-jar-plugin + org.springframework.boot + spring-boot-maven-plugin + 2.1.3.RELEASE - - - *.properties - *.yml - *.yaml - *.xml - - - - - com.casic.CasicApplication - - true - - lib/ - - false - - - - config/ - - + true + + com.casic.CasicApplication + exec + true - - - - org.apache.maven.plugins - maven-dependency-plugin - copy-dependencies - package - copy-dependencies + repackage - ${project.build.directory}/lib - - - - - - - maven-resources-plugin - - - copy-resources - package - - copy-resources - - - - - - src/main/resources/ - - *.properties - *.yml - *.yaml - *.xml - - - - ${project.build.directory}/config - org.apache.maven.plugins - maven-compiler-plugin - 3.1 + maven-war-plugin + + + false + diff --git a/pom.xml b/pom.xml index ea8fb2d..aa28411 100644 --- a/pom.xml +++ b/pom.xml @@ -18,7 +18,6 @@ - org.springframework.boot spring-boot-starter @@ -47,7 +46,8 @@ mysql mysql-connector-java - 8.0.28 + 5.1.44 + compile @@ -88,21 +88,10 @@ 3.9 - - 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 + cn.hutool + hutool-all + 5.8.31 @@ -110,83 +99,32 @@ - org.apache.maven.plugins - maven-jar-plugin + org.springframework.boot + spring-boot-maven-plugin + 2.1.3.RELEASE - - - *.properties - *.yml - *.yaml - *.xml - - - - - com.casic.CasicApplication - - true - - lib/ - - false - - - - config/ - - + true + + com.casic.CasicApplication + exec + true - - - - org.apache.maven.plugins - maven-dependency-plugin - copy-dependencies - package - copy-dependencies + repackage - ${project.build.directory}/lib - - - - - - - maven-resources-plugin - - - copy-resources - package - - copy-resources - - - - - - src/main/resources/ - - *.properties - *.yml - *.yaml - *.xml - - - - ${project.build.directory}/config - org.apache.maven.plugins - maven-compiler-plugin - 3.1 + maven-war-plugin + + + false + diff --git a/src/main/java/com/casic/dao/mapper/mapping/BusDeviceMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/BusDeviceMapper.xml index 37c0c9c..3cb8b8d 100644 --- a/src/main/java/com/casic/dao/mapper/mapping/BusDeviceMapper.xml +++ b/src/main/java/com/casic/dao/mapper/mapping/BusDeviceMapper.xml @@ -1,6 +1,6 @@ - + @@ -10,11 +10,13 @@ + + - ID, DEVCODE, DEVICE_NAME, DEVICE_TYPE, MASTER_API_KEY, SECRET_KEY + ID, DEVCODE, DEVICE_NAME, DEVICE_TYPE, MASTER_API_KEY, SECRET_KEY, NB_DEVICE_ID, NB_PRODUCT_ID diff --git a/src/main/java/com/casic/dao/model/BusDevice.java b/src/main/java/com/casic/dao/model/BusDevice.java index 2288afe..ffc6712 100644 --- a/src/main/java/com/casic/dao/model/BusDevice.java +++ b/src/main/java/com/casic/dao/model/BusDevice.java @@ -57,4 +57,15 @@ @TableField("SECRET_KEY") private String secretKey; + /** + * NB平台DEVICEID + */ + @TableField("NB_DEVICE_ID") + private String nbDeviceId; + + /** + * NB平台PRODUCTID + */ + @TableField("NB_PRODUCT_ID") + private String nbProductId; } diff --git a/pom.xml b/pom.xml index ea8fb2d..aa28411 100644 --- a/pom.xml +++ b/pom.xml @@ -18,7 +18,6 @@ - org.springframework.boot spring-boot-starter @@ -47,7 +46,8 @@ mysql mysql-connector-java - 8.0.28 + 5.1.44 + compile @@ -88,21 +88,10 @@ 3.9 - - 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 + cn.hutool + hutool-all + 5.8.31 @@ -110,83 +99,32 @@ - org.apache.maven.plugins - maven-jar-plugin + org.springframework.boot + spring-boot-maven-plugin + 2.1.3.RELEASE - - - *.properties - *.yml - *.yaml - *.xml - - - - - com.casic.CasicApplication - - true - - lib/ - - false - - - - config/ - - + true + + com.casic.CasicApplication + exec + true - - - - org.apache.maven.plugins - maven-dependency-plugin - copy-dependencies - package - copy-dependencies + repackage - ${project.build.directory}/lib - - - - - - - maven-resources-plugin - - - copy-resources - package - - copy-resources - - - - - - src/main/resources/ - - *.properties - *.yml - *.yaml - *.xml - - - - ${project.build.directory}/config - org.apache.maven.plugins - maven-compiler-plugin - 3.1 + maven-war-plugin + + + false + diff --git a/src/main/java/com/casic/dao/mapper/mapping/BusDeviceMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/BusDeviceMapper.xml index 37c0c9c..3cb8b8d 100644 --- a/src/main/java/com/casic/dao/mapper/mapping/BusDeviceMapper.xml +++ b/src/main/java/com/casic/dao/mapper/mapping/BusDeviceMapper.xml @@ -1,6 +1,6 @@ - + @@ -10,11 +10,13 @@ + + - ID, DEVCODE, DEVICE_NAME, DEVICE_TYPE, MASTER_API_KEY, SECRET_KEY + ID, DEVCODE, DEVICE_NAME, DEVICE_TYPE, MASTER_API_KEY, SECRET_KEY, NB_DEVICE_ID, NB_PRODUCT_ID diff --git a/src/main/java/com/casic/dao/model/BusDevice.java b/src/main/java/com/casic/dao/model/BusDevice.java index 2288afe..ffc6712 100644 --- a/src/main/java/com/casic/dao/model/BusDevice.java +++ b/src/main/java/com/casic/dao/model/BusDevice.java @@ -57,4 +57,15 @@ @TableField("SECRET_KEY") private String secretKey; + /** + * NB平台DEVICEID + */ + @TableField("NB_DEVICE_ID") + private String nbDeviceId; + + /** + * NB平台PRODUCTID + */ + @TableField("NB_PRODUCT_ID") + private String nbProductId; } diff --git a/src/main/java/com/casic/senitnel/controller/SentinelDataController.java b/src/main/java/com/casic/senitnel/controller/SentinelDataController.java index 633c072..6e75bba 100644 --- a/src/main/java/com/casic/senitnel/controller/SentinelDataController.java +++ b/src/main/java/com/casic/senitnel/controller/SentinelDataController.java @@ -1,11 +1,14 @@ package com.casic.senitnel.controller; +import cn.hutool.core.util.ObjectUtil; +import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.casic.common.CasicFrame; import com.casic.common.general.ConfigFrame; import com.casic.dao.model.BusDevice; import com.casic.dao.service.IBusDeviceService; import com.casic.senitnel.service.ISentinelFrameService; +import com.casic.util.ReturnDTO; import com.casic.util.aep.AepCommandSend; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; @@ -56,6 +59,7 @@ if (frame != null) { // 回复响应 String replyFrameStr = frameService.replyMessage(frame.getDeviceCode(), frame.getSequence()); + log.info("回复响应: {}", JSON.toJSONString(replyFrameStr)); // 从数据库中获取master-api-key 回复响应消息 BusDevice device = deviceService.getDeviceByCode(frame.getDeviceCode()); @@ -87,13 +91,18 @@ } @RequestMapping("/sentinel/config/send") - public Object configSend(@RequestBody Map map) throws Exception { + public Object configSend(@RequestBody Map map) throws Exception { JSONObject retObj = new JSONObject(); log.info(JSONObject.toJSONString(map)); + if (!map.containsKey("devCode")) { + return new ReturnDTO<>(500, "设备编号不能为空"); + } + String devCode = (String) map.get("devCode"); + CasicFrame cmdFrame = new ConfigFrame(); cmdFrame.setDeviceType("21"); // 设备类型为 燃气监测桩(防第三方破坏) - cmdFrame.setDeviceCode((String) map.get("devCode")); + cmdFrame.setDeviceCode(devCode); cmdFrame.setSequence("01"); cmdFrame.setUptime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 当前时刻 @@ -102,12 +111,28 @@ cmdFrame.setMessageBody(messageBody); String frameStr = frameService.doBuildCommand(cmdFrame); + log.info("下发指令: {}", JSON.toJSONString(frameStr)); - // TODO-LIST - // 这三个参数根据设备编号从数据库中取 - String deviceId = (String) map.get("deviceId"); - String productId = (String) map.get("productId"); - String masterApiKey = (String) map.get("masterApiKey"); + // 从数据库中获取master-api-key 回复响应消息 + BusDevice device = deviceService.getDeviceByCode(devCode); + + // 判空及抛出异常 + if (ObjectUtil.isNull(device)) { + return new ReturnDTO<>(500, "没有找到编号为" + devCode + "设备"); + } + if (ObjectUtil.isNull(device.getNbDeviceId())) { + return new ReturnDTO<>(500, "NB_Device_ID为空"); + } + if (ObjectUtil.isNull(device.getNbProductId())) { + return new ReturnDTO<>(500, "NB_Product_ID为空"); + } + if (ObjectUtil.isNull(device.getMasterApiKey())) { + return new ReturnDTO<>(500, "masterApiKey为空"); + } + + String deviceId = device.getNbDeviceId(); + String productId = device.getNbProductId(); + String masterApiKey = device.getMasterApiKey(); AepCommandSend aepCommandSend = new AepCommandSend(deviceId, productId, masterApiKey); int code = aepCommandSend.handleAndReply(frameStr); diff --git a/src/main/java/com/casic/tube/controller/TubeDataController.java b/src/main/java/com/casic/tube/controller/TubeDataController.java index 4965449..b2476df 100644 --- a/src/main/java/com/casic/tube/controller/TubeDataController.java +++ b/src/main/java/com/casic/tube/controller/TubeDataController.java @@ -1,9 +1,14 @@ package com.casic.tube.controller; +import cn.hutool.core.util.ObjectUtil; +import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.casic.common.CasicFrame; import com.casic.common.general.ConfigFrame; +import com.casic.dao.model.BusDevice; +import com.casic.dao.service.IBusDeviceService; import com.casic.tube.service.ITubeFrameService; +import com.casic.util.ReturnDTO; import com.casic.util.aep.AepCommandSend; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.RequestBody; @@ -23,6 +28,9 @@ @Resource private ITubeFrameService frameService; + @Resource + private IBusDeviceService deviceService; + @RequestMapping("/tube/data/recv") public Object dataRecv(@RequestBody Map map) { JSONObject retObj = new JSONObject(); @@ -64,6 +72,11 @@ JSONObject retObj = new JSONObject(); log.info(JSONObject.toJSONString(map)); + if (!map.containsKey("devCode")) { + return new ReturnDTO<>(500, "设备编号不能为空"); + } + String devCode = (String) map.get("devCode"); + CasicFrame cmdFrame = new ConfigFrame(); cmdFrame.setDeviceType("34"); // 设备类型为 管线浓度监测设备-管盯(管线哨兵) cmdFrame.setDeviceCode((String) map.get("devCode")); @@ -75,12 +88,28 @@ cmdFrame.setMessageBody(messageBody); String frameStr = frameService.doBuildCommand(cmdFrame); + log.info("下发指令: {}", JSON.toJSONString(frameStr)); - // TODO-LIST - // 这三个参数根据设备编号从数据库中取 - String deviceId = (String) map.get("deviceId"); - String productId = (String) map.get("productId"); - String masterApiKey = (String) map.get("masterApiKey"); + // 从数据库中获取master-api-key 回复响应消息 + BusDevice device = deviceService.getDeviceByCode(devCode); + + // 判空及抛出异常 + if (ObjectUtil.isNull(device)) { + return new ReturnDTO<>(500, "没有找到编号为" + devCode + "设备"); + } + if (ObjectUtil.isNull(device.getNbDeviceId())) { + return new ReturnDTO<>(500, "NB_Device_ID为空"); + } + if (ObjectUtil.isNull(device.getNbProductId())) { + return new ReturnDTO<>(500, "NB_Product_ID为空"); + } + if (ObjectUtil.isNull(device.getMasterApiKey())) { + return new ReturnDTO<>(500, "masterApiKey为空"); + } + + String deviceId = device.getNbDeviceId(); + String productId = device.getNbProductId(); + String masterApiKey = device.getMasterApiKey(); AepCommandSend aepCommandSend = new AepCommandSend(deviceId, productId, masterApiKey); int code = aepCommandSend.handleAndReply(frameStr); diff --git a/pom.xml b/pom.xml index ea8fb2d..aa28411 100644 --- a/pom.xml +++ b/pom.xml @@ -18,7 +18,6 @@ - org.springframework.boot spring-boot-starter @@ -47,7 +46,8 @@ mysql mysql-connector-java - 8.0.28 + 5.1.44 + compile @@ -88,21 +88,10 @@ 3.9 - - 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 + cn.hutool + hutool-all + 5.8.31 @@ -110,83 +99,32 @@ - org.apache.maven.plugins - maven-jar-plugin + org.springframework.boot + spring-boot-maven-plugin + 2.1.3.RELEASE - - - *.properties - *.yml - *.yaml - *.xml - - - - - com.casic.CasicApplication - - true - - lib/ - - false - - - - config/ - - + true + + com.casic.CasicApplication + exec + true - - - - org.apache.maven.plugins - maven-dependency-plugin - copy-dependencies - package - copy-dependencies + repackage - ${project.build.directory}/lib - - - - - - - maven-resources-plugin - - - copy-resources - package - - copy-resources - - - - - - src/main/resources/ - - *.properties - *.yml - *.yaml - *.xml - - - - ${project.build.directory}/config - org.apache.maven.plugins - maven-compiler-plugin - 3.1 + maven-war-plugin + + + false + diff --git a/src/main/java/com/casic/dao/mapper/mapping/BusDeviceMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/BusDeviceMapper.xml index 37c0c9c..3cb8b8d 100644 --- a/src/main/java/com/casic/dao/mapper/mapping/BusDeviceMapper.xml +++ b/src/main/java/com/casic/dao/mapper/mapping/BusDeviceMapper.xml @@ -1,6 +1,6 @@ - + @@ -10,11 +10,13 @@ + + - ID, DEVCODE, DEVICE_NAME, DEVICE_TYPE, MASTER_API_KEY, SECRET_KEY + ID, DEVCODE, DEVICE_NAME, DEVICE_TYPE, MASTER_API_KEY, SECRET_KEY, NB_DEVICE_ID, NB_PRODUCT_ID diff --git a/src/main/java/com/casic/dao/model/BusDevice.java b/src/main/java/com/casic/dao/model/BusDevice.java index 2288afe..ffc6712 100644 --- a/src/main/java/com/casic/dao/model/BusDevice.java +++ b/src/main/java/com/casic/dao/model/BusDevice.java @@ -57,4 +57,15 @@ @TableField("SECRET_KEY") private String secretKey; + /** + * NB平台DEVICEID + */ + @TableField("NB_DEVICE_ID") + private String nbDeviceId; + + /** + * NB平台PRODUCTID + */ + @TableField("NB_PRODUCT_ID") + private String nbProductId; } diff --git a/src/main/java/com/casic/senitnel/controller/SentinelDataController.java b/src/main/java/com/casic/senitnel/controller/SentinelDataController.java index 633c072..6e75bba 100644 --- a/src/main/java/com/casic/senitnel/controller/SentinelDataController.java +++ b/src/main/java/com/casic/senitnel/controller/SentinelDataController.java @@ -1,11 +1,14 @@ package com.casic.senitnel.controller; +import cn.hutool.core.util.ObjectUtil; +import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.casic.common.CasicFrame; import com.casic.common.general.ConfigFrame; import com.casic.dao.model.BusDevice; import com.casic.dao.service.IBusDeviceService; import com.casic.senitnel.service.ISentinelFrameService; +import com.casic.util.ReturnDTO; import com.casic.util.aep.AepCommandSend; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; @@ -56,6 +59,7 @@ if (frame != null) { // 回复响应 String replyFrameStr = frameService.replyMessage(frame.getDeviceCode(), frame.getSequence()); + log.info("回复响应: {}", JSON.toJSONString(replyFrameStr)); // 从数据库中获取master-api-key 回复响应消息 BusDevice device = deviceService.getDeviceByCode(frame.getDeviceCode()); @@ -87,13 +91,18 @@ } @RequestMapping("/sentinel/config/send") - public Object configSend(@RequestBody Map map) throws Exception { + public Object configSend(@RequestBody Map map) throws Exception { JSONObject retObj = new JSONObject(); log.info(JSONObject.toJSONString(map)); + if (!map.containsKey("devCode")) { + return new ReturnDTO<>(500, "设备编号不能为空"); + } + String devCode = (String) map.get("devCode"); + CasicFrame cmdFrame = new ConfigFrame(); cmdFrame.setDeviceType("21"); // 设备类型为 燃气监测桩(防第三方破坏) - cmdFrame.setDeviceCode((String) map.get("devCode")); + cmdFrame.setDeviceCode(devCode); cmdFrame.setSequence("01"); cmdFrame.setUptime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 当前时刻 @@ -102,12 +111,28 @@ cmdFrame.setMessageBody(messageBody); String frameStr = frameService.doBuildCommand(cmdFrame); + log.info("下发指令: {}", JSON.toJSONString(frameStr)); - // TODO-LIST - // 这三个参数根据设备编号从数据库中取 - String deviceId = (String) map.get("deviceId"); - String productId = (String) map.get("productId"); - String masterApiKey = (String) map.get("masterApiKey"); + // 从数据库中获取master-api-key 回复响应消息 + BusDevice device = deviceService.getDeviceByCode(devCode); + + // 判空及抛出异常 + if (ObjectUtil.isNull(device)) { + return new ReturnDTO<>(500, "没有找到编号为" + devCode + "设备"); + } + if (ObjectUtil.isNull(device.getNbDeviceId())) { + return new ReturnDTO<>(500, "NB_Device_ID为空"); + } + if (ObjectUtil.isNull(device.getNbProductId())) { + return new ReturnDTO<>(500, "NB_Product_ID为空"); + } + if (ObjectUtil.isNull(device.getMasterApiKey())) { + return new ReturnDTO<>(500, "masterApiKey为空"); + } + + String deviceId = device.getNbDeviceId(); + String productId = device.getNbProductId(); + String masterApiKey = device.getMasterApiKey(); AepCommandSend aepCommandSend = new AepCommandSend(deviceId, productId, masterApiKey); int code = aepCommandSend.handleAndReply(frameStr); diff --git a/src/main/java/com/casic/tube/controller/TubeDataController.java b/src/main/java/com/casic/tube/controller/TubeDataController.java index 4965449..b2476df 100644 --- a/src/main/java/com/casic/tube/controller/TubeDataController.java +++ b/src/main/java/com/casic/tube/controller/TubeDataController.java @@ -1,9 +1,14 @@ package com.casic.tube.controller; +import cn.hutool.core.util.ObjectUtil; +import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.casic.common.CasicFrame; import com.casic.common.general.ConfigFrame; +import com.casic.dao.model.BusDevice; +import com.casic.dao.service.IBusDeviceService; import com.casic.tube.service.ITubeFrameService; +import com.casic.util.ReturnDTO; import com.casic.util.aep.AepCommandSend; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.RequestBody; @@ -23,6 +28,9 @@ @Resource private ITubeFrameService frameService; + @Resource + private IBusDeviceService deviceService; + @RequestMapping("/tube/data/recv") public Object dataRecv(@RequestBody Map map) { JSONObject retObj = new JSONObject(); @@ -64,6 +72,11 @@ JSONObject retObj = new JSONObject(); log.info(JSONObject.toJSONString(map)); + if (!map.containsKey("devCode")) { + return new ReturnDTO<>(500, "设备编号不能为空"); + } + String devCode = (String) map.get("devCode"); + CasicFrame cmdFrame = new ConfigFrame(); cmdFrame.setDeviceType("34"); // 设备类型为 管线浓度监测设备-管盯(管线哨兵) cmdFrame.setDeviceCode((String) map.get("devCode")); @@ -75,12 +88,28 @@ cmdFrame.setMessageBody(messageBody); String frameStr = frameService.doBuildCommand(cmdFrame); + log.info("下发指令: {}", JSON.toJSONString(frameStr)); - // TODO-LIST - // 这三个参数根据设备编号从数据库中取 - String deviceId = (String) map.get("deviceId"); - String productId = (String) map.get("productId"); - String masterApiKey = (String) map.get("masterApiKey"); + // 从数据库中获取master-api-key 回复响应消息 + BusDevice device = deviceService.getDeviceByCode(devCode); + + // 判空及抛出异常 + if (ObjectUtil.isNull(device)) { + return new ReturnDTO<>(500, "没有找到编号为" + devCode + "设备"); + } + if (ObjectUtil.isNull(device.getNbDeviceId())) { + return new ReturnDTO<>(500, "NB_Device_ID为空"); + } + if (ObjectUtil.isNull(device.getNbProductId())) { + return new ReturnDTO<>(500, "NB_Product_ID为空"); + } + if (ObjectUtil.isNull(device.getMasterApiKey())) { + return new ReturnDTO<>(500, "masterApiKey为空"); + } + + String deviceId = device.getNbDeviceId(); + String productId = device.getNbProductId(); + String masterApiKey = device.getMasterApiKey(); AepCommandSend aepCommandSend = new AepCommandSend(deviceId, productId, masterApiKey); int code = aepCommandSend.handleAndReply(frameStr); diff --git a/src/main/java/com/casic/util/ReturnDTO.java b/src/main/java/com/casic/util/ReturnDTO.java new file mode 100644 index 0000000..dad1068 --- /dev/null +++ b/src/main/java/com/casic/util/ReturnDTO.java @@ -0,0 +1,31 @@ +package com.casic.util; + +import lombok.Data; + +import java.io.Serializable; + +/** + * @Description: + * @Author: cz + * @Date: 2023/11/21 + */ +@Data +public class ReturnDTO implements Serializable { + private Integer code; + private String message; + private T data; + + public ReturnDTO(Integer code, String message, T data) { + this.code = code; + this.message = message; + this.data = data; + } + + public ReturnDTO(Integer code, String message) { + this.code = code; + this.message = message; + } + + public ReturnDTO() { + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/util/aep/AepCommandSend.java b/src/main/java/com/casic/util/aep/AepCommandSend.java index d35f83f..1350fdd 100644 --- a/src/main/java/com/casic/util/aep/AepCommandSend.java +++ b/src/main/java/com/casic/util/aep/AepCommandSend.java @@ -1,27 +1,36 @@ package com.casic.util.aep; +import cn.hutool.http.HttpRequest; +import cn.hutool.http.HttpResponse; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.casic.util.SpringContextUtil; -import com.ctg.ag.sdk.biz.AepDeviceCommandClient; -import com.ctg.ag.sdk.biz.aep_device_command.CreateCommandRequest; -import com.ctg.ag.sdk.biz.aep_device_command.CreateCommandResponse; +import lombok.Data; import lombok.extern.slf4j.Slf4j; import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; /** * @author cz * @date 2024-04-24 */ @Slf4j +@Data public class AepCommandSend { private String deviceId; private String productId; private String masterApiKey; + private Long offset = 0L; + private Long lastGetOffsetTime = 0L; + + private final String CREATE_COMMAND_PATH = "/aep_device_command/command"; + private final String CREATE_COMMAND_LWM2M_PROFILE_PATH = "/aep_device_command_lwm_profile/commandLwm2mProfile"; + public AepCommandSend() { } @@ -34,15 +43,47 @@ /** * 处理电信平台的报文解析,并组装回复报文,发送电信平台 * - * @param frameStr + * @param frameStr 业务数据的payload内容 */ public int handleAndReply(String frameStr) throws Exception { + HttpResponse response = createCommand(frameStr); + + JSONObject retObj = new JSONObject(); + try { + retObj = JSON.parseObject(new String(response.body().getBytes(), StandardCharsets.UTF_8)); + + log.info("AEP平台返回消息: {}", retObj.toJSONString()); + } catch (Exception ex) { + log.error("AEP平台发送失败,异常信息{}", ex.getMessage()); + } + + return (int) retObj.get("code"); + } + + private Long getTimeOffset() { AepConfig aepConfig = SpringContextUtil.getBean(AepConfig.class); - AepDeviceCommandClient client = getAepClient(aepConfig); + String timeUrl = aepConfig.getTimeUrl(); - CreateCommandRequest request = new CreateCommandRequest(); - request.setParamMasterKey(masterApiKey); + try { + HttpResponse response = HttpRequest.get(timeUrl).execute(); + String timeAg = response.header("x-ag-timestamp"); + return Long.parseLong(timeAg) - System.currentTimeMillis(); + } catch (Exception ex) { + return 0L; + } + } + + private String signature(Long timestamp, String appSecret, String appKey, String masterApiKey, byte[] bodyBytes) throws Exception { + return Signature.sign(appSecret, appKey, String.valueOf(timestamp), masterApiKey, bodyBytes); + } + + private HttpResponse createCommand(String frameStr) throws Exception { + AepConfig aepConfig = SpringContextUtil.getBean(AepConfig.class); + + String baseUrl = aepConfig.getBaseUrl(); + + // 消息体 AepCommandBody body = new AepCommandBody(); body.setDeviceId(deviceId); body.setProductId(productId); @@ -51,35 +92,29 @@ body.setLevel(aepConfig.getLevel()); body.setPayloadString(frameStr); - request.setBody(JSONObject.toJSONString(body).getBytes()); - log.info("向AEP平台发送指令: {}", JSON.toJSONString(body)); + log.info("向AEP平台发送消息: {}", JSON.toJSONString(body)); - JSONObject retObj = new JSONObject(); - - try { - CreateCommandResponse msgResponse = client.CreateCommand(request); - retObj = JSON.parseObject(new String(msgResponse.getBody(), StandardCharsets.UTF_8)); - - log.info("AEP平台返回消息: {}", retObj.toJSONString()); - } catch (Exception ex) { - log.error("AEP平台发送失败,异常信息{}", ex.getMessage()); - } finally { - client.shutdown(); + // 计算时间戳 用于签名 + long currentTime = System.currentTimeMillis(); + if (currentTime - lastGetOffsetTime > 300 * 1000) //300秒调用一次 + { + offset = getTimeOffset(); + lastGetOffsetTime = currentTime; } + long timestamp = currentTime + offset; - return (int) retObj.get("code"); - } + // 消息头 + Map header = new HashMap<>(); + header.put("application", aepConfig.getKey()); + header.put("version", "20190712225145"); + header.put("timestamp", String.valueOf(timestamp)); + header.put("MasterKey", masterApiKey); + header.put("signature", signature(timestamp, aepConfig.getSecret(), aepConfig.getKey(), masterApiKey, JSONObject.toJSONString(body).getBytes())); - /** - * 获取电信平台客户端 - * - * @param aepConfig - * @return - */ - private AepDeviceCommandClient getAepClient(AepConfig aepConfig) { - String aepKey = aepConfig.getKey(); - String aepSecret = aepConfig.getSecret(); - - return AepDeviceCommandClient.newClient().appKey(aepKey).appSecret(aepSecret).build(); + return HttpRequest.post(baseUrl + CREATE_COMMAND_PATH) + .body(JSON.toJSONString(body)) + .addHeaders(header) + .contentType("application/json; charset=UTF-8") + .execute(); } } diff --git a/pom.xml b/pom.xml index ea8fb2d..aa28411 100644 --- a/pom.xml +++ b/pom.xml @@ -18,7 +18,6 @@ - org.springframework.boot spring-boot-starter @@ -47,7 +46,8 @@ mysql mysql-connector-java - 8.0.28 + 5.1.44 + compile @@ -88,21 +88,10 @@ 3.9 - - 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 + cn.hutool + hutool-all + 5.8.31 @@ -110,83 +99,32 @@ - org.apache.maven.plugins - maven-jar-plugin + org.springframework.boot + spring-boot-maven-plugin + 2.1.3.RELEASE - - - *.properties - *.yml - *.yaml - *.xml - - - - - com.casic.CasicApplication - - true - - lib/ - - false - - - - config/ - - + true + + com.casic.CasicApplication + exec + true - - - - org.apache.maven.plugins - maven-dependency-plugin - copy-dependencies - package - copy-dependencies + repackage - ${project.build.directory}/lib - - - - - - - maven-resources-plugin - - - copy-resources - package - - copy-resources - - - - - - src/main/resources/ - - *.properties - *.yml - *.yaml - *.xml - - - - ${project.build.directory}/config - org.apache.maven.plugins - maven-compiler-plugin - 3.1 + maven-war-plugin + + + false + diff --git a/src/main/java/com/casic/dao/mapper/mapping/BusDeviceMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/BusDeviceMapper.xml index 37c0c9c..3cb8b8d 100644 --- a/src/main/java/com/casic/dao/mapper/mapping/BusDeviceMapper.xml +++ b/src/main/java/com/casic/dao/mapper/mapping/BusDeviceMapper.xml @@ -1,6 +1,6 @@ - + @@ -10,11 +10,13 @@ + + - ID, DEVCODE, DEVICE_NAME, DEVICE_TYPE, MASTER_API_KEY, SECRET_KEY + ID, DEVCODE, DEVICE_NAME, DEVICE_TYPE, MASTER_API_KEY, SECRET_KEY, NB_DEVICE_ID, NB_PRODUCT_ID diff --git a/src/main/java/com/casic/dao/model/BusDevice.java b/src/main/java/com/casic/dao/model/BusDevice.java index 2288afe..ffc6712 100644 --- a/src/main/java/com/casic/dao/model/BusDevice.java +++ b/src/main/java/com/casic/dao/model/BusDevice.java @@ -57,4 +57,15 @@ @TableField("SECRET_KEY") private String secretKey; + /** + * NB平台DEVICEID + */ + @TableField("NB_DEVICE_ID") + private String nbDeviceId; + + /** + * NB平台PRODUCTID + */ + @TableField("NB_PRODUCT_ID") + private String nbProductId; } diff --git a/src/main/java/com/casic/senitnel/controller/SentinelDataController.java b/src/main/java/com/casic/senitnel/controller/SentinelDataController.java index 633c072..6e75bba 100644 --- a/src/main/java/com/casic/senitnel/controller/SentinelDataController.java +++ b/src/main/java/com/casic/senitnel/controller/SentinelDataController.java @@ -1,11 +1,14 @@ package com.casic.senitnel.controller; +import cn.hutool.core.util.ObjectUtil; +import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.casic.common.CasicFrame; import com.casic.common.general.ConfigFrame; import com.casic.dao.model.BusDevice; import com.casic.dao.service.IBusDeviceService; import com.casic.senitnel.service.ISentinelFrameService; +import com.casic.util.ReturnDTO; import com.casic.util.aep.AepCommandSend; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; @@ -56,6 +59,7 @@ if (frame != null) { // 回复响应 String replyFrameStr = frameService.replyMessage(frame.getDeviceCode(), frame.getSequence()); + log.info("回复响应: {}", JSON.toJSONString(replyFrameStr)); // 从数据库中获取master-api-key 回复响应消息 BusDevice device = deviceService.getDeviceByCode(frame.getDeviceCode()); @@ -87,13 +91,18 @@ } @RequestMapping("/sentinel/config/send") - public Object configSend(@RequestBody Map map) throws Exception { + public Object configSend(@RequestBody Map map) throws Exception { JSONObject retObj = new JSONObject(); log.info(JSONObject.toJSONString(map)); + if (!map.containsKey("devCode")) { + return new ReturnDTO<>(500, "设备编号不能为空"); + } + String devCode = (String) map.get("devCode"); + CasicFrame cmdFrame = new ConfigFrame(); cmdFrame.setDeviceType("21"); // 设备类型为 燃气监测桩(防第三方破坏) - cmdFrame.setDeviceCode((String) map.get("devCode")); + cmdFrame.setDeviceCode(devCode); cmdFrame.setSequence("01"); cmdFrame.setUptime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 当前时刻 @@ -102,12 +111,28 @@ cmdFrame.setMessageBody(messageBody); String frameStr = frameService.doBuildCommand(cmdFrame); + log.info("下发指令: {}", JSON.toJSONString(frameStr)); - // TODO-LIST - // 这三个参数根据设备编号从数据库中取 - String deviceId = (String) map.get("deviceId"); - String productId = (String) map.get("productId"); - String masterApiKey = (String) map.get("masterApiKey"); + // 从数据库中获取master-api-key 回复响应消息 + BusDevice device = deviceService.getDeviceByCode(devCode); + + // 判空及抛出异常 + if (ObjectUtil.isNull(device)) { + return new ReturnDTO<>(500, "没有找到编号为" + devCode + "设备"); + } + if (ObjectUtil.isNull(device.getNbDeviceId())) { + return new ReturnDTO<>(500, "NB_Device_ID为空"); + } + if (ObjectUtil.isNull(device.getNbProductId())) { + return new ReturnDTO<>(500, "NB_Product_ID为空"); + } + if (ObjectUtil.isNull(device.getMasterApiKey())) { + return new ReturnDTO<>(500, "masterApiKey为空"); + } + + String deviceId = device.getNbDeviceId(); + String productId = device.getNbProductId(); + String masterApiKey = device.getMasterApiKey(); AepCommandSend aepCommandSend = new AepCommandSend(deviceId, productId, masterApiKey); int code = aepCommandSend.handleAndReply(frameStr); diff --git a/src/main/java/com/casic/tube/controller/TubeDataController.java b/src/main/java/com/casic/tube/controller/TubeDataController.java index 4965449..b2476df 100644 --- a/src/main/java/com/casic/tube/controller/TubeDataController.java +++ b/src/main/java/com/casic/tube/controller/TubeDataController.java @@ -1,9 +1,14 @@ package com.casic.tube.controller; +import cn.hutool.core.util.ObjectUtil; +import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.casic.common.CasicFrame; import com.casic.common.general.ConfigFrame; +import com.casic.dao.model.BusDevice; +import com.casic.dao.service.IBusDeviceService; import com.casic.tube.service.ITubeFrameService; +import com.casic.util.ReturnDTO; import com.casic.util.aep.AepCommandSend; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.RequestBody; @@ -23,6 +28,9 @@ @Resource private ITubeFrameService frameService; + @Resource + private IBusDeviceService deviceService; + @RequestMapping("/tube/data/recv") public Object dataRecv(@RequestBody Map map) { JSONObject retObj = new JSONObject(); @@ -64,6 +72,11 @@ JSONObject retObj = new JSONObject(); log.info(JSONObject.toJSONString(map)); + if (!map.containsKey("devCode")) { + return new ReturnDTO<>(500, "设备编号不能为空"); + } + String devCode = (String) map.get("devCode"); + CasicFrame cmdFrame = new ConfigFrame(); cmdFrame.setDeviceType("34"); // 设备类型为 管线浓度监测设备-管盯(管线哨兵) cmdFrame.setDeviceCode((String) map.get("devCode")); @@ -75,12 +88,28 @@ cmdFrame.setMessageBody(messageBody); String frameStr = frameService.doBuildCommand(cmdFrame); + log.info("下发指令: {}", JSON.toJSONString(frameStr)); - // TODO-LIST - // 这三个参数根据设备编号从数据库中取 - String deviceId = (String) map.get("deviceId"); - String productId = (String) map.get("productId"); - String masterApiKey = (String) map.get("masterApiKey"); + // 从数据库中获取master-api-key 回复响应消息 + BusDevice device = deviceService.getDeviceByCode(devCode); + + // 判空及抛出异常 + if (ObjectUtil.isNull(device)) { + return new ReturnDTO<>(500, "没有找到编号为" + devCode + "设备"); + } + if (ObjectUtil.isNull(device.getNbDeviceId())) { + return new ReturnDTO<>(500, "NB_Device_ID为空"); + } + if (ObjectUtil.isNull(device.getNbProductId())) { + return new ReturnDTO<>(500, "NB_Product_ID为空"); + } + if (ObjectUtil.isNull(device.getMasterApiKey())) { + return new ReturnDTO<>(500, "masterApiKey为空"); + } + + String deviceId = device.getNbDeviceId(); + String productId = device.getNbProductId(); + String masterApiKey = device.getMasterApiKey(); AepCommandSend aepCommandSend = new AepCommandSend(deviceId, productId, masterApiKey); int code = aepCommandSend.handleAndReply(frameStr); diff --git a/src/main/java/com/casic/util/ReturnDTO.java b/src/main/java/com/casic/util/ReturnDTO.java new file mode 100644 index 0000000..dad1068 --- /dev/null +++ b/src/main/java/com/casic/util/ReturnDTO.java @@ -0,0 +1,31 @@ +package com.casic.util; + +import lombok.Data; + +import java.io.Serializable; + +/** + * @Description: + * @Author: cz + * @Date: 2023/11/21 + */ +@Data +public class ReturnDTO implements Serializable { + private Integer code; + private String message; + private T data; + + public ReturnDTO(Integer code, String message, T data) { + this.code = code; + this.message = message; + this.data = data; + } + + public ReturnDTO(Integer code, String message) { + this.code = code; + this.message = message; + } + + public ReturnDTO() { + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/util/aep/AepCommandSend.java b/src/main/java/com/casic/util/aep/AepCommandSend.java index d35f83f..1350fdd 100644 --- a/src/main/java/com/casic/util/aep/AepCommandSend.java +++ b/src/main/java/com/casic/util/aep/AepCommandSend.java @@ -1,27 +1,36 @@ package com.casic.util.aep; +import cn.hutool.http.HttpRequest; +import cn.hutool.http.HttpResponse; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.casic.util.SpringContextUtil; -import com.ctg.ag.sdk.biz.AepDeviceCommandClient; -import com.ctg.ag.sdk.biz.aep_device_command.CreateCommandRequest; -import com.ctg.ag.sdk.biz.aep_device_command.CreateCommandResponse; +import lombok.Data; import lombok.extern.slf4j.Slf4j; import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; /** * @author cz * @date 2024-04-24 */ @Slf4j +@Data public class AepCommandSend { private String deviceId; private String productId; private String masterApiKey; + private Long offset = 0L; + private Long lastGetOffsetTime = 0L; + + private final String CREATE_COMMAND_PATH = "/aep_device_command/command"; + private final String CREATE_COMMAND_LWM2M_PROFILE_PATH = "/aep_device_command_lwm_profile/commandLwm2mProfile"; + public AepCommandSend() { } @@ -34,15 +43,47 @@ /** * 处理电信平台的报文解析,并组装回复报文,发送电信平台 * - * @param frameStr + * @param frameStr 业务数据的payload内容 */ public int handleAndReply(String frameStr) throws Exception { + HttpResponse response = createCommand(frameStr); + + JSONObject retObj = new JSONObject(); + try { + retObj = JSON.parseObject(new String(response.body().getBytes(), StandardCharsets.UTF_8)); + + log.info("AEP平台返回消息: {}", retObj.toJSONString()); + } catch (Exception ex) { + log.error("AEP平台发送失败,异常信息{}", ex.getMessage()); + } + + return (int) retObj.get("code"); + } + + private Long getTimeOffset() { AepConfig aepConfig = SpringContextUtil.getBean(AepConfig.class); - AepDeviceCommandClient client = getAepClient(aepConfig); + String timeUrl = aepConfig.getTimeUrl(); - CreateCommandRequest request = new CreateCommandRequest(); - request.setParamMasterKey(masterApiKey); + try { + HttpResponse response = HttpRequest.get(timeUrl).execute(); + String timeAg = response.header("x-ag-timestamp"); + return Long.parseLong(timeAg) - System.currentTimeMillis(); + } catch (Exception ex) { + return 0L; + } + } + + private String signature(Long timestamp, String appSecret, String appKey, String masterApiKey, byte[] bodyBytes) throws Exception { + return Signature.sign(appSecret, appKey, String.valueOf(timestamp), masterApiKey, bodyBytes); + } + + private HttpResponse createCommand(String frameStr) throws Exception { + AepConfig aepConfig = SpringContextUtil.getBean(AepConfig.class); + + String baseUrl = aepConfig.getBaseUrl(); + + // 消息体 AepCommandBody body = new AepCommandBody(); body.setDeviceId(deviceId); body.setProductId(productId); @@ -51,35 +92,29 @@ body.setLevel(aepConfig.getLevel()); body.setPayloadString(frameStr); - request.setBody(JSONObject.toJSONString(body).getBytes()); - log.info("向AEP平台发送指令: {}", JSON.toJSONString(body)); + log.info("向AEP平台发送消息: {}", JSON.toJSONString(body)); - JSONObject retObj = new JSONObject(); - - try { - CreateCommandResponse msgResponse = client.CreateCommand(request); - retObj = JSON.parseObject(new String(msgResponse.getBody(), StandardCharsets.UTF_8)); - - log.info("AEP平台返回消息: {}", retObj.toJSONString()); - } catch (Exception ex) { - log.error("AEP平台发送失败,异常信息{}", ex.getMessage()); - } finally { - client.shutdown(); + // 计算时间戳 用于签名 + long currentTime = System.currentTimeMillis(); + if (currentTime - lastGetOffsetTime > 300 * 1000) //300秒调用一次 + { + offset = getTimeOffset(); + lastGetOffsetTime = currentTime; } + long timestamp = currentTime + offset; - return (int) retObj.get("code"); - } + // 消息头 + Map header = new HashMap<>(); + header.put("application", aepConfig.getKey()); + header.put("version", "20190712225145"); + header.put("timestamp", String.valueOf(timestamp)); + header.put("MasterKey", masterApiKey); + header.put("signature", signature(timestamp, aepConfig.getSecret(), aepConfig.getKey(), masterApiKey, JSONObject.toJSONString(body).getBytes())); - /** - * 获取电信平台客户端 - * - * @param aepConfig - * @return - */ - private AepDeviceCommandClient getAepClient(AepConfig aepConfig) { - String aepKey = aepConfig.getKey(); - String aepSecret = aepConfig.getSecret(); - - return AepDeviceCommandClient.newClient().appKey(aepKey).appSecret(aepSecret).build(); + return HttpRequest.post(baseUrl + CREATE_COMMAND_PATH) + .body(JSON.toJSONString(body)) + .addHeaders(header) + .contentType("application/json; charset=UTF-8") + .execute(); } } diff --git a/src/main/java/com/casic/util/aep/AepConfig.java b/src/main/java/com/casic/util/aep/AepConfig.java index c2a7371..3edc10d 100644 --- a/src/main/java/com/casic/util/aep/AepConfig.java +++ b/src/main/java/com/casic/util/aep/AepConfig.java @@ -16,6 +16,12 @@ @Value("${casic.aep.app.secret}") private String secret; + @Value("${casic.aep.time-url}") + private String timeUrl; + + @Value("${casic.aep.base-url}") + private String baseUrl; + private Integer ttl = 7200; private Integer level = 1; private String operator = "birmm"; diff --git a/src/main/java/com/casic/util/aep/Signature.java b/src/main/java/com/casic/util/aep/Signature.java new file mode 100644 index 0000000..ce87ddc --- /dev/null +++ b/src/main/java/com/casic/util/aep/Signature.java @@ -0,0 +1,67 @@ +package com.casic.util.aep; + +import org.apache.commons.codec.binary.Base64; + +import javax.crypto.Mac; +import javax.crypto.SecretKey; +import javax.crypto.spec.SecretKeySpec; +import java.io.ByteArrayOutputStream; +import java.nio.charset.StandardCharsets; + +public class Signature { + + public Signature() { + } + + /** + * 签名 + * 使用AppKey、AppSecretKey、timestamp、MasterAPIKey和业务数据进行签名 + * @param secret AppSecretKey + * @param application AppKey + * @param timestamp 时间戳 + * @param masterKey 产品的MasterAPIKey + * @param body 业务数据 + * @return 返回的签名数据 + * @throws Exception 抛出的需要处理的异常 + */ + public static String sign(String secret, String application, String timestamp, String masterKey, byte[] body) throws Exception { + if (secret == null) { + throw new Exception("Secret cannot be null"); + } else if (application == null) { + throw new Exception("Application cannot be null"); + } else if (timestamp == null) { + throw new Exception("Timestamp cannot be null"); + } else if (masterKey == null) { + throw new Exception("MasterAPIKey cannot be null"); + } + + StringBuilder sb = new StringBuilder(); + sb.append("application").append(":").append(application).append("\n"); + sb.append("timestamp").append(":").append(timestamp).append("\n"); + sb.append("MasterKey").append(":").append(masterKey).append("\n"); + + ByteArrayOutputStream outStream = new ByteArrayOutputStream(); + outStream.write(sb.toString().getBytes(StandardCharsets.UTF_8)); + if (body != null && body.length > 0) { + outStream.write(body); + outStream.write("\n".getBytes(StandardCharsets.UTF_8)); + } + + return new String(Base64.encodeBase64(encryptHMAC(secret, outStream.toByteArray()))); + } + + public static byte[] encryptHMAC(String secret, byte[] data) { + byte[] bytes = null; + + try { + SecretKey secretKey = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSha1"); + Mac mac = Mac.getInstance(secretKey.getAlgorithm()); + mac.init(secretKey); + bytes = mac.doFinal(data); + } catch (Exception var5) { + var5.printStackTrace(System.err); + } + + return bytes; + } +} diff --git a/pom.xml b/pom.xml index ea8fb2d..aa28411 100644 --- a/pom.xml +++ b/pom.xml @@ -18,7 +18,6 @@ - org.springframework.boot spring-boot-starter @@ -47,7 +46,8 @@ mysql mysql-connector-java - 8.0.28 + 5.1.44 + compile @@ -88,21 +88,10 @@ 3.9 - - 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 + cn.hutool + hutool-all + 5.8.31 @@ -110,83 +99,32 @@ - org.apache.maven.plugins - maven-jar-plugin + org.springframework.boot + spring-boot-maven-plugin + 2.1.3.RELEASE - - - *.properties - *.yml - *.yaml - *.xml - - - - - com.casic.CasicApplication - - true - - lib/ - - false - - - - config/ - - + true + + com.casic.CasicApplication + exec + true - - - - org.apache.maven.plugins - maven-dependency-plugin - copy-dependencies - package - copy-dependencies + repackage - ${project.build.directory}/lib - - - - - - - maven-resources-plugin - - - copy-resources - package - - copy-resources - - - - - - src/main/resources/ - - *.properties - *.yml - *.yaml - *.xml - - - - ${project.build.directory}/config - org.apache.maven.plugins - maven-compiler-plugin - 3.1 + maven-war-plugin + + + false + diff --git a/src/main/java/com/casic/dao/mapper/mapping/BusDeviceMapper.xml b/src/main/java/com/casic/dao/mapper/mapping/BusDeviceMapper.xml index 37c0c9c..3cb8b8d 100644 --- a/src/main/java/com/casic/dao/mapper/mapping/BusDeviceMapper.xml +++ b/src/main/java/com/casic/dao/mapper/mapping/BusDeviceMapper.xml @@ -1,6 +1,6 @@ - + @@ -10,11 +10,13 @@ + + - ID, DEVCODE, DEVICE_NAME, DEVICE_TYPE, MASTER_API_KEY, SECRET_KEY + ID, DEVCODE, DEVICE_NAME, DEVICE_TYPE, MASTER_API_KEY, SECRET_KEY, NB_DEVICE_ID, NB_PRODUCT_ID diff --git a/src/main/java/com/casic/dao/model/BusDevice.java b/src/main/java/com/casic/dao/model/BusDevice.java index 2288afe..ffc6712 100644 --- a/src/main/java/com/casic/dao/model/BusDevice.java +++ b/src/main/java/com/casic/dao/model/BusDevice.java @@ -57,4 +57,15 @@ @TableField("SECRET_KEY") private String secretKey; + /** + * NB平台DEVICEID + */ + @TableField("NB_DEVICE_ID") + private String nbDeviceId; + + /** + * NB平台PRODUCTID + */ + @TableField("NB_PRODUCT_ID") + private String nbProductId; } diff --git a/src/main/java/com/casic/senitnel/controller/SentinelDataController.java b/src/main/java/com/casic/senitnel/controller/SentinelDataController.java index 633c072..6e75bba 100644 --- a/src/main/java/com/casic/senitnel/controller/SentinelDataController.java +++ b/src/main/java/com/casic/senitnel/controller/SentinelDataController.java @@ -1,11 +1,14 @@ package com.casic.senitnel.controller; +import cn.hutool.core.util.ObjectUtil; +import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.casic.common.CasicFrame; import com.casic.common.general.ConfigFrame; import com.casic.dao.model.BusDevice; import com.casic.dao.service.IBusDeviceService; import com.casic.senitnel.service.ISentinelFrameService; +import com.casic.util.ReturnDTO; import com.casic.util.aep.AepCommandSend; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; @@ -56,6 +59,7 @@ if (frame != null) { // 回复响应 String replyFrameStr = frameService.replyMessage(frame.getDeviceCode(), frame.getSequence()); + log.info("回复响应: {}", JSON.toJSONString(replyFrameStr)); // 从数据库中获取master-api-key 回复响应消息 BusDevice device = deviceService.getDeviceByCode(frame.getDeviceCode()); @@ -87,13 +91,18 @@ } @RequestMapping("/sentinel/config/send") - public Object configSend(@RequestBody Map map) throws Exception { + public Object configSend(@RequestBody Map map) throws Exception { JSONObject retObj = new JSONObject(); log.info(JSONObject.toJSONString(map)); + if (!map.containsKey("devCode")) { + return new ReturnDTO<>(500, "设备编号不能为空"); + } + String devCode = (String) map.get("devCode"); + CasicFrame cmdFrame = new ConfigFrame(); cmdFrame.setDeviceType("21"); // 设备类型为 燃气监测桩(防第三方破坏) - cmdFrame.setDeviceCode((String) map.get("devCode")); + cmdFrame.setDeviceCode(devCode); cmdFrame.setSequence("01"); cmdFrame.setUptime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))); // 当前时刻 @@ -102,12 +111,28 @@ cmdFrame.setMessageBody(messageBody); String frameStr = frameService.doBuildCommand(cmdFrame); + log.info("下发指令: {}", JSON.toJSONString(frameStr)); - // TODO-LIST - // 这三个参数根据设备编号从数据库中取 - String deviceId = (String) map.get("deviceId"); - String productId = (String) map.get("productId"); - String masterApiKey = (String) map.get("masterApiKey"); + // 从数据库中获取master-api-key 回复响应消息 + BusDevice device = deviceService.getDeviceByCode(devCode); + + // 判空及抛出异常 + if (ObjectUtil.isNull(device)) { + return new ReturnDTO<>(500, "没有找到编号为" + devCode + "设备"); + } + if (ObjectUtil.isNull(device.getNbDeviceId())) { + return new ReturnDTO<>(500, "NB_Device_ID为空"); + } + if (ObjectUtil.isNull(device.getNbProductId())) { + return new ReturnDTO<>(500, "NB_Product_ID为空"); + } + if (ObjectUtil.isNull(device.getMasterApiKey())) { + return new ReturnDTO<>(500, "masterApiKey为空"); + } + + String deviceId = device.getNbDeviceId(); + String productId = device.getNbProductId(); + String masterApiKey = device.getMasterApiKey(); AepCommandSend aepCommandSend = new AepCommandSend(deviceId, productId, masterApiKey); int code = aepCommandSend.handleAndReply(frameStr); diff --git a/src/main/java/com/casic/tube/controller/TubeDataController.java b/src/main/java/com/casic/tube/controller/TubeDataController.java index 4965449..b2476df 100644 --- a/src/main/java/com/casic/tube/controller/TubeDataController.java +++ b/src/main/java/com/casic/tube/controller/TubeDataController.java @@ -1,9 +1,14 @@ package com.casic.tube.controller; +import cn.hutool.core.util.ObjectUtil; +import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.casic.common.CasicFrame; import com.casic.common.general.ConfigFrame; +import com.casic.dao.model.BusDevice; +import com.casic.dao.service.IBusDeviceService; import com.casic.tube.service.ITubeFrameService; +import com.casic.util.ReturnDTO; import com.casic.util.aep.AepCommandSend; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.RequestBody; @@ -23,6 +28,9 @@ @Resource private ITubeFrameService frameService; + @Resource + private IBusDeviceService deviceService; + @RequestMapping("/tube/data/recv") public Object dataRecv(@RequestBody Map map) { JSONObject retObj = new JSONObject(); @@ -64,6 +72,11 @@ JSONObject retObj = new JSONObject(); log.info(JSONObject.toJSONString(map)); + if (!map.containsKey("devCode")) { + return new ReturnDTO<>(500, "设备编号不能为空"); + } + String devCode = (String) map.get("devCode"); + CasicFrame cmdFrame = new ConfigFrame(); cmdFrame.setDeviceType("34"); // 设备类型为 管线浓度监测设备-管盯(管线哨兵) cmdFrame.setDeviceCode((String) map.get("devCode")); @@ -75,12 +88,28 @@ cmdFrame.setMessageBody(messageBody); String frameStr = frameService.doBuildCommand(cmdFrame); + log.info("下发指令: {}", JSON.toJSONString(frameStr)); - // TODO-LIST - // 这三个参数根据设备编号从数据库中取 - String deviceId = (String) map.get("deviceId"); - String productId = (String) map.get("productId"); - String masterApiKey = (String) map.get("masterApiKey"); + // 从数据库中获取master-api-key 回复响应消息 + BusDevice device = deviceService.getDeviceByCode(devCode); + + // 判空及抛出异常 + if (ObjectUtil.isNull(device)) { + return new ReturnDTO<>(500, "没有找到编号为" + devCode + "设备"); + } + if (ObjectUtil.isNull(device.getNbDeviceId())) { + return new ReturnDTO<>(500, "NB_Device_ID为空"); + } + if (ObjectUtil.isNull(device.getNbProductId())) { + return new ReturnDTO<>(500, "NB_Product_ID为空"); + } + if (ObjectUtil.isNull(device.getMasterApiKey())) { + return new ReturnDTO<>(500, "masterApiKey为空"); + } + + String deviceId = device.getNbDeviceId(); + String productId = device.getNbProductId(); + String masterApiKey = device.getMasterApiKey(); AepCommandSend aepCommandSend = new AepCommandSend(deviceId, productId, masterApiKey); int code = aepCommandSend.handleAndReply(frameStr); diff --git a/src/main/java/com/casic/util/ReturnDTO.java b/src/main/java/com/casic/util/ReturnDTO.java new file mode 100644 index 0000000..dad1068 --- /dev/null +++ b/src/main/java/com/casic/util/ReturnDTO.java @@ -0,0 +1,31 @@ +package com.casic.util; + +import lombok.Data; + +import java.io.Serializable; + +/** + * @Description: + * @Author: cz + * @Date: 2023/11/21 + */ +@Data +public class ReturnDTO implements Serializable { + private Integer code; + private String message; + private T data; + + public ReturnDTO(Integer code, String message, T data) { + this.code = code; + this.message = message; + this.data = data; + } + + public ReturnDTO(Integer code, String message) { + this.code = code; + this.message = message; + } + + public ReturnDTO() { + } +} \ No newline at end of file diff --git a/src/main/java/com/casic/util/aep/AepCommandSend.java b/src/main/java/com/casic/util/aep/AepCommandSend.java index d35f83f..1350fdd 100644 --- a/src/main/java/com/casic/util/aep/AepCommandSend.java +++ b/src/main/java/com/casic/util/aep/AepCommandSend.java @@ -1,27 +1,36 @@ package com.casic.util.aep; +import cn.hutool.http.HttpRequest; +import cn.hutool.http.HttpResponse; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.casic.util.SpringContextUtil; -import com.ctg.ag.sdk.biz.AepDeviceCommandClient; -import com.ctg.ag.sdk.biz.aep_device_command.CreateCommandRequest; -import com.ctg.ag.sdk.biz.aep_device_command.CreateCommandResponse; +import lombok.Data; import lombok.extern.slf4j.Slf4j; import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; /** * @author cz * @date 2024-04-24 */ @Slf4j +@Data public class AepCommandSend { private String deviceId; private String productId; private String masterApiKey; + private Long offset = 0L; + private Long lastGetOffsetTime = 0L; + + private final String CREATE_COMMAND_PATH = "/aep_device_command/command"; + private final String CREATE_COMMAND_LWM2M_PROFILE_PATH = "/aep_device_command_lwm_profile/commandLwm2mProfile"; + public AepCommandSend() { } @@ -34,15 +43,47 @@ /** * 处理电信平台的报文解析,并组装回复报文,发送电信平台 * - * @param frameStr + * @param frameStr 业务数据的payload内容 */ public int handleAndReply(String frameStr) throws Exception { + HttpResponse response = createCommand(frameStr); + + JSONObject retObj = new JSONObject(); + try { + retObj = JSON.parseObject(new String(response.body().getBytes(), StandardCharsets.UTF_8)); + + log.info("AEP平台返回消息: {}", retObj.toJSONString()); + } catch (Exception ex) { + log.error("AEP平台发送失败,异常信息{}", ex.getMessage()); + } + + return (int) retObj.get("code"); + } + + private Long getTimeOffset() { AepConfig aepConfig = SpringContextUtil.getBean(AepConfig.class); - AepDeviceCommandClient client = getAepClient(aepConfig); + String timeUrl = aepConfig.getTimeUrl(); - CreateCommandRequest request = new CreateCommandRequest(); - request.setParamMasterKey(masterApiKey); + try { + HttpResponse response = HttpRequest.get(timeUrl).execute(); + String timeAg = response.header("x-ag-timestamp"); + return Long.parseLong(timeAg) - System.currentTimeMillis(); + } catch (Exception ex) { + return 0L; + } + } + + private String signature(Long timestamp, String appSecret, String appKey, String masterApiKey, byte[] bodyBytes) throws Exception { + return Signature.sign(appSecret, appKey, String.valueOf(timestamp), masterApiKey, bodyBytes); + } + + private HttpResponse createCommand(String frameStr) throws Exception { + AepConfig aepConfig = SpringContextUtil.getBean(AepConfig.class); + + String baseUrl = aepConfig.getBaseUrl(); + + // 消息体 AepCommandBody body = new AepCommandBody(); body.setDeviceId(deviceId); body.setProductId(productId); @@ -51,35 +92,29 @@ body.setLevel(aepConfig.getLevel()); body.setPayloadString(frameStr); - request.setBody(JSONObject.toJSONString(body).getBytes()); - log.info("向AEP平台发送指令: {}", JSON.toJSONString(body)); + log.info("向AEP平台发送消息: {}", JSON.toJSONString(body)); - JSONObject retObj = new JSONObject(); - - try { - CreateCommandResponse msgResponse = client.CreateCommand(request); - retObj = JSON.parseObject(new String(msgResponse.getBody(), StandardCharsets.UTF_8)); - - log.info("AEP平台返回消息: {}", retObj.toJSONString()); - } catch (Exception ex) { - log.error("AEP平台发送失败,异常信息{}", ex.getMessage()); - } finally { - client.shutdown(); + // 计算时间戳 用于签名 + long currentTime = System.currentTimeMillis(); + if (currentTime - lastGetOffsetTime > 300 * 1000) //300秒调用一次 + { + offset = getTimeOffset(); + lastGetOffsetTime = currentTime; } + long timestamp = currentTime + offset; - return (int) retObj.get("code"); - } + // 消息头 + Map header = new HashMap<>(); + header.put("application", aepConfig.getKey()); + header.put("version", "20190712225145"); + header.put("timestamp", String.valueOf(timestamp)); + header.put("MasterKey", masterApiKey); + header.put("signature", signature(timestamp, aepConfig.getSecret(), aepConfig.getKey(), masterApiKey, JSONObject.toJSONString(body).getBytes())); - /** - * 获取电信平台客户端 - * - * @param aepConfig - * @return - */ - private AepDeviceCommandClient getAepClient(AepConfig aepConfig) { - String aepKey = aepConfig.getKey(); - String aepSecret = aepConfig.getSecret(); - - return AepDeviceCommandClient.newClient().appKey(aepKey).appSecret(aepSecret).build(); + return HttpRequest.post(baseUrl + CREATE_COMMAND_PATH) + .body(JSON.toJSONString(body)) + .addHeaders(header) + .contentType("application/json; charset=UTF-8") + .execute(); } } diff --git a/src/main/java/com/casic/util/aep/AepConfig.java b/src/main/java/com/casic/util/aep/AepConfig.java index c2a7371..3edc10d 100644 --- a/src/main/java/com/casic/util/aep/AepConfig.java +++ b/src/main/java/com/casic/util/aep/AepConfig.java @@ -16,6 +16,12 @@ @Value("${casic.aep.app.secret}") private String secret; + @Value("${casic.aep.time-url}") + private String timeUrl; + + @Value("${casic.aep.base-url}") + private String baseUrl; + private Integer ttl = 7200; private Integer level = 1; private String operator = "birmm"; diff --git a/src/main/java/com/casic/util/aep/Signature.java b/src/main/java/com/casic/util/aep/Signature.java new file mode 100644 index 0000000..ce87ddc --- /dev/null +++ b/src/main/java/com/casic/util/aep/Signature.java @@ -0,0 +1,67 @@ +package com.casic.util.aep; + +import org.apache.commons.codec.binary.Base64; + +import javax.crypto.Mac; +import javax.crypto.SecretKey; +import javax.crypto.spec.SecretKeySpec; +import java.io.ByteArrayOutputStream; +import java.nio.charset.StandardCharsets; + +public class Signature { + + public Signature() { + } + + /** + * 签名 + * 使用AppKey、AppSecretKey、timestamp、MasterAPIKey和业务数据进行签名 + * @param secret AppSecretKey + * @param application AppKey + * @param timestamp 时间戳 + * @param masterKey 产品的MasterAPIKey + * @param body 业务数据 + * @return 返回的签名数据 + * @throws Exception 抛出的需要处理的异常 + */ + public static String sign(String secret, String application, String timestamp, String masterKey, byte[] body) throws Exception { + if (secret == null) { + throw new Exception("Secret cannot be null"); + } else if (application == null) { + throw new Exception("Application cannot be null"); + } else if (timestamp == null) { + throw new Exception("Timestamp cannot be null"); + } else if (masterKey == null) { + throw new Exception("MasterAPIKey cannot be null"); + } + + StringBuilder sb = new StringBuilder(); + sb.append("application").append(":").append(application).append("\n"); + sb.append("timestamp").append(":").append(timestamp).append("\n"); + sb.append("MasterKey").append(":").append(masterKey).append("\n"); + + ByteArrayOutputStream outStream = new ByteArrayOutputStream(); + outStream.write(sb.toString().getBytes(StandardCharsets.UTF_8)); + if (body != null && body.length > 0) { + outStream.write(body); + outStream.write("\n".getBytes(StandardCharsets.UTF_8)); + } + + return new String(Base64.encodeBase64(encryptHMAC(secret, outStream.toByteArray()))); + } + + public static byte[] encryptHMAC(String secret, byte[] data) { + byte[] bytes = null; + + try { + SecretKey secretKey = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSha1"); + Mac mac = Mac.getInstance(secretKey.getAlgorithm()); + mac.init(secretKey); + bytes = mac.doFinal(data); + } catch (Exception var5) { + var5.printStackTrace(System.err); + } + + return bytes; + } +} diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 3f2ad30..cd5ed67 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -3,8 +3,8 @@ ################### spring配置 ################### spring: datasource: - driver-class-name: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://111.198.10.15:11102/smartwell_br_test?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=GMT%2B8&&allowMultiQueries=true + driver-class-name: com.mysql.jdbc.Driver + url: jdbc:mysql://111.198.10.15:11102/smartwell_br_test?useSSL=false&useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=GMT%2B8&&allowMultiQueries=true username: root password: Casic203! session: diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 8f37be9..ab8ce5d 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -32,6 +32,8 @@ app: key: ke4zM3hld29 secret: 35ykNutA1t + time-url: https://ag-api.ctwing.cn/echo + base-url: https://ag-api.ctwing.cn # type 可燃气体的设备类型 # minutes: 燃气外协设备上传数据的分钟数 \ No newline at end of file