张世豪
3 小时以前 d22349714c8d199c02f336f90fba841ef8f5cd39
src/chuankou/SerialDataReceiver.java
@@ -6,21 +6,26 @@
public class SerialDataReceiver {
    private static final int BUFFER_SIZE = 1024;
    private static byte[] staticDataBuffer = new byte[BUFFER_SIZE];
    private static int staticBufferPosition = 0;
    private static final int MIN_PACKET_LENGTH = 9;
    private static final byte[] START_MARKER = {(byte) 0xDD, (byte) 0xCC};
    // 使用非静态成员避免多线程环境下的竞争条件
    private byte[] dataBuffer = new byte[BUFFER_SIZE];
    private int bufferPosition = 0;
    private final List<byte[]> reusablePackets = new ArrayList<>();
    
    /**
     * 静态方法:接收串口原始数据并解析完整数据包
     * 实例方法:接收串口原始数据并解析完整数据包
     * @param rawData 原始数据
     * @param debugEnabled 是否启用调试
     * @param maxRawDataPrintLength 最大打印长度
     * @return 解析出的完整数据包列表,如果没有完整包则返回空列表
     */
    public static List<byte[]> receiveData(byte[] rawData, boolean debugEnabled, int maxRawDataPrintLength) {
        List<byte[]> completePackets = new ArrayList<>();
    public List<byte[]> receiveData(byte[] rawData, boolean debugEnabled, int maxRawDataPrintLength) {
        reusablePackets.clear();
        
        if (rawData == null || rawData.length == 0) {
            return completePackets;
            return reusablePackets;
        }
        
        // 打印原始接收数据(调试用)
@@ -28,88 +33,114 @@
            printRawData("收到串口原始数据", rawData, maxRawDataPrintLength);
        }
        
        // 将数据添加到缓冲区
        if (staticBufferPosition + rawData.length > staticDataBuffer.length) {
        // 检查缓冲区容量,动态处理
        if (!ensureBufferCapacity(rawData.length)) {
            // 缓冲区不足时,清理并重新开始
            System.arraycopy(staticDataBuffer, staticBufferPosition - rawData.length,
                           staticDataBuffer, 0, rawData.length);
            staticBufferPosition = rawData.length;
        } else {
            System.arraycopy(rawData, 0, staticDataBuffer, staticBufferPosition, rawData.length);
            staticBufferPosition += rawData.length;
            if (debugEnabled) {
                System.out.println("缓冲区不足,清空缓冲区重新开始");
            }
            bufferPosition = 0;
        }
        
        // 处理缓冲区中的数据并收集完整包
        processBuffer(completePackets, debugEnabled);
        // 将数据添加到缓冲区
        System.arraycopy(rawData, 0, dataBuffer, bufferPosition, rawData.length);
        bufferPosition += rawData.length;
        
        return completePackets;
        // 处理缓冲区中的数据并收集完整包
        processBuffer(reusablePackets, debugEnabled);
        return new ArrayList<>(reusablePackets);
    }
    /**
     * 确保缓冲区有足够容量,如不够则尝试压缩
     */
    private boolean ensureBufferCapacity(int required) {
        if (bufferPosition + required <= dataBuffer.length) {
            return true;
        }
        // 尝试通过压缩缓冲区来腾出空间
        int startIndex = findStartMarker();
        if (startIndex > 0) {
            compactBuffer(startIndex);
            return bufferPosition + required <= dataBuffer.length;
        }
        return false;
    }
    
    /**
     * 处理缓冲区中的数据,解析完整数据包
     */
    private static void processBuffer(List<byte[]> completePackets, boolean debugEnabled) {
        final int MIN_PACKET_LENGTH = 9;
        final byte[] START_MARKER = {(byte) 0xDD, (byte) 0xCC};
        while (staticBufferPosition >= MIN_PACKET_LENGTH) {
    private void processBuffer(List<byte[]> completePackets, boolean debugEnabled) {
        while (bufferPosition >= MIN_PACKET_LENGTH) {
            // 查找起始标记
            int startIndex = findStartMarker(START_MARKER);
            int startIndex = findStartMarker();
            if (startIndex == -1) {
                // 没有找到起始标记,清空无效数据
                if (debugEnabled) {
                    //System.out.println("未找到起始标记,清空缓冲区");
                    System.out.println("未找到起始标记,清空缓冲区");
                }
                staticBufferPosition = 0;
                bufferPosition = 0;
                return;
            }
            
            // 检查是否有足够的数据读取数据长度
            if (startIndex + 4 > staticBufferPosition) {
            if (startIndex + 4 > bufferPosition) {
                // 数据不足,等待更多数据
                compactBuffer(startIndex);
                return;
            }
            
            // 读取数据长度 (大端序)
            int dataLength = ((staticDataBuffer[startIndex + 2] & 0xFF) << 8) |
                           (staticDataBuffer[startIndex + 3] & 0xFF);
            int dataLength = ((dataBuffer[startIndex + 2] & 0xFF) << 8) |
                           (dataBuffer[startIndex + 3] & 0xFF);
            int totalPacketLength = 2 + 2 + dataLength + 2; // 起始标记2 + 数据长度2 + 数据内容 + CRC2
            
            // 检查数据长度有效性
            if (dataLength < 0 || totalPacketLength > BUFFER_SIZE) {
                if (debugEnabled) {
                    System.out.println("无效数据长度: " + dataLength + ", 跳过起始字节");
                }
                // 跳过错误的起始标记,继续查找
                compactBuffer(startIndex + 1);
                continue;
            }
            // 检查是否收到完整数据包
            if (startIndex + totalPacketLength > staticBufferPosition) {
            if (startIndex + totalPacketLength > bufferPosition) {
                // 数据包不完整,等待更多数据
                compactBuffer(startIndex);
                return;
            }
            
            // 提取完整数据包
            byte[] packet = new byte[totalPacketLength];
            System.arraycopy(staticDataBuffer, startIndex, packet, 0, totalPacketLength);
            byte[] packet = Arrays.copyOfRange(dataBuffer, startIndex, startIndex + totalPacketLength);
            
            if (debugEnabled) {
                //System.out.println("解析到完整数据包: " + bytesToHex(packet));
                System.out.println("解析到完整数据包: " + bytesToHex(packet));
            }
            
            // 添加到返回列表
            completePackets.add(packet);
            
            // 移动缓冲区位置
            int remaining = staticBufferPosition - (startIndex + totalPacketLength);
            int remaining = bufferPosition - (startIndex + totalPacketLength);
            if (remaining > 0) {
                System.arraycopy(staticDataBuffer, startIndex + totalPacketLength,
                               staticDataBuffer, 0, remaining);
                System.arraycopy(dataBuffer, startIndex + totalPacketLength,
                               dataBuffer, 0, remaining);
            }
            staticBufferPosition = remaining;
            bufferPosition = remaining;
        }
    }
    
    /**
     * 查找起始标记位置
     */
    private static int findStartMarker(byte[] startMarker) {
        for (int i = 0; i <= staticBufferPosition - startMarker.length; i++) {
            if (staticDataBuffer[i] == startMarker[0] && staticDataBuffer[i + 1] == startMarker[1]) {
    private int findStartMarker() {
        for (int i = 0; i <= bufferPosition - START_MARKER.length; i++) {
            if (dataBuffer[i] == START_MARKER[0] && dataBuffer[i + 1] == START_MARKER[1]) {
                return i;
            }
        }
@@ -119,20 +150,20 @@
    /**
     * 压缩缓冲区,将有效数据移到开头
     */
    private static void compactBuffer(int startIndex) {
        if (startIndex > 0) {
            System.arraycopy(staticDataBuffer, startIndex, staticDataBuffer, 0,
                           staticBufferPosition - startIndex);
            staticBufferPosition -= startIndex;
    private void compactBuffer(int startIndex) {
        if (startIndex > 0 && startIndex < bufferPosition) {
            System.arraycopy(dataBuffer, startIndex, dataBuffer, 0,
                           bufferPosition - startIndex);
            bufferPosition -= startIndex;
        }
    }
    
    /**
     * 打印原始数据(调试用)
     */
    private static void printRawData(String prefix, byte[] data, int maxPrintLength) {
    private void printRawData(String prefix, byte[] data, int maxPrintLength) {
        if (data == null || data.length == 0) {
            //System.out.println(prefix + ": 空数据");
            System.out.println(prefix + ": 空数据");
            return;
        }
        
@@ -148,13 +179,13 @@
            sb.append("... [截断,总长度: ").append(data.length).append("]");
        }
        
        //System.out.println(sb.toString());
        System.out.println(sb.toString());
    }
    
    /**
     * 工具方法:字节数组转十六进制字符串
     */
    private static String bytesToHex(byte[] bytes) {
    private String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02X ", b));
@@ -165,16 +196,23 @@
    /**
     * 清空缓冲区(避免内存泄漏)
     */
    public static void clearBuffer() {
        staticBufferPosition = 0;
    public void clearBuffer() {
        bufferPosition = 0;
        // 可选:清空缓冲区内容
        Arrays.fill(staticDataBuffer, (byte) 0);
        Arrays.fill(dataBuffer, (byte) 0);
    }
    
    /**
     * 获取当前缓冲区状态
     */
    public static int getBufferStatus() {
        return staticBufferPosition;
    public int getBufferStatus() {
        return bufferPosition;
    }
    /**
     * 获取缓冲区容量
     */
    public int getBufferCapacity() {
        return dataBuffer.length;
    }
}