src/Dell55aa/Dell55AA01.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/Dell55aa/Dell55AA12HighPerf.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/dell55AAData/Dell55AA01Parser.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/dell55AAData/Dell55AA12HighPerf.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/dell55AAData/HexUtils.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/dell55AAData/PacketParser.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/dell_system/SerialCommPanel.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
systemfile/Messages_zh.properties | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
systemfile/logfile/openlog.txt | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
src/Dell55aa/Dell55AA01.java
ÎļþÒÑɾ³ý src/Dell55aa/Dell55AA12HighPerf.java
ÎļþÒÑɾ³ý 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; } } 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]); } } } 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; } } 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(); } } 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; @@ -330,94 +329,24 @@ 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()); 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)); } 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()); 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æ¹æ³ systemfile/Messages_zh.properties
@@ -1,13 +1,13 @@ # æ°å¢èµæºé®å¼å¯¹ 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=鿢 @@ -15,10 +15,10 @@ status.vibration=éå¨ status.uwb_switch=UWBå¼å ³ parser.ready=è§£æå¨: 就绪 yes=æ¯ no=å¦ on=å¼ off=å ³ yes=1 no=0 on=1 off=0 ENABLE_PARSING=Enable Parsing PARSER=Parser EXPORT=Export 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ç§ -----------------------------------