src/dell55AAData/Dell55AA01Parser.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/udptcp/PacketParser.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/udptcp/PacketProcessingSystem.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/udptcp/UDPPortAReceiver.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/window/WelcomeFrame.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
systemfile/Messages_en.properties | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
systemfile/Messages_zh.properties | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
systemfile/logfile/openlog.txt | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
src/dell55AAData/Dell55AA01Parser.java
@@ -1,7 +1,9 @@ package dell55AAData; import dell_system.MessageViewPanel; 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 = @@ -10,8 +12,8 @@ // 解析结果类 public static class ParseResult { public int sequenceNum; // 序列号 public String tagId; // 标签ID(4字节十六进制) public String anchorId; // 锚点ID(4字节十六进制) public String tagId; // 标签ID(4字节小端序) public String anchorId; // 锚点ID(4字节小端序) public int distance; // 距离(毫米) public int power; // 电量(0-100) public boolean buttonPressed; // 按钮状态 @@ -29,55 +31,73 @@ /** * 解析55AA01协议数据 * @param message 十六进制字符串 * @return 解析结果(失败返回null) * @return 解析结果(错误时返回null) */ public static ParseResult parse(String message) { // 参数检查 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) // 协议头校验 (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(); char[] chars = HexUtils.getThreadLocalBuffer(); message.getChars(0, Math.min(message.length(), chars.length), chars, 0); try { if (message.length() < 30) { // 确保有足够长度访问charAt(28) return null; } // 解析序列号 (位置8-9) result.sequenceNum = HexUtils.fastHexToByte(chars[8], chars[9]); result.sequenceNum = HexUtils.fastHexToByte( message.charAt(8), message.charAt(9) ); // 解析标签ID (位置10-13, 小端序) result.tagId = new String(new char[] { chars[12], chars[13], // 高位 chars[10], chars[11] // 低位 message.charAt(12), message.charAt(13), // 高位 message.charAt(10), message.charAt(11) // 低位 }); // 解析锚点ID (位置14-17, 小端序) result.anchorId = new String(new char[] { chars[16], chars[17], // 高位 chars[14], chars[15] // 低位 message.charAt(16), message.charAt(17), // 高位 message.charAt(14), message.charAt(15) // 低位 }); // 解析距离 (位置18-25, 4字节小端序整数) int b0 = HexUtils.fastHexToByte(chars[18], chars[19]); // 最低位 int b1 = HexUtils.fastHexToByte(chars[20], chars[21]); int b2 = HexUtils.fastHexToByte(chars[22], chars[23]); int b3 = HexUtils.fastHexToByte(chars[24], chars[25]); // 最高位 // 解析距离 (位置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(chars[26], chars[27]); result.power = HexUtils.fastHexToByte(message.charAt(26), message.charAt(27)); // 解析按钮状态 (位置28-29) result.buttonPressed = HexUtils.fastHexToByte(chars[28], chars[29]) == 1; 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; } src/udptcp/PacketParser.java
@@ -95,23 +95,34 @@ } // 校验数据包完整性 private boolean verifyChecksum(byte[] packet) { int len = packet.length; if (len < 4) return false; // 长度不足 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; // 计算从第3字节到倒数第3字节的和(跳过包头和校验位) for (int i = 2; i < len - 2; i++) { sum += packet[i] & 0xFF; // 遍历数据部分(跳过包头和最后2字节校验码) for (int i = 2; i < data.length - 2; i++) { // 无符号累加(0x00~0xFF) sum = (sum + (data[i] & 0xFF)) & 0xFFFF; // 维持16位范围 } // 取反得到16位校验和 sum = ~sum & 0xFFFF; // 提取包中的校验和(小端格式) int receivedChecksum = ((packet[len - 1] & 0xFF) << 8) | (packet[len - 2] & 0xFF); // 计算校验码(取反后取低16位) int checksum = (~sum) & 0xFFFF; // 比较校验和 return sum == receivedChecksum; // 按小端序拆分校验码(低字节在前) 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; } // 解析单个数据包 @@ -125,6 +136,7 @@ public static class DataPacket { private final int packetType; // 包类型 private final byte[] packet;//包数据 public DataPacket(int packetType, byte[] packet) { this.packetType = packetType; @@ -160,4 +172,47 @@ } 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); } } src/udptcp/PacketProcessingSystem.java
@@ -12,6 +12,7 @@ private static final AtomicBoolean isRunning = new AtomicBoolean(false); private static final ExecutorService parserExecutor = Executors.newSingleThreadExecutor(); private static Thread parserThread; private static boolean a1=true; // 报文存储结构 public static class HexPacket { @@ -26,10 +27,30 @@ this.hexData = hexData; this.timestamp = timestamp; } public String getIp() { return ip; } public int getPort() { return port; } public String getHexData() { return hexData; } public long getTimestamp() { return timestamp; } } // 接收端存储报文(UDPPortAReceiver中调用) public static void storePacket(String ip, int port, String hexData) { if(a1) { startProcessing(); a1=false; } if (packetQueue.size() < 100000) { // 限制队列大小防止OOM packetQueue.offer(new HexPacket(ip, port, hexData, System.currentTimeMillis())); } @@ -53,6 +74,8 @@ try { // 转换HEX为字节数据 byte[] rawData = PacketParser.hexStringToBytes(packet.hexData); String ip=packet.getIp(); int port=packet.getPort(); // 追加到缓冲区并解析 bufferManager.appendData(rawData, rawData.length); List<PacketParser.DataPacket> parsedPackets = bufferManager.parsePackets(); @@ -62,9 +85,9 @@ // 根据包头类型路由到不同解析器 switch (p.getPacketType()) { case 0x01: processType01(p);break; processType01(p,ip,port);break; case 0x02: processType02(p);break; processType02(p,ip,port);break; default: System.err.println("未知包类型: " + p.getPacketType()); @@ -90,12 +113,12 @@ } // 示例解析方法(需根据实际协议实现) private static void processType01(PacketParser.DataPacket packet) { private static void processType01(PacketParser.DataPacket packet,String ip,int port) { String hexData = PacketParser.bytesToHexString(packet.getPacket()); Dell55AA01Parser.parse(hexData); Dell55AA01Parser.parse(hexData,ip,port); } private static void processType02(PacketParser.DataPacket packet) { private static void processType02(PacketParser.DataPacket packet,String ip,int port) { System.out.println("处理55AA02包: " + packet); // 实际业务逻辑 } src/udptcp/UDPPortAReceiver.java
@@ -33,17 +33,32 @@ socket.receive(packet); executor.execute(() -> { try { String ip = packet.getAddress().getHostAddress(); InetAddress address = packet.getAddress(); if (address == null) { System.err.println("Received packet with null address"); return; } String ip = address.getHostAddress(); int port = packet.getPort(); String hexData = bytesToHex(packet.getData(), packet.getLength()); byte[] packetData = packet.getData(); int length = packet.getLength(); if (packetData == null || length <= 0) { System.err.println("Invalid packet data"); return; } String hexData = bytesToHex(packetData, length); // 调用时添加本地端口参数 PacketProcessingSystem.storePacket(ip, port, hexData); // 报文查看窗口显示数据 MessageViewPanel.showData(hexData, ip, port, PORT,"1"); MessageViewPanel.showData(hexData, ip, port, PORT,"UDPA","ALL","ALL"); // +++ 增加包计数 +++ packetCount.incrementAndGet(); // 关键修复:增加计数器 } catch (Exception e) { System.err.println("Error processing UDP-A packet: " + e.getMessage()); System.err.println("Error processing UDP-A packet: "); e.printStackTrace(); // 添加详细堆栈跟踪 } }); } @@ -91,6 +106,7 @@ private static String bytesToHex(byte[] bytes, int length) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < length; i++) { // 确保生成大写、无分隔符的十六进制 sb.append(String.format("%02X", bytes[i])); } return sb.toString(); src/window/WelcomeFrame.java
@@ -6,7 +6,9 @@ import java.sql.Statement; import javax.swing.*; import javax.swing.border.EmptyBorder; import java.util.ResourceBundle; import udptcp.UDPPortAReceiver; import udptcp.UDPPortBReceiver; import dell_targets.Dell_BaseStation; systemfile/Messages_en.properties
@@ -508,8 +508,8 @@ MESSAGE_VIEW_START=Start MESSAGE_VIEW_PAUSE=Pause MESSAGE_VIEW_CLEAR=Clear MESSAGE_VIEW_DATA_TYPE=Data Type MESSAGE_VIEW_PROTOCOL=Protocol MESSAGE_VIEW_DATA_TYPE=DataFrom MESSAGE_VIEW_PROTOCOL=DataType MESSAGE_VIEW_DEVICE_ID=Device ID MESSAGE_VIEW_AUTO_SAVE=Auto Save Messages MESSAGE_VIEW_SHOW_SOURCE=Show Data Source systemfile/Messages_zh.properties
@@ -504,8 +504,8 @@ MESSAGE_VIEW_START=开始 MESSAGE_VIEW_PAUSE=暂停 MESSAGE_VIEW_CLEAR=清空 MESSAGE_VIEW_DATA_TYPE=数据类型 MESSAGE_VIEW_PROTOCOL=通信协议 MESSAGE_VIEW_DATA_TYPE=数据来源 MESSAGE_VIEW_PROTOCOL=数据类型 MESSAGE_VIEW_DEVICE_ID=设备编号 MESSAGE_VIEW_AUTO_SAVE=自动保存报文 MESSAGE_VIEW_SHOW_SOURCE=显示数据来源 systemfile/logfile/openlog.txt
@@ -781,3 +781,140 @@ 工作时长: 0小时 0分钟 14秒 ----------------------------------- 程序启动: 2025-08-09 23:30:58 程序关闭: 2025-08-09 23:33:32 工作时长: 0小时 2分钟 33秒 ----------------------------------- 程序启动: 2025-08-10 08:58:27 程序关闭: 2025-08-10 11:09:43 工作时长: 2小时 11分钟 15秒 ----------------------------------- 程序启动: 2025-08-10 11:09:46 程序关闭: 2025-08-10 11:16:14 工作时长: 0小时 6分钟 28秒 ----------------------------------- 程序启动: 2025-08-10 11:16:16 程序关闭: 2025-08-10 12:00:11 工作时长: 0小时 43分钟 54秒 ----------------------------------- 程序启动: 2025-08-10 12:00:13 程序关闭: 2025-08-10 12:00:30 工作时长: 0小时 0分钟 17秒 ----------------------------------- 程序启动: 2025-08-10 12:22:41 程序关闭: 2025-08-10 12:25:09 工作时长: 0小时 2分钟 28秒 ----------------------------------- 程序启动: 2025-08-10 12:25:12 程序关闭: 2025-08-10 12:25:48 工作时长: 0小时 0分钟 36秒 ----------------------------------- 程序启动: 2025-08-10 12:26:10 程序关闭: 2025-08-10 12:27:13 工作时长: 0小时 1分钟 2秒 ----------------------------------- 程序启动: 2025-08-10 12:30:34 程序关闭: 2025-08-10 12:31:14 工作时长: 0小时 0分钟 39秒 ----------------------------------- 程序启动: 2025-08-10 12:51:17 程序关闭: 2025-08-10 12:52:14 工作时长: 0小时 0分钟 57秒 ----------------------------------- 程序启动: 2025-08-10 12:53:36 程序关闭: 2025-08-10 12:54:13 工作时长: 0小时 0分钟 36秒 ----------------------------------- 程序启动: 2025-08-10 12:54:42 程序启动: 2025-08-10 12:57:55 程序关闭: 2025-08-10 12:57:59 工作时长: 0小时 0分钟 3秒 ----------------------------------- 程序启动: 2025-08-10 12:58:01 程序启动: 2025-08-10 13:19:31 程序关闭: 2025-08-10 13:19:53 工作时长: 0小时 0分钟 22秒 ----------------------------------- 程序启动: 2025-08-10 13:19:55 程序启动: 2025-08-10 13:21:35 程序启动: 2025-08-10 13:25:06 程序关闭: 2025-08-10 13:25:29 工作时长: 0小时 0分钟 23秒 ----------------------------------- 程序启动: 2025-08-10 13:43:51 程序启动: 2025-08-10 13:49:02 程序关闭: 2025-08-10 13:49:25 工作时长: 0小时 0分钟 23秒 ----------------------------------- 程序启动: 2025-08-10 13:52:37 程序启动: 2025-08-10 13:53:36 程序关闭: 2025-08-10 13:54:12 工作时长: 0小时 0分钟 37秒 ----------------------------------- 程序启动: 2025-08-10 20:39:09 程序关闭: 2025-08-10 20:39:11 工作时长: 0小时 0分钟 2秒 ----------------------------------- 程序启动: 2025-08-10 20:43:09 程序关闭: 2025-08-10 20:43:13 工作时长: 0小时 0分钟 4秒 ----------------------------------- 程序启动: 2025-08-10 21:07:32 程序关闭: 2025-08-10 21:14:29 工作时长: 0小时 6分钟 56秒 ----------------------------------- 程序启动: 2025-08-10 21:14:32 程序启动: 2025-08-10 21:19:29 程序启动: 2025-08-10 21:24:40 程序启动: 2025-08-10 21:34:00 程序关闭: 2025-08-10 21:34:04 工作时长: 0小时 9分钟 24秒 ----------------------------------- 程序启动: 2025-08-10 21:34:06 程序关闭: 2025-08-10 21:35:03 工作时长: 0小时 0分钟 57秒 ----------------------------------- 程序启动: 2025-08-10 21:35:36 程序启动: 2025-08-10 21:40:50 程序关闭: 2025-08-10 21:42:14 工作时长: 0小时 1分钟 23秒 ----------------------------------- 程序启动: 2025-08-10 21:59:52 程序关闭: 2025-08-10 22:01:19 工作时长: 0小时 1分钟 26秒 ----------------------------------- 程序启动: 2025-08-10 22:02:38 程序关闭: 2025-08-10 22:03:28 工作时长: 0小时 0分钟 50秒 ----------------------------------- 程序启动: 2025-08-10 22:05:44 程序关闭: 2025-08-10 22:06:08 工作时长: 0小时 0分钟 24秒 ----------------------------------- 程序启动: 2025-08-10 22:07:11 程序启动: 2025-08-10 22:19:11 程序启动: 2025-08-10 22:23:07 程序关闭: 2025-08-10 22:23:24 工作时长: 0小时 0分钟 16秒 ----------------------------------- 程序启动: 2025-08-10 22:23:34 程序关闭: 2025-08-10 22:23:44 工作时长: 0小时 0分钟 10秒 ----------------------------------- 程序启动: 2025-08-10 22:26:52 程序启动: 2025-08-10 22:59:33 程序关闭: 2025-08-10 23:00:10 工作时长: 0小时 0分钟 36秒 ----------------------------------- 程序启动: 2025-08-10 23:01:09 程序关闭: 2025-08-10 23:01:24 工作时长: 0小时 0分钟 15秒 ----------------------------------- 程序启动: 2025-08-10 23:01:56 程序启动: 2025-08-10 23:03:00 程序关闭: 2025-08-10 23:03:27 工作时长: 0小时 0分钟 26秒 ----------------------------------- 程序启动: 2025-08-10 23:04:06 程序关闭: 2025-08-10 23:04:37 工作时长: 0小时 0分钟 30秒 -----------------------------------