package Dell55aa; public class Dell55AA12HighPerf { // ¸ßÐÔÄܽâÎöÀà // ³£Á¿¶¨Ò壨±ÜÃâÖØ¸´´´½¨£© private static final String HEADER = "55AA12"; // °üÍ·³£Á¿ private static final int MIN_LENGTH = 34; // ×îСÓÐЧ³¤¶È private static final ThreadLocal RESULT_CACHE = // Ï̱߳¾µØ½á¹û»º´æ ThreadLocal.withInitial(ParseResult::new); private static final ThreadLocal CHAR_BUF_CACHE = // ×Ö·û»º³åÇø»º´æ ThreadLocal.withInitial(() -> new char[256]); // Ê®Áù½øÖÆ×Ö·ûת»»±í£¨±ÜÃâÖØ¸´¼ÆË㣩 private static final int[] HEX_VALUES = new int[128]; static { for (int i = 0; i < HEX_VALUES.length; i++) { char c = (char) i; if (c >= '0' && c <= '9') HEX_VALUES[i] = c - '0'; else if (c >= 'A' && c <= 'F') HEX_VALUES[i] = 10 + (c - 'A'); else if (c >= 'a' && c <= 'f') HEX_VALUES[i] = 10 + (c - 'a'); else HEX_VALUES[i] = -1; // ·Ç·¨×Ö·û±ê¼Ç } } // ½âÎö½á¹û¸´ÓÃÀࣨ¶ÔÏó³ØÄ£Ê½£© public static class ParseResult { public int tagId; public int sequenceNum; public int power; public int vibrationState; public boolean tagRemoved; public boolean isSleeping; public boolean isStatic; public boolean sosButtonPressed; public int tagHeight; public int anchorCount; public int[] anchorIds = new int[0]; public int[] distances = new int[0]; public int[] anchorPowers = new int[0]; public int[] signalStrengths1 = new int[0]; public int[] signalStrengths2 = new int[0]; // ÖØÖ÷½·¨£¨±ÜÃâÖØÐ´´½¨Êý×飩 public void reset() { tagId = 0; sequenceNum = 0; power = 0; vibrationState = 0; tagRemoved = false; isSleeping = false; isStatic = false; sosButtonPressed = false; tagHeight = 0; anchorCount = 0; // ±£ÁôÊý×飬½öÖØÖó¤¶È } } /** * ¸ßÐÔÄܽâÎö·½·¨ * @param message ԭʼ16½øÖÆÏûÏ¢ * @return ½âÎö½á¹û¶ÔÏó£¨Ïß³ÌÄÚ¸´Óã© */ public static ParseResult parse(String message) { // ¿ìËÙ³¤¶ÈУÑé if (message == null || message.length() < MIN_LENGTH) { return null; // ¿ìËÙʧ°Ü } // °üÍ·¼ì²é£¨±ÜÃâ´´½¨×Ó×Ö·û´®£© if (!(message.charAt(0) == '5' && message.charAt(1) == '5' && message.charAt(2) == 'A' && message.charAt(3) == 'A' && message.charAt(4) == '1' && message.charAt(5) == '2')) { return null; // °üÍ·ÎÞЧ } // ´ÓÏ̻߳º´æ»ñÈ¡½á¹û¶ÔÏó ParseResult result = RESULT_CACHE.get(); result.reset(); // ÖØÖöÔÏó״̬ // Ö±½Ó²Ù×÷×Ö·ûÊý×飨±ÜÃâ×Ö·û´®²Ù×÷£© char[] chars = CHAR_BUF_CACHE.get(); message.getChars(0, Math.min(message.length(), chars.length), chars, 0); // ½âÎöÊý¾Ý³¤¶È£¨Ö±½Ó¼ÆË㣩 int dataLength = (fastHexToByte(chars[6], chars[7]) * 2) + 8; if (message.length() != dataLength) { return null; // ³¤¶È²»Æ¥Åä } // ½âÎö±êÇ©ÐÅÏ¢£¨ÎÞÁÙʱ¶ÔÏó´´½¨£© parseTagInfo(chars, result); // ½âÎö»ùÕ¾ÐÅÏ¢£¨Êý×鸴Óã© parseAnchorInfo(chars, result); return result; } /** * ±êÇ©ÐÅÏ¢½âÎö£¨ÎÞ¶ÔÏó´´½¨£© */ private static void parseTagInfo(char[] chars, ParseResult result) { // ±êÇ©ID£¨Ö±½Ó¼ÆË㣩 result.tagId = (fastHexToByte(chars[10], chars[11]) << 8) | fastHexToByte(chars[8], chars[9]); // °üÐòÁкţ¨Ö±½Ó¼ÆË㣩 result.sequenceNum = (fastHexToByte(chars[14], chars[15]) << 8) | fastHexToByte(chars[12], chars[13]); // µçÁ¿£¨µ¥×Ö½Úת»»£© result.power = fastHexToByte(chars[16], chars[17]); // °´¼ü״̬£¨Î»ÔËËã´úÌæ×Ö·û´®²Ù×÷£© int buttonState = fastHexToByte(chars[18], chars[19]); result.vibrationState = (buttonState >> 5) & 1; // µÚ2λ result.tagRemoved = ((buttonState >> 3) & 1) == 1; // µÚ4λ result.isSleeping = ((buttonState >> 2) & 1) == 1; // µÚ5λ result.isStatic = ((buttonState >> 1) & 1) == 1; // µÚ6λ result.sosButtonPressed = (buttonState & 1) == 1; // µÚ7λ // ±êÇ©¸ß¶È£¨Ö±½Ó¼ÆË㣩 result.tagHeight = (fastHexToByte(chars[22], chars[23]) << 8) | fastHexToByte(chars[20], chars[21]); } /** * »ùÕ¾ÐÅÏ¢½âÎö£¨Êý×鸴Óã© */ private static void parseAnchorInfo(char[] chars, ParseResult result) { // »ùÕ¾ÊýÁ¿ result.anchorCount = fastHexToByte(chars[32], chars[33]); if (result.anchorCount == 0) return; // Êý×鸴Óüì²é£¨±ÜÃâÖØ¸´´´½¨£© if (result.anchorIds.length < result.anchorCount) { result.anchorIds = new int[result.anchorCount]; result.distances = new int[result.anchorCount]; result.anchorPowers = new int[result.anchorCount]; result.signalStrengths1 = new int[result.anchorCount]; result.signalStrengths2 = new int[result.anchorCount]; } // »ùÕ¾ÐÅÏ¢½âÎö£¨Ö±½ÓË÷Òý¼ÆË㣩 int baseIndex = 34; int powerIndex = 34 + result.anchorCount * 4; for (int i = 0; i < result.anchorCount; i++) { // »ùÕ¾ID£¨Ð¡¶ËÐò£© int idLow = fastHexToByte(chars[baseIndex], chars[baseIndex+1]); int idHigh = fastHexToByte(chars[baseIndex+2], chars[baseIndex+3]); result.anchorIds[i] = (idHigh << 8) | idLow; // »ùÕ¾¾àÀë int distLow = fastHexToByte(chars[baseIndex+4], chars[baseIndex+5]); int distHigh = fastHexToByte(chars[baseIndex+6], chars[baseIndex+7]); result.distances[i] = (distHigh << 8) | distLow; // »ùÕ¾µçÁ¿ result.anchorPowers[i] = fastHexToByte(chars[powerIndex], chars[powerIndex+1]); baseIndex += 8; // ÿ¸ö»ùÕ¾Õ¼ÓÃ8×Ö·û powerIndex += 2; // ÿ¸öµçÁ¿Õ¼ÓÃ2×Ö·û } } /** * ¿ìËÙÊ®Áù½øÖÆ×ª×Ö½Ú£¨²é±í·¨£© */ private static int fastHexToByte(char c1, char c2) { int high = (c1 < 128) ? HEX_VALUES[c1] : -1; int low = (c2 < 128) ? HEX_VALUES[c2] : -1; if (high < 0 || low < 0) return 0; // ÎÞЧ×Ö·û´¦Àí return (high << 4) | low; } }