package Dell55aa;
|
|
public class Dell55AA12HighPerf { // ¸ßÐÔÄܽâÎöÀà
|
|
// ³£Á¿¶¨Ò壨±ÜÃâÖØ¸´´´½¨£©
|
private static final String HEADER = "55AA12"; // °üÍ·³£Á¿
|
private static final int MIN_LENGTH = 34; // ×îСÓÐЧ³¤¶È
|
private static final ThreadLocal<ParseResult> RESULT_CACHE = // Ï̱߳¾µØ½á¹û»º´æ
|
ThreadLocal.withInitial(ParseResult::new);
|
private static final ThreadLocal<char[]> 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;
|
}
|
}
|