From 1562f05c0c85fb45cc8ffba8ac6984e9b6f96bd4 Mon Sep 17 00:00:00 2001
From: 826220679@qq.com <826220679@qq.com>
Date: 星期五, 08 八月 2025 23:07:50 +0800
Subject: [PATCH] 串口通信

---
 /dev/null                                |  180 ------------
 src/dell55AAData/Dell55AA12HighPerf.java |  168 ++++++++++++
 systemfile/Messages_zh.properties        |   22 
 src/dell55AAData/Dell55AA01Parser.java   |   84 ++++++
 src/dell55AAData/PacketParser.java       |  105 +++++++
 src/dell55AAData/HexUtils.java           |   40 ++
 src/dell_system/SerialCommPanel.java     |  110 +------
 systemfile/logfile/openlog.txt           |   79 +++++
 8 files changed, 502 insertions(+), 286 deletions(-)

diff --git a/src/Dell55aa/Dell55AA01.java b/src/Dell55aa/Dell55AA01.java
deleted file mode 100644
index 4ca9bef..0000000
--- a/src/Dell55aa/Dell55AA01.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package Dell55aa;
-
-public class Dell55AA01 {
-
-}
diff --git a/src/Dell55aa/Dell55AA12HighPerf.java b/src/Dell55aa/Dell55AA12HighPerf.java
deleted file mode 100644
index 5a754a9..0000000
--- a/src/Dell55aa/Dell55AA12HighPerf.java
+++ /dev/null
@@ -1,180 +0,0 @@
-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;
-    }
-}
\ No newline at end of file
diff --git a/src/dell55AAData/Dell55AA01Parser.java b/src/dell55AAData/Dell55AA01Parser.java
new file mode 100644
index 0000000..f95489e
--- /dev/null
+++ b/src/dell55AAData/Dell55AA01Parser.java
@@ -0,0 +1,84 @@
+package dell55AAData;
+
+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);
+
+    // 解析结果类
+    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;
+        }
+    }
+
+    /**
+     * 解析55AA01协议数据
+     * @param message 十六进制字符串
+     * @return 解析结果(失败返回null)
+     */
+    public static ParseResult parse(String message) {
+        // 参数检查
+        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();
+        char[] chars = HexUtils.getThreadLocalBuffer();
+        message.getChars(0, Math.min(message.length(), chars.length), chars, 0);
+        
+        // 解析序列号 (位置8-9)
+        result.sequenceNum = HexUtils.fastHexToByte(chars[8], chars[9]);
+        
+        // 解析标签ID (位置10-13, 小端序)
+        result.tagId = new String(new char[] {
+            chars[12], chars[13], // 高位
+            chars[10], chars[11]   // 低位
+        });
+        
+        // 解析锚点ID (位置14-17, 小端序)
+        result.anchorId = new String(new char[] {
+            chars[16], chars[17], // 高位
+            chars[14], chars[15]   // 低位
+        });
+        
+        // 解析距离 (位置18-25, 4字节小端序整数)
+        int b0 = HexUtils.fastHexToByte(chars[18], chars[19]); // 最低位
+        int b1 = HexUtils.fastHexToByte(chars[20], chars[21]);
+        int b2 = HexUtils.fastHexToByte(chars[22], chars[23]);
+        int b3 = HexUtils.fastHexToByte(chars[24], chars[25]); // 最高位
+        int raw = (b3 << 24) | (b2 << 16) | (b1 << 8) | b0;
+        result.distance = raw; // 保持原始整数值
+        
+        // 解析电量 (位置26-27)
+        result.power = HexUtils.fastHexToByte(chars[26], chars[27]);
+        
+        // 解析按钮状态 (位置28-29)
+        result.buttonPressed = HexUtils.fastHexToByte(chars[28], chars[29]) == 1;
+        
+        return result;
+    }
+}
\ No newline at end of file
diff --git a/src/dell55AAData/Dell55AA12HighPerf.java b/src/dell55AAData/Dell55AA12HighPerf.java
new file mode 100644
index 0000000..06f29dd
--- /dev/null
+++ b/src/dell55AAData/Dell55AA12HighPerf.java
@@ -0,0 +1,168 @@
+package dell55AAData;
+
+public class Dell55AA12HighPerf {
+    
+    // 协议常量
+    @SuppressWarnings("unused")
+	private static final String HEADER = "55AA12"; // 协议头
+    private static final int MIN_LENGTH = 34; // 最小数据长度
+    private static final ThreadLocal<ParseResult> RESULT_CACHE = // 解析结果缓存
+        ThreadLocal.withInitial(ParseResult::new);
+
+    // 解析结果类
+    public static class ParseResult { 
+        public String tagId; // 标签ID
+        public int sequenceNum; // 序列号
+        public int power; // 电量
+        public int vibrationState; // 振动状态
+        public boolean tagRemoved; // 标签移除状态
+        public boolean isSleeping; // 休眠状态
+        public boolean isStatic; // 静止状态
+        public boolean sosButtonPressed; // SOS按钮状态
+        public int tagHeight; // 标签高度
+        public int anchorCount; // 锚点数量
+        public String[] anchorIds = new String[0]; // 锚点ID数组
+        public int[] distances = new int[0]; // 距离数组
+        public int[] anchorPowers = new int[0]; // 锚点电量数组
+        public int[] signalStrengths1 = new int[0]; // 信号强度1
+        public int[] signalStrengths2 = new int[0]; // 信号强度2
+        
+        // 重置方法
+        public void reset() {
+            tagId = "";
+            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 = HexUtils.getThreadLocalBuffer();
+        message.getChars(0, Math.min(message.length(), chars.length), chars, 0);
+        
+        // 解析数据长度
+        int dataLength = (HexUtils.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 = new String(new char[] { 
+                chars[10], chars[11], // 高字节
+                chars[8], chars[9]    // 低字节
+            }); 
+        // 序列号(小端序)
+        result.sequenceNum = (HexUtils.fastHexToByte(chars[14], chars[15]) << 8 | 
+                            HexUtils.fastHexToByte(chars[12], chars[13]));
+        
+        // 电量
+        result.power = HexUtils.fastHexToByte(chars[16], chars[17]);
+        
+        // 状态标志
+        int buttonState = HexUtils.fastHexToByte(chars[18], chars[19]);
+        result.vibrationState = (buttonState >> 5) & 1;
+        result.tagRemoved = ((buttonState >> 3) & 1) == 1;
+        result.isSleeping = ((buttonState >> 2) & 1) == 1;
+        result.isStatic = ((buttonState >> 1) & 1) == 1;
+        result.sosButtonPressed = (buttonState & 1) == 1;
+        
+        // 标签高度(小端序)
+        result.tagHeight = (HexUtils.fastHexToByte(chars[22], chars[23]) << 8 | 
+                          HexUtils.fastHexToByte(chars[20], chars[21]));
+    }
+
+    /**
+     * 解析锚点信息
+     */
+    private static void parseAnchorInfo(char[] chars, ParseResult result) {
+        // 锚点数量
+        result.anchorCount = HexUtils.fastHexToByte(chars[32], chars[33]);
+        if (result.anchorCount == 0) return;
+
+        // 动态扩展数组
+        if (result.anchorIds.length < result.anchorCount) {
+            result.anchorIds = new String[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; // 锚点ID起始位置
+        int distanceStart = baseIndex + result.anchorCount * 4; // 距离起始位置
+        int powerStart = distanceStart + result.anchorCount * 4; // 电量起始位置
+
+        // 解析锚点ID(小端序)
+        for (int i = 0; i < result.anchorCount; i++) {
+            int idOffset = baseIndex + i * 4;
+            result.anchorIds[i] = new String(new char[]{
+                chars[idOffset + 2], // 高字节1
+                chars[idOffset + 3], // 高字节2
+                chars[idOffset],     // 低字节1
+                chars[idOffset + 1]  // 低字节2
+            });
+        }
+
+        // 解析距离(有符号整数处理)
+        for (int i = 0; i < result.anchorCount; i++) {
+            int distOffset = distanceStart + i * 4;
+            int distLow = HexUtils.fastHexToByte(chars[distOffset], chars[distOffset + 1]);
+            int distHigh = HexUtils.fastHexToByte(chars[distOffset + 2], chars[distOffset + 3]);
+            int rawDistance = (distHigh << 8) | distLow;
+            result.distances[i] = (rawDistance > 0x7FFF)
+                                ? (rawDistance - 0x10000)
+                                : rawDistance;
+        }
+
+        // 解析锚点电量
+        for (int i = 0; i < result.anchorCount; i++) {
+            int powerOffset = powerStart + i * 2;
+            result.anchorPowers[i] = HexUtils.fastHexToByte(chars[powerOffset], chars[powerOffset + 1]);
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/dell55AAData/HexUtils.java b/src/dell55AAData/HexUtils.java
new file mode 100644
index 0000000..162b2e0
--- /dev/null
+++ b/src/dell55AAData/HexUtils.java
@@ -0,0 +1,40 @@
+package dell55AAData;
+
+public class HexUtils {
+    // 十六进制字符快速转换表 (ASCII范围内)
+    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;
+        }
+    }
+
+    // 线程安全的字符缓冲区 (初始大小256)
+    private static final ThreadLocal<char[]> CHAR_BUF_CACHE = 
+        ThreadLocal.withInitial(() -> new char[256]);
+
+    /**
+     * 获取线程本地字符缓冲区
+     * @return 可复用的char[256]缓冲区
+     */
+    public static char[] getThreadLocalBuffer() {
+        return CHAR_BUF_CACHE.get();
+    }
+
+    /**
+     * 快速将两个十六进制字符转换为字节
+     * @param c1 高位字符 (0-9, A-F, a-f)
+     * @param c2 低位字符 (0-9, A-F, a-f)
+     * @return 转换后的字节值 (无效字符返回0)
+     */
+    public 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;
+    }
+}
\ No newline at end of file
diff --git a/src/dell55AAData/PacketParser.java b/src/dell55AAData/PacketParser.java
new file mode 100644
index 0000000..bc75351
--- /dev/null
+++ b/src/dell55AAData/PacketParser.java
@@ -0,0 +1,105 @@
+package dell55AAData;
+import dell55AAData.Dell55AA12HighPerf;
+import dell55AAData.Dell55AA12HighPerf.ParseResult;
+import dell55AAData.Dell55AA01Parser;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.ResourceBundle;
+
+/**
+ * 公共解析器:根据包头统一解析 55AA01 / 55AA12 / 未知协议
+ * 可被任何 UI 或业务类直接调用
+ */
+public final class PacketParser {
+
+    private static final SimpleDateFormat SDF = new SimpleDateFormat("HH:mm:ss.SSS");
+
+    private PacketParser() { /* 工具类,禁止实例化 */ }
+
+    /**
+     * 解析入口
+     *
+     * @param data     完整字节数组
+     * @param bundle   国际化资源
+     * @param showTime 是否在结果前加时间戳
+     * @return 解析后的可读字符串,若解析失败返回提示
+     */
+    public static String parse(byte[] data,ResourceBundle bundle,boolean showTime) {
+        String hex = bytesToHex(data).toUpperCase();
+        StringBuilder sb = new StringBuilder();
+        if (showTime) {
+            sb.append('[').append(SDF.format(new Date())).append("]");
+        }
+
+        if (hex.startsWith("55AA01")) {
+            Dell55AA01Parser.ParseResult r = Dell55AA01Parser.parse(hex);
+            if (r == null) {
+                sb.append(bundle.getString("parser.invalid")).append(" 55AA01");
+                return sb.toString();
+            }
+
+            String button = r.buttonPressed ? bundle.getString("yes") : bundle.getString("no");
+            sb.append(bundle.getString("label.sequence")).append(": ").append(r.sequenceNum).append(',')
+              .append(bundle.getString("label.id")).append(": ").append(r.tagId).append(',')
+              .append(bundle.getString("label.anchor_ids")).append(": ").append(r.anchorId).append(',')
+              .append(bundle.getString("label.distances")).append(": ").append(r.distance).append(',')
+              .append(bundle.getString("label.power")).append(": ").append(r.power).append("%,")
+              .append(bundle.getString("status.button")).append(": ").append(button);
+
+        } else if (hex.startsWith("55AA12")) {
+            ParseResult r = Dell55AA12HighPerf.parse(hex);
+            if (r == null) {
+                sb.append(bundle.getString("parser.invalid")).append(" 55AA12");
+                return sb.toString();
+            }
+
+            // 组装基站信息
+            StringBuilder ids = new StringBuilder();
+            StringBuilder dists = new StringBuilder();
+            StringBuilder powers = new StringBuilder();
+            for (int i = 0; i < r.anchorCount; i++) {
+                if (i > 0) {
+                    ids.append(',');
+                    dists.append(',');
+                    powers.append(',');
+                }
+                ids.append(r.anchorIds[i]);
+                dists.append(r.distances[i]);
+                powers.append(r.anchorPowers[i]);
+            }
+
+            String button   = r.sosButtonPressed ? bundle.getString("yes") : bundle.getString("no");
+            String stat     = r.isStatic        ? bundle.getString("yes") : bundle.getString("no");
+            String sleep    = r.isSleeping      ? bundle.getString("yes") : bundle.getString("no");
+            String vibrate  = (r.vibrationState == 1) ? bundle.getString("on") : bundle.getString("off");
+            String uwb      = r.tagRemoved      ? bundle.getString("off") : bundle.getString("on");
+
+            sb.append(bundle.getString("label.id")).append(": ").append(r.tagId).append('\n')
+              .append(bundle.getString("label.sequence")).append(": ").append(r.sequenceNum).append('\n')
+              .append(bundle.getString("label.power")).append(": ").append(r.power).append("%\n")
+              .append(bundle.getString("label.status")).append(": ")
+              .append(bundle.getString("status.button")).append('[').append(button).append("], ")
+              .append(bundle.getString("status.static")).append('[').append(stat).append("], ")
+              .append(bundle.getString("status.sleeping")).append('[').append(sleep).append("], ")
+              .append(bundle.getString("status.vibration")).append('[').append(vibrate).append("], ")
+              .append(bundle.getString("status.uwb_switch")).append('[').append(uwb).append("]\n")
+              .append(bundle.getString("label.tag_height")).append(": ").append(r.tagHeight).append('\n')
+              .append(bundle.getString("label.anchor_count")).append(": ").append(r.anchorCount).append('\n')
+              .append(bundle.getString("label.anchor_ids")).append(": (").append(ids).append(")\n")
+              .append(bundle.getString("label.distances")).append(": (").append(dists).append(")\n")
+              .append(bundle.getString("label.anchor_powers")).append(": (").append(powers).append(")\n");
+
+        } else {
+            sb.append(bundle.getString("parser.unknown"));
+        }
+
+        sb.append("\n");
+        return sb.toString();
+    }
+
+    private static String bytesToHex(byte[] bytes) {
+        StringBuilder sb = new StringBuilder(bytes.length * 2);
+        for (byte b : bytes) sb.append(String.format("%02X", b));
+        return sb.toString();
+    }
+}
\ No newline at end of file
diff --git a/src/dell_system/SerialCommPanel.java b/src/dell_system/SerialCommPanel.java
index 2ab154d..a4aee12 100644
--- a/src/dell_system/SerialCommPanel.java
+++ b/src/dell_system/SerialCommPanel.java
@@ -1,7 +1,6 @@
 package dell_system;
 import com.fazecast.jSerialComm.SerialPort;
-import Dell55aa.Dell55AA12HighPerf;
-import Dell55aa.Dell55AA12HighPerf.ParseResult;
+import dell55AAData.PacketParser;
 import javax.swing.*;
 import javax.swing.border.TitledBorder;
 import javax.swing.event.PopupMenuEvent;
@@ -327,97 +326,27 @@
     /* ================= 解析数据显示 ================= */
     private void appendParsedData(byte[] data) {
         if (!chkEnableParsing.isSelected()) return;
-        
+
         SwingUtilities.invokeLater(() -> {
             packetCounter++;
-            lblPacketCount.setText(String.format(messages.getString("packet.count.format"), packetCounter)); // 更新计数标签
-            
+            lblPacketCount.setText(String.format(messages.getString("packet.count.format"), packetCounter));
+
             try {
-                // 将字节数据转换为十六进制字符串
-                String hexData = bytesToHex(data).toUpperCase();
-                // 使用Dell55AA12HighPerf解析
-                ParseResult result = Dell55AA12HighPerf.parse(hexData);
-                
-                if (result != null) {
-                    // 构建状态字符串
-                    String buttonStatus = result.sosButtonPressed ? messages.getString("yes") : messages.getString("no");
-                    String staticStatus = result.isStatic ? messages.getString("yes") : messages.getString("no");
-                    String sleepStatus = result.isSleeping ? messages.getString("yes") : messages.getString("no");
-                    String vibrationStatus = (result.vibrationState == 1) ? messages.getString("on") : messages.getString("off");
-                    String uwbStatus = result.tagRemoved ? messages.getString("off") : messages.getString("on");
-                    
-                    // 构建基站信息
-                    StringBuilder anchorIds = new StringBuilder();
-                    StringBuilder distances = new StringBuilder();
-                    StringBuilder anchorPowers = new StringBuilder();
-                    
-                    for (int i = 0; i < result.anchorCount; i++) {
-                        if (i > 0) {
-                            anchorIds.append(",");
-                            distances.append(",");
-                            anchorPowers.append(",");
-                        }
-                        anchorIds.append(result.anchorIds[i]);
-                        distances.append(result.distances[i]);
-                        anchorPowers.append(result.anchorPowers[i]);
-                    }
-                    
-                    // 格式化输出
-                    StringBuilder parsedOutput = new StringBuilder();
-                    
-                    // 添加时间戳(如果勾选)
-                    if (chkTimestamp.isSelected()) {
-                        parsedOutput.append("[").append(sdf.format(new Date())).append("]\n");
-                    }
-                    
-                    parsedOutput.append(String.format(
-                        "%s: %d\n%s: %d\n%s: %d%%\n%s: %s[%s], %s[%s], %s[%s], %s[%s], %s[%s]\n%s: %d\n%s: %d\n%s: (%s)\n%s: (%s)\n%s: (%s)\n\n",
-                        messages.getString("label.id"), result.tagId,
-                        messages.getString("label.sequence"), result.sequenceNum,
-                        messages.getString("label.power"), result.power,
-                        messages.getString("label.status"),
-                        messages.getString("status.button"), buttonStatus,
-                        messages.getString("status.static"), staticStatus,
-                        messages.getString("status.sleeping"), sleepStatus,
-                        messages.getString("status.vibration"), vibrationStatus,
-                        messages.getString("status.uwb_switch"), uwbStatus,
-                        messages.getString("label.tag_height"), result.tagHeight,
-                        messages.getString("label.anchor_count"), result.anchorCount,
-                        messages.getString("label.anchor_ids"), anchorIds.toString(),
-                        messages.getString("label.distances"), distances.toString(),
-                        messages.getString("label.anchor_powers"), anchorPowers.toString()
-                    ));
-                    
-                    txtParsedData.append(parsedOutput.toString());
-                    txtParsedData.setCaretPosition(txtParsedData.getDocument().getLength());
-                    lblParseStatus.setText(String.format("%s (Packets: %d)", messages.getString("parser.ready"), packetCounter));
-                } else {
-                    StringBuilder invalidMsg = new StringBuilder();
-                    // 添加时间戳(如果勾选)
-                    if (chkTimestamp.isSelected()) {
-                    	
-                        invalidMsg.append("[").append(sdf.format(new Date())).append("]\n");
-                    }
-                    invalidMsg.append(String.format("[Packet #%d] Not a valid 55AA12 packet\n\n", packetCounter));
-                    
-                    txtParsedData.append(invalidMsg.toString());
-                    lblParseStatus.setText(String.format("Parser: Invalid (Packets: %d)", packetCounter));
-                }
-            } catch (Exception e) {
-                StringBuilder errorMsg = new StringBuilder();
-                // 添加时间戳(如果勾选)
-                if (chkTimestamp.isSelected()) {
-                    errorMsg.append("[").append(sdf.format(new Date())).append("]\n");
-                }
-                errorMsg.append(String.format("[Packet #%d] Parse error: %s\n\n", 
-                        packetCounter, e.getMessage()));
-                
-                txtParsedData.append(errorMsg.toString());
+                String parsed = PacketParser.parse(data, messages, chkTimestamp.isSelected());
+                txtParsedData.append(parsed);
+                txtParsedData.setCaretPosition(txtParsedData.getDocument().getLength());
+                lblParseStatus.setText(
+                        String.format("%s (Packets: %d)",
+                                      messages.getString("parser.ready"), packetCounter));
+            } catch (Exception ex) {
+                StringBuilder sb = new StringBuilder();
+                if (chkTimestamp.isSelected()) sb.append('[').append(sdf.format(new Date())).append("]\n");
+                sb.append(String.format("[Packet #%d] Parse error: %s\n\n", packetCounter, ex.getMessage()));
+                txtParsedData.append(sb.toString());
                 lblParseStatus.setText(String.format("Parser: Error (Packets: %d)", packetCounter));
             }
         });
     }
-    
     /* ================= UI 更新 ================= */
     private void appendRawData(byte[] bytes) {
         SwingUtilities.invokeLater(() -> {
@@ -564,15 +493,6 @@
                 }
             });
         }
-    }
-    
-    // 新增辅助方法:字节数组转十六进制字符串
-    private String bytesToHex(byte[] bytes) {
-        StringBuilder sb = new StringBuilder();
-        for (byte b : bytes) {
-            sb.append(String.format("%02X", b));
-        }
-        return sb.toString();
     }
     
     // 修改clearDisplay方法
diff --git a/systemfile/Messages_zh.properties b/systemfile/Messages_zh.properties
index b2607af..3fd7abd 100644
--- a/systemfile/Messages_zh.properties
+++ b/systemfile/Messages_zh.properties
@@ -1,24 +1,24 @@
 # 鏂板璧勬簮閿�煎
 packet.count.format=鏀跺埌鏁版嵁:%d鏉�
 label.id=鏍囩缂栧彿
-label.sequence=鍖呭簭
-label.power=鐢甸噺
-label.status=鐘舵��
-label.tag_height=鏍囩楂�
-label.anchor_count=鍩虹珯鏁�
+label.sequence=閫氫俊鍖呭簭
+label.power=鏍囩鐢甸噺
+label.status=鏍囩鐘舵��
+label.tag_height=鏍囩楂樺害
+label.anchor_count=鍩虹珯鏁伴噺
 label.anchor_ids=鍩虹珯缂栧彿
-label.distances=娴嬭窛鍊�
+label.distances=娴嬭窛璺濈
 label.anchor_powers=鍩虹珯鐢甸噺
 status.button=鎸夐敭
 status.static=闈欐
 status.sleeping=浼戠湢
 status.vibration=闇囧姩
 status.uwb_switch=UWB寮�鍏�
-parser.ready=瑙f瀽鍣�: 灏辩华
-yes=鏄�
-no=鍚�
-on=寮�
-off=鍏�
+parser.ready=瑙f瀽鍣�:灏辩华
+yes=1
+no=0
+on=1
+off=0
 ENABLE_PARSING=Enable Parsing
 PARSER=Parser
 EXPORT=Export
diff --git a/systemfile/logfile/openlog.txt b/systemfile/logfile/openlog.txt
index 56da0b0..1950da1 100644
--- a/systemfile/logfile/openlog.txt
+++ b/systemfile/logfile/openlog.txt
@@ -555,3 +555,82 @@
 程序关闭: 2025-08-07 23:52:43
 工作时长: 0小时 0分钟 36秒
 -----------------------------------
+程序启动: 2025-08-08 11:29:39
+程序启动: 2025-08-08 11:29:41
+程序关闭: 2025-08-08 12:01:06
+工作时长: 0小时 31分钟 26秒
+-----------------------------------
+程序启动: 2025-08-08 12:17:57
+程序关闭: 2025-08-08 12:18:22
+工作时长: 0小时 0分钟 25秒
+-----------------------------------
+程序启动: 2025-08-08 12:23:35
+程序关闭: 2025-08-08 12:34:34
+工作时长: 0小时 10分钟 59秒
+-----------------------------------
+程序启动: 2025-08-08 12:34:36
+程序关闭: 2025-08-08 12:37:55
+工作时长: 0小时 3分钟 18秒
+-----------------------------------
+程序启动: 2025-08-08 12:39:03
+程序关闭: 2025-08-08 14:23:40
+工作时长: 1小时 44分钟 37秒
+-----------------------------------
+程序启动: 2025-08-08 14:23:43
+程序关闭: 2025-08-08 14:59:18
+工作时长: 0小时 35分钟 35秒
+-----------------------------------
+程序启动: 2025-08-08 15:15:56
+程序关闭: 2025-08-08 15:50:22
+工作时长: 0小时 34分钟 26秒
+-----------------------------------
+程序启动: 2025-08-08 17:16:52
+程序关闭: 2025-08-08 17:54:58
+工作时长: 0小时 38分钟 5秒
+-----------------------------------
+程序启动: 2025-08-08 21:57:21
+程序启动: 2025-08-08 22:21:20
+程序关闭: 2025-08-08 22:21:27
+工作时长: 0小时 24分钟 6秒
+-----------------------------------
+程序启动: 2025-08-08 22:21:29
+程序关闭: 2025-08-08 22:22:07
+工作时长: 0小时 0分钟 38秒
+-----------------------------------
+程序启动: 2025-08-08 22:25:06
+程序关闭: 2025-08-08 22:25:45
+工作时长: 0小时 0分钟 38秒
+-----------------------------------
+程序启动: 2025-08-08 22:26:08
+程序关闭: 2025-08-08 22:26:57
+工作时长: 0小时 0分钟 48秒
+-----------------------------------
+程序启动: 2025-08-08 22:27:44
+程序关闭: 2025-08-08 22:28:32
+工作时长: 0小时 0分钟 48秒
+-----------------------------------
+程序启动: 2025-08-08 22:29:10
+程序关闭: 2025-08-08 22:29:41
+工作时长: 0小时 0分钟 31秒
+-----------------------------------
+程序启动: 2025-08-08 22:30:36
+程序关闭: 2025-08-08 22:31:01
+工作时长: 0小时 0分钟 24秒
+-----------------------------------
+程序启动: 2025-08-08 22:31:22
+程序启动: 2025-08-08 23:02:47
+程序关闭: 2025-08-08 23:02:51
+工作时长: 0小时 31分钟 29秒
+-----------------------------------
+程序启动: 2025-08-08 23:02:53
+程序关闭: 2025-08-08 23:03:18
+工作时长: 0小时 0分钟 25秒
+-----------------------------------
+程序启动: 2025-08-08 23:04:41
+程序关闭: 2025-08-08 23:04:58
+工作时长: 0小时 0分钟 16秒
+-----------------------------------
+程序启动: 2025-08-08 23:05:41
+程序关闭: 2025-08-08 23:06:23
+工作时长: 0小时 0分钟 41秒
+-----------------------------------

--
Gitblit v1.9.3