package chuankou;
|
|
import java.util.ArrayList;
|
import java.util.Arrays;
|
import java.util.List;
|
|
public class SerialDataReceiver {
|
private static final int BUFFER_SIZE = 1024;
|
private static byte[] staticDataBuffer = new byte[BUFFER_SIZE];
|
private static int staticBufferPosition = 0;
|
|
/**
|
* 静态方法:接收串口原始数据并解析完整数据包
|
* @param rawData 原始数据
|
* @param debugEnabled 是否启用调试
|
* @param maxRawDataPrintLength 最大打印长度
|
* @return 解析出的完整数据包列表,如果没有完整包则返回空列表
|
*/
|
public static List<byte[]> receiveData(byte[] rawData, boolean debugEnabled, int maxRawDataPrintLength) {
|
List<byte[]> completePackets = new ArrayList<>();
|
|
if (rawData == null || rawData.length == 0) {
|
return completePackets;
|
}
|
|
// 打印原始接收数据(调试用)
|
if (debugEnabled) {
|
printRawData("收到串口原始数据", rawData, maxRawDataPrintLength);
|
}
|
|
// 将数据添加到缓冲区
|
if (staticBufferPosition + rawData.length > staticDataBuffer.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;
|
}
|
|
// 处理缓冲区中的数据并收集完整包
|
processBuffer(completePackets, debugEnabled);
|
|
return completePackets;
|
}
|
|
/**
|
* 处理缓冲区中的数据,解析完整数据包
|
*/
|
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) {
|
// 查找起始标记
|
int startIndex = findStartMarker(START_MARKER);
|
if (startIndex == -1) {
|
// 没有找到起始标记,清空无效数据
|
if (debugEnabled) {
|
//System.out.println("未找到起始标记,清空缓冲区");
|
}
|
staticBufferPosition = 0;
|
return;
|
}
|
|
// 检查是否有足够的数据读取数据长度
|
if (startIndex + 4 > staticBufferPosition) {
|
// 数据不足,等待更多数据
|
compactBuffer(startIndex);
|
return;
|
}
|
|
// 读取数据长度 (大端序)
|
int dataLength = ((staticDataBuffer[startIndex + 2] & 0xFF) << 8) |
|
(staticDataBuffer[startIndex + 3] & 0xFF);
|
int totalPacketLength = 2 + 2 + dataLength + 2; // 起始标记2 + 数据长度2 + 数据内容 + CRC2
|
|
// 检查是否收到完整数据包
|
if (startIndex + totalPacketLength > staticBufferPosition) {
|
// 数据包不完整,等待更多数据
|
compactBuffer(startIndex);
|
return;
|
}
|
|
// 提取完整数据包
|
byte[] packet = new byte[totalPacketLength];
|
System.arraycopy(staticDataBuffer, startIndex, packet, 0, totalPacketLength);
|
|
if (debugEnabled) {
|
//System.out.println("解析到完整数据包: " + bytesToHex(packet));
|
}
|
|
// 添加到返回列表
|
completePackets.add(packet);
|
|
// 移动缓冲区位置
|
int remaining = staticBufferPosition - (startIndex + totalPacketLength);
|
if (remaining > 0) {
|
System.arraycopy(staticDataBuffer, startIndex + totalPacketLength,
|
staticDataBuffer, 0, remaining);
|
}
|
staticBufferPosition = 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]) {
|
return i;
|
}
|
}
|
return -1;
|
}
|
|
/**
|
* 压缩缓冲区,将有效数据移到开头
|
*/
|
private static void compactBuffer(int startIndex) {
|
if (startIndex > 0) {
|
System.arraycopy(staticDataBuffer, startIndex, staticDataBuffer, 0,
|
staticBufferPosition - startIndex);
|
staticBufferPosition -= startIndex;
|
}
|
}
|
|
/**
|
* 打印原始数据(调试用)
|
*/
|
private static void printRawData(String prefix, byte[] data, int maxPrintLength) {
|
if (data == null || data.length == 0) {
|
//System.out.println(prefix + ": 空数据");
|
return;
|
}
|
|
StringBuilder sb = new StringBuilder();
|
sb.append(prefix).append(" [长度: ").append(data.length).append("]: ");
|
|
int printLength = Math.min(data.length, maxPrintLength);
|
for (int i = 0; i < printLength; i++) {
|
sb.append(String.format("%02X ", data[i]));
|
}
|
|
if (data.length > maxPrintLength) {
|
sb.append("... [截断,总长度: ").append(data.length).append("]");
|
}
|
|
//System.out.println(sb.toString());
|
}
|
|
/**
|
* 工具方法:字节数组转十六进制字符串
|
*/
|
private static String bytesToHex(byte[] bytes) {
|
StringBuilder sb = new StringBuilder();
|
for (byte b : bytes) {
|
sb.append(String.format("%02X ", b));
|
}
|
return sb.toString().trim();
|
}
|
|
/**
|
* 清空缓冲区(避免内存泄漏)
|
*/
|
public static void clearBuffer() {
|
staticBufferPosition = 0;
|
// 可选:清空缓冲区内容
|
Arrays.fill(staticDataBuffer, (byte) 0);
|
}
|
|
/**
|
* 获取当前缓冲区状态
|
*/
|
public static int getBufferStatus() {
|
return staticBufferPosition;
|
}
|
}
|