| | |
| | | } |
| | | |
| | | // 校验数据包完整性 |
| | | 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; |
| | | } |
| | | |
| | | // 解析单个数据包 |
| | |
| | | public static class DataPacket { |
| | | private final int packetType; // 包类型 |
| | | private final byte[] packet;//包数据 |
| | | |
| | | |
| | | public DataPacket(int packetType, byte[] packet) { |
| | | this.packetType = packetType; |
| | |
| | | } |
| | | 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); |
| | | } |
| | | } |