zsh_root
2025-12-10 8d662de2fd262b3a485f16e197cb4d0ca2a61cdf
src/home/PacketParser.java
@@ -1,33 +1,34 @@
package home;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
// 重命名为PacketParser,表示数据包解析器
// 重命名为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];
@@ -39,73 +40,73 @@
      return new String(hexChars);
   }
   // 解析缓冲区中的所有完整数据包
   // 解析缓冲区中的所有完整数据包
   public List<DataPacket> parsePackets() {
      List<DataPacket> packets = new ArrayList<>();
      int index = 0;  // 当前解析位置索引
      int index = 0;  // 当前解析位置索引
      // 遍历缓冲区查找完整数据包
      while (index <= bufferLength - 4) { // 确保有足够数据检查包头
         // 检查包头标识 0x55 0xAA
      // 遍历缓冲区查找完整数据包
      while (index <= bufferLength - 4) { // 确保有足够数据检查包头
         // 检查包头标识 0x55 0xAA
         if (buffer[index] == 0x55 && (buffer[index + 1] & 0xFF) == 0xAA) {
            // 获取包类型(第3字节)
            // 获取包类型(第3字节)
            int packetType = buffer[index + 2] & 0xFF;
            // 获取数据长度(第4字节)
            // 获取数据长度(第4字节)
            int dataLenField = buffer[index + 3] & 0xFF;
            // 计算完整包长度(包头+数据+校验)
            int totalPacketLen = 2 + dataLenField + 2;  // 增加2字节校验位
            // 计算完整包长度(包头+数据+校验)
            int totalPacketLen = 2 + dataLenField + 2;  // 增加2字节校验位
            // 检查是否有足够数据构成完整包
            // 检查是否有足够数据构成完整包
            if (index + totalPacketLen > bufferLength) {
               break; // 数据不足,等待更多数据
               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); // 添加到结果列表
                  packets.add(packet); // 添加到结果列表
               }
               index += totalPacketLen; // 移动到下一个包
               index += totalPacketLen; // 移动到下一个包
            } else {
               index++; // 校验失败,跳过当前字节
               index++; // 校验失败,跳过当前字节
            }
         } else {
            index++; // 非包头标识,继续查找
            index++; // 非包头标识,继续查找
         }
      }
      // 清理已处理数据
      // 清理已处理数据
      if (index > 0) {
         int remaining = bufferLength - index;
         if (remaining > 0) {
            // 移动剩余数据到缓冲区开头
            // 移动剩余数据到缓冲区开头
            System.arraycopy(buffer, index, buffer, 0, remaining);
         }
         bufferLength = remaining; // 更新缓冲区长度
         bufferLength = remaining; // 更新缓冲区长度
      }
      return packets;
   }
   // 校验数据包
   // 校验数据包
   private boolean verifyChecksum(byte[] packet) {
       int len = packet.length;
       if (len < 4) return false;
       int sum = 0;
       // 从数据类型开始到校验码前结束 (包头2字节已跳过)
       // 从数据类型开始到校验码前结束 (包头2字节已跳过)
       for (int i = 2; i < len - 2; i++) {
           sum += packet[i] & 0xFF;
       }
       sum = ~sum & 0xFFFF; // 取反并保留16位
       sum = ~sum & 0xFFFF; // 取反并保留16位
       // 获取包中的校验码 (小端模式)
       // 获取包中的校验码 (小端模式)
       int receivedChecksum = ((packet[len - 1] & 0xFF) << 8) | (packet[len - 2] & 0xFF);
       return sum == receivedChecksum;
@@ -113,17 +114,17 @@
   // 解析单个数据包
   // 解析单个数据包
   private DataPacket parseSinglePacket(int packetType, byte[] packet) {        
      // 创建数据包对象(包含包类型)
      // 创建数据包对象(包含包类型)
      return new DataPacket(packetType, packet);
   }
   // 数据包内部类
   // 数据包内部类
   public static class DataPacket {
      private final int packetType;  // 包类型
      private final byte[] packet;//包数据
      private final int packetType;  // 包类型
      private final byte[] packet;//包数据
      public DataPacket(int packetType, byte[] packet) {
@@ -131,30 +132,30 @@
         this.packet = packet;
      }
      // 获取包类型
      // 获取包类型
      public int getPacketType() {
         return packetType;
      }
      // 包数据
      // 包数据
      public byte[] getPacket() {
         return packet;
      }
   }
   // HEX字符串转字节数组
   // 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);
      }
@@ -164,56 +165,51 @@
   
   
   /**输出校验码*/
   /**输出校验码*/
   public static String calculateChecksum(String input) {
      // 检查输入是否为空
      // 检查输入是否为空
      if (input == null) {
         throw new IllegalArgumentException("输入不能为null");
         throw new IllegalArgumentException("输入不能为null");
      }
      // 移除所有空格
      // 移除所有空格
      String cleanInput = input.replaceAll("\\s", "");
      // 验证处理后的字符串
      // 验证处理后的字符串
      if (cleanInput.length() < 8 || !cleanInput.startsWith("55AA")) {
         throw new IllegalArgumentException("输入字符串必须以55AA开头且长度至少为8(去除空格后)");
         throw new IllegalArgumentException("输入字符串必须以55AA开头且长度至少为8(去除空格后)");
      }
      // 去掉包头(55AA)和最后4个字符
      // 去掉包头(55AA)和最后4个字符
      String dataPart = cleanInput.substring(4, cleanInput.length() - 4);
      // 检查中间部分长度是否为偶数
      // 检查中间部分长度是否为偶数
      if (dataPart.length() % 2 != 0) {
         throw new IllegalArgumentException("校验出错中间部分长度必须是偶数(去除空格后)");
         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位范围
         sum = (sum + byteValue) & 0xFFFF; // 保持16位范围
      }
      // 取反并保持16位
      // 取反并保持16位
      int checksum = (~sum) & 0xFFFF;
      // 显式处理高位在前格式
      int  lowByte= (checksum >>> 8) & 0xFF;  // 高8位
      int  highByte= checksum & 0xFF;           // 低8位
      // 显式处理高位在前格式
      int  lowByte= (checksum >>> 8) & 0xFF;  // 高8位
      int  highByte= checksum & 0xFF;           // 低8位
      // 格式化为4位十六进制字符串(大写),高位在前
      // 格式化为4位十六进制字符串(大写),高位在前
      return String.format("%02X%02X", highByte, lowByte);
   }
   /** 将字节数组转为十六进制字符串,例如 [55 AA 01 02 ...] */
   /** 将字节数组转为十六进制字符串,例如 [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);
   }