| src/main/java/com/ard/hiksdk/service/impl/FMSGCallBack.java | ●●●●● patch | view | raw | blame | history | |
| src/main/java/com/ard/hiksdk/util/DateUtils.java | ●●●●● patch | view | raw | blame | history | |
| src/main/java/com/ard/utils/ByteUtils.java | ●●●●● patch | view | raw | blame | history | |
| src/main/java/com/ard/utils/DateUtils.java | ●●●●● patch | view | raw | blame | history | |
| src/main/java/com/ard/utils/GisUtils.java | ●●●●● patch | view | raw | blame | history | |
| src/main/java/com/ard/utils/LonlatConver.java | ●●●●● patch | view | raw | blame | history | |
| src/main/java/com/ard/utils/SpringTool.java | ●●●●● patch | view | raw | blame | history | |
| src/main/java/com/ard/utils/mqtt/MqttConsumer.java | ●●●●● patch | view | raw | blame | history | |
| src/main/java/com/ard/utils/tcp/MessageParsing.java | ●●●●● patch | view | raw | blame | history | |
| src/main/java/com/ard/utils/tcp/NettyTcpClientHandler.java | ●●●●● patch | view | raw | blame | history | |
| src/main/resources/application.yml | ●●●●● patch | view | raw | blame | history |
src/main/java/com/ard/hiksdk/service/impl/FMSGCallBack.java
@@ -7,9 +7,9 @@ import com.ard.config.MinioClientSingleton; import com.ard.hiksdk.common.GlobalVariable; import com.ard.hiksdk.domain.alarmEventInfo; import com.ard.hiksdk.util.DateUtils; import com.ard.hiksdk.util.hikSdkUtil.HCNetSDK; import com.ard.hiksdk.util.minio.MinioUtils; import com.ard.utils.DateUtils; import com.ard.utils.SpringTool; import com.ard.utils.mqtt.MqttConsumer; import com.sun.jna.Pointer; src/main/java/com/ard/hiksdk/util/DateUtils.java
File was deleted src/main/java/com/ard/utils/ByteUtils.java
New file @@ -0,0 +1,82 @@ package com.ard.utils; import javax.xml.bind.DatatypeConverter; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * @Description: 字节工具类 * @ClassName: byteUtils * @Author: 刘苏义 * @Date: 2023年07月03日15:18 * @Version: 1.0 **/ public class ByteUtils { /** * Byte字节转Hex * @param b 字节 * @return Hex */ public static String byteToHex(byte b) { String hexString = Integer.toHexString(b & 0xFF); //由于十六进制是由0~9、A~F来表示1~16,所以如果Byte转换成Hex后如果是<16,就会是一个字符(比如A=10),通常是使用两个字符来表示16进制位的, //假如一个字符的话,遇到字符串11,这到底是1个字节,还是1和1两个字节,容易混淆,如果是补0,那么1和1补充后就是0101,11就表示纯粹的11 if (hexString.length() < 2) { hexString = new StringBuilder(String.valueOf(0)).append(hexString).toString(); } return hexString.toUpperCase(); } /** * byte数组转float */ public static float bytesToFloat(byte[] bytes) { ByteBuffer buffer = ByteBuffer.wrap(bytes); return buffer.getFloat(); } /** * byte数组转整型 */ public static int bytesToDecimal(byte[] byteArray) { int decimalValue = 0; for (int i = 0; i < byteArray.length; i++) { decimalValue = (decimalValue << 8) | (byteArray[i] & 0xFF); } return decimalValue; } /** * byte数组转Double */ public static double bytesToDouble(byte[] byteArray) { long longBits = 0; // 根据字节数组的长度和字节顺序,将字节数组转换为长整型 for (int i = 0; i < byteArray.length; i++) { longBits |= (long) (byteArray[i] & 0xFF) << (8 * (byteArray.length - 1 - i)); } // 使用Double.longBitsToDouble方法将长整型转换为Double类型 return Double.longBitsToDouble(longBits); } /** * 大端转小端 */ public static byte[] toLittleEndian(byte[] bigEndianBytes) { byte[] littleEndianBytes = new byte[bigEndianBytes.length]; for (int i = 0; i < bigEndianBytes.length; i++) { int j = bigEndianBytes.length - i - 1; littleEndianBytes[i] = bigEndianBytes[j]; } return littleEndianBytes; } } src/main/java/com/ard/utils/DateUtils.java
@@ -1,16 +1,201 @@ package com.ard.utils; import org.apache.commons.lang3.time.DateFormatUtils; import java.time.LocalDateTime; import java.lang.management.ManagementFactory; import java.text.ParseException; import java.text.SimpleDateFormat; import java.time.*; import java.time.format.DateTimeFormatter; import java.util.Date; /** * @Description: 时间处理工具 * @ClassName: DateUtils * @Author: 刘苏义 * @Date: 2023年06月06日10:04 * @Version: 1.0 **/ public class DateUtils { * @ClassName DateUtils * @Description: 这是一个时间工具类 * @Author 刘苏义 * @Date 2023/2/16 21:58 * @Version 1.0 */ public class DateUtils extends org.apache.commons.lang3.time.DateUtils { public static String YYYY = "yyyy"; public static String YYYY_MM = "yyyy-MM"; public static String YYYY_MM_DD = "yyyy-MM-dd"; public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss"; public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss"; private static String[] parsePatterns = { "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM", "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM", "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"}; /** * 获取当前Date型日期 * * @return Date() 当前日期 */ public static Date getNowDate() { return new Date(); } /** * 获取当前日期, 默认格式为yyyy-MM-dd * * @return String */ public static String getDate() { return dateTimeNow(YYYY_MM_DD); } public static final String getTime() { return dateTimeNow(YYYY_MM_DD_HH_MM_SS); } public static final String dateTimeNow() { return dateTimeNow(YYYYMMDDHHMMSS); } public static final String dateTimeNow(final String format) { return parseDateToStr(format, new Date()); } public static final String dateTime(final Date date) { return parseDateToStr(YYYY_MM_DD, date); } public static final String parseDateToStr(final String format, final Date date) { return new SimpleDateFormat(format).format(date); } public static final Date dateTime(final String format, final String ts) { try { return new SimpleDateFormat(format).parse(ts); } catch (ParseException e) { throw new RuntimeException(e); } } /** * 日期路径 即年/月/日 如2018/08/08 */ public static final String datePath() { Date now = new Date(); return DateFormatUtils.format(now, "yyyy/MM/dd"); } /** * 日期路径 即年/月/日 如20180808 */ public static final String dateTime() { Date now = new Date(); return DateFormatUtils.format(now, "yyyyMMdd"); } /** * 日期型字符串转化为日期 格式 */ public static Date parseDate(Object str) { if (str == null) { return null; } try { return parseDate(str.toString(), parsePatterns); } catch (ParseException e) { return null; } } /** * 获取服务器启动时间 */ public static Date getServerStartDate() { long time = ManagementFactory.getRuntimeMXBean().getStartTime(); return new Date(time); } /** * 计算相差天数 */ public static int differentDaysByMillisecond(Date date1, Date date2) { return Math.abs((int) ((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24))); } /** * 计算两个时间差 */ public static String getDatePoor(Date endDate, Date nowDate) { long nd = 1000 * 24 * 60 * 60; long nh = 1000 * 60 * 60; long nm = 1000 * 60; // long ns = 1000; // 获得两个时间的毫秒时间差异 long diff = endDate.getTime() - nowDate.getTime(); // 计算差多少天 long day = diff / nd; // 计算差多少小时 long hour = diff % nd / nh; // 计算差多少分钟 long min = diff % nd % nh / nm; // 计算差多少秒//输出结果 // long sec = diff % nd % nh % nm / ns; return day + "天" + hour + "小时" + min + "分钟"; } /** * 增加 LocalDateTime ==> Date */ public static Date toDate(LocalDateTime temporalAccessor) { ZonedDateTime zdt = temporalAccessor.atZone(ZoneId.systemDefault()); return Date.from(zdt.toInstant()); } /** * 增加 LocalDate ==> Date */ public static Date toDate(LocalDate temporalAccessor) { LocalDateTime localDateTime = LocalDateTime.of(temporalAccessor, LocalTime.of(0, 0, 0)); ZonedDateTime zdt = localDateTime.atZone(ZoneId.systemDefault()); return Date.from(zdt.toInstant()); } //SDK时间解析 public static String parseTime(int time) { int year=(time>>26)+2000; int month=(time>>22)&15; int day=(time>>17)&31; int hour=(time>>12)&31; int min=(time>>6)&63; int second=(time>>0)&63; String sTime=String.format("%04d-%02d-%02d %02d:%02d:%02d", year, month, day, hour, min, second); return sTime; } /** * 日期字符串的月日时分秒自动补零,并将/替换成- src/main/java/com/ard/utils/GisUtils.java
New file @@ -0,0 +1,29 @@ package com.ard.utils; import org.gavaghan.geodesy.Ellipsoid; import org.gavaghan.geodesy.GeodeticCalculator; import org.gavaghan.geodesy.GlobalCoordinates; /** * @Description: gis工具类 * @ClassName: GisUtils * @Author: 刘苏义 * @Date: 2023年07月03日15:23 * @Version: 1.0 **/ public class GisUtils { /** * 通过A点坐标,长度和Y轴角度计算B点坐标 */ public static Double[] CalculateCoordinates(Double[] radarCoordinates, Double distance, Double angle) { double[] to_wgs84 = LonlatConver.gcj02_To_Wgs84(radarCoordinates[0], radarCoordinates[1]); double Ax = to_wgs84[0]; // A 点的 X 坐标 double Ay = to_wgs84[1]; // A 点的 Y 坐标 double AB = distance; // AB 的长度 double angleWithYAxisDegrees = angle; // AB 与 Y 轴的角度(以度数表示) GeodeticCalculator calculator = new GeodeticCalculator(); GlobalCoordinates globalCoordinates = new GlobalCoordinates(Ay, Ax); GlobalCoordinates globalCoordinates1 = calculator.calculateEndingGlobalCoordinates(Ellipsoid.WGS84, globalCoordinates, angleWithYAxisDegrees, AB); return new Double[]{globalCoordinates1.getLongitude(), globalCoordinates1.getLatitude()}; } } src/main/java/com/ard/utils/LonlatConver.java
@@ -1,6 +1,11 @@ package com.ard.utils; /** * 经纬度转换工具 * 刘苏义 * 2023/7/3 15:15 */ public class LonlatConver { /** * a */ src/main/java/com/ard/utils/SpringTool.java
@@ -4,6 +4,9 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component; import java.nio.ByteBuffer; /** * @Description: * @ClassName: SpringTool @@ -33,20 +36,4 @@ return getApplicationContext().getBean(name); } /** * Byte字节转Hex * @param b 字节 * @return Hex */ public static String byteToHex(byte b) { String hexString = Integer.toHexString(b & 0xFF); //由于十六进制是由0~9、A~F来表示1~16,所以如果Byte转换成Hex后如果是<16,就会是一个字符(比如A=10),通常是使用两个字符来表示16进制位的, //假如一个字符的话,遇到字符串11,这到底是1个字节,还是1和1两个字节,容易混淆,如果是补0,那么1和1补充后就是0101,11就表示纯粹的11 if (hexString.length() < 2) { hexString = new StringBuilder(String.valueOf(0)).append(hexString).toString(); } return hexString.toUpperCase(); } } src/main/java/com/ard/utils/mqtt/MqttConsumer.java
@@ -75,7 +75,7 @@ // 设置会话心跳时间 options.setKeepAliveInterval(PropertiesUtil.MQTT_KEEP_ALIVE); // 是否清除session options.setCleanSession(false); options.setCleanSession(true); log.info("--生成mqtt配置对象"); return options; } src/main/java/com/ard/utils/tcp/MessageParsing.java
New file @@ -0,0 +1,96 @@ package com.ard.utils.tcp; import javax.xml.bind.DatatypeConverter; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * @Description: 报文解析 * @ClassName: MessageParsing * @Author: 刘苏义 * @Date: 2023年07月03日15:30 * @Version: 1.0 **/ public class MessageParsing { // 创建缓冲区列表 private static List<Byte> buffer = new ArrayList<>(); /** * 接收完整包 */ public static byte[] receiveCompletePacket(byte[] receivedData) { // 定义包尾字节序列 byte[] packetEnd = {0x01, 0x02, 0x00}; // 添加已接收的数据到缓冲区 for (byte data : receivedData) { buffer.add(data); } // 检查缓冲区中的数据是否包含完整的包 while (buffer.size() >= packetEnd.length) { int endIndex = findPacketEndIndex(buffer, packetEnd); if (endIndex != -1) { // 找到完整的包 byte[] packet = extractPacketFromBuffer(buffer, endIndex + packetEnd.length); return packet; } else { // 未找到包尾,继续接收数据 break; } } // 未找到完整的包 return null; } /** * 获取包结束索引 */ public static int findPacketEndIndex(List<Byte> buffer, byte[] packetEnd) { for (int i = 0; i <= buffer.size() - packetEnd.length; i++) { boolean isMatch = true; for (int j = 0; j < packetEnd.length; j++) { if (buffer.get(i + j) != packetEnd[j]) { isMatch = false; break; } } if (isMatch) { return i; } } return -1; } /** * 从缓冲区提取数据包 */ public static byte[] extractPacketFromBuffer(List<Byte> buffer, int endIndex) { byte[] packet = new byte[endIndex]; for (int i = 0; i < endIndex; i++) { packet[i] = buffer.get(i); } buffer.subList(0, endIndex).clear(); return packet; } /** * 去掉包头和包尾校验及转义 */ public static byte[] transferData(byte[] data) { data = Arrays.copyOfRange(data, 3, data.length); data = Arrays.copyOfRange(data, 0, data.length - 7); String dataStr = DatatypeConverter.printHexBinary(data); if (dataStr.contains("01020201")) {//转义01020201 dataStr = dataStr.replaceAll("01020201", "010201"); } if (dataStr.contains("01020200")) {//转义01020200 dataStr = dataStr.replaceAll("01020200", "010200"); } if (dataStr.contains("01020202")) {//转义01020202 dataStr = dataStr.replaceAll("01020202", "010202"); } data = DatatypeConverter.parseHexBinary(dataStr); return data; } } src/main/java/com/ard/utils/tcp/NettyTcpClientHandler.java
@@ -4,18 +4,14 @@ import com.ard.alarm.radar.domain.ArdEquipRadar; import com.ard.alarm.radar.domain.RadarAlarmData; import com.ard.alarm.radar.domain.ArdAlarmRadar; import com.ard.utils.LonlatConver; import com.ard.utils.ByteUtils; import com.ard.utils.GisUtils; import com.ard.utils.mqtt.MqttConsumer; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import lombok.extern.slf4j.Slf4j; import org.gavaghan.geodesy.Ellipsoid; import org.gavaghan.geodesy.GeodeticCalculator; import org.gavaghan.geodesy.GlobalCoordinates; import javax.xml.bind.DatatypeConverter; import java.nio.ByteBuffer; import java.text.SimpleDateFormat; import java.util.*; import java.util.concurrent.ScheduledFuture; @@ -35,6 +31,7 @@ private Integer port; private Double longitude; private Double lagitude; private Double altitude; private String name; private String id; @@ -45,6 +42,7 @@ this.lagitude = ardEquipRadar.getLatitude(); this.name = ardEquipRadar.getName(); this.id = ardEquipRadar.getId(); this.altitude = ardEquipRadar.getAltitude(); } private ChannelHandlerContext context; @@ -55,10 +53,8 @@ // 处理接收到的消息 byte[] byteArray = new byte[msg.readableBytes()]; msg.getBytes(msg.readerIndex(), byteArray); byte[] bytes = receiveCompletePacket(byteArray); byte[] bytes = MessageParsing.receiveCompletePacket(byteArray); if (bytes != null) { // String hexString = DatatypeConverter.printHexBinary(bytes); // log.info(hexString); processData(bytes); } } @@ -109,7 +105,9 @@ */ public void processData(byte[] data) { try { data = transferData(data);//去掉包头和包尾、校验及转义 //log.info("原始数据:" + DatatypeConverter.printHexBinary(data)); log.info("雷达信息:" + host + "【port】" + port + "【X】" + longitude + "【Y】" + lagitude + "【Z】" + altitude); data = MessageParsing.transferData(data);//去掉包头和包尾、校验及转义 byte[] type = Arrays.copyOfRange(data, 0, 1);//命令类型 // log.info("命令类型:" + DatatypeConverter.printHexBinary(type)); @@ -118,40 +116,41 @@ // log.info("命令ID:" + DatatypeConverter.printHexBinary(cmdId)); byte[] payloadSize = Arrays.copyOfRange(data, 2, 4);//有效负载大小 payloadSize = toLittleEndian(payloadSize); int payloadSizeToDecimal = byteArrayToDecimal(payloadSize); payloadSize = ByteUtils.toLittleEndian(payloadSize); int payloadSizeToDecimal = ByteUtils.bytesToDecimal(payloadSize); // log.info("有效负载大小(转整型):" + payloadSizeToDecimal); List<ArdAlarmRadar> radarAlarmInfos = new ArrayList<>(); String alarmTime=""; if (Arrays.equals(cmdId, new byte[]{0x01})) { byte[] dwTim = Arrays.copyOfRange(data, 4, 8); dwTim = toLittleEndian(dwTim); dwTim = ByteUtils.toLittleEndian(dwTim); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); long l = byteArrayToDecimal(dwTim); String alarmTime = sdf.format(l * 1000); long l = ByteUtils.bytesToDecimal(dwTim); alarmTime = sdf.format(l * 1000); // log.info("周视图像的出现时间(转date):" + alarmTime); byte[] wTargetNum = Arrays.copyOfRange(data, 8, 10); wTargetNum = toLittleEndian(wTargetNum); int targetNum = byteArrayToDecimal(wTargetNum); wTargetNum = ByteUtils.toLittleEndian(wTargetNum); int targetNum = ByteUtils.bytesToDecimal(wTargetNum); //log.info("目标总点数(转整型):" + targetNum); //解析NET_TARGET_UNIT(64是NET_TARGET_HEAD的字节数) int uintSize = (payloadSizeToDecimal - 64) / targetNum; // log.info("单条报警大小:" + uintSize); List<ArdAlarmRadar> radarAlarmInfos = new ArrayList<>(); for (int i = 0; i < targetNum; i++) { Integer index = 68 + uintSize * i; byte[] dwID = Arrays.copyOfRange(data, index, index + 4); // log.info("目标ID:" + DatatypeConverter.printHexBinary(cmdId)); dwID = toLittleEndian(dwID); int id = byteArrayToDecimal(dwID); dwID = ByteUtils.toLittleEndian(dwID); int id = ByteUtils.bytesToDecimal(dwID); // log.info("目标ID号:" + id); byte[] iDistance = Arrays.copyOfRange(data, index + 8, index + 12); iDistance = toLittleEndian(iDistance); int Distance = byteArrayToDecimal(iDistance); iDistance = ByteUtils.toLittleEndian(iDistance); Double Distance = ByteUtils.bytesToDouble(iDistance); // log.info("目标当前距离(m):" + Distance); //region 不需要的字段 // byte[] dwGSum = Arrays.copyOfRange(data, index + 4, index + 8); @@ -200,7 +199,7 @@ //endregion String alarmType = ""; byte[] cStat = Arrays.copyOfRange(data, index + 23, index + 24); cStat = toLittleEndian(cStat); cStat = ByteUtils.toLittleEndian(cStat); String binaryString = String.format("%8s", Integer.toBinaryString(cStat[0] & 0xFF)).replace(' ', '0'); // log.info("目标当前状态:" + binaryString); // 提取第4位至第6位的值 @@ -215,7 +214,7 @@ byte[] szName = Arrays.copyOfRange(data, index + 64, index + 96); int position = findIndexOfDoubleZero(szName); String alarmPointName = ""; String alarmPointName; if (position != -1) { byte[] result = new byte[position]; System.arraycopy(szName, 0, result, 0, position); @@ -225,16 +224,15 @@ } // log.info("所属告警区域名称:" + alarmPointName); byte[] afTx = Arrays.copyOfRange(data, index + 96, index + 100); afTx = toLittleEndian(afTx); float fTx = bytesToFloat(afTx); afTx = ByteUtils.toLittleEndian(afTx); float fTx = ByteUtils.bytesToFloat(afTx); // log.info("水平角度:" + fTx); byte[] afTy = Arrays.copyOfRange(data, index + 112, index + 116); afTy = toLittleEndian(afTy); float fTy = bytesToFloat(afTy); afTy = ByteUtils.toLittleEndian(afTy); float fTy = ByteUtils.bytesToFloat(afTy); // log.info("垂直角度:" + fTy); // log.info("雷达信息:" + host + "【port】" + port + "【X】" + longitude + "【Y】" + lagitude); Double[] radarXY = {longitude, lagitude}; Double[] alarmXY = CalculateCoordinates(radarXY, Distance, (double) fTx); Double[] alarmXY = GisUtils.CalculateCoordinates(radarXY, Distance, (double) fTx); // log.info("报警信息:" + "【id】" + id + "【name】" + alarmPointName + "【alarmType】" + alarmType + "【alarmTime】" + alarmTime + "【distance】" + Distance + "【P】" + fTx + "【T】" + fTy + "【X】" + alarmXY[0] + "【Y】" + alarmXY[1]); ArdAlarmRadar ardAlarmRadar = new ArdAlarmRadar(); ardAlarmRadar.setTargetId(id); @@ -244,134 +242,109 @@ ardAlarmRadar.setAlarmType(alarmType); radarAlarmInfos.add(ardAlarmRadar); } RadarAlarmData radarAlarmData = new RadarAlarmData(); radarAlarmData.setRadarId(id); radarAlarmData.setRadarName(name); radarAlarmData.setAlarmTime(alarmTime); radarAlarmData.setArdAlarmRadars(radarAlarmInfos); MqttConsumer.publish(2, false, "radar", JSON.toJSONString(radarAlarmData)); } } catch (Exception ex) { log.error(ex.getMessage()); } } if (Arrays.equals(cmdId, new byte[]{0x04})) { //String hexString = DatatypeConverter.printHexBinary(data); //log.info(hexString); /** * byte数组转float */ private float bytesToFloat(byte[] bytes) { ByteBuffer buffer = ByteBuffer.wrap(bytes); return buffer.getFloat(); } byte[] dwTim = Arrays.copyOfRange(data, 4, 8); dwTim = ByteUtils.toLittleEndian(dwTim); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); long l = ByteUtils.bytesToDecimal(dwTim); alarmTime = sdf.format(l * 1000); //log.info("周视图像的出现时间(转date):" + alarmTime); byte[] wTargetNum = Arrays.copyOfRange(data, 8, 10); wTargetNum = ByteUtils.toLittleEndian(wTargetNum); int targetNum = ByteUtils.bytesToDecimal(wTargetNum); //log.info("目标总点数(转整型):" + targetNum); /** * byte数组转整型 */ public int byteArrayToDecimal(byte[] byteArray) { int decimalValue = 0; //解析NET_TARGET_UNIT(64是NET_TARGET_HEAD的字节数) int uintSize = (payloadSizeToDecimal - 64) / targetNum; //log.info("单条报警大小:" + uintSize); for (int i = 0; i < targetNum; i++) { Integer index = 68 + uintSize * i; byte[] dwID = Arrays.copyOfRange(data, index, index + 4); //log.info("目标ID:" + DatatypeConverter.printHexBinary(dwID)); dwID = ByteUtils.toLittleEndian(dwID); int id = ByteUtils.bytesToDecimal(dwID); //log.info("目标ID号:" + id); //region 不需要的字段 byte[] iTw = Arrays.copyOfRange(data, index + 4, index + 8); iTw = ByteUtils.toLittleEndian(iTw); int Tw = ByteUtils.bytesToDecimal(iTw); // log.info("目标当前的像素宽度:" + Tw); for (int i = 0; i < byteArray.length; i++) { decimalValue = (decimalValue << 8) | (byteArray[i] & 0xFF); } byte[] iTh = Arrays.copyOfRange(data, index + 8, index + 12); iTh = ByteUtils.toLittleEndian(iTh); int Th = ByteUtils.bytesToDecimal(iTh); //log.info("目标当前的像素高度:" + Th); return decimalValue; } byte[] fTx = Arrays.copyOfRange(data, index + 12, index + 16); fTx = ByteUtils.toLittleEndian(fTx); float fTxAngle = ByteUtils.bytesToFloat(fTx); //log.info("p角度:" + fTxAngle); byte[] fTy = Arrays.copyOfRange(data, index + 16, index + 20); fTy = ByteUtils.toLittleEndian(fTy); float fTyAngle = ByteUtils.bytesToFloat(fTy); //log.info("t角度:" + fTyAngle); /** * 大端转小端 */ public byte[] toLittleEndian(byte[] bigEndianBytes) { byte[] littleEndianBytes = new byte[bigEndianBytes.length]; byte[] sAreaNo = Arrays.copyOfRange(data, index + 20, index + 22); sAreaNo = ByteUtils.toLittleEndian(sAreaNo); int AreaNo = ByteUtils.bytesToDecimal(sAreaNo); //log.info("目标归属的告警区域号:" + AreaNo); for (int i = 0; i < bigEndianBytes.length; i++) { int j = bigEndianBytes.length - i - 1; littleEndianBytes[i] = bigEndianBytes[j]; } byte[] cGrp = Arrays.copyOfRange(data, index + 22, index + 23); cGrp = ByteUtils.toLittleEndian(cGrp); int Grp = ByteUtils.bytesToDecimal(cGrp); //log.info("所属组:" + Grp); //endregion String alarmType; byte[] cStat = Arrays.copyOfRange(data, index + 23, index + 24); cStat = ByteUtils.toLittleEndian(cStat); //String binaryString = String.format("%8s", Integer.toBinaryString(cStat[0] & 0xFF)).replace(' ', '0'); //log.info("目标当前状态:" + binaryString); // 提取第0位值 // 使用位运算操作判断第0位是否为1 boolean isBitSet = (cStat[0] & 0x01) == 0x00; // 判断提取的值 if (isBitSet) { alarmType = "雷达抽油机停机"; } else { continue; } //log.info("报警类型:" + alarmType); return littleEndianBytes; } // 创建缓冲区列表 List<Byte> buffer = new ArrayList<>(); /** * 接收完整包 */ public byte[] receiveCompletePacket(byte[] receivedData) { // 定义包尾字节序列 byte[] packetEnd = {0x01, 0x02, 0x00}; // 添加已接收的数据到缓冲区 for (byte data : receivedData) { buffer.add(data); } // 检查缓冲区中的数据是否包含完整的包 while (buffer.size() >= packetEnd.length) { int endIndex = findPacketEndIndex(buffer, packetEnd); if (endIndex != -1) { // 找到完整的包 byte[] packet = extractPacketFromBuffer(buffer, endIndex + packetEnd.length); return packet; } else { // 未找到包尾,继续接收数据 break; } } // 未找到完整的包 return null; } /** * 获取包结束索引 */ public int findPacketEndIndex(List<Byte> buffer, byte[] packetEnd) { for (int i = 0; i <= buffer.size() - packetEnd.length; i++) { boolean isMatch = true; for (int j = 0; j < packetEnd.length; j++) { if (buffer.get(i + j) != packetEnd[j]) { isMatch = false; break; byte[] szName = Arrays.copyOfRange(data, index + 32, index + 64); //log.info("所属告警区域名称:" + DatatypeConverter.printHexBinary(szName)); int position = findIndexOfDoubleZero(szName); String alarmPointName; if (position != -1) { byte[] result = new byte[position]; System.arraycopy(szName, 0, result, 0, position); alarmPointName = new String(result, "GBK"); } else { alarmPointName = new String(szName, "GBK"); } // log.info("所属告警区域名称:" + alarmPointName); //log.info("报警信息:" + "【id】" + id + "【name】" + alarmPointName + "【alarmType】" + alarmType + "【alarmTime】" + alarmTime); ArdAlarmRadar ardAlarmRadar = new ArdAlarmRadar(); ardAlarmRadar.setTargetId(id); ardAlarmRadar.setName(alarmPointName); ardAlarmRadar.setAlarmType(alarmType); radarAlarmInfos.add(ardAlarmRadar); } } if (isMatch) { return i; } RadarAlarmData radarAlarmData = new RadarAlarmData(); radarAlarmData.setRadarId(id); radarAlarmData.setRadarName(name); radarAlarmData.setAlarmTime(alarmTime); radarAlarmData.setArdAlarmRadars(radarAlarmInfos); MqttConsumer.publish(2, false, "radar", JSON.toJSONString(radarAlarmData)); } catch (Exception ex) { log.error("雷达报文解析异常:" + ex.getMessage()); } return -1; } /** * 从缓冲区提取数据包 */ public byte[] extractPacketFromBuffer(List<Byte> buffer, int endIndex) { byte[] packet = new byte[endIndex]; for (int i = 0; i < endIndex; i++) { packet[i] = buffer.get(i); } buffer.subList(0, endIndex).clear(); return packet; } /** * 去掉包头和包尾校验及转义 */ public byte[] transferData(byte[] data) { data = Arrays.copyOfRange(data, 3, data.length); data = Arrays.copyOfRange(data, 0, data.length - 7); String dataStr = DatatypeConverter.printHexBinary(data); if (dataStr.contains("01020201")) {//转义01020201 dataStr = dataStr.replaceAll("01020201", "010201"); } if (dataStr.contains("01020200")) {//转义01020200 dataStr = dataStr.replaceAll("01020200", "010200"); } if (dataStr.contains("01020202")) {//转义01020202 dataStr = dataStr.replaceAll("01020202", "010202"); } data = DatatypeConverter.parseHexBinary(dataStr); return data; } /** @@ -384,21 +357,6 @@ } } return -1; } /** * 通过A点坐标,长度和Y轴角度计算B点坐标 */ public Double[] CalculateCoordinates(Double[] radarCoordinates, Integer distance, Double angle) { double[] to_wgs84 = LonlatConver.gcj02_To_Wgs84(radarCoordinates[0], radarCoordinates[1]); double Ax = to_wgs84[0]; // A 点的 X 坐标 double Ay = to_wgs84[1]; // A 点的 Y 坐标 double AB = distance; // AB 的长度 double angleWithYAxisDegrees = angle; // AB 与 Y 轴的角度(以度数表示) GeodeticCalculator calculator = new GeodeticCalculator(); GlobalCoordinates globalCoordinates = new GlobalCoordinates(Ay, Ax); GlobalCoordinates globalCoordinates1 = calculator.calculateEndingGlobalCoordinates(Ellipsoid.WGS84, globalCoordinates, angleWithYAxisDegrees, AB); return new Double[]{globalCoordinates1.getLongitude(), globalCoordinates1.getLatitude()}; } } src/main/resources/application.yml
@@ -9,7 +9,7 @@ enabled: true mqtt: host: tcp://192.168.1.15:1883 clientId: c3 clientId: cc3 username: admin password: xzx12345 topic: tube @@ -20,12 +20,12 @@ url: http://iot.zhdk.net:8090/Warning/GetWarning?userName=cy4oil datasource: driver-class-name: org.postgresql.Driver url: jdbc:postgresql://111.40.46.199:15432/ry-vue?stringtype=unspecified username: postgres password: Yykj.2021 # url: jdbc:postgresql://192.168.1.15:5432/ry-vue?stringtype=unspecified # url: jdbc:postgresql://111.40.46.199:15432/ry-vue?stringtype=unspecified # username: postgres # password: postgres # password: Yykj.2021 url: jdbc:postgresql://192.168.1.15:5432/ry-vue?stringtype=unspecified username: postgres password: postgres mybatis: typeAliasesPackage: com.ard.alarm.**.domain mapperLocations: classpath:/mapper/*.xml