From 487a5b943571d6ab57c4baddca1cbcc7b2062e73 Mon Sep 17 00:00:00 2001
From: 826220679@qq.com <826220679@qq.com>
Date: 星期三, 27 八月 2025 23:06:57 +0800
Subject: [PATCH] 20250827

---
 src/home/Dell55AA1FParser.java              |   36 +
 bin/home/Dell55AA1FParser.class             |    0 
 bin/home/AOAFollowSystem$HomePanel.class    |    0 
 bin/home/VisualizationPanel$1.class         |    0 
 bin/home/AOAFollowSystem$1.class            |    0 
 src/home/TagDell55AA03Parser.java           |  236 +++++++++++++
 systemfile/logfile/openlog.txt              |  220 ++++++++++++
 bin/home/AOAFollowSystem$HomePanel$1.class  |    0 
 systemfile/1.png                            |    0 
 systemfile/Messages_en.properties           |    5 
 systemfile/Messages_zh.properties           |    5 
 bin/home/VisualizationPanel.class           |    0 
 src/home/VisualizationPanel.java            |   56 ++
 src/home/AOAFollowSystem.java               |  217 ++++++++----
 bin/home/AOAFollowSystem$HomePanel$2.class  |    0 
 bin/home/AOAFollowSystem.class              |    0 
 src/home/Dell55AA51Parser.java              |  228 +++++++++++++
 bin/home/Dell55AA1FParser$ParseResult.class |    0 
 18 files changed, 909 insertions(+), 94 deletions(-)

diff --git a/bin/home/AOAFollowSystem$1.class b/bin/home/AOAFollowSystem$1.class
index a4024a2..9185775 100644
--- a/bin/home/AOAFollowSystem$1.class
+++ b/bin/home/AOAFollowSystem$1.class
Binary files differ
diff --git a/bin/home/AOAFollowSystem$HomePanel$1.class b/bin/home/AOAFollowSystem$HomePanel$1.class
index d46b37e..a26d366 100644
--- a/bin/home/AOAFollowSystem$HomePanel$1.class
+++ b/bin/home/AOAFollowSystem$HomePanel$1.class
Binary files differ
diff --git a/bin/home/AOAFollowSystem$HomePanel$2.class b/bin/home/AOAFollowSystem$HomePanel$2.class
index 8ca4a8f..5e4cc60 100644
--- a/bin/home/AOAFollowSystem$HomePanel$2.class
+++ b/bin/home/AOAFollowSystem$HomePanel$2.class
Binary files differ
diff --git a/bin/home/AOAFollowSystem$HomePanel.class b/bin/home/AOAFollowSystem$HomePanel.class
index 7c2825e..ed94e59 100644
--- a/bin/home/AOAFollowSystem$HomePanel.class
+++ b/bin/home/AOAFollowSystem$HomePanel.class
Binary files differ
diff --git a/bin/home/AOAFollowSystem.class b/bin/home/AOAFollowSystem.class
index 86ebcc8..42f24c4 100644
--- a/bin/home/AOAFollowSystem.class
+++ b/bin/home/AOAFollowSystem.class
Binary files differ
diff --git a/bin/home/Dell55AA1FParser$ParseResult.class b/bin/home/Dell55AA1FParser$ParseResult.class
index 5179218..b4e7737 100644
--- a/bin/home/Dell55AA1FParser$ParseResult.class
+++ b/bin/home/Dell55AA1FParser$ParseResult.class
Binary files differ
diff --git a/bin/home/Dell55AA1FParser.class b/bin/home/Dell55AA1FParser.class
index 82d8494..123f8f8 100644
--- a/bin/home/Dell55AA1FParser.class
+++ b/bin/home/Dell55AA1FParser.class
Binary files differ
diff --git a/bin/home/VisualizationPanel$1.class b/bin/home/VisualizationPanel$1.class
index 0fbade4..8c57660 100644
--- a/bin/home/VisualizationPanel$1.class
+++ b/bin/home/VisualizationPanel$1.class
Binary files differ
diff --git a/bin/home/VisualizationPanel.class b/bin/home/VisualizationPanel.class
index b288737..4813e2b 100644
--- a/bin/home/VisualizationPanel.class
+++ b/bin/home/VisualizationPanel.class
Binary files differ
diff --git a/src/home/AOAFollowSystem.java b/src/home/AOAFollowSystem.java
index 432b760..499cbea 100644
--- a/src/home/AOAFollowSystem.java
+++ b/src/home/AOAFollowSystem.java
@@ -110,6 +110,12 @@
 		case "ascii": return "ASCII";
 		case "hex_send": return "HEX鍙戦��";
 		case "display_format": return "鏄剧ず鏍煎紡";
+		case "pair_tooltip": 
+		    return currentLocale.equals(Locale.SIMPLIFIED_CHINESE) ? 
+		           "鐐瑰嚮鍙戦�佸悗杩涘叆20绉掗厤瀵规ā寮�" : 
+		           "Enter 20-second pairing mode after clicking send";
+		case "scale": 
+            return currentLocale.equals(Locale.SIMPLIFIED_CHINESE) ? "缂╂斁" : "Scale";
 		default: return key;
 		}
 	}
@@ -188,7 +194,10 @@
 		// 鏇存柊鍚勯潰鏉挎枃鏈�
 		homePanel.updateLanguage();
 		configPanel.updateLanguage();
+		 // 鏇存柊閰嶅澶嶉�夋鐨勬彁绀轰俊鎭�
+	    homePanel.updatePairCheckboxTooltip();
 	}
