From 559890c482f5973f06aafdfec9550fee5ba3c7f2 Mon Sep 17 00:00:00 2001
From: wenxiangchao <wenxiangchao@ihengxin.com.cn>
Date: 星期一, 09 十一月 2026 17:02:15 +0800
Subject: [PATCH] feat: CAN 模拟器 TCP 化 + 多设备并发调试 + 后台生命周期管理

---
 docs/DeviceConfig_DeviceDebug_Architecture.html |  660 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 660 insertions(+), 0 deletions(-)

diff --git a/docs/DeviceConfig_DeviceDebug_Architecture.html b/docs/DeviceConfig_DeviceDebug_Architecture.html
new file mode 100644
index 0000000..5bf9a25
--- /dev/null
+++ b/docs/DeviceConfig_DeviceDebug_Architecture.html
@@ -0,0 +1,660 @@
+<!DOCTYPE html>
+<html lang="zh-CN">
+<head>
+<meta charset="UTF-8">
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<title>浠櫒娉ㄥ唽涓庣‖浠惰皟璇曡皟鐢ㄥ叧绯绘⒊鐞�</title>
+<script src="https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.min.js"></script>
+<style>
+    * { box-sizing: border-box; }
+    body {
+        font-family: -apple-system, "Segoe UI", "Microsoft YaHei", "PingFang SC", sans-serif;
+        max-width: 1200px;
+        margin: 0 auto;
+        padding: 32px 24px 80px;
+        background: #FAFAFA;
+        color: #212121;
+        line-height: 1.75;
+    }
+    h1 {
+        font-size: 32px;
+        color: #1565C0;
+        border-bottom: 3px solid #1976D2;
+        padding-bottom: 12px;
+        margin-bottom: 8px;
+    }
+    h2 {
+        font-size: 24px;
+        color: #0D47A1;
+        margin-top: 40px;
+        padding-left: 12px;
+        border-left: 4px solid #FF9800;
+    }
+    h3 {
+        font-size: 18px;
+        color: #37474F;
+        margin-top: 24px;
+    }
+    .subtitle {
+        color: #757575;
+        font-size: 14px;
+        margin-bottom: 24px;
+    }
+    .card {
+        background: white;
+        border-radius: 8px;
+        padding: 20px 24px;
+        margin: 16px 0;
+        box-shadow: 0 2px 8px rgba(0,0,0,0.06);
+    }
+    .highlight {
+        background: #FFF8E1;
+        border-left: 4px solid #FFC107;
+        padding: 12px 16px;
+        margin: 12px 0;
+        border-radius: 4px;
+    }
+    .info {
+        background: #E3F2FD;
+        border-left: 4px solid #2196F3;
+        padding: 12px 16px;
+        margin: 12px 0;
+        border-radius: 4px;
+    }
+    .success {
+        background: #E8F5E9;
+        border-left: 4px solid #4CAF50;
+        padding: 12px 16px;
+        margin: 12px 0;
+        border-radius: 4px;
+    }
+    table {
+        width: 100%;
+        border-collapse: collapse;
+        margin: 16px 0;
+        background: white;
+        border-radius: 6px;
+        overflow: hidden;
+        box-shadow: 0 1px 4px rgba(0,0,0,0.06);
+    }
+    th {
+        background: #1976D2;
+        color: white;
+        padding: 12px 14px;
+        text-align: left;
+        font-weight: 600;
+    }
+    td {
+        padding: 10px 14px;
+        border-bottom: 1px solid #EEEEEE;
+    }
+    tr:nth-child(even) td { background: #FAFAFA; }
+    tr:hover td { background: #E3F2FD; }
+    code {
+        font-family: "Consolas", "Monaco", monospace;
+        background: #F5F5F5;
+        color: #C62828;
+        padding: 2px 6px;
+        border-radius: 3px;
+        font-size: 13px;
+    }
+    pre {
+        background: #263238;
+        color: #ECEFF1;
+        padding: 16px 20px;
+        border-radius: 6px;
+        overflow-x: auto;
+        font-family: "Consolas", "Monaco", monospace;
+        font-size: 13px;
+        line-height: 1.6;
+    }
+    pre code {
+        background: transparent;
+        color: inherit;
+        padding: 0;
+    }
+    .mermaid {
+        background: white;
+        padding: 20px;
+        border-radius: 8px;
+        margin: 20px 0;
+        text-align: center;
+        box-shadow: 0 2px 8px rgba(0,0,0,0.06);
+        overflow-x: auto;
+    }
+    ul { padding-left: 22px; }
+    li { margin: 4px 0; }
+    .badge {
+        display: inline-block;
+        padding: 2px 8px;
+        border-radius: 10px;
+        font-size: 12px;
+        font-weight: 600;
+        margin: 0 3px;
+    }
+    .badge-write { background: #FFCDD2; color: #B71C1C; }
+    .badge-read { background: #C8E6C9; color: #1B5E20; }
+    .badge-api { background: #BBDEFB; color: #0D47A1; }
+    .toc {
+        background: #F5F5F5;
+        padding: 16px 24px;
+        border-radius: 6px;
+        margin: 20px 0;
+    }
+    .toc a {
+        color: #1976D2;
+        text-decoration: none;
+        display: block;
+        padding: 4px 0;
+    }
+    .toc a:hover { text-decoration: underline; }
+    .arrow { color: #FF9800; font-weight: bold; }
+    .flow-step {
+        background: white;
+        border: 1px solid #E0E0E0;
+        border-radius: 6px;
+        padding: 12px 16px;
+        margin: 8px 0;
+    }
+    .flow-step strong { color: #1976D2; }
+    footer {
+        margin-top: 60px;
+        padding-top: 20px;
+        border-top: 1px solid #E0E0E0;
+        color: #757575;
+        font-size: 12px;
+        text-align: center;
+    }
+</style>
+</head>
+<body>
+
+<h1>浠櫒娉ㄥ唽 &amp; 纭欢璋冭瘯 璋冪敤鍏崇郴姊崇悊</h1>
+<div class="subtitle">TapProject 路 Plugin.DeviceConfig 鈫� Plugin.DeviceDebug 浜や簰鏋舵瀯璇存槑</div>
+
+<div class="toc">
+    <strong>鐩綍</strong>
+    <a href="#sec1">1. 鏁翠綋鏋舵瀯锛堜笁灞傦級</a>
+    <a href="#sec2">2. 鏁版嵁灞傝�﹀悎锛氫袱涓彃浠堕�氳繃 data.db 鍏变韩</a>
+    <a href="#sec3">3. 瀹屾暣璋冪敤閾捐矾锛堢敤鎴疯瑙掞級</a>
+    <a href="#sec4">4. 鍏抽敭鎺ュ彛渚濊禆锛圓ging.Infrastructure锛�</a>
+    <a href="#sec5">5. 浼氳瘽鐘舵�佹満锛堣法妯″潡鐨勬牳蹇冨崗璋冪偣锛�</a>
+    <a href="#sec6">6. 闆嗘垚娴嬭瘯椤圭洰閲岀殑缁勫悎婕旂ず</a>
+    <a href="#sec7">7. 鏃跺簭鍥撅細瀹屾暣鏁版嵁娴佸姩</a>
+    <a href="#sec8">8. 鏍稿績璁捐鎬濇兂</a>
+</div>
+
+<!-- ========== Section 1 ========== -->
+<h2 id="sec1">1. 鏁翠綋鏋舵瀯锛堜笁灞傦級</h2>
+
+<div class="mermaid">
+graph TB
+    subgraph UI灞俒"UI 灞� - Plugin.*"]
+        A["Plugin.DeviceConfig<br/>浠櫒浠〃娉ㄥ唽"]
+        B["Plugin.DeviceDebug<br/>纭欢璋冭瘯"]
+        B1["PowerSupplyDebugPanel"]
+        B2["CanDebugPanel"]
+        B3["PlcDebugPanel"]
+    end
+
+    subgraph 鍩虹璁炬柦灞俒"Aging.Infrastructure<br/>鍏变韩鍩虹璁炬柦"]
+        C["IDeviceManager<br/>璁惧鐢熷懡鍛ㄦ湡"]
+        D["IDeviceService<br/>鍛戒护鎵ц"]
+        E["IResourceManager<br/>璧勬簮棰勭害/绉熺害"]
+        F["DebugSessionManager<br/>璋冭瘯浼氳瘽鐘舵�佹満"]
+        G["DriverFactory<br/>椹卞姩宸ュ巶"]
+        H["IDeviceDriver<br/>CAN/ModBus/S7/SCPI/Tcp"]
+    end
+
+    subgraph 鏁版嵁灞俒"SQLite"]
+        DB1[("data.db<br/>DeviceDefinition<br/>DeviceChannel<br/>SlotDeviceMapping<br/>DeviceConfigVersion<br/>DeviceGroupTemplate")]
+        DB2[("debug.db<br/>debug_session<br/>debug_operation")]
+    end
+
+    A -->|Save/Query| DB1
+    B -->|璇昏澶囧垪琛▅ DB1
+    B -->|鍐欎細璇�/瀹¤| DB2
+    B --> B1 & B2 & B3
+    B -->|Connect/Command| C
+    C -->|Create| G
+    G -->|Instantiate| H
+    B -->|Validate maintenance| F
+    F -->|Reserve/Release| E
+    D -->|SendCommandAsync| H
+</div>
+
+<div class="info">
+    <strong>涓夊眰鑱岃矗锛�</strong>
+    <ul>
+        <li><strong>UI 灞�</strong>锛氭彃浠剁殑 WPF 鐣岄潰锛岃礋璐f暟鎹睍绀哄拰鐢ㄦ埛浜や簰</li>
+        <li><strong>鍩虹璁炬柦灞�</strong>锛欰ging.Infrastructure 鎻愪緵鐨勬帴鍙�/鏈嶅姟锛岃礋璐i┍鍔ㄨ皟搴︺�佹潈闄愩�佷細璇濈鐞�</li>
+        <li><strong>鏁版嵁灞�</strong>锛歋QLite 鏁版嵁搴擄紝璐熻矗鎸佷箙鍖栬澶囬厤缃拰璋冭瘯瀹¤</li>
+    </ul>
+</div>
+
+<!-- ========== Section 2 ========== -->
+<h2 id="sec2">2. 鏁版嵁灞傝�﹀悎锛氫袱涓彃浠堕�氳繃 <code>data.db</code> 鍏变韩</h2>
+
+<div class="highlight">
+    <strong>鏈�鍏抽敭鐨勮璁★細</strong> DeviceConfig 鏄�<strong>鐢熶骇鏂�</strong>锛堝啓鍏ワ級锛孌eviceDebug 鏄�<strong>娑堣垂鏂�</strong>锛堣鍙栵級銆�
+    涓よ�呬笉閫氳繃 API 鐩存帴璋冪敤锛岃�屾槸閫氳繃鍏变韩鐨� <code>data.db</code> 闅愬紡濂戠害銆�
+</div>
+
+<table>
+    <thead>
+        <tr><th>琛ㄥ悕</th><th>璋佸啓鍏�</th><th>璋佽鍙�</th><th>璇存槑</th></tr>
+    </thead>
+    <tbody>
+        <tr>
+            <td><code>DeviceDefinition</code></td>
+            <td><span class="badge badge-write">DeviceConfig</span></td>
+            <td><span class="badge badge-read">DeviceDebug</span></td>
+            <td>璁惧涓昏〃锛圖eviceId / Kind / Transport / Endpoint / DriverType锛�</td>
+        </tr>
+        <tr>
+            <td><code>DeviceChannel</code></td>
+            <td><span class="badge badge-write">DeviceConfig</span></td>
+            <td><span class="badge badge-read">DeviceDebug</span></td>
+            <td>璁惧閫氶亾锛圕hannelId / Capability / 鐢靛帇鐢垫祦涓婇檺锛�</td>
+        </tr>
+        <tr>
+            <td><code>SlotDeviceMapping</code></td>
+            <td><span class="badge badge-write">DeviceConfig</span></td>
+            <td><span class="badge badge-read">DeviceDebug</span></td>
+            <td>Slot 鈫� 璁惧閫氶亾 鐨勬槧灏勮〃</td>
+        </tr>
+        <tr>
+            <td><code>DeviceConfigVersion</code></td>
+            <td><span class="badge badge-write">DeviceConfig</span></td>
+            <td><span class="badge badge-read">DeviceDebug</span></td>
+            <td>閰嶇疆鐗堟湰锛圖raft/Published/Effective锛�</td>
+        </tr>
+        <tr>
+            <td><code>debug_session</code></td>
+            <td><span class="badge badge-write">DeviceDebug</span></td>
+            <td><span class="badge badge-read">DeviceDebug</span></td>
+            <td>璋冭瘯浼氳瘽锛堝惈鐘舵�佹満鏁版嵁锛�</td>
+        </tr>
+        <tr>
+            <td><code>debug_operation</code></td>
+            <td><span class="badge badge-write">DeviceDebug</span></td>
+            <td><span class="badge badge-read">DeviceDebug</span></td>
+            <td>璋冭瘯鎿嶄綔瀹¤鏃ュ織</td>
+        </tr>
+    </tbody>
+</table>
+
+<h3>鍏变韩鏈哄埗婧愮爜</h3>
+
+<div class="flow-step">
+<strong>DeviceDebug.xaml.cs 绗� 95 琛岄檮杩戯細</strong>
+<pre><code>_deviceConfigDbPath = Path.Combine(BaseFolder, "data.db");   <span style="color:#4CAF50">// 涓� DeviceConfig 鍚岀洰褰�</span>
+var sqliteHelper = new SqliteHelper(_deviceConfigDbPath);
+var dt = sqliteHelper.GetDataTable(
+    "SELECT DeviceId, Kind FROM DeviceDefinition ORDER BY DeviceId");</code></pre>
+</div>
+
+<div class="flow-step">
+<strong>鍏抽敭鐐癸細</strong>BaseFolder 鏄富绋嬪簭鍦� <code>PluginLoader</code> 閲岀粺涓�娉ㄥ叆鐨勭洰褰曪紝涓や釜鎻掍欢閮借鍐欏悓涓�涓� <code>data.db</code>銆�
+</div>
+
+<!-- ========== Section 3 ========== -->
+<h2 id="sec3">3. 瀹屾暣璋冪敤閾捐矾锛堢敤鎴疯瑙掞級</h2>
+
+<h3>鍦烘櫙 A锛氭敞鍐岃澶囷紙DeviceConfig锛�</h3>
+
+<div class="mermaid">
+sequenceDiagram
+    participant U as 鐢ㄦ埛
+    participant UI as DeviceConfig<br/>UI
+    participant M as DeviceEditModal
+    participant Model as DeviceConfigModel
+    participant DB as data.db
+
+    U->>UI: 鐐瑰嚮"鏂板璁惧"
+    UI->>M: OpenDeviceEditModal(new DeviceDefinition)
+    M->>M: 濉〃 + 閫氶亾閰嶇疆
+    U->>M: 鐐瑰嚮"淇濆瓨"
+    M->>Model: SaveDevice(device)
+    Model->>DB: INSERT OR REPLACE DeviceDefinition
+    M->>Model: SaveChannel(ch)
+    Model->>DB: INSERT OR REPLACE DeviceChannel
+    M-->>UI: DialogResult = true
+    UI->>UI: RefreshAllData()
+</div>
+
+<h3>鍦烘櫙 B锛氳皟璇曡澶囷紙DeviceDebug锛�</h3>
+
+<div class="mermaid">
+sequenceDiagram
+    participant U as 鐢ㄦ埛
+    participant DD as DeviceDebug<br/>UI
+    participant SM as DebugSessionManager
+    participant DM as DeviceManager
+    participant DF as DriverFactory
+    participant DRV as CanDriverAdapter
+    participant SIM as CanSimulator
+    participant DB as SQLite
+
+    U->>DD: 閫夋嫨 CAN-001 涓嬫媺椤�
+    DD->>DB: SELECT * FROM DeviceDefinition<br/>锛堣鍙� data.db锛�
+    DD->>SM: OpenSession(...)
+    SM->>DB: INSERT debug_session (state=ReadOnly)
+    DD->>DM: ConnectAsync("CAN-001")
+    DM->>DF: CreateDriver("CAN", "CAN_BUS_1:0")
+    DF->>DRV: new CanDriverAdapter
+    DRV->>SIM: ConnectAsync 鈫� 娉ㄥ唽鑺傜偣鍒版�荤嚎
+    
+    Note over DD: 鍔犺浇 CanDebugPanel<br/>AutoConnectOnLoad=true
+    U->>DD: 杩涘叆缁存姢妯″紡
+    DD->>SM: RequestMaintenance(sessionId)
+    SM->>DB: UPDATE debug_session SET state=Acquiring
+    SM->>SM: ResourceManager.Reserve(...)
+    DD->>SM: ActivateMaintenance(sessionId)
+    SM->>DB: UPDATE debug_session SET state=MaintenanceActive
+    DD->>DD: LoadPanel 閲嶆柊鍔犺浇<br/>CanDebugPanel.IsMaintenanceMode = true
+    
+    U->>DD: 鍙戦�� CAN 甯�
+    DD->>SM: ValidateCommand(sessionId, cmd)
+    SM-->>DD: true
+    DD->>DRV: SendCommandAsync("SEND:0x100:AA BB CC DD")
+    DRV->>SIM: CanNode.SendFrame(frame)
+    SIM-->>DRV: DriverFrameReceived (鑷姩鍝嶅簲)
+    DRV-->>DD: 浜嬩欢鍥炶皟
+    DD->>DB: INSERT debug_operation (瀹¤)
+</div>
+
+<!-- ========== Section 4 ========== -->
+<h2 id="sec4">4. 鍏抽敭鎺ュ彛渚濊禆锛圓ging.Infrastructure锛�</h2>
+
+<div class="card">
+    <strong>璇存槑锛�</strong>DeviceConfig 鍙仛鏁版嵁绠$悊锛屼笉鐩存帴璋冪敤鎺ュ彛锛汥eviceDebug 閫氳繃鎺ュ彛璋冪敤搴曞眰鏈嶅姟銆�
+</div>
+
+<table>
+    <thead>
+        <tr><th>鎺ュ彛</th><th>瀹氫箟鏂囦欢</th><th>璋佺敤</th><th>浣滅敤</th></tr>
+    </thead>
+    <tbody>
+        <tr>
+            <td><code>IDeviceDriver</code></td>
+            <td>Contracts/IDeviceDriver.cs</td>
+            <td>鎵�鏈夐┍鍔ㄩ�傞厤鍣�</td>
+            <td>缁熶竴鐨勮繛鎺�/鍛戒护/鏌ヨ鎺ュ彛</td>
+        </tr>
+        <tr>
+            <td><code>IDeviceManager</code></td>
+            <td>Contracts/IDeviceManager.cs</td>
+            <td>DeviceDebug</td>
+            <td>璁惧鐢熷懡鍛ㄦ湡绠$悊锛堟敞鍐�/杩炴帴/鏂紑锛�</td>
+        </tr>
+        <tr>
+            <td><code>IDeviceService</code></td>
+            <td>Contracts/IDeviceService.cs</td>
+            <td>DeviceDebug</td>
+            <td>鍛戒护鎵ц锛堝惈 OwnerToken 鏉冮檺妫�鏌ワ級</td>
+        </tr>
+        <tr>
+            <td><code>IResourceManager</code></td>
+            <td>Contracts/IResourceManager.cs</td>
+            <td>DebugSessionManager</td>
+            <td>璧勬簮棰勭害/閲婃斁锛岄槻姝㈣皟璇曚笌鐢熶骇鍐茬獊</td>
+        </tr>
+        <tr>
+            <td><code>IOperationLease</code></td>
+            <td>Contracts/IOperationLease.cs</td>
+            <td>ResourceManager</td>
+            <td>鎿嶄綔绉熺害锛堣秴鏃惰嚜鍔ㄩ噴鏀撅級</td>
+        </tr>
+        <tr>
+            <td><code>ResourceOwnerToken</code></td>
+            <td>Contracts/ResourceOwnerToken.cs</td>
+            <td>鏁翠釜鍩虹璁炬柦灞�</td>
+            <td>Owner 绫诲瀷 + ID锛堝 Maintenance:sessionId锛�</td>
+        </tr>
+    </tbody>
+</table>
+
+<h3>DriverFactory 鏀寔鐨勪紶杈撶被鍨�</h3>
+
+<table>
+    <thead>
+        <tr><th>Transport</th><th>Adapter</th><th>搴曞眰渚濊禆</th><th>Endpoint 鏍煎紡</th></tr>
+    </thead>
+    <tbody>
+        <tr><td>Tcp</td><td>TcpRawDriverAdapter</td><td>ConnectionUtil.TcpClient</td><td>IP:Port</td></tr>
+        <tr><td>SCPI</td><td>ScpiDriverAdapter</td><td>SCPI over TCP</td><td>IP:Port</td></tr>
+        <tr><td>ModBus</td><td>ModBusDriverAdapter</td><td>HslCommunication.ModbusTcpNet</td><td>IP:Port:slaveId</td></tr>
+        <tr><td>S7</td><td>S7DriverAdapter</td><td>S7netplus</td><td>IP:Port</td></tr>
+        <tr><td><strong>CAN</strong></td><td><strong>CanDriverAdapter</strong></td><td><strong>CanSimulator</strong></td><td><strong>BusName:NodeIndex</strong></td></tr>
+    </tbody>
+</table>
+
+<!-- ========== Section 5 ========== -->
+<h2 id="sec5">5. 浼氳瘽鐘舵�佹満锛堣法妯″潡鐨勬牳蹇冨崗璋冪偣锛�</h2>
+
+<div class="mermaid">
+stateDiagram-v2
+    [*] --> ReadOnly: OpenSession
+    ReadOnly --> AcquiringMaintenance: RequestMaintenance<br/>(妫�鏌ヨ祫婧愰绾�)
+    AcquiringMaintenance --> MaintenanceActive: ActivateMaintenance
+    AcquiringMaintenance --> ReadOnly: 鎷掔粷<br/>(琚敓浜ч绾�)
+    MaintenanceActive --> Closing: CloseSession<br/>(瀹夊叏鐘舵�佹鏌�)
+    Closing --> Closed
+    Closed --> [*]
+    
+    MaintenanceActive --> Faulted: FaultSession<br/>(閫氫俊/纭欢閿欒)
+    Faulted --> RecoveryRequired: MarkRecoveryRequired
+    RecoveryRequired --> ReadOnly: 鎭㈠鍚庨噸鏂拌繛鎺�
+    RecoveryRequired --> [*]: 鏃犳硶鎭㈠鍒欏叧闂�
+</div>
+
+<h3>鐘舵�佸涓婂眰鐨勫奖鍝�</h3>
+
+<table>
+    <thead>
+        <tr><th>鐘舵��</th><th>鍙彂閫佸懡浠�</th><th>UI 鏄剧ず</th><th>璧勬簮鍗犵敤</th></tr>
+    </thead>
+    <tbody>
+        <tr><td>ReadOnly</td><td>鉂� 鍙鐩戞帶</td><td>闈㈡澘鎸夐挳绂佺敤</td><td>鏃�</td></tr>
+        <tr><td>AcquiringMaintenance</td><td>鉂� 鐢宠涓�</td><td>杩囨浮鐘舵��</td><td>姝e湪鎶㈠崰</td></tr>
+        <tr><td>MaintenanceActive</td><td>鉁� 鍏佽鍐�</td><td>闈㈡澘鎸夐挳鍚敤</td><td>鎸佹湁 Maintenance 绉熺害</td></tr>
+        <tr><td>Closing</td><td>鉂� 鍏抽棴涓�</td><td>杩囨浮鐘舵��</td><td>閲婃斁涓�</td></tr>
+        <tr><td>Faulted</td><td>鉂� 鏁呴殰</td><td>绾㈣壊鍛婅</td><td>宸查噴鏀�</td></tr>
+        <tr><td>RecoveryRequired</td><td>鉂� 寰呮仮澶�</td><td>姗欒壊璀﹀憡</td><td>鏃�</td></tr>
+        <tr><td>Closed</td><td>鈥�</td><td>浼氳瘽缁撴潫</td><td>鏃�</td></tr>
+    </tbody>
+</table>
+
+<div class="success">
+    <strong>璁捐宸у涔嬪锛�</strong>浼氳瘽鐘舵�佹満鍚屾椂鍐冲畾浜�
+    <ul>
+        <li>UI 灞傦細CanDebugPanel.IsMaintenanceMode 鈫� 鍙戦�佹寜閽槸鍚﹀彲鐐�</li>
+        <li>涓氬姟灞傦細DeviceService 鏄惁鎺ュ彈璇ュ懡浠� 鈫� OwnerToken 鏉冮檺楠岃瘉</li>
+        <li>璧勬簮灞傦細ResourceManager 鏄惁浠嶆寔鏈夌绾� 鈫� 闃叉琚敓浜ф姠鍗�</li>
+    </ul>
+</div>
+
+<!-- ========== Section 6 ========== -->
+<h2 id="sec6">6. 闆嗘垚娴嬭瘯椤圭洰閲岀殑缁勫悎婕旂ず</h2>
+
+<div class="mermaid">
+graph LR
+    subgraph "Plugin.IntegrationTest<br/>_testDir = %LOCALAPPDATA%/PluginIntegrationTest"
+        Tab1["Tab 1: DeviceConfig<br/>(宓屽叆瀹炰緥)"]
+        Tab2["Tab 2: DeviceDebug<br/>(宓屽叆瀹炰緥)"]
+        Tab3["Tab 3: CanDebugPanel<br/>(鐙珛瀹炰緥)"]
+        DB[("data.db<br/>+ debug.db")]
+    end
+    
+    Tab1 -->|鍐欏叆| DB
+    Tab2 -->|璇诲彇| DB
+    Tab3 -->|椹卞姩璋冪敤| SIM["CanSimulator<br/>(鍐呭瓨铏氭嫙鎬荤嚎)"]
+</div>
+
+<div class="info">
+    <strong>鍏抽敭鐐癸細</strong>涓変釜 Tab 鍏变韩鍚屼竴涓� <code>_testDir</code> 浣滀负 BaseFolder锛屾墍浠ュ湪 Tab 1 娣诲姞鐨勮澶� 鈫� 鍒锋柊鍚� Tab 2 绔嬪嵆鍙 鈫� 閫変腑鍗宠嚜鍔ㄨ繛鎺� Tab 3 鐨勬ā鎷熸�荤嚎銆�
+</div>
+
+<h3>娴嬭瘯鏁版嵁娴�</h3>
+<ol>
+    <li><strong>棰勭疆闃舵</strong>锛�<code>SeedPresetCanDevices()</code> 鍐欏叆 CAN-001 / CAN-002</li>
+    <li><strong>娉ㄥ唽闃舵</strong>锛氬湪 Tab 1 涓柊澧炶澶囷紙濡� CAN-003 鈫� CAN_BUS_1:2锛�</li>
+    <li><strong>璋冭瘯闃舵</strong>锛氬湪 Tab 2 涓�夋嫨 CAN-003锛孋anDebugPanel 鑷姩杩炴帴鎬荤嚎</li>
+    <li><strong>妯℃嫙闃舵</strong>锛氬湪 Tab 3 涓惎鍔ㄦ�荤嚎锛屽紑鍚嚜鍔ㄥ搷搴�</li>
+    <li><strong>楠岃瘉闃舵</strong>锛歍ab 2 鍙戦�佸抚 鈫� 鏀跺埌 Tab 3 鐨勮嚜鍔ㄥ搷搴�</li>
+</ol>
+
+<!-- ========== Section 7 ========== -->
+<h2 id="sec7">7. 鏃跺簭鍥撅細瀹屾暣鏁版嵁娴佸姩</h2>
+
+<div class="mermaid">
+sequenceDiagram
+    autonumber
+    participant U as 鐢ㄦ埛
+    participant DC as DeviceConfig<br/>UI
+    participant DM1 as DeviceConfigModel
+    participant DB1 as data.db
+    participant DD as DeviceDebug<br/>UI
+    participant SM as SessionManager
+    participant DM2 as DeviceDebugModel
+    participant DB2 as debug.db
+    participant MGR as DeviceManager
+    participant SVC as DeviceService
+    participant DRV as CanDriverAdapter
+    participant SIM as CanSimulator<br/>鎬荤嚎
+
+    rect rgb(255, 248, 225)
+    Note over U,DB1: 闃舵1锛氭敞鍐岃澶�
+    U->>DC: 鏂板 CAN-001
+    DC->>DM1: SaveDevice
+    DM1->>DB1: INSERT DeviceDefinition<br/>Endpoint=CAN_BUS_1:0
+    end
+
+    rect rgb(227, 242, 253)
+    Note over U,SIM: 闃舵2锛氭墦寮�璋冭瘯浼氳瘽
+    U->>DD: 閫夋嫨 CAN-001
+    DD->>DB1: SELECT DeviceDefinition
+    DB1-->>DD: {Kind=CanDevice, Endpoint=CAN_BUS_1:0}
+    DD->>SM: OpenSession
+    SM->>DM2: CreateSession
+    DM2->>DB2: INSERT debug_session (ReadOnly)
+    DD->>MGR: ConnectAsync("CAN-001")
+    MGR->>DRV: DriverFactory.CreateDriver("CAN",...)
+    DRV->>SIM: 娉ㄥ唽鑺傜偣0鍒癈AN_BUS_1鎬荤嚎
+    end
+
+    rect rgb(232, 245, 233)
+    Note over U,DRV: 闃舵3锛氳繘鍏ョ淮鎶ゆā寮�
+    U->>DD: 杩涘叆缁存姢
+    DD->>SM: RequestMaintenance
+    SM->>DB2: UPDATE state=Acquiring
+    SM->>SM: ResourceManager.Reserve
+    DD->>SM: ActivateMaintenance
+    SM->>DB2: UPDATE state=MaintenanceActive
+    DD->>DD: LoadPanel(kind)<br/>IsMaintenanceMode=true
+    end
+
+    rect rgb(255, 224, 178)
+    Note over U,SIM: 闃舵4锛氬彂閫佽皟璇曞懡浠�
+    U->>DD: 鐐瑰嚮"鍙戦��"甯�
+    DD->>SM: ValidateCommand(sessionId, cmd)
+    SM-->>DD: 鉁� true
+    DD->>SVC: ExecuteCommandAsync
+    SVC->>DRV: SendCommandAsync("SEND:0x100:AA BB CC")
+    DRV->>SIM: CanNode.SendFrame(frame)
+    SIM->>SIM: 璺敱鍒板叾浠栬妭鐐�<br/>+ 妫�鏌� AutoResponse
+    SIM-->>DRV: DriverFrameReceived (鍝嶅簲甯�)
+    DRV-->>SVC: 缁撴灉
+    SVC-->>DD: ExecuteResult
+    DD->>DM2: RecordOperation(op)
+    DM2->>DB2: INSERT debug_operation
+    DD->>DD: 鏇存柊瀹¤鍒楄〃
+    end
+
+    rect rgb(255, 205, 210)
+    Note over U,DB2: 闃舵5锛氬叧闂細璇�
+    U->>DD: 閫�鍑虹淮鎶�
+    DD->>SM: CloseSession
+    SM->>DB2: UPDATE state=Closed<br/>SET closed_at=now
+    SM->>SM: ResourceManager.ReleaseReservation
+    SM->>DRV: DisconnectAsync
+    DRV->>SIM: 浠庢�荤嚎娉ㄩ攢鑺傜偣
+    end
+</div>
+
+<!-- ========== Section 8 ========== -->
+<h2 id="sec8">8. 鏍稿績璁捐鎬濇兂</h2>
+
+<div class="card">
+<h3>馃幆 鏁版嵁鍏变韩 = 闅愬紡濂戠害</h3>
+DeviceDebug 鍙緷璧� DeviceConfig 鍐欏ソ鐨� <code>data.db</code>锛屼笉闇�瑕� API 璋冪敤銆備袱涓彃浠剁殑 <strong>BaseFolder 涓�鑷�</strong>鏄牳蹇冨墠鎻愶紝涓荤▼搴忛�氳繃 PluginLoader 娉ㄥ叆銆�
+</div>
+
+<div class="card">
+<h3>馃幆 鐘舵�侀泦涓� = DebugSessionManager</h3>
+鎵�鏈夋潈闄愭鏌ヨ蛋鍚屼竴涓姸鎬佹満銆俇I銆侀┍鍔ㄣ�佸璁′笁澶勯兘閫氳繃鐘舵�佹煡璇㈠悓姝ャ�傞伩鍏嶅悇澶勯浂鏁e垽鏂鑷翠笉涓�鑷淬��
+</div>
+
+<div class="card">
+<h3>馃幆 椹卞姩鎶借薄 = IDeviceDriver</h3>
+涓婂眰闈㈡澘涓嶇煡閬撳簳灞傛槸 TCP銆丮odbus銆丼7銆丼CPI 杩樻槸妯℃嫙 CAN 鎬荤嚎銆�<code>DriverFactory.CreateDevice(id, transport, endpoint)</code> 缁熶竴鍒嗘淳銆�
+</div>
+
+<div class="card">
+<h3>馃幆 璧勬簮棰勭害 = IResourceManager</h3>
+璋冭瘯妯″紡鍜岀敓浜фā寮忎簰鏂ワ紝閫氳繃 <code>ResourceOwnerToken</code> + 绉熺害鏈哄埗淇濊瘉锛�<br>
+- 鐢熶骇浠诲姟杩愯涓� 鈫� 璋冭瘯璇锋眰澶辫触<br>
+- 璋冭瘯鎸佹湁绉熺害 鈫� 鐢熶骇浠诲姟琚嫆缁�<br>
+- 绉熺害瓒呮椂鏈画 鈫� 寮哄埗閲婃斁锛岄伩鍏嶆閿�
+</div>
+
+<div class="card">
+<h3>馃幆 瀹¤闂幆 = debug_operation</h3>
+姣忎竴娆″懡浠ら兘璁板綍锛�<code>SessionId 路 CommandType 路 Parameters 路 Outcome 路 Readback 路 Error</code>銆備簨鍚庡彲浠ュ畬鏁撮噸鐜拌皟璇曡繃绋嬶紝鏄淮鎶よ矗浠昏拷婧殑鍏抽敭銆�
+</div>
+
+<div class="card">
+<h3>馃幆 鐗堟湰绠$悊 = DeviceConfigVersion</h3>
+閰嶇疆涓嶆槸"鏀逛簡灏辩敓鏁�"锛岃�屾槸璧� <strong>Draft 鈫� Published 鈫� Effective</strong> 涓夐樁娈碉細
+<ol>
+    <li>DeviceConfig 淇濆瓨鑽夌 鈫� Draft</li>
+    <li>鎻愪氦鍙戝竷 鈫� Published锛堥檮甯﹂厤缃搱甯岋級</li>
+    <li>搴旂敤鍒扮敓浜� 鈫� Effective锛堟棫鐨� Published 鍥為��锛�</li>
+</ol>
+杩欐牱鑳戒繚璇佺敓浜х幆澧冮厤缃ǔ瀹氾紝璋冭瘯鏃跺彲鍥炴粴銆�
+</div>
+
+<h2>闄勫綍锛氭枃浠惰矾寰勯�熸煡</h2>
+
+<table>
+    <thead>
+        <tr><th>缁勪欢</th><th>璺緞</th></tr>
+    </thead>
+    <tbody>
+        <tr><td>浠櫒浠〃娉ㄥ唽鎻掍欢</td><td><code>d:\TestPlatform\TapProject\Plugin.DeviceConfig\</code></td></tr>
+        <tr><td>纭欢璋冭瘯鎻掍欢</td><td><code>d:\TestPlatform\TapProject\Plugin.DeviceDebug\</code></td></tr>
+        <tr><td>鍩虹璁炬柦 & 椹卞姩</td><td><code>d:\TestPlatform\TapProject\Aging.Infrastructure\</code></td></tr>
+        <tr><td>CAN 妯℃嫙鍣ㄦ牳蹇�</td><td><code>d:\TestPlatform\TapProject\CanSimulator\</code></td></tr>
+        <tr><td>闆嗘垚娴嬭瘯鐜</td><td><code>d:\TestPlatform\TapProject\Plugin.IntegrationTest\</code></td></tr>
+        <tr><td>鎸佷箙鍖栨暟鎹洰褰�</td><td><code>%LOCALAPPDATA%\PluginIntegrationTest\data.db</code></td></tr>
+    </tbody>
+</table>
+
+<footer>
+    Generated for TapProject 路 浠櫒娉ㄥ唽涓庣‖浠惰皟璇曟ā鍧楁灦鏋勫垎鏋� 路 2026-11-02
+</footer>
+
+<script>
+    mermaid.initialize({ 
+        startOnLoad: true,
+        theme: 'default',
+        securityLevel: 'loose',
+        fontFamily: 'Segoe UI, Microsoft YaHei, sans-serif',
+        flowchart: { curve: 'basis', padding: 20 },
+        sequence: { showSequenceNumbers: false, actorMargin: 60 }
+    });
+</script>
+
+</body>
+</html>

--
Gitblit v1.9.1