From 6d5ff381cafca9b82e11407dc67bf6b74f1397ee Mon Sep 17 00:00:00 2001 From: 826220679@qq.com <826220679@qq.com> Date: 星期一, 11 八月 2025 23:15:40 +0800 Subject: [PATCH] 20250811 --- src/dell55AAData/Dell55AA12HighPerf.java | 2 src/dell55AAData/Dell55AA01Parser.java | 228 +++++++++------ src/chushihua/Chushihua.java | 2 src/window/WelcomeFrame.java | 2 src/dell_system/MessageViewPanel.java | 2 systemfile/logfile/openlog.txt | 42 +++ src/publicsWay/PacketProcessingSystem.java | 15 /dev/null | 218 --------------- src/dell_targets/Dell_BaseStation.java | 4 src/publicsWay/PacketParser.java | 222 +++++++++++++++ src/publicsWay/EfficientTimeFormatter.java | 36 ++ src/publicsWay/UDPPortAReceiver.java | 8 src/udptcp/UDPPortBReceiver.java | 2 13 files changed, 456 insertions(+), 327 deletions(-) diff --git a/src/chushihua/Chushihua.java b/src/chushihua/Chushihua.java index f99cc13..eb33bb9 100644 --- a/src/chushihua/Chushihua.java +++ b/src/chushihua/Chushihua.java @@ -8,7 +8,7 @@ import dell_targets.Dell_BaseStation; import dell_targets.Dell_SystemConfiguration; import dell_targets.Dell_tag; -import udptcp.UDPPortAReceiver; +import publicsWay.UDPPortAReceiver; public class Chushihua { public static void getchushihua() { diff --git a/src/dell55AAData/Dell55AA01Parser.java b/src/dell55AAData/Dell55AA01Parser.java index e44c3e8..7e6cdff 100644 --- a/src/dell55AAData/Dell55AA01Parser.java +++ b/src/dell55AAData/Dell55AA01Parser.java @@ -1,104 +1,140 @@ package dell55AAData; +import java.util.Arrays; + import dell_system.MessageViewPanel; +import dell_targets.Dell_BaseStation; +import dell_targets.Dell_tag; +import publicsWay.EfficientTimeFormatter; public class Dell55AA01Parser { - // 常量定义 - private static final String EXPECTED_HEADER = "55AA01"; // 协议头 - private static final int MIN_LENGTH = 42; // 最小长度(21字节*2字符) - private static final ThreadLocal<ParseResult> RESULT_CACHE = - ThreadLocal.withInitial(ParseResult::new); + // 常量定义 + private static final String EXPECTED_HEADER = "55AA01"; // 协议头 + private static final int MIN_LENGTH = 42; // 最小长度(21字节*2字符) + private static final ThreadLocal<ParseResult> RESULT_CACHE = + ThreadLocal.withInitial(ParseResult::new); - // 解析结果类 - public static class ParseResult { - public int sequenceNum; // 序列号 - public String tagId; // 标签ID(4字节小端序) - public String anchorId; // 锚点ID(4字节小端序) - public int distance; // 距离(毫米) - public int power; // 电量(0-100) - public boolean buttonPressed; // 按钮状态 - - public void reset() { - sequenceNum = 0; - tagId = ""; - anchorId = ""; - distance = 0; - power = 0; - buttonPressed = false; - } - } + // 解析结果类 + public static class ParseResult { + public int sequenceNum; // 序列号 + public String tagId; // 标签ID(4字节小端序) + public String anchorId; // 锚点ID(4字节小端序) + public int distance; // 距离(毫米) + public int power; // 电量(0-100) + public int buttonPressed; // 按钮状态 - /** - * 解析55AA01协议数据 - * @param message 十六进制字符串 - * @return 解析结果(错误时返回null) - */ - public static ParseResult parse(String message, String ip, int port) { - if (message == null || message.isEmpty()) { - return null; - } - // 清洗数据:移除所有非十六进制字符 - message = message.replaceAll("[^0-9A-Fa-f]", "").toUpperCase(); - - // 数据校验 - if (message == null || message.length() < MIN_LENGTH) { - return null; - } - - // 协议头校验 (55AA01) - for (int i = 0; i < 6; i++) { - if (message.charAt(i) != EXPECTED_HEADER.charAt(i)) { - return null; - } - } - - ParseResult result = RESULT_CACHE.get(); - result.reset(); - - try { - if (message.length() < 30) { // 确保有足够长度访问charAt(28) - return null; - } - // 解析序列号 (位置8-9) - result.sequenceNum = HexUtils.fastHexToByte( - message.charAt(8), message.charAt(9) - ); - - // 解析标签ID (位置10-13, 小端序) - result.tagId = new String(new char[] { - message.charAt(12), message.charAt(13), // 高位 - message.charAt(10), message.charAt(11) // 低位 - }); - - // 解析锚点ID (位置14-17, 小端序) - result.anchorId = new String(new char[] { - message.charAt(16), message.charAt(17), // 高位 - message.charAt(14), message.charAt(15) // 低位 - }); - - // 解析距离 (位置18-25, 4字节小端整数) - int b0 = HexUtils.fastHexToByte(message.charAt(18), message.charAt(19)); // 最低位 - int b1 = HexUtils.fastHexToByte(message.charAt(20), message.charAt(21)); - int b2 = HexUtils.fastHexToByte(message.charAt(22), message.charAt(23)); - int b3 = HexUtils.fastHexToByte(message.charAt(24), message.charAt(25)); // 最高位 - int raw = (b3 << 24) | (b2 << 16) | (b1 << 8) | b0; - result.distance = raw; // 保持原始整数值 - - // 解析电量 (位置26-27) - result.power = HexUtils.fastHexToByte(message.charAt(26), message.charAt(27)); - - // 解析按钮状态 (位置28-29) - result.buttonPressed = HexUtils.fastHexToByte(message.charAt(28), message.charAt(29)) == 1; - - String hexData = "55AA01标签地址:" + result.tagId + "基站地址:" + result.anchorId + - "距离:" + result.distance + "电量:" + result.power + - "按钮状态:" + result.buttonPressed; - MessageViewPanel.showData(hexData, ip, port, 0, "UDPA", "55AA01", "ALL"); - } catch (IndexOutOfBoundsException | NumberFormatException e) { - System.err.println("Parsing error in packet from " + ip + ":" + port); - return null; - } - - return result; - } + public void reset() { + sequenceNum = 0; + tagId = ""; + anchorId = ""; + distance = 0; + power = 0; + buttonPressed = 0; + } + } + + /** + * 解析55AA01协议数据 + * @param message 十六进制字符串 + * @return 解析结果(错误时返回null) + */ + public static ParseResult parse(String message, String ip, int port) { + if (message == null || message.isEmpty()) { + return null; + } + + // 清洗数据:移除所有非十六进制字符 + char[] cleanedMessage = cleanMessage(message); + + // 数据校验 + if (cleanedMessage == null || cleanedMessage.length < MIN_LENGTH) { + return null; + } + + // 协议头校验 (55AA01) + if (!new String(cleanedMessage, 0, 6).equals(EXPECTED_HEADER)) { + return null; + } + + ParseResult result = RESULT_CACHE.get(); + result.reset(); + + try { + if (cleanedMessage.length < 30) { // 确保有足够长度访问charAt(28) + return null; + } + + // 解析序列号 (位置8-9) + result.sequenceNum = HexUtils.fastHexToByte(cleanedMessage[8], cleanedMessage[9]); + + // 解析标签ID (位置10-13, 小端序) + result.tagId = new String(new char[]{ + cleanedMessage[12], cleanedMessage[13], // 高位 + cleanedMessage[10], cleanedMessage[11] // 低位 + }); + + // 解析锚点ID (位置14-17, 小端序) + result.anchorId = new String(new char[]{ + cleanedMessage[16], cleanedMessage[17], // 高位 + cleanedMessage[14], cleanedMessage[15] // 低位 + }); + + // 解析距离 (位置18-25, 4字节小端整数) + int b0 = HexUtils.fastHexToByte(cleanedMessage[18], cleanedMessage[19]); // 最低位 + int b1 = HexUtils.fastHexToByte(cleanedMessage[20], cleanedMessage[21]); + int b2 = HexUtils.fastHexToByte(cleanedMessage[22], cleanedMessage[23]); + int b3 = HexUtils.fastHexToByte(cleanedMessage[24], cleanedMessage[25]); // 最高位 + int raw = (b3 << 24) | (b2 << 16) | (b1 << 8) | b0; + result.distance = raw; // 保持原始整数值 + + // 解析电量 (位置26-27) + result.power = HexUtils.fastHexToByte(cleanedMessage[26], cleanedMessage[27]); + + // 解析按钮状态 (位置28-29) + result.buttonPressed = HexUtils.fastHexToByte(cleanedMessage[28], cleanedMessage[29]); + + // 日志和更新操作可以考虑优化或减少调用频率 + String hexData = "55AA01 包序:" + result.sequenceNum + ",标签编号:" + result.tagId + ",基站编号:" + result.anchorId + + ",距离:" + result.distance + ",电量:" + result.power + + ",按钮状态:" + result.buttonPressed; + MessageViewPanel.showData(hexData, ip, port, 0, "UDPA", "55AA01", "ALL"); + + String time = EfficientTimeFormatter.getCurrentTimeFormatted(); + Dell_BaseStation.updateBaseStationProperty(result.anchorId, "ipAddress", ip); + Dell_BaseStation.updateBaseStationProperty(result.anchorId, "port", port + ""); + Dell_BaseStation.updateBaseStationProperty(result.anchorId, "status", "1"); + Dell_BaseStation.updateBaseStationProperty(result.anchorId, "onlineTime", time); + + Dell_tag.updateLocationTagProperty(result.tagId, "sosStatus", result.buttonPressed + ""); + Dell_tag.updateLocationTagProperty(result.tagId, "onlineStatus", "1"); + Dell_tag.updateLocationTagProperty(result.tagId, "lastUwbSignalTime", time); + Dell_tag.updateLocationTagProperty(result.tagId, "latestRangingSeq", result.sequenceNum + ""); + Dell_tag.updateLocationTagProperty(result.tagId, "latestRangingBaseId", result.anchorId); + Dell_tag.updateLocationTagProperty(result.tagId, "latestRangingDistance", result.distance + ""); + Dell_tag.updateLocationTagProperty(result.tagId, "latestRangingBaseCount", "1"); + + } catch (IndexOutOfBoundsException | NumberFormatException e) { + System.err.println("Parsing error in packet from " + ip + ":" + port); + return null; + } + + return result; + } + + private static char[] cleanMessage(String message) { + char[] cleaned = new char[message.length()]; + int j = 0; + for (char c : message.toCharArray()) { + if (Character.isDigit(c) || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f')) { + cleaned[j++] = Character.toUpperCase(c); + } + } + if (j == 0) return null; + return Arrays.copyOf(cleaned, j); + } + + public static void updateBase(String baseStationId, String propertyName, String value) { + Dell_BaseStation.updateBaseStationProperty(baseStationId, propertyName, value); + Dell_BaseStation.updateBaseStationProperty(baseStationId, propertyName, value); + } } \ No newline at end of file diff --git a/src/dell55AAData/Dell55AA12HighPerf.java b/src/dell55AAData/Dell55AA12HighPerf.java index 06f29dd..46f169a 100644 --- a/src/dell55AAData/Dell55AA12HighPerf.java +++ b/src/dell55AAData/Dell55AA12HighPerf.java @@ -48,7 +48,7 @@ * @param message 原始16进制字符串 * @return 解析结果对象(线程安全) */ - public static ParseResult parse(String message) { + public static ParseResult parse(String message,String ip,int port) { // 长度校验 if (message == null || message.length() < MIN_LENGTH) { return null; diff --git a/src/dell_system/MessageViewPanel.java b/src/dell_system/MessageViewPanel.java index 7d090dd..aaab8a1 100644 --- a/src/dell_system/MessageViewPanel.java +++ b/src/dell_system/MessageViewPanel.java @@ -12,7 +12,7 @@ import java.util.ResourceBundle; import dell_targets.Dell_tag; import publicsWay.Languages; -import udptcp.UDPPortAReceiver; +import publicsWay.UDPPortAReceiver; import udptcp.UDPPortBReceiver; public class MessageViewPanel extends JPanel { diff --git a/src/dell_targets/Dell_BaseStation.java b/src/dell_targets/Dell_BaseStation.java index c58dd3b..18ded24 100644 --- a/src/dell_targets/Dell_BaseStation.java +++ b/src/dell_targets/Dell_BaseStation.java @@ -113,6 +113,8 @@ station.setBattery(value); break; // 更新电量 case "ipAddress": station.setIpAddress(value); break; // 更新IP地址 + case "port": + station.setPort(value); break; //更新端口 case "onlineTime": station.setOnlineTime(value); break; // 更新上线时间 case "offlineTime": @@ -123,7 +125,7 @@ station.setSyncStatus(value); break; //同步状态 case "barometerReading": station.setBarometerReading(value); break; //同步状态 - + // 添加其他高频属性... default: throw new IllegalArgumentException("不支持属性: " + propertyName); diff --git a/src/publicsWay/EfficientTimeFormatter.java b/src/publicsWay/EfficientTimeFormatter.java new file mode 100644 index 0000000..b2ccf5b --- /dev/null +++ b/src/publicsWay/EfficientTimeFormatter.java @@ -0,0 +1,36 @@ +package publicsWay; +import java.time.Instant; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeFormatterBuilder; +import java.time.temporal.ChronoField; + +public class EfficientTimeFormatter { + + // 使用 ThreadLocal 来存储每个线程的 DateTimeFormatter + private static final ThreadLocal<DateTimeFormatter> formatterThreadLocal = ThreadLocal.withInitial(() -> { + // 使用 DateTimeFormatterBuilder 构建一个高效的格式化器 + return new DateTimeFormatterBuilder() + .appendValue(ChronoField.YEAR, 4) + .appendLiteral('-') + .appendValue(ChronoField.MONTH_OF_YEAR, 2) + .appendLiteral('-') + .appendValue(ChronoField.DAY_OF_MONTH, 2) + .appendLiteral(' ') + .appendValue(ChronoField.HOUR_OF_DAY, 2) + .appendLiteral(':') + .appendValue(ChronoField.MINUTE_OF_HOUR, 2) + .appendLiteral(':') + .appendValue(ChronoField.SECOND_OF_MINUTE, 2) + .toFormatter(); + }); + + // 获取当前时间的字符串表示 + public static String getCurrentTimeFormatted() { + Instant now = Instant.now(); // 获取当前时间 + DateTimeFormatter formatter = formatterThreadLocal.get(); // 获取当前线程的格式化器 + return formatter.format(now.atZone(ZoneId.systemDefault())); // 格式化时间 + } + + +} \ No newline at end of file diff --git a/src/publicsWay/PacketParser.java b/src/publicsWay/PacketParser.java new file mode 100644 index 0000000..4ebf1a6 --- /dev/null +++ b/src/publicsWay/PacketParser.java @@ -0,0 +1,222 @@ +package publicsWay; + +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; + +// 重命名为PacketParser,表示数据包解析器 +public class PacketParser { + // 添加十六进制字符数组常量 + private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray(); + // 缓冲区字节数组 + private byte[] buffer = new byte[4096]; + // 当前缓冲区有效数据长度 + private int bufferLength = 0; + + // 追加新数据到缓冲区 + public void appendData(byte[] newData, int length) { + // 检查缓冲区是否足够 + if (bufferLength + length > buffer.length) { + // 创建新的更大缓冲区 + byte[] newBuffer = new byte[bufferLength + length]; + // 复制原有数据 + System.arraycopy(buffer, 0, newBuffer, 0, bufferLength); + buffer = newBuffer; + } + // 追加新数据 + System.arraycopy(newData, 0, buffer, bufferLength, length); + // 更新缓冲区长度 + bufferLength += length; + } + + // 新增方法:字节数组转十六进制字符串 + public static String bytesToHexString(byte[] bytes) { + if (bytes == null) return ""; + char[] hexChars = new char[bytes.length * 2]; + for (int j = 0; j < bytes.length; j++) { + int v = bytes[j] & 0xFF; + hexChars[j * 2] = HEX_ARRAY[v >>> 4]; + hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F]; + } + return new String(hexChars); + } + + // 解析缓冲区中的所有完整数据包 + public List<DataPacket> parsePackets() { + List<DataPacket> packets = new ArrayList<>(); + int index = 0; // 当前解析位置索引 + + // 遍历缓冲区查找完整数据包 + while (index <= bufferLength - 4) { // 确保有足够数据检查包头 + // 检查包头标识 0x55 0xAA + if (buffer[index] == 0x55 && (buffer[index + 1] & 0xFF) == 0xAA) { + // 获取包类型(第3字节) + int packetType = buffer[index + 2] & 0xFF; + // 获取数据长度(第4字节) + int dataLenField = buffer[index + 3] & 0xFF; + // 计算完整包长度(包头+数据+校验) + int totalPacketLen = 2 + dataLenField + 2; // 增加2字节校验位 + + // 检查是否有足够数据构成完整包 + if (index + totalPacketLen > bufferLength) { + break; // 数据不足,等待更多数据 + } + + // 提取完整数据包 + byte[] packetData = new byte[totalPacketLen]; + System.arraycopy(buffer, index, packetData, 0, totalPacketLen); + + // 验证校验和 + if (verifyChecksum(packetData)) { + // 解析单个数据包 + DataPacket packet = parseSinglePacket(packetType, packetData); + if (packet != null) { + packets.add(packet); // 添加到结果列表 + } + index += totalPacketLen; // 移动到下一个包 + } else { + index++; // 校验失败,跳过当前字节 + } + } else { + index++; // 非包头标识,继续查找 + } + } + + // 清理已处理数据 + if (index > 0) { + int remaining = bufferLength - index; + if (remaining > 0) { + // 移动剩余数据到缓冲区开头 + System.arraycopy(buffer, index, buffer, 0, remaining); + } + bufferLength = remaining; // 更新缓冲区长度 + } + + return packets; + } + + // 校验数据包 + private boolean verifyChecksum(byte[] packet) { + int len = packet.length; + if (len < 4) return false; + + int sum = 0; + // 从数据类型开始到校验码前结束 (包头2字节已跳过) + for (int i = 2; i < len - 2; i++) { + sum += packet[i] & 0xFF; + } + sum = ~sum & 0xFFFF; // 取反并保留16位 + + // 获取包中的校验码 (小端模式) + int receivedChecksum = ((packet[len - 1] & 0xFF) << 8) | (packet[len - 2] & 0xFF); + + return sum == receivedChecksum; + } + + + + // 解析单个数据包 + private DataPacket parseSinglePacket(int packetType, byte[] packet) { + + // 创建数据包对象(包含包类型) + return new DataPacket(packetType, packet); + } + + // 数据包内部类 + public static class DataPacket { + private final int packetType; // 包类型 + private final byte[] packet;//包数据 + + + public DataPacket(int packetType, byte[] packet) { + this.packetType = packetType; + this.packet = packet; + } + + // 获取包类型 + public int getPacketType() { + return packetType; + } + + // 包数据 + public byte[] getPacket() { + return packet; + } + + } + + // HEX字符串转字节数组 + public static byte[] hexStringToBytes(String hex) { + // 移除空格 + hex = hex.replaceAll("\\s", ""); + int len = hex.length(); + // 创建结果数组 + byte[] data = new byte[len / 2]; + // 每两个字符转换一个字节 + for (int i = 0; i < len; i += 2) { + // 高位转换 + int high = Character.digit(hex.charAt(i), 16) << 4; + // 低位转换 + int low = Character.digit(hex.charAt(i + 1), 16); + data[i / 2] = (byte) (high | low); + } + return data; + } + + + + + /**输出校验码*/ + public static String calculateChecksum(String input) { + // 检查输入是否为空 + if (input == null) { + throw new IllegalArgumentException("输入不能为null"); + } + + // 移除所有空格 + String cleanInput = input.replaceAll("\\s", ""); + + // 验证处理后的字符串 + if (cleanInput.length() < 8 || !cleanInput.startsWith("55AA")) { + throw new IllegalArgumentException("输入字符串必须以55AA开头且长度至少为8(去除空格后)"); + } + + // 去掉包头(55AA)和最后4个字符 + String dataPart = cleanInput.substring(4, cleanInput.length() - 4); + + // 检查中间部分长度是否为偶数 + if (dataPart.length() % 2 != 0) { + throw new IllegalArgumentException("中间部分长度必须是偶数(去除空格后)"); + } + + int sum = 0; + // 每两个字符解析为一个字节 + for (int i = 0; i < dataPart.length(); i += 2) { + String byteStr = dataPart.substring(i, i + 2); + int byteValue = Integer.parseInt(byteStr, 16); + sum = (sum + byteValue) & 0xFFFF; // 保持16位范围 + } + + // 取反并保持16位 + int checksum = (~sum) & 0xFFFF; + + // 显式处理高位在前格式 + int lowByte= (checksum >>> 8) & 0xFF; // 高8位 + int highByte= checksum & 0xFF; // 低8位 + + // 格式化为4位十六进制字符串(大写),高位在前 + System.out.println(String.format("%02X%02X", highByte, lowByte)); + return String.format("%02X%02X", highByte, lowByte); + } + + /** 将字节数组转为十六进制字符串,例如 [55 AA 01 02 ...] */ + private static String bytesToHex(byte[] bytes) { + if (bytes == null) return "null"; + StringBuilder sb = new StringBuilder(bytes.length * 3); + for (byte b : bytes) { + sb.append(String.format("%02X ", b & 0xFF)); + } + // 去掉最后一个空格 + return sb.substring(0, sb.length() - 1); + } +} \ No newline at end of file diff --git a/src/udptcp/PacketProcessingSystem.java b/src/publicsWay/PacketProcessingSystem.java similarity index 88% rename from src/udptcp/PacketProcessingSystem.java rename to src/publicsWay/PacketProcessingSystem.java index 7a31faf..24dcf5c 100644 --- a/src/udptcp/PacketProcessingSystem.java +++ b/src/publicsWay/PacketProcessingSystem.java @@ -1,8 +1,10 @@ -package udptcp; +package publicsWay; import java.util.List; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.atomic.AtomicBoolean; import dell55AAData.Dell55AA01Parser; +import dell55AAData.Dell55AA12HighPerf; + import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -62,8 +64,7 @@ isRunning.set(true); parserThread = new Thread(() -> { - PacketParser bufferManager = new PacketParser(); - + PacketParser bufferManager = new PacketParser(); while (isRunning.get()) { HexPacket packet = packetQueue.poll(); if (packet == null) { @@ -88,7 +89,8 @@ processType01(p,ip,port);break; case 0x02: processType02(p,ip,port);break; - + case 0x12: + processType12(p,ip,port);break; default: System.err.println("未知包类型: " + p.getPacketType()); } @@ -119,9 +121,14 @@ } private static void processType02(PacketParser.DataPacket packet,String ip,int port) { + String hexData = PacketParser.bytesToHexString(packet.getPacket()); System.out.println("处理55AA02包: " + packet); // 实际业务逻辑 } + private static void processType12(PacketParser.DataPacket packet,String ip,int port) { + String hexData = PacketParser.bytesToHexString(packet.getPacket()); + Dell55AA12HighPerf.parse(hexData,ip,port); + } // 其他类型处理方法... } diff --git a/src/udptcp/UDPPortAReceiver.java b/src/publicsWay/UDPPortAReceiver.java similarity index 95% rename from src/udptcp/UDPPortAReceiver.java rename to src/publicsWay/UDPPortAReceiver.java index 29b5f97..2c68130 100644 --- a/src/udptcp/UDPPortAReceiver.java +++ b/src/publicsWay/UDPPortAReceiver.java @@ -1,4 +1,4 @@ -package udptcp; +package publicsWay; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; @@ -104,10 +104,10 @@ } private static String bytesToHex(byte[] bytes, int length) { + if (bytes == null || length <= 0) return ""; StringBuilder sb = new StringBuilder(); - for (int i = 0; i < length; i++) { - // 确保生成大写、无分隔符的十六进制 - sb.append(String.format("%02X", bytes[i])); + for (int i = 0; i < length && i < bytes.length; i++) { + sb.append(String.format("%02X", bytes[i] & 0xFF)); } return sb.toString(); } diff --git a/src/udptcp/PacketParser.java b/src/udptcp/PacketParser.java deleted file mode 100644 index d2ce8d3..0000000 --- a/src/udptcp/PacketParser.java +++ /dev/null @@ -1,218 +0,0 @@ -package udptcp; - -import java.util.ArrayList; -import java.util.List; - -// 重命名为PacketParser,表示数据包解析器 -public class PacketParser { - // 添加十六进制字符数组常量 - private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray(); - // 缓冲区字节数组 - private byte[] buffer = new byte[4096]; - // 当前缓冲区有效数据长度 - private int bufferLength = 0; - - // 追加新数据到缓冲区 - public void appendData(byte[] newData, int length) { - // 检查缓冲区是否足够 - if (bufferLength + length > buffer.length) { - // 创建新的更大缓冲区 - byte[] newBuffer = new byte[bufferLength + length]; - // 复制原有数据 - System.arraycopy(buffer, 0, newBuffer, 0, bufferLength); - buffer = newBuffer; - } - // 追加新数据 - System.arraycopy(newData, 0, buffer, bufferLength, length); - // 更新缓冲区长度 - bufferLength += length; - } - - // 新增方法:字节数组转十六进制字符串 - public static String bytesToHexString(byte[] bytes) { - if (bytes == null) return ""; - char[] hexChars = new char[bytes.length * 2]; - for (int j = 0; j < bytes.length; j++) { - int v = bytes[j] & 0xFF; - hexChars[j * 2] = HEX_ARRAY[v >>> 4]; - hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F]; - } - return new String(hexChars); - } - - // 解析缓冲区中的所有完整数据包 - public List<DataPacket> parsePackets() { - List<DataPacket> packets = new ArrayList<>(); - int index = 0; // 当前解析位置索引 - - // 遍历缓冲区查找完整数据包 - while (index <= bufferLength - 4) { // 确保有足够数据检查包头 - // 检查包头标识 0x55 0xAA - if (buffer[index] == 0x55 && (buffer[index + 1] & 0xFF) == 0xAA) { - // 获取包类型(第3字节) - int packetType = buffer[index + 2] & 0xFF; - // 获取数据长度(第4字节) - int dataLenField = buffer[index + 3] & 0xFF; - // 计算完整包长度(包头+数据+校验) - int totalPacketLen = 4 + dataLenField + 2; // 增加2字节校验位 - - // 检查是否有足够数据构成完整包 - if (index + totalPacketLen > bufferLength) { - break; // 数据不足,等待更多数据 - } - - // 提取完整数据包 - byte[] packetData = new byte[totalPacketLen]; - System.arraycopy(buffer, index, packetData, 0, totalPacketLen); - - // 验证校验和 - if (verifyChecksum(packetData)) { - // 解析单个数据包 - DataPacket packet = parseSinglePacket(packetType, packetData); - if (packet != null) { - packets.add(packet); // 添加到结果列表 - } - index += totalPacketLen; // 移动到下一个包 - } else { - index++; // 校验失败,跳过当前字节 - } - } else { - index++; // 非包头标识,继续查找 - } - } - - // 清理已处理数据 - if (index > 0) { - int remaining = bufferLength - index; - if (remaining > 0) { - // 移动剩余数据到缓冲区开头 - System.arraycopy(buffer, index, buffer, 0, remaining); - } - bufferLength = remaining; // 更新缓冲区长度 - } - - return packets; - } - - // 校验数据包完整性 - public static boolean verifyChecksum(byte[] data) { - // 检查输入是否为null - if (data == null) { - throw new IllegalArgumentException("输入不能为null"); - } - - // 验证长度和包头 - if (data.length < 8 || data[0] != 0x55 || data[1] != (byte)0xAA) { - throw new IllegalArgumentException("输入必须以0x55和0xAA开头且长度至少为8字节"); - } - - int sum = 0; - // 遍历数据部分(跳过包头和最后2字节校验码) - for (int i = 2; i < data.length - 2; i++) { - // 无符号累加(0x00~0xFF) - sum = (sum + (data[i] & 0xFF)) & 0xFFFF; // 维持16位范围 - } - - // 计算校验码(取反后取低16位) - int checksum = (~sum) & 0xFFFF; - - // 按小端序拆分校验码(低字节在前) - byte calcLow = (byte)(checksum & 0xFF); // 低8位 - byte calcHigh = (byte)((checksum >>> 8) & 0xFF); // 高8位 - - // 直接比较最后两个字节(避免创建新对象) - boolean a1=(data[data.length - 2] == calcLow) &&(data[data.length - 1] == calcHigh); - return true; - } - - // 解析单个数据包 - private DataPacket parseSinglePacket(int packetType, byte[] packet) { - - // 创建数据包对象(包含包类型) - return new DataPacket(packetType, packet); - } - - // 数据包内部类 - public static class DataPacket { - private final int packetType; // 包类型 - private final byte[] packet;//包数据 - - - public DataPacket(int packetType, byte[] packet) { - this.packetType = packetType; - this.packet = packet; - } - - // 获取包类型 - public int getPacketType() { - return packetType; - } - - // 包数据 - public byte[] getPacket() { - return packet; - } - - } - - // HEX字符串转字节数组 - public static byte[] hexStringToBytes(String hex) { - // 移除空格 - hex = hex.replaceAll("\\s", ""); - int len = hex.length(); - // 创建结果数组 - byte[] data = new byte[len / 2]; - // 每两个字符转换一个字节 - for (int i = 0; i < len; i += 2) { - // 高位转换 - int high = Character.digit(hex.charAt(i), 16) << 4; - // 低位转换 - int low = Character.digit(hex.charAt(i + 1), 16); - data[i / 2] = (byte) (high | low); - } - return data; - } - - - /**输出校验码*/ - public static String calculateChecksum(String input) { - // 检查输入是否为空 - if (input == null) { - throw new IllegalArgumentException("输入不能为null"); - } - - // 移除所有空格 - String cleanInput = input.replaceAll("\\s", ""); - - // 验证处理后的字符串 - if (cleanInput.length() < 8 || !cleanInput.startsWith("55AA")) { - throw new IllegalArgumentException("输入字符串必须以55AA开头且长度至少为8(去除空格后)"); - } - - // 去掉包头(55AA)和最后4个字符 - String dataPart = cleanInput.substring(4, cleanInput.length() - 4); - - // 检查中间部分长度是否为偶数 - if (dataPart.length() % 2 != 0) { - throw new IllegalArgumentException("中间部分长度必须是偶数(去除空格后)"); - } - - int sum = 0; - // 每两个字符解析为一个字节 - for (int i = 0; i < dataPart.length(); i += 2) { - String byteStr = dataPart.substring(i, i + 2); - int byteValue = Integer.parseInt(byteStr, 16); - sum = (sum + byteValue) & 0xFFFF; // 保持16位范围 - } - - // 取反并保持16位 - int checksum = (~sum) & 0xFFFF; - - // 显式处理高位在前格式 - int lowByte= (checksum >>> 8) & 0xFF; // 高8位 - int highByte= checksum & 0xFF; // 低8位 - - // 格式化为4位十六进制字符串(大写),高位在前 - return String.format("%02X%02X", highByte, lowByte); - } -} \ No newline at end of file diff --git a/src/udptcp/UDPPortBReceiver.java b/src/udptcp/UDPPortBReceiver.java index 9e006a4..9ba1dd9 100644 --- a/src/udptcp/UDPPortBReceiver.java +++ b/src/udptcp/UDPPortBReceiver.java @@ -6,6 +6,8 @@ import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicLong; +import publicsWay.PacketProcessingSystem; + public class UDPPortBReceiver { public static final int PORT = 7000; @SuppressWarnings("unused") diff --git a/src/window/WelcomeFrame.java b/src/window/WelcomeFrame.java index 8d081b6..7867f43 100644 --- a/src/window/WelcomeFrame.java +++ b/src/window/WelcomeFrame.java @@ -9,10 +9,10 @@ import java.util.ResourceBundle; -import udptcp.UDPPortAReceiver; import udptcp.UDPPortBReceiver; import dell_targets.Dell_BaseStation; import dell_targets.Dell_tag; +import publicsWay.UDPPortAReceiver; import dell_targets.Dell_SystemConfiguration; public class WelcomeFrame extends JInternalFrame { diff --git a/systemfile/logfile/openlog.txt b/systemfile/logfile/openlog.txt index 9e68708..0f4e122 100644 --- a/systemfile/logfile/openlog.txt +++ b/systemfile/logfile/openlog.txt @@ -918,3 +918,45 @@ 程序关闭: 2025-08-10 23:04:37 工作时长: 0小时 0分钟 30秒 ----------------------------------- +程序启动: 2025-08-11 21:15:59 +程序启动: 2025-08-11 21:17:08 +程序关闭: 2025-08-11 21:17:13 +工作时长: 0小时 1分钟 13秒 +----------------------------------- +程序启动: 2025-08-11 21:17:15 +程序启动: 2025-08-11 21:19:09 +程序关闭: 2025-08-11 21:19:13 +工作时长: 0小时 1分钟 57秒 +----------------------------------- +程序启动: 2025-08-11 21:19:15 +程序启动: 2025-08-11 21:31:02 +程序关闭: 2025-08-11 21:31:05 +工作时长: 0小时 11分钟 50秒 +----------------------------------- +程序启动: 2025-08-11 21:31:07 +程序启动: 2025-08-11 21:31:57 +程序启动: 2025-08-11 21:47:14 +程序启动: 2025-08-11 21:48:16 +程序启动: 2025-08-11 21:56:20 +程序关闭: 2025-08-11 22:00:14 +工作时长: 0小时 3分钟 54秒 +----------------------------------- +程序启动: 2025-08-11 22:00:17 +程序启动: 2025-08-11 22:03:49 +程序启动: 2025-08-11 22:14:55 +程序关闭: 2025-08-11 22:14:57 +工作时长: 0小时 0分钟 2秒 +----------------------------------- +程序启动: 2025-08-11 22:15:01 +程序启动: 2025-08-11 22:16:04 +程序启动: 2025-08-11 22:18:00 +程序启动: 2025-08-11 22:21:23 +程序启动: 2025-08-11 22:25:32 +程序关闭: 2025-08-11 22:25:37 +工作时长: 0小时 0分钟 5秒 +----------------------------------- +程序启动: 2025-08-11 22:27:02 +程序关闭: 2025-08-11 22:27:28 +工作时长: 0小时 0分钟 25秒 +----------------------------------- +程序启动: 2025-08-11 23:04:55 -- Gitblit v1.9.3