+	
 
 	private JButton createNavButton(String text, Color color) {
 		JButton button = new JButton(text);
@@ -301,10 +310,26 @@
 			formatPanel.add(displayFormatLabel);
 
 			ButtonGroup formatGroup = new ButtonGroup();
-			hexRadio = new JRadioButton(getString("hex"), true); // 榛樿閫変腑HEX
-			asciiRadio = new JRadioButton(getString("ascii"));
-			
+			asciiRadio = new JRadioButton(getString("ascii"), true); // 榛樿閫変腑ASCI
+			asciiRadio.addItemListener(e -> {
+			    if (asciiRadio.isSelected()) {
+			    	asciiRadio.setForeground(Color.RED);
+			    } else {
+			    	asciiRadio.setForeground(null); // 鎭㈠榛樿棰滆壊
+			    }
+			});
+			hexRadio = new JRadioButton(getString("hex"), false); // 榛樿涓嶉�変腑HEX
+			hexRadio.addItemListener(e -> {
+			    if (hexRadio.isSelected()) {
+			        hexRadio.setForeground(Color.RED);
+			    } else {
+			        hexRadio.setForeground(null); // 鎭㈠榛樿棰滆壊
+			    }
+			});
+
 			pairCheckBox = new JCheckBox(getString("pair"), false); // 榛樿涓嶅嬀閫�
+			// 涓洪厤瀵瑰閫夋娣诲姞鎻愮ず淇℃伅
+			pairCheckBox.setToolTipText(getString("pair_tooltip"));
 			pairCheckBox.addItemListener(e -> {
 			    if (pairCheckBox.isSelected()) {
 			        sendField.setText("55AA030304F5FF");
@@ -413,7 +438,7 @@
 			sendBtn.addActionListener(e -> sendData());
 
 			// 鏂板锛欻EX鍙戦�佸閫夋
-			hexSendCheckBox = new JCheckBox(getString("hex_send"), true); // 榛樿鍕鹃��
+			hexSendCheckBox = new JCheckBox(getString("hex_send"), false); // 榛樿鍕鹃��
 			sendControlPanel.add(hexSendCheckBox, BorderLayout.WEST);
 			sendControlPanel.add(sendBtn, BorderLayout.EAST);
 
@@ -426,6 +451,11 @@
 			// 娣诲姞宸﹀彸闈㈡澘
 			add(leftPanel, BorderLayout.CENTER);
 			add(rightPanel, BorderLayout.EAST);
+		}
+
+		// 鍦℉omePanel绫讳腑娣诲姞鏇存柊閰嶅澶嶉�夋鎻愮ず淇℃伅鐨勬柟娉�
+		public void updatePairCheckboxTooltip() {
+		    pairCheckBox.setToolTipText(getString("pair_tooltip"));
 		}
 
 		private JButton createColoredButton(String text, Color color) {
@@ -566,74 +596,116 @@
 		}
 
 		private void processReceivedData(byte[] data) {
-			// 浼樺寲锛氶噸鐢⊿tringBuilder瀵硅薄
-			hexBuilder.setLength(0);
-			for (byte b : data) {
-				hexBuilder.append(String.format("%02X", b));
-			}
-			String displayText = hexBuilder.toString();
-			
-			String displayText1 = new String(data).replaceAll("\\s+", "");
-			
-			if (displayText.startsWith("55AA1F")) {
-				Dell55AA1FParser.ParseResult result = Dell55AA1FParser.parse(displayText, "127.0.0.1", 0);
-				if (result != null) {
-					updateTable(result);
-					visualizationPanel.updatePosition(result.distance, result.angle,result.signalQuality);
-					visualizationPanel.setTagId(result.tagId);
-				}
-			}else if(displayText.startsWith("55AA01")) {            	
-				ParseResult result=Dell55AA01Parser.parse(displayText, "127.0.0.1", 0);
-				visualizationPanel.updatePosition(result.distance,270,0);				
-				visualizationPanel.setTagId(result.tagId);
-				
-			}
+		    // 浼樺寲锛氶噸鐢⊿tringBuilder瀵硅薄
+		    hexBuilder.setLength(0);
+		    for (byte b : data) {
+		        hexBuilder.append(String.format("%02X", b));
+		    }
+		    String displayText = hexBuilder.toString();
+		    
+		    String displayText1 = new String(data).replaceAll("\\s+", "");
+		    
+		    // 鍏堟鏌ユ暟鎹暱搴︽槸鍚﹁冻澶熻繘琛岃В鏋�
+		    if (displayText.length() < 30) { // 鑷冲皯闇�瑕�30涓瓧绗�(15瀛楄妭)鎵嶈兘瑙f瀽鍩烘湰瀛楁
+		        appendLog("鏁版嵁闀垮害涓嶈冻: " + displayText);
+		        return;
+		    }
+		    
+		    if (displayText.startsWith("55AA1F")) {
+		        Dell55AA1FParser.ParseResult result = Dell55AA1FParser.parse(displayText, "127.0.0.1", 0);
+		        if (result != null) {
+		            updateTable(result);
+		            visualizationPanel.updatePosition(result.distance, result.angle, result.signalQuality);
+		            visualizationPanel.setTagId(result.tagId);
+		        } else {
+		            appendLog("55AA1F鍗忚瑙f瀽澶辫触: " + displayText);
+		        }
+		    } else if(displayText.startsWith("55AA01")) {                
+		        ParseResult result = Dell55AA01Parser.parse(displayText, "127.0.0.1", 0);
+		        if (result != null) {
+		            visualizationPanel.updatePosition(result.distance, 270, 0);                
+		            visualizationPanel.setTagId(result.tagId);
+		        } else {
+		            appendLog("55AA01鍗忚瑙f瀽澶辫触: " + displayText);
+		        }
+		    } else if(displayText.startsWith("55AA51")) {                
+		        Dell55AA51Parser.ParseResult result = Dell55AA51Parser.parse(displayText, "127.0.0.1", 0);
+		        if (result != null) {
+		            visualizationPanel.updatePosition(result.distance, result.horizontalAngle, result.signalStrength);                
+		            visualizationPanel.setTagId(result.tagId);
+		        } else {
+		            appendLog("55AA51鍗忚瑙f瀽澶辫触: " + displayText);
+		        }
+		    } else {
+		        // 濡傛灉涓嶆槸宸茬煡鍗忚锛岀洿鎺ヨ褰曞師濮嬫暟鎹�
+		        appendLog("鏈煡鍗忚: " + displayText);
+		    }
 
-			if (hexRadio.isSelected()) {				
-				appendLog(displayText);
-			} else {
-				if (displayText.startsWith("55AA1F")) {
-					Dell55AA1FParser.ParseResult result = Dell55AA1FParser.parse(displayText, "127.0.0.1", 0);								
-					// 浼樺寲锛氶噸鐢⊿tringBuilder瀵硅薄
-					displayBuilder.setLength(0);
-					displayBuilder.append("1F:")
-					.append(result.dataLength)
-					.append(",")
-					.append(result.messageType)
-					.append(",id:")
-					.append(result.tagId)
-					.append(",Dis:")
-					.append(result.distance)
-					.append("cm,Angle:")
-					.append(result.angle)
-					.append("掳,Signal:")
-					.append(result.signalQuality)
-					.append(",Button:")
-					.append(result.buttonPressed)
-					.append(",Power:")
-					.append(result.power);
-					appendLog(displayBuilder.toString());
-				}else if(displayText.startsWith("55AA01")) {            	
-					ParseResult result=Dell55AA01Parser.parse(displayText, "127.0.0.1", 0);
-					// 浼樺寲锛氶噸鐢⊿tringBuilder瀵硅薄
-					displayBuilder.setLength(0);
-					displayBuilder.append("55AA01 Seq:")
-					.append(result.sequenceNum)
-					.append(",Tagid:")
-					.append(result.tagId)
-					.append(",Anchorid:")
-					.append(result.anchorId)
-					.append(",Distance:")
-					.append(result.distance)
-					.append(",Power:")
-					.append(result.power)
-					.append(",Button:")
-					.append(result.buttonPressed);
-					appendLog(displayBuilder.toString());
-				}else {					
-					appendLog(displayText1);
-				}
-			}
+		    if (hexRadio.isSelected()) {                
+		        appendLog(displayText);
+		    } else {
+		        if (displayText.startsWith("55AA1F")) {
+		            Dell55AA1FParser.ParseResult result = Dell55AA1FParser.parse(displayText, "127.0.0.1", 0);
+		            if (result != null) {
+		                // 浼樺寲锛氶噸鐢⊿tringBuilder瀵硅薄
+		                displayBuilder.setLength(0);
+		                displayBuilder.append(result.tagId)
+		                .append(",Dis:")
+		                .append(result.distance)
+		                .append("cm,Angle:")
+		                .append(result.angle)
+		                .append("掳,Signal:")
+		                .append(result.signalQuality)
+		                .append(",Button:")
+		                .append(result.buttonPressed)
+		                .append(",Power:")
+		                .append(result.power);
+		                appendLog(displayBuilder.toString());
+		            }
+		        } else if(displayText.startsWith("55AA01")) {                
+		            ParseResult result = Dell55AA01Parser.parse(displayText, "127.0.0.1", 0);
+		            if (result != null) {
+		                // 浼樺寲锛氶噸鐢⊿tringBuilder瀵硅薄
+		                displayBuilder.setLength(0);
+		                displayBuilder.append("55AA01 Seq:")
+		                .append(result.sequenceNum)
+		                .append(",Tagid:")
+		                .append(result.tagId)
+		                .append(",Anchorid:")
+		                .append(result.anchorId)
+		                .append(",Distance:")
+		                .append(result.distance)
+		                .append(",Power:")
+		                .append(result.power)
+		                .append(",Button:")
+		                .append(result.buttonPressed);
+		                appendLog(displayBuilder.toString());
+		            }
+		        } else if(displayText.startsWith("55AA51")) {                
+		            Dell55AA51Parser.ParseResult result = Dell55AA51Parser.parse(displayText, "127.0.0.1", 0);
+		            if (result != null) {
+		                displayBuilder.setLength(0);
+		                displayBuilder.append(result.tagId)
+		                .append(",Dis:")
+		                .append(result.distance)
+		                .append("cm,HAngle:")
+		                .append(result.horizontalAngle)
+		                .append("掳,VAngle:")
+		                .append(result.verticalAngle)
+		                .append("掳,Signal:")
+		                .append(result.signalStrength)
+		                .append("掳,ASignal:")
+		                .append(result.angleConfidence)
+		                .append(",Power:")
+		                .append(result.tagBattery)
+		                .append("%,Status:")
+		                .append(result.deviceStatus);
+		                appendLog(displayBuilder.toString());
+		            }
+		        } else {                    
+		            appendLog(displayText1);
+		        }
+		    }
 		}
 
 		private void appendLog(String message) {
@@ -732,7 +804,8 @@
 			asciiRadio.setText(getString("ascii"));
 			hexSendCheckBox.setText(getString("hex_send"));
 			pairCheckBox.setText(getString("pair"));
-
+			// 鏇存柊閰嶅澶嶉�夋鐨勬彁绀轰俊鎭�
+		    updatePairCheckboxTooltip();
 			// 鏇存柊杈规鏍囬
 			updateBorderTitles(this);
 
diff --git a/src/home/Dell55AA1FParser.java b/src/home/Dell55AA1FParser.java
index ad2cdf4..31f2104 100644
--- a/src/home/Dell55AA1FParser.java
+++ b/src/home/Dell55AA1FParser.java
@@ -4,6 +4,7 @@
 public class Dell55AA1FParser {
     // 常量定义
     private static final String EXPECTED_HEADER = "55AA1F"; // 协议头
+    private static final int MIN_PACKET_LENGTH = 36; // 最小包长度(字符数): 固定字段18字节=36字符
     private static final int FIXED_FIELDS_LENGTH = 11; // 从标签ID到保留字段的固定长度(字节)
     private static final ThreadLocal<ParseResult> RESULT_CACHE = 
             ThreadLocal.withInitial(ParseResult::new);
@@ -44,6 +45,7 @@
      */
     public static ParseResult parse(String message, String ip, int port) {
         if (message == null || message.isEmpty()) {
+            System.err.println("Empty message from " + ip + ":" + port);
             return null;
         }
 
@@ -51,12 +53,22 @@
         char[] cleanedMessage = cleanMessage(message);
 
         if (cleanedMessage == null) {
+            System.err.println("Invalid characters in message from " + ip + ":" + port);
+            return null;
+        }
+
+        // 检查最小长度
+        if (cleanedMessage.length < MIN_PACKET_LENGTH) {
+            System.err.println("Message too short from " + ip + ":" + port + 
+                             ". Expected at least " + MIN_PACKET_LENGTH + 
+                             " characters, got " + cleanedMessage.length);
             return null;
         }
 
         // 协议头校验 (55AA1F)
         if (cleanedMessage.length < 6 || 
             !new String(cleanedMessage, 0, 6).equals(EXPECTED_HEADER)) {
+            System.err.println("Invalid header in message from " + ip + ":" + port);
             return null;
         }
 
@@ -68,13 +80,12 @@
             result.dataLength = HexUtils.fastHexToByte(cleanedMessage[6], cleanedMessage[7]);
             
             // 计算期望的总字符长度
-            int expectedCharLength = 8 + // 包头(4字符) + 消息类型(2字符) + 数据长度(2字符)
-                                    result.dataLength * 2 + // 数据部分
-                                    4; // 校验和(4字符)
+            int expectedCharLength = 14 + result.dataLength * 2; // 14=包头6+消息类型2+数据长度2+校验和4
 
-//            if (cleanedMessage.length != expectedCharLength) {
-//                System.err.println("Data length mismatch: expected " + expectedCharLength + 
-//                                 ", got " + cleanedMessage.length);
+//            if (cleanedMessage.length < expectedCharLength) {
+//                System.err.println("Incomplete message from " + ip + ":" + port + 
+//                                 ". Expected " + expectedCharLength + 
+//                                 " characters, got " + cleanedMessage.length);
 //                return null;
 //            }
 
@@ -83,6 +94,12 @@
 
             // 解析标签ID (位置8-11),直接取字符串
             result.tagId = new String(cleanedMessage, 8, 4);
+
+            // 检查是否有足够长度解析固定字段
+            if (cleanedMessage.length < 30) { // 需要至少15字节=30字符
+                System.err.println("Message too short for fixed fields from " + ip + ":" + port);
+                return null;
+            }
 
             // 解析距离 (位置12-15, 2字节小端整数)
             int distLow = HexUtils.fastHexToByte(cleanedMessage[12], cleanedMessage[13]);
@@ -111,7 +128,12 @@
 //            int userDataStart = 30;
 //            int userDataCharLength = (result.dataLength - FIXED_FIELDS_LENGTH) * 2;
 //            if (userDataCharLength > 0) {
-//                result.userData = new String(cleanedMessage, userDataStart, userDataCharLength);
+//                if (userDataStart + userDataCharLength <= cleanedMessage.length) {
+//                    result.userData = new String(cleanedMessage, userDataStart, userDataCharLength);
+//                } else {
+//                    System.err.println("User data truncated in message from " + ip + ":" + port);
+//                    result.userData = "";
+//                }
 //            } else {
 //                result.userData = "";
 //            }
diff --git a/src/home/Dell55AA51Parser.java b/src/home/Dell55AA51Parser.java
new file mode 100644
index 0000000..f40e10e
--- /dev/null
+++ b/src/home/Dell55AA51Parser.java
@@ -0,0 +1,228 @@
+package home;
+
+import java.util.Arrays;
+
+public class Dell55AA51Parser {
+    // 预期包头
+    private static final String EXPECTED_HEADER = "55AA51";
+    private static final ThreadLocal<ParseResult> RESULT_CACHE = 
+            ThreadLocal.withInitial(ParseResult::new);
+
+    // 解析结果类
+    public static class ParseResult {
+        public int dataLength;          // 数据长度(十进制)
+        public String baseStationId;    // 基站ID(2字节,低位在前)
+        public String tagId;            // 标签ID(2字节,低位在前)
+        public int packetSequence;      // 包序(十进制)
+        public int distance;            // 测距距离(十进制)
+        public int horizontalAngle;     // 水平角度(十进制)
+        public int verticalAngle;       // 俯仰角度(十进制,有符号)
+        public int signalStrength;      // 信号强度(十进制)
+        public int angleConfidence;     // 角度置信度(十进制)
+        public int tagBattery;          // 标签电量(十进制)
+        public int deviceStatus;        // 设备状态
+        public int airPressure;         // 气压值(十进制)
+        public String reserved;         // 保留字段
+        public String checksum;         // 校验和
+        
+        public void reset() {
+            dataLength = 0;
+            baseStationId = "";
+            tagId = "";
+            packetSequence = 0;
+            distance = 0;
+            horizontalAngle = 0;
+            verticalAngle = 0;
+            signalStrength = 0;
+            angleConfidence = 0;
+            tagBattery = 0;
+            deviceStatus = 0;
+            airPressure = 0;
+            reserved = "";
+            checksum = "";
+        }
+        
+        @Override
+        public String toString() {
+            return "ParseResult{" +
+                    "dataLength=" + dataLength +
+                    ", baseStationId='" + baseStationId + '\'' +
+                    ", tagId='" + tagId + '\'' +
+                    ", packetSequence=" + packetSequence +
+                    ", distance=" + distance +
+                    ", horizontalAngle=" + horizontalAngle +
+                    ", verticalAngle=" + verticalAngle +
+                    ", signalStrength=" + signalStrength +
+                    ", angleConfidence=" + angleConfidence +
+                    ", tagBattery=" + tagBattery +
+                    ", deviceStatus=" + deviceStatus +
+                    ", airPressure=" + airPressure +
+                    ", reserved='" + reserved + '\'' +
+                    ", checksum='" + checksum + '\'' +
+                    '}';
+        }
+    }
+
+    /**
+     * 解析55AA51数据包
+     * @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) {
+            return null;
+        }
+
+        // 检查包头 (55AA51)
+        if (cleanedMessage.length < 6 || 
+            !new String(cleanedMessage, 0, 6).equals(EXPECTED_HEADER)) {
+            return null;
+        }
+
+        ParseResult result = RESULT_CACHE.get();
+        result.reset();
+
+        try {
+            // 解析数据长度 (位置6-7),转换为十进制
+            result.dataLength = HexUtils.fastHexToByte(cleanedMessage[6], cleanedMessage[7]);
+            
+            // 计算期望的消息长度
+            int expectedCharLength = 6 + // 包头(3字节)
+                                    2 + // 数据长度(1字节)
+                                    result.dataLength * 2 + // 数据内容
+                                    4; // 校验和(2字节)
+
+            if (cleanedMessage.length != expectedCharLength) {
+                System.err.println("Data length mismatch: expected " + expectedCharLength + 
+                                 ", got " + cleanedMessage.length);
+                return null;
+            }
+
+            // 解析基站ID (位置8-11,2字节,低位在前)
+            int baseIdLow = HexUtils.fastHexToByte(cleanedMessage[8], cleanedMessage[9]);
+            int baseIdHigh = HexUtils.fastHexToByte(cleanedMessage[10], cleanedMessage[11]);
+            int baseIdValue = (baseIdHigh << 8) | baseIdLow;
+            result.baseStationId = String.valueOf(baseIdValue); // 转换为十进制字符串
+
+            // 解析标签ID (位置12-15,2字节,低位在前)
+            int tagIdLow = HexUtils.fastHexToByte(cleanedMessage[12], cleanedMessage[13]);
+            int tagIdHigh = HexUtils.fastHexToByte(cleanedMessage[14], cleanedMessage[15]);
+            int tagIdValue = (tagIdHigh << 8) | tagIdLow;
+            result.tagId = String.valueOf(tagIdValue); // 转换为十进制字符串
+
+            // 解析包序 (位置16-17),转换为十进制
+            result.packetSequence = HexUtils.fastHexToByte(cleanedMessage[16], cleanedMessage[17]);
+
+            // 解析测距距离 (位置18-21,2字节,低位在前),转换为十进制
+            int distLow = HexUtils.fastHexToByte(cleanedMessage[18], cleanedMessage[19]);
+            int distHigh = HexUtils.fastHexToByte(cleanedMessage[20], cleanedMessage[21]);
+            result.distance = (distHigh << 8) | distLow;
+
+            // 解析水平角度 (位置22-25,2字节,低位在前),转换为十进制
+            int hAngleLow = HexUtils.fastHexToByte(cleanedMessage[22], cleanedMessage[23]);
+            int hAngleHigh = HexUtils.fastHexToByte(cleanedMessage[24], cleanedMessage[25]);
+            result.horizontalAngle = (hAngleHigh << 8) | hAngleLow;
+
+            // 解析俯仰角度 (位置26-29,2字节,低位在前),转换为十进制
+            // 注意:这是有符号数,范围-180到180度
+            int vAngleLow = HexUtils.fastHexToByte(cleanedMessage[26], cleanedMessage[27]);
+            int vAngleHigh = HexUtils.fastHexToByte(cleanedMessage[28], cleanedMessage[29]);
+            short vAngleShort = (short) ((vAngleHigh << 8) | vAngleLow);
+            result.verticalAngle = vAngleShort;
+
+            // 解析信号强度 (位置30-31),转换为十进制
+            result.signalStrength = HexUtils.fastHexToByte(cleanedMessage[30], cleanedMessage[31]);
+
+            // 解析角度置信度 (位置32-33),转换为十进制
+            result.angleConfidence = HexUtils.fastHexToByte(cleanedMessage[32], cleanedMessage[33]);
+
+            // 解析标签电量 (位置34-35),转换为十进制
+            result.tagBattery = HexUtils.fastHexToByte(cleanedMessage[34], cleanedMessage[35]);
+
+            // 解析设备状态 (位置36-39,2字节,低位在前)
+            int statusLow = HexUtils.fastHexToByte(cleanedMessage[36], cleanedMessage[37]);
+            int statusHigh = HexUtils.fastHexToByte(cleanedMessage[38], cleanedMessage[39]);
+            result.deviceStatus = (statusHigh << 8) | statusLow;
+
+            // 解析气压值 (位置40-43,2字节,低位在前),转换为十进制
+            int pressureLow = HexUtils.fastHexToByte(cleanedMessage[40], cleanedMessage[41]);
+            int pressureHigh = HexUtils.fastHexToByte(cleanedMessage[42], cleanedMessage[43]);
+            result.airPressure = (pressureHigh << 8) | pressureLow;
+
+            // 解析保留字段 (位置44-51,4字节)
+            result.reserved = new String(cleanedMessage, 44, 8);
+
+            // 解析校验和 (最后4个字符)
+            result.checksum = new String(cleanedMessage, cleanedMessage.length - 4, 4);
+
+            // 验证校验和
+            byte[] packetBytes = hexStringToByteArray(new String(cleanedMessage));
+            if (!verifyChecksum(packetBytes)) {
+                System.err.println("Checksum verification failed for packet from " + ip + ":" + port);
+                return null;
+            }
+
+        } catch (IndexOutOfBoundsException | NumberFormatException e) {
+            System.err.println("Parsing error in 55AA51 packet from " + ip + ":" + port);
+            e.printStackTrace();
+            return null;
+        }
+
+        return result;
+    }
+
+    /**
+     * 将十六进制字符串转换为字节数组
+     */
+    private static byte[] hexStringToByteArray(String s) {
+        int len = s.length();
+        byte[] data = new byte[len / 2];
+        for (int i = 0; i < len; i += 2) {
+            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+                                 + Character.digit(s.charAt(i+1), 16));
+        }
+        return data;
+    }
+
+    /**
+     * 验证数据包校验和
+     * 从数据类型字段开始到保留字段结束,校验和为双字节补码
+     */
+    private static boolean verifyChecksum(byte[] packet) {
+        int len = packet.length;
+        if (len < 4) return false;
+
+        int sum = 0;
+        // 从数据类型字段开始到保留字段结束 (跳过包头2字节)
+        for (int i = 3; i < len - 2; i++) {
+            sum += packet[i] & 0xFF;
+        }
+        sum = ~sum & 0xFFFF; // 取反并保留16位
+
+        // 获取接收到的校验和 (低位在前)
+        int receivedChecksum = ((packet[len - 2] & 0xFF) << 8) | (packet[len - 1] & 0xFF);
+
+        return sum == receivedChecksum;
+    }
+
+    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);
+    }
+    
+    
+}
\ No newline at end of file
diff --git a/src/home/TagDell55AA03Parser.java b/src/home/TagDell55AA03Parser.java
new file mode 100644
index 0000000..4882e6a
--- /dev/null
+++ b/src/home/TagDell55AA03Parser.java
@@ -0,0 +1,236 @@
+package home;
+
+import java.util.Arrays;
+
+public class TagDell55AA03Parser {
+    // 预期报文头
+    private static final String EXPECTED_HEADER = "55AA03";
+    // 最小长度(根据文档,至少应有40个字段,每个字段2字节,加上包头和类型共4字节)
+    private static final int MIN_LENGTH = 84; // (4 + 40*2) * 2字符 = 168字符,但实际可能更多
+    
+    private static final ThreadLocal<ParseResult> RESULT_CACHE = 
+            ThreadLocal.withInitial(ParseResult::new);
+
+    // 解析结果类
+    public static class ParseResult {
+        public String header;          // 数据包头(55AA)
+        public int dataType;           // 数据类型(03)
+        public int dataLength;         // 数据长度
+        public String version;         // 版本号(XX.XX格式)
+        public int deviceId;           // 设备编号(小端序)
+        public int commFrequency;      // 通信频率(毫秒)
+        public int maxAnchors;         // 单次通信基站数
+        public int minAnchors;         // 小组编号/最少基站数
+        public int distanceCalibration;// 距离校准值
+        public int deviceType;         // 设备类型(0:基站, 1:标签)
+        public int anchorActiveRanging;// 基站主动测距
+        public int alarmDevice;        // 报警设备
+        public int imuIdleTime;        // IMU静止时间
+        public int pressureAnchorId;   // 气压基站编号
+        public int peripheralControl;  // 外设控制(1:打开RTK, 2:关闭RTK)
+        public int pairingId;          // 配对编号
+        public int uwbStatus;          // UWB开关状态(0:关闭)
+        public int modbusMode;         // MODBUS模式
+        public int vibrationDuration;  // 震动时长(秒)
+        public int[] neighborAnchorIds = new int[10]; // 临近基站ID(10个)
+        public int power;              // 功率
+        public int accelerometerThreshold; // 加速计阈值
+        public int idleSleepTime;      // 静止休眠时间
+        public int vibrationEnable;    // 震动使能
+        public int accelerometerEnable;// 加速计使能
+        public int configStatus;       // 标签下发配置状态
+        public int accelerometerDuration; // 加速计时长
+        public int activationStatus;   // 设备激活状态位(0:未激活, 1:激活)
+        public int syncAnchorType;     // 同步基站类型(0:不发同步, 1:主基站, 2:从基站)
+        public int speedFilterLimit;   // 速度滤波限值
+        public int pressureCalibration;// 气压高度校准值
+        
+        public void reset() {
+            header = "";
+            dataType = 0;
+            dataLength = 0;
+            version = "";
+            deviceId = 0;
+            commFrequency = 0;
+            maxAnchors = 0;
+            minAnchors = 0;
+            distanceCalibration = 0;
+            deviceType = 0;
+            anchorActiveRanging = 0;
+            alarmDevice = 0;
+            imuIdleTime = 0;
+            pressureAnchorId = 0;
+            peripheralControl = 0;
+            pairingId = 0;
+            uwbStatus = 0;
+            modbusMode = 0;
+            vibrationDuration = 0;
+            Arrays.fill(neighborAnchorIds, 0);
+            power = 0;
+            accelerometerThreshold = 0;
+            idleSleepTime = 0;
+            vibrationEnable = 0;
+            accelerometerEnable = 0;
+            configStatus = 0;
+            accelerometerDuration = 0;
+            activationStatus = 0;
+            syncAnchorType = 0;
+            speedFilterLimit = 0;
+            pressureCalibration = 0;
+        }
+    }
+
+    /**
+     * 解析55AA03协议报文
+     * @param message 接收到的十六进制字符串
+     * @return 解析结果(解析失败返回null)
+     */
+    public static ParseResult parse(String message, String ip, int port) {
+        if (message == null || message.isEmpty()) {
+            return null;
+        }
+
+        // 清理消息:只保留数字和A-F字符
+        char[] cleanedMessage = cleanMessage(message);
+
+        // 检查最小长度
+        if (cleanedMessage == null || cleanedMessage.length < MIN_LENGTH) {
+            return null;
+        }
+
+        // 检查报文头 (55AA03)
+        if (!new String(cleanedMessage, 0, 6).equals(EXPECTED_HEADER)) {
+            return null;
+        }
+
+        ParseResult result = RESULT_CACHE.get();
+        result.reset();
+
+        try {
+            // 设置包头和数据类型
+            result.header = new String(cleanedMessage, 0, 4);
+            result.dataType = HexUtils.fastHexToByte(cleanedMessage[4], cleanedMessage[5]);
+            
+            // 解析数据长度 (位置6-7)
+            result.dataLength = HexUtils.fastHexToByte(cleanedMessage[6], cleanedMessage[7]);
+            
+            // 解析版本号 (位置8-11, 形如XX.XX)
+            int versionPart1 = HexUtils.fastHexToByte(cleanedMessage[8], cleanedMessage[9]);
+            int versionPart2 = HexUtils.fastHexToByte(cleanedMessage[10], cleanedMessage[11]);
+            result.version = String.format("%d.%02d", versionPart1, versionPart2);
+            
+            // 解析设备编号 (位置12-15, 低位在前)
+            result.deviceId = parseLittleEndian(cleanedMessage, 12);
+            
+            // 解析通信频率 (位置16-19)
+            result.commFrequency = parseLittleEndian(cleanedMessage, 16);
+            
+            // 解析单次通信基站数 (位置20-23)
+            result.maxAnchors = parseLittleEndian(cleanedMessage, 20);
+            
+            // 解析小组编号/最少基站数 (位置24-27)
+            result.minAnchors = parseLittleEndian(cleanedMessage, 24);
+            
+            // 解析距离校准值 (位置28-31)
+            result.distanceCalibration = parseLittleEndian(cleanedMessage, 28);
+            
+            // 解析设备类型 (位置32-35, 0:基站, 1:标签)
+            result.deviceType = parseLittleEndian(cleanedMessage, 32);
+            
+            // 解析基站主动测距 (位置36-39)
+            result.anchorActiveRanging = parseLittleEndian(cleanedMessage, 36);
+            
+            // 解析报警设备 (位置40-43)
+            result.alarmDevice = parseLittleEndian(cleanedMessage, 40);
+            
+            // 解析IMU静止时间 (位置44-47)
+            result.imuIdleTime = parseLittleEndian(cleanedMessage, 44);
+            
+            // 解析气压基站编号 (位置48-51)
+            result.pressureAnchorId = parseLittleEndian(cleanedMessage, 48);
+            
+            // 解析外设控制 (位置52-55, 1:打开RTK, 2:关闭RTK)
+            result.peripheralControl = parseLittleEndian(cleanedMessage, 52);
+            
+            // 解析配对编号 (位置56-59)
+            result.pairingId = parseLittleEndian(cleanedMessage, 56);
+            
+            // 解析UWB开关状态 (位置60-63, 0:关闭)
+            result.uwbStatus = parseLittleEndian(cleanedMessage, 60);
+            
+            // 解析MODBUS模式 (位置64-67)
+            result.modbusMode = parseLittleEndian(cleanedMessage, 64);
+            
+            // 解析震动时长 (位置68-71, 单位秒)
+            result.vibrationDuration = parseLittleEndian(cleanedMessage, 68);
+            
+            // 解析临近基站ID (位置72-111, 10个基站)
+            for (int i = 0; i < 10; i++) {
+                result.neighborAnchorIds[i] = parseLittleEndian(cleanedMessage, 72 + i * 4);
+            }
+            
+            // 解析功率 (位置112-115)
+            result.power = parseLittleEndian(cleanedMessage, 112);
+            
+            // 解析加速计阈值 (位置116-119)
+            result.accelerometerThreshold = parseLittleEndian(cleanedMessage, 116);
+            
+            // 解析静止休眠时间 (位置120-123)
+            result.idleSleepTime = parseLittleEndian(cleanedMessage, 120);
+            
+            // 解析震动使能 (位置124-127)
+            result.vibrationEnable = parseLittleEndian(cleanedMessage, 124);
+            
+            // 解析加速计使能 (位置128-131)
+            result.accelerometerEnable = parseLittleEndian(cleanedMessage, 128);
+            
+            // 解析标签下发配置状态 (位置132-135)
+            result.configStatus = parseLittleEndian(cleanedMessage, 132);
+            
+            // 解析加速计时长 (位置136-139)
+            result.accelerometerDuration = parseLittleEndian(cleanedMessage, 136);
+            
+            // 解析设备激活状态位 (位置140-143, 0:未激活, 1:激活)
+            result.activationStatus = parseLittleEndian(cleanedMessage, 140);
+            
+            // 解析同步基站类型 (位置144-147, 0:不发同步, 1:主基站, 2:从基站)
+            result.syncAnchorType = parseLittleEndian(cleanedMessage, 144);
+            
+            // 解析速度滤波限值 (位置148-151)
+            result.speedFilterLimit = parseLittleEndian(cleanedMessage, 148);
+            
+            // 解析气压高度校准值 (位置152-155)
+            result.pressureCalibration = parseLittleEndian(cleanedMessage, 152);
+            
+        } catch (IndexOutOfBoundsException | NumberFormatException e) {
+            System.err.println("Parsing error in packet from " + ip + ":" + port);
+            return null;
+        }
+
+        return result;
+    }
+
+    /**
+     * 解析小端序的16位整数(4个字符)
+     */
+    private static int parseLittleEndian(char[] message, int startIndex) {
+        int lowByte = HexUtils.fastHexToByte(message[startIndex], message[startIndex + 1]);
+        int highByte = HexUtils.fastHexToByte(message[startIndex + 2], message[startIndex + 3]);
+        return (highByte << 8) | lowByte;
+    }
+
+    /**
+     * 清理消息,只保留十六进制字符
+     */
+    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);
+    }
+}
\ No newline at end of file
diff --git a/src/home/VisualizationPanel.java b/src/home/VisualizationPanel.java
index 8b24e30..47e2180 100644
--- a/src/home/VisualizationPanel.java
+++ b/src/home/VisualizationPanel.java
@@ -4,11 +4,16 @@
 import java.awt.Font;
 import java.awt.Graphics;
 import java.awt.Graphics2D;
+import java.awt.Image;
 import java.awt.RenderingHints;
+
+import javax.imageio.ImageIO;
 import javax.swing.BorderFactory;
 import javax.swing.JPanel;
 import java.awt.event.MouseWheelEvent;
 import java.awt.event.MouseWheelListener;
+import java.io.File;
+import java.io.IOException;
 
 // 可视化面板类
 class VisualizationPanel extends JPanel {
@@ -30,12 +35,20 @@
     private Font boldFont = new Font("Microsoft YaHei", Font.BOLD, 14);
     private Font normalFont = new Font("Microsoft YaHei", Font.PLAIN, 12);
     private Font titleFont = new Font("Microsoft YaHei", Font.BOLD, 12);
+    private Image logoImage; // 添加图片变量
     
     public VisualizationPanel(AOAFollowSystem parentFrame) {
         this.parentFrame = parentFrame;
         setPreferredSize(new Dimension(400, 400));
         setBorder(BorderFactory.createTitledBorder(parentFrame.getString("visualization")));
         
+     // 加载图片
+        try {
+            logoImage = ImageIO.read(new File("systemfile/1.png"));
+        } catch (IOException e) {
+            System.err.println("无法加载图片: systemfile/1.png");
+            e.printStackTrace();
+        }
         // 添加鼠标滚轮监听器
         addMouseWheelListener(new MouseWheelListener() {
             @Override
@@ -84,11 +97,22 @@
 
         int centerX = getWidth() / 2;
         int centerY = getHeight()/ 2 - 30;
-        int maxRadius = (int) (Math.min(centerX, centerY) * scaleFactor - 20);
+        int baseRadius = Math.min(centerX, centerY) - 20; // 基础半径(不缩放)
+        int maxRadius = (int) (baseRadius * scaleFactor); // 缩放后的半径
 
         // 设置背景颜色
         g2d.setColor(new Color(240, 240, 240));
         g2d.fillRect(0, 0, getWidth(), getHeight());
+        
+     // 在左下角绘制图片
+        if (logoImage != null) {
+            int imgWidth = logoImage.getWidth(this);
+            int imgHeight = logoImage.getHeight(this);
+            // 调整图片大小,使其适合面板
+            int scaledWidth =150; // 设置图片宽度
+            int scaledHeight = (int) (imgHeight * (scaledWidth * 1.0 / imgWidth)); // 按比例计算高度
+            g2d.drawImage(logoImage, 5, getHeight() - scaledHeight - 5, scaledWidth, scaledHeight, this);
+        }
 
         // 绘制坐标轴
         g2d.setColor(Color.LIGHT_GRAY);
@@ -123,8 +147,8 @@
         for (int i = 1; i <= 5; i++) {
             int radius = maxRadius * i / 5;
             g2d.drawOval(centerX - radius, centerY - radius, radius * 2, radius * 2);
-            // 修改:将距离标签显示在圆圈正南方中间
-            String distanceLabel = (int)(i * 200 * scaleFactor) + "cm"; // 修改:乘以scaleFactor而不是除以
+            // 修改:距离标签不随缩放变化,保持实际距离
+            String distanceLabel = i * 200 + "cm";
             int labelWidth = g2d.getFontMetrics().stringWidth(distanceLabel);
             g2d.drawString(distanceLabel, centerX - labelWidth / 2, centerY + radius + 15);
         }
@@ -140,7 +164,7 @@
         // 绘制B点(标签点)
         if (distance > 0) {
             // 根据距离计算缩放比例(最大1000厘米)
-            double scaledDistance = Math.min(distance, 1000) * maxRadius / 1000.0 ; // 修改:添加乘以scaleFactor
+            double scaledDistance = Math.min(distance, 1000) * maxRadius / 1000.0;
             
             // 将导航角度转换为数学角度(从正东方向开始,逆时针为正)
             double mathAngle = 90 - angle; // 导航角度转换为数学角度
@@ -162,13 +186,7 @@
             g2d.setFont(boldFont);
             g2d.setColor(Color.RED);
             
-            // 计算文本位置(B点正下方)
-            int textY = bY + 25;
-            g2d.drawString(distanceText, bX - g2d.getFontMetrics().stringWidth(distanceText)/2, textY);
-            g2d.drawString(angleText, bX - g2d.getFontMetrics().stringWidth(angleText)/2, textY + 20);
             
-            // 恢复原始字体
-            g2d.setFont(normalFont);
 
             // 在面板底部显示距离和角度信息 - 实时获取字符串,不使用缓存
             g2d.setFont(boldFont);
@@ -179,18 +197,30 @@
             g2d.drawString(parentFrame.getString("signal") + signalQuality, 10, 100);
             g2d.setFont(normalFont);
             g2d.setColor(Color.BLUE);
-            g2d.fillOval(bX - 5, bY - 5, 10, 10);
+            g2d.fillOval(bX -10, bY -10, 20, 20);
             
             // B点正上方显示设备编号
             g2d.setFont(titleFont);
-            g2d.drawString(tagid, bX - g2d.getFontMetrics().stringWidth(tagid)/2, bY - 15);
+            g2d.setColor(Color.BLUE);
+            g2d.drawString(tagid, bX - g2d.getFontMetrics().stringWidth(tagid)/2, bY - 25);
             g2d.setFont(normalFont);
+            
+         // 计算文本位置(B点正下方)
+            int textY = bY + 25;
+            g2d.setColor(Color.BLUE);
+            g2d.drawString(distanceText, bX - g2d.getFontMetrics().stringWidth(distanceText)/2, textY);
+            g2d.drawString(angleText, bX - g2d.getFontMetrics().stringWidth(angleText)/2, textY + 20);
+            g2d.setFont(normalFont);
+            
+            
             
         }
         
         // 显示当前缩放比例
         g2d.setColor(Color.DARK_GRAY);
-        g2d.drawString(String.format("缩放: %.1fx", scaleFactor), getWidth() - 80, 20);
+        g2d.drawString(String.format("%s: %.1fx", parentFrame.getString("scale"), scaleFactor), getWidth() - 80, 20);
+    
+     
     }
 
     public void updateLanguage() {
diff --git a/systemfile/1.png b/systemfile/1.png
new file mode 100644
index 0000000..07830e5
--- /dev/null
+++ b/systemfile/1.png
Binary files differ
diff --git a/systemfile/Messages_en.properties b/systemfile/Messages_en.properties
index 002aef8..c178b19 100644
--- a/systemfile/Messages_en.properties
+++ b/systemfile/Messages_en.properties
@@ -48,4 +48,7 @@
 hex=HEX
 ascii=ASCII
 hex_send=HEX Send
-close_serial=Close Serial
\ No newline at end of file
+close_serial=Close Serial
+signal=Signal:
+pair=Pair
+pair_tooltip=Enter 20-second pairing mode after clicking send
\ No newline at end of file
diff --git a/systemfile/Messages_zh.properties b/systemfile/Messages_zh.properties
index 2cb98e5..ef70e9e 100644
--- a/systemfile/Messages_zh.properties
+++ b/systemfile/Messages_zh.properties
@@ -48,4 +48,7 @@
 hex=HEX
 ascii=ASCII
 hex_send=HEX鍙戦��
-close_serial=鍏抽棴涓插彛
\ No newline at end of file
+close_serial=鍏抽棴涓插彛
+signal=淇″彿锛�
+pair=閰嶅
+pair_tooltip=鐐瑰嚮鍙戦�佸悗杩涘叆20绉掗厤瀵规ā寮�
\ No newline at end of file
diff --git a/systemfile/logfile/openlog.txt b/systemfile/logfile/openlog.txt
index 59defae..4b9c4e7 100644
--- a/systemfile/logfile/openlog.txt
+++ b/systemfile/logfile/openlog.txt
@@ -380,3 +380,223 @@
 工作时长: 1小时 9分钟 40秒
 -----------------------------------
 程序启动: 2025-08-26 17:12:20
+程序关闭: 2025-08-26 17:22:39
+工作时长: 0小时 10分钟 18秒
+-----------------------------------
+程序启动: 2025-08-26 17:22:41
+程序启动: 2025-08-26 21:05:09
+程序关闭: 2025-08-26 21:27:08
+工作时长: 0小时 21分钟 58秒
+-----------------------------------
+程序启动: 2025-08-26 21:29:00
+程序关闭: 2025-08-26 21:29:29
+工作时长: 0小时 0分钟 29秒
+-----------------------------------
+程序启动: 2025-08-26 21:29:42
+程序关闭: 2025-08-26 21:35:17
+工作时长: 0小时 5分钟 35秒
+-----------------------------------
+程序启动: 2025-08-26 21:35:22
+程序关闭: 2025-08-26 21:35:38
+工作时长: 0小时 0分钟 16秒
+-----------------------------------
+程序启动: 2025-08-26 21:35:48
+程序启动: 2025-08-26 21:40:46
+程序启动: 2025-08-26 21:40:46
+程序关闭: 2025-08-26 21:48:25
+工作时长: 0小时 12分钟 36秒
+-----------------------------------
+程序启动: 2025-08-26 21:56:14
+程序关闭: 2025-08-26 21:58:13
+工作时长: 0小时 1分钟 58秒
+-----------------------------------
+程序启动: 2025-08-26 21:58:15
+程序关闭: 2025-08-26 21:58:35
+工作时长: 0小时 0分钟 20秒
+-----------------------------------
+程序启动: 2025-08-26 21:59:03
+程序启动: 2025-08-26 22:14:47
+程序关闭: 2025-08-26 22:14:51
+工作时长: 0小时 15分钟 47秒
+-----------------------------------
+程序启动: 2025-08-26 22:14:53
+程序关闭: 2025-08-26 22:23:31
+工作时长: 0小时 8分钟 38秒
+-----------------------------------
+程序启动: 2025-08-26 22:28:20
+程序关闭: 2025-08-26 22:30:20
+工作时长: 0小时 2分钟 0秒
+-----------------------------------
+程序启动: 2025-08-26 22:37:12
+程序关闭: 2025-08-26 22:37:24
+工作时长: 0小时 0分钟 11秒
+-----------------------------------
+程序启动: 2025-08-26 22:39:02
+程序启动: 2025-08-26 22:40:39
+程序关闭: 2025-08-26 22:40:44
+工作时长: 0小时 1分钟 41秒
+-----------------------------------
+程序启动: 2025-08-26 22:40:46
+程序关闭: 2025-08-26 22:41:08
+工作时长: 0小时 0分钟 22秒
+-----------------------------------
+程序启动: 2025-08-26 22:44:30
+程序关闭: 2025-08-26 22:45:02
+工作时长: 0小时 0分钟 32秒
+-----------------------------------
+程序启动: 2025-08-26 22:45:54
+程序关闭: 2025-08-26 22:47:55
+工作时长: 0小时 2分钟 1秒
+-----------------------------------
+程序启动: 2025-08-26 22:47:58
+程序关闭: 2025-08-26 22:48:09
+工作时长: 0小时 0分钟 10秒
+-----------------------------------
+程序启动: 2025-08-26 22:52:06
+程序启动: 2025-08-26 22:52:52
+程序关闭: 2025-08-26 22:52:56
+工作时长: 0小时 0分钟 50秒
+-----------------------------------
+程序启动: 2025-08-26 22:52:57
+程序关闭: 2025-08-26 22:54:36
+工作时长: 0小时 1分钟 38秒
+-----------------------------------
+程序启动: 2025-08-26 22:55:43
+程序关闭: 2025-08-26 22:56:31
+工作时长: 0小时 0分钟 48秒
+-----------------------------------
+程序启动: 2025-08-26 23:00:05
+程序关闭: 2025-08-26 23:01:59
+工作时长: 0小时 1分钟 53秒
+-----------------------------------
+程序启动: 2025-08-27 07:28:02
+程序关闭: 2025-08-27 07:38:02
+工作时长: 0小时 10分钟 0秒
+-----------------------------------
+程序启动: 2025-08-27 07:38:04
+程序关闭: 2025-08-27 07:38:33
+工作时长: 0小时 0分钟 28秒
+-----------------------------------
+程序启动: 2025-08-27 07:45:36
+程序关闭: 2025-08-27 07:45:46
+工作时长: 0小时 0分钟 10秒
+-----------------------------------
+程序启动: 2025-08-27 07:46:16
+程序关闭: 2025-08-27 07:48:27
+工作时长: 0小时 2分钟 11秒
+-----------------------------------
+程序启动: 2025-08-27 07:48:29
+程序关闭: 2025-08-27 07:48:40
+工作时长: 0小时 0分钟 10秒
+-----------------------------------
+程序启动: 2025-08-27 07:49:58
+程序关闭: 2025-08-27 07:50:13
+工作时长: 0小时 0分钟 14秒
+-----------------------------------
+程序启动: 2025-08-27 07:54:23
+程序关闭: 2025-08-27 08:00:10
+工作时长: 0小时 5分钟 46秒
+-----------------------------------
+程序启动: 2025-08-27 08:00:12
+程序关闭: 2025-08-27 08:07:42
+工作时长: 0小时 7分钟 30秒
+-----------------------------------
+程序启动: 2025-08-27 08:07:44
+程序关闭: 2025-08-27 08:29:47
+工作时长: 0小时 22分钟 2秒
+-----------------------------------
+程序启动: 2025-08-27 08:29:50
+程序关闭: 2025-08-27 08:30:13
+工作时长: 0小时 0分钟 22秒
+-----------------------------------
+程序启动: 2025-08-27 22:07:56
+程序关闭: 2025-08-27 22:08:12
+工作时长: 0小时 0分钟 15秒
+-----------------------------------
+程序启动: 2025-08-27 22:09:24
+程序关闭: 2025-08-27 22:09:41
+工作时长: 0小时 0分钟 16秒
+-----------------------------------
+程序启动: 2025-08-27 22:09:59
+程序关闭: 2025-08-27 22:10:10
+工作时长: 0小时 0分钟 10秒
+-----------------------------------
+程序启动: 2025-08-27 22:10:34
+程序关闭: 2025-08-27 22:10:37
+工作时长: 0小时 0分钟 3秒
+-----------------------------------
+程序启动: 2025-08-27 22:10:42
+程序关闭: 2025-08-27 22:10:53
+工作时长: 0小时 0分钟 10秒
+-----------------------------------
+程序启动: 2025-08-27 22:11:22
+程序关闭: 2025-08-27 22:12:30
+工作时长: 0小时 1分钟 7秒
+-----------------------------------
+程序启动: 2025-08-27 22:13:23
+程序关闭: 2025-08-27 22:13:56
+工作时长: 0小时 0分钟 32秒
+-----------------------------------
+程序启动: 2025-08-27 22:15:06
+程序启动: 2025-08-27 22:16:54
+程序关闭: 2025-08-27 22:17:02
+工作时长: 0小时 0分钟 8秒
+-----------------------------------
+程序启动: 2025-08-27 22:18:07
+程序关闭: 2025-08-27 22:18:25
+工作时长: 0小时 0分钟 18秒
+-----------------------------------
+程序启动: 2025-08-27 22:18:38
+程序关闭: 2025-08-27 22:19:08
+工作时长: 0小时 0分钟 30秒
+-----------------------------------
+程序启动: 2025-08-27 22:19:33
+程序关闭: 2025-08-27 22:19:45
+工作时长: 0小时 0分钟 12秒
+-----------------------------------
+程序启动: 2025-08-27 22:20:55
+程序关闭: 2025-08-27 22:21:18
+工作时长: 0小时 0分钟 22秒
+-----------------------------------
+程序启动: 2025-08-27 22:22:15
+程序关闭: 2025-08-27 22:22:36
+工作时长: 0小时 0分钟 21秒
+-----------------------------------
+程序启动: 2025-08-27 22:24:27
+程序启动: 2025-08-27 22:36:01
+程序关闭: 2025-08-27 22:36:04
+工作时长: 0小时 11分钟 37秒
+-----------------------------------
+程序启动: 2025-08-27 22:36:05
+程序关闭: 2025-08-27 22:36:07
+工作时长: 0小时 0分钟 1秒
+-----------------------------------
+程序启动: 2025-08-27 22:36:59
+程序关闭: 2025-08-27 22:37:13
+工作时长: 0小时 0分钟 14秒
+-----------------------------------
+程序启动: 2025-08-27 22:43:27
+程序启动: 2025-08-27 22:45:39
+程序关闭: 2025-08-27 22:45:43
+工作时长: 0小时 2分钟 15秒
+-----------------------------------
+程序启动: 2025-08-27 22:45:45
+程序关闭: 2025-08-27 22:45:54
+工作时长: 0小时 0分钟 9秒
+-----------------------------------
+程序启动: 2025-08-27 22:48:06
+程序关闭: 2025-08-27 22:49:36
+工作时长: 0小时 1分钟 29秒
+-----------------------------------
+程序启动: 2025-08-27 22:49:38
+程序关闭: 2025-08-27 22:49:43
+工作时长: 0小时 0分钟 5秒
+-----------------------------------
+程序启动: 2025-08-27 22:50:11
+程序关闭: 2025-08-27 22:50:25
+工作时长: 0小时 0分钟 13秒
+-----------------------------------
+程序启动: 2025-08-27 22:51:03
+程序关闭: 2025-08-27 22:51:23
+工作时长: 0小时 0分钟 20秒
+-----------------------------------

--
Gitblit v1.9.3