package publicsWay; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; // ÖØÃüÃûΪ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]; for (int j = 0; j < bytes.length; j++) { int v = bytes[j] & 0xFF; hexChars[j * 2] = HEX_ARRAY[v >>> 4]; hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F]; } return new String(hexChars); } // ½âÎö»º³åÇøÖеÄËùÓÐÍêÕûÊý¾Ý°ü public List parsePackets() { List packets = new ArrayList<>(); int index = 0; // µ±Ç°½âÎöλÖÃË÷Òý // ±éÀú»º³åÇø²éÕÒÍêÕûÊý¾Ý°ü while (index <= bufferLength - 4) { // È·±£ÓÐ×ã¹»Êý¾Ý¼ì²é°üÍ· // ¼ì²é°üÍ·±êʶ 0x55 0xAA if (buffer[index] == 0x55 && (buffer[index + 1] & 0xFF) == 0xAA) { // »ñÈ¡°üÀàÐÍ£¨µÚ3×Ö½Ú£© int packetType = buffer[index + 2] & 0xFF; // »ñÈ¡Êý¾Ý³¤¶È£¨µÚ4×Ö½Ú£© int dataLenField = buffer[index + 3] & 0xFF; // ¼ÆËãÍêÕû°ü³¤¶È£¨°üÍ·+Êý¾Ý+УÑ飩 int totalPacketLen = 2 + dataLenField + 2; // Ôö¼Ó2×Ö½ÚУÑéλ // ¼ì²éÊÇ·ñÓÐ×ã¹»Êý¾Ý¹¹³ÉÍêÕû°ü if (index + totalPacketLen > bufferLength) { 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); // Ìí¼Óµ½½á¹ûÁбí } index += totalPacketLen; // ÒÆ¶¯µ½ÏÂÒ»¸ö°ü } else { index++; // УÑéʧ°Ü£¬Ìø¹ýµ±Ç°×Ö½Ú } } else { index++; // ·Ç°üÍ·±êʶ£¬¼ÌÐø²éÕÒ } } // ÇåÀíÒÑ´¦ÀíÊý¾Ý if (index > 0) { int remaining = bufferLength - index; if (remaining > 0) { // ÒÆ¶¯Ê£ÓàÊý¾Ýµ½»º³åÇø¿ªÍ· System.arraycopy(buffer, index, buffer, 0, remaining); } bufferLength = remaining; // ¸üлº³åÇø³¤¶È } return packets; } // УÑéÊý¾Ý°ü private boolean verifyChecksum(byte[] packet) { int len = packet.length; if (len < 4) return false; int sum = 0; // ´ÓÊý¾ÝÀàÐÍ¿ªÊ¼µ½Ð£ÑéÂëǰ½áÊø (°üÍ·2×Ö½ÚÒÑÌø¹ý) for (int i = 2; i < len - 2; i++) { sum += packet[i] & 0xFF; } sum = ~sum & 0xFFFF; // È¡·´²¢±£Áô16λ // »ñÈ¡°üÖеÄУÑéÂë (С¶Ëģʽ) int receivedChecksum = ((packet[len - 1] & 0xFF) << 8) | (packet[len - 2] & 0xFF); return sum == receivedChecksum; } // ½âÎöµ¥¸öÊý¾Ý°ü private DataPacket parseSinglePacket(int packetType, byte[] packet) { // ´´½¨Êý¾Ý°ü¶ÔÏ󣨰üº¬°üÀàÐÍ£© return new DataPacket(packetType, packet); } // Êý¾Ý°üÄÚ²¿Àà public static class DataPacket { private final int packetType; // °üÀàÐÍ private final byte[] packet;//°üÊý¾Ý public DataPacket(int packetType, byte[] packet) { this.packetType = packetType; this.packet = packet; } // »ñÈ¡°üÀàÐÍ public int getPacketType() { return packetType; } // °üÊý¾Ý public byte[] getPacket() { return packet; } } // 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); } 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λʮÁù½øÖÆ×Ö·û´®£¨´óд£©£¬¸ßλÔÚǰ System.out.println(String.format("%02X%02X", highByte, lowByte)); return String.format("%02X%02X", highByte, lowByte); } /** ½«×Ö½ÚÊý×éתΪʮÁù½øÖÆ×Ö·û´®£¬ÀýÈç [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); } }