From 6d5ff381cafca9b82e11407dc67bf6b74f1397ee Mon Sep 17 00:00:00 2001 From: 826220679@qq.com <826220679@qq.com> Date: 星期一, 11 八月 2025 23:15:40 +0800 Subject: [PATCH] 20250811 --- src/dell55AAData/Dell55AA01Parser.java | 228 +++++++++++++++++++++++++++++++++------------------------ 1 files changed, 132 insertions(+), 96 deletions(-) diff --git a/src/dell55AAData/Dell55AA01Parser.java b/src/dell55AAData/Dell55AA01Parser.java index e44c3e8..7e6cdff 100644 --- a/src/dell55AAData/Dell55AA01Parser.java +++ b/src/dell55AAData/Dell55AA01Parser.java @@ -1,104 +1,140 @@ package dell55AAData; +import java.util.Arrays; + import dell_system.MessageViewPanel; +import dell_targets.Dell_BaseStation; +import dell_targets.Dell_tag; +import publicsWay.EfficientTimeFormatter; public class Dell55AA01Parser { - // 常量定义 - private static final String EXPECTED_HEADER = "55AA01"; // 协议头 - private static final int MIN_LENGTH = 42; // 最小长度(21字节*2字符) - private static final ThreadLocal<ParseResult> RESULT_CACHE = - ThreadLocal.withInitial(ParseResult::new); + // 常量定义 + private static final String EXPECTED_HEADER = "55AA01"; // 协议头 + private static final int MIN_LENGTH = 42; // 最小长度(21字节*2字符) + private static final ThreadLocal<ParseResult> RESULT_CACHE = + ThreadLocal.withInitial(ParseResult::new); - // 解析结果类 - public static class ParseResult { - public int sequenceNum; // 序列号 - public String tagId; // 标签ID(4字节小端序) - public String anchorId; // 锚点ID(4字节小端序) - public int distance; // 距离(毫米) - public int power; // 电量(0-100) - public boolean buttonPressed; // 按钮状态 - - public void reset() { - sequenceNum = 0; - tagId = ""; - anchorId = ""; - distance = 0; - power = 0; - buttonPressed = false; - } - } + // 解析结果类 + public static class ParseResult { + public int sequenceNum; // 序列号 + public String tagId; // 标签ID(4字节小端序) + public String anchorId; // 锚点ID(4字节小端序) + public int distance; // 距离(毫米) + public int power; // 电量(0-100) + public int buttonPressed; // 按钮状态 - /** - * 解析55AA01协议数据 - * @param message 十六进制字符串 - * @return 解析结果(错误时返回null) - */ - public static ParseResult parse(String message, String ip, int port) { - if (message == null || message.isEmpty()) { - return null; - } - // 清洗数据:移除所有非十六进制字符 - message = message.replaceAll("[^0-9A-Fa-f]", "").toUpperCase(); - - // 数据校验 - if (message == null || message.length() < MIN_LENGTH) { - return null; - } - - // 协议头校验 (55AA01) - for (int i = 0; i < 6; i++) { - if (message.charAt(i) != EXPECTED_HEADER.charAt(i)) { - return null; - } - } - - ParseResult result = RESULT_CACHE.get(); - result.reset(); - - try { - if (message.length() < 30) { // 确保有足够长度访问charAt(28) - return null; - } - // 解析序列号 (位置8-9) - result.sequenceNum = HexUtils.fastHexToByte( - message.charAt(8), message.charAt(9) - ); - - // 解析标签ID (位置10-13, 小端序) - result.tagId = new String(new char[] { - message.charAt(12), message.charAt(13), // 高位 - message.charAt(10), message.charAt(11) // 低位 - }); - - // 解析锚点ID (位置14-17, 小端序) - result.anchorId = new String(new char[] { - message.charAt(16), message.charAt(17), // 高位 - message.charAt(14), message.charAt(15) // 低位 - }); - - // 解析距离 (位置18-25, 4字节小端整数) - int b0 = HexUtils.fastHexToByte(message.charAt(18), message.charAt(19)); // 最低位 - int b1 = HexUtils.fastHexToByte(message.charAt(20), message.charAt(21)); - int b2 = HexUtils.fastHexToByte(message.charAt(22), message.charAt(23)); - int b3 = HexUtils.fastHexToByte(message.charAt(24), message.charAt(25)); // 最高位 - int raw = (b3 << 24) | (b2 << 16) | (b1 << 8) | b0; - result.distance = raw; // 保持原始整数值 - - // 解析电量 (位置26-27) - result.power = HexUtils.fastHexToByte(message.charAt(26), message.charAt(27)); - - // 解析按钮状态 (位置28-29) - result.buttonPressed = HexUtils.fastHexToByte(message.charAt(28), message.charAt(29)) == 1; - - String hexData = "55AA01标签地址:" + result.tagId + "基站地址:" + result.anchorId + - "距离:" + result.distance + "电量:" + result.power + - "按钮状态:" + result.buttonPressed; - MessageViewPanel.showData(hexData, ip, port, 0, "UDPA", "55AA01", "ALL"); - } catch (IndexOutOfBoundsException | NumberFormatException e) { - System.err.println("Parsing error in packet from " + ip + ":" + port); - return null; - } - - return result; - } + public void reset() { + sequenceNum = 0; + tagId = ""; + anchorId = ""; + distance = 0; + power = 0; + buttonPressed = 0; + } + } + + /** + * 解析55AA01协议数据 + * @param message 十六进制字符串 + * @return 解析结果(错误时返回null) + */ + public static ParseResult parse(String message, String ip, int port) { + if (message == null || message.isEmpty()) { + return null; + } + + // 清洗数据:移除所有非十六进制字符 + char[] cleanedMessage = cleanMessage(message); + + // 数据校验 + if (cleanedMessage == null || cleanedMessage.length < MIN_LENGTH) { + return null; + } + + // 协议头校验 (55AA01) + if (!new String(cleanedMessage, 0, 6).equals(EXPECTED_HEADER)) { + return null; + } + + ParseResult result = RESULT_CACHE.get(); + result.reset(); + + try { + if (cleanedMessage.length < 30) { // 确保有足够长度访问charAt(28) + return null; + } + + // 解析序列号 (位置8-9) + result.sequenceNum = HexUtils.fastHexToByte(cleanedMessage[8], cleanedMessage[9]); + + // 解析标签ID (位置10-13, 小端序) + result.tagId = new String(new char[]{ + cleanedMessage[12], cleanedMessage[13], // 高位 + cleanedMessage[10], cleanedMessage[11] // 低位 + }); + + // 解析锚点ID (位置14-17, 小端序) + result.anchorId = new String(new char[]{ + cleanedMessage[16], cleanedMessage[17], // 高位 + cleanedMessage[14], cleanedMessage[15] // 低位 + }); + + // 解析距离 (位置18-25, 4字节小端整数) + int b0 = HexUtils.fastHexToByte(cleanedMessage[18], cleanedMessage[19]); // 最低位 + int b1 = HexUtils.fastHexToByte(cleanedMessage[20], cleanedMessage[21]); + int b2 = HexUtils.fastHexToByte(cleanedMessage[22], cleanedMessage[23]); + int b3 = HexUtils.fastHexToByte(cleanedMessage[24], cleanedMessage[25]); // 最高位 + int raw = (b3 << 24) | (b2 << 16) | (b1 << 8) | b0; + result.distance = raw; // 保持原始整数值 + + // 解析电量 (位置26-27) + result.power = HexUtils.fastHexToByte(cleanedMessage[26], cleanedMessage[27]); + + // 解析按钮状态 (位置28-29) + result.buttonPressed = HexUtils.fastHexToByte(cleanedMessage[28], cleanedMessage[29]); + + // 日志和更新操作可以考虑优化或减少调用频率 + String hexData = "55AA01 包序:" + result.sequenceNum + ",标签编号:" + result.tagId + ",基站编号:" + result.anchorId + + ",距离:" + result.distance + ",电量:" + result.power + + ",按钮状态:" + result.buttonPressed; + MessageViewPanel.showData(hexData, ip, port, 0, "UDPA", "55AA01", "ALL"); + + String time = EfficientTimeFormatter.getCurrentTimeFormatted(); + Dell_BaseStation.updateBaseStationProperty(result.anchorId, "ipAddress", ip); + Dell_BaseStation.updateBaseStationProperty(result.anchorId, "port", port + ""); + Dell_BaseStation.updateBaseStationProperty(result.anchorId, "status", "1"); + Dell_BaseStation.updateBaseStationProperty(result.anchorId, "onlineTime", time); + + Dell_tag.updateLocationTagProperty(result.tagId, "sosStatus", result.buttonPressed + ""); + Dell_tag.updateLocationTagProperty(result.tagId, "onlineStatus", "1"); + Dell_tag.updateLocationTagProperty(result.tagId, "lastUwbSignalTime", time); + Dell_tag.updateLocationTagProperty(result.tagId, "latestRangingSeq", result.sequenceNum + ""); + Dell_tag.updateLocationTagProperty(result.tagId, "latestRangingBaseId", result.anchorId); + Dell_tag.updateLocationTagProperty(result.tagId, "latestRangingDistance", result.distance + ""); + Dell_tag.updateLocationTagProperty(result.tagId, "latestRangingBaseCount", "1"); + + } catch (IndexOutOfBoundsException | NumberFormatException e) { + System.err.println("Parsing error in packet from " + ip + ":" + port); + return null; + } + + return result; + } + + private static char[] cleanMessage(String message) { + char[] cleaned = new char[message.length()]; + int j = 0; + for (char c : message.toCharArray()) { + if (Character.isDigit(c) || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f')) { + cleaned[j++] = Character.toUpperCase(c); + } + } + if (j == 0) return null; + return Arrays.copyOf(cleaned, j); + } + + public static void updateBase(String baseStationId, String propertyName, String value) { + Dell_BaseStation.updateBaseStationProperty(baseStationId, propertyName, value); + Dell_BaseStation.updateBaseStationProperty(baseStationId, propertyName, value); + } } \ No newline at end of file -- Gitblit v1.9.3