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/OpenTAP_Instrument_Package_Analysis.html |  486 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 486 insertions(+), 0 deletions(-)

diff --git a/docs/OpenTAP_Instrument_Package_Analysis.html b/docs/OpenTAP_Instrument_Package_Analysis.html
new file mode 100644
index 0000000..1a671b8
--- /dev/null
+++ b/docs/OpenTAP_Instrument_Package_Analysis.html
@@ -0,0 +1,486 @@
+<!DOCTYPE html>
+<html lang="zh-CN">
+<head>
+<meta charset="UTF-8">
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<title>OpenTAP Instrument + 鎻掍欢鍖呮満鍒跺垎鏋愭姤鍛�</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: 1240px;
+        margin: 0 auto;
+        padding: 32px 24px 80px;
+        background: #FAFAFA;
+        color: #212121;
+        line-height: 1.75;
+    }
+    h1 { font-size: 30px; color: #1565C0; border-bottom: 3px solid #1976D2; padding-bottom: 12px; }
+    h2 { font-size: 23px; color: #0D47A1; margin-top: 42px; padding-left: 12px; border-left: 4px solid #FF9800; }
+    h3 { font-size: 17px; color: #37474F; margin-top: 24px; }
+    .subtitle { color: #757575; font-size: 14px; margin-bottom: 24px; }
+    .card { background: white; border-radius: 8px; padding: 18px 22px; 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; }
+    .warn { background: #FBE9E7; border-left: 4px solid #FF5722; 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); font-size: 14px; }
+    th { background: #1976D2; color: white; padding: 10px 14px; text-align: left; font-weight: 600; }
+    td { padding: 9px 14px; border-bottom: 1px solid #EEEEEE; vertical-align: top; }
+    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", monospace; font-size: 13px; line-height: 1.55; }
+    pre code { background: transparent; color: inherit; padding: 0; font-size: 13px; }
+    .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; }
+    .toc { background: #F5F5F5; padding: 16px 24px; border-radius: 6px; margin: 20px 0; }
+    .toc a { color: #1976D2; text-decoration: none; display: block; padding: 3px 0; }
+    .toc a:hover { text-decoration: underline; }
+    .kwd { color: #FFCC80; } .str { color: #C5E1A5; . } .cmt { color: #546E7A; }
+    footer { margin-top: 60px; padding-top: 20px; border-top: 1px solid #E0E0E0; color: #757575; font-size: 12px; text-align: center; }
+    .tag { display:inline-block; background:#E1F5FE; color:#0277BD; border-radius:12px; padding:1px 10px; font-size:12px; margin:2px; }
+</style>
+</head>
+<body>
+
+<h1>OpenTAP Instrument + 鎻掍欢鍖呮満鍒跺垎鏋愭姤鍛�</h1>
+<div class="subtitle">閽堝 TestPlatform Aging Software锛�.NET Framework 4.7.2 + OpenTAP 9.31.0锛夐┍鍔ㄧ儹鎻掓嫈鏀归�犵殑鎶�鏈皟鐮� 路 2026-11-03</div>
+
+<div class="toc">
+    <strong>鐩綍</strong>
+    <a href="#s1">1. OpenTAP 鎻掍欢浣撶郴鎬昏</a>
+    <a href="#s2">2. Instrument 鎶借薄娣卞叆瑙f瀽</a>
+    <a href="#s3">3. 娴嬭瘯姝ラ濡備綍寮曠敤浠櫒</a>
+    <a href="#s4">4. 鍖咃紙Package锛夋満鍒跺叏鏅�</a>
+    <a href="#s5">5. package.xml 娓呭崟鏂囦欢璇﹁В</a>
+    <a href="#s6">6. 渚濊禆瑙f瀽涓庣増鏈ā鍨�</a>
+    <a href="#s7">7. 椹卞姩鎻掍欢寮�鍙�-鍒嗗彂-瀹夎宸ヤ綔娴�</a>
+    <a href="#s8">8. Image API锛氬畨瑁呯洰褰曠姸鎬佺鐞�</a>
+    <a href="#s9">9. 涓� TapProject 鐜版湁鏋舵瀯鐨勬槧灏勪笌宸窛</a>
+    <a href="#s10">10. 钀藉湴璺嚎寤鸿涓庢垚鏈瘎浼�</a>
+    <a href="#s11">11. 缁撹</a>
+</div>
+
+<!-- ============================================================ -->
+<h2 id="s1">1. OpenTAP 鎻掍欢浣撶郴鎬昏</h2>
+
+<div class="card">
+OpenTAP 鐨勬牳蹇冨摬瀛︽槸 <strong>鈥滀竴鍒囩殕鎻掍欢锛圗verything is a Plugin锛夆��</strong>銆傛祴璇曟楠ゃ�佷华鍣ㄩ┍鍔ㄣ�佽娴嬩欢锛圖UT锛夈�佺粨鏋滅洃鍚櫒銆佺敋鑷� CLI 鍛戒护鏈韩锛岄兘鏄户鎵胯嚜鏌愪釜鎶借薄鍩虹被鐨� C# 绫汇�傚紩鎿庡惎鍔ㄦ椂閫氳繃 <code>PluginSearcher</code> 鎵弿瀹夎鐩綍涓嬫墍鏈夌▼搴忛泦锛屾瀯寤烘彃浠剁被鍨嬪浘璋憋紝渚涘簭鍒楀寲鍣ㄤ笌缂栬緫鍣紙Editor锛夊姩鎬佸彂鐜颁娇鐢ㄣ��
+</div>
+
+<div class="mermaid">
+graph TB
+    subgraph 鎵弿["鍚姩鏃舵彃浠跺彂鐜� (PluginSearcher)"]
+        A["鎵弿瀹夎鏍圭洰褰� *.dll"] --> B["鎵弿 Packages/** 瀛愮洰褰�"]
+        B --> C["鍙嶅皠鎻愬彇缁ф壙鑷彃浠跺熀绫荤殑绫诲瀷"]
+        C --> D["鏋勫缓绫诲瀷缂撳瓨<br/>PluginManager 鍙煡璇�"]
+    end
+    subgraph 鍩虹被["鎻掍欢鍩虹被锛圤penTap.dll / 鎻掍欢鍖咃級"]
+        T1["TestStep"]
+        T2["Instrument : Resource"]
+        T3["Dut : Resource"]
+        T4["ResultListener"]
+        T5["SerializerPlugin"]
+        T6["ICliAction (tap 瀛愬懡浠�)"]
+    end
+    D --> T1 & T2 & T3 & T4 & T5 & T6
+</div>
+
+<h3>鍏抽敭缁勪欢</h3>
+<table>
+    <tr><th>缁勪欢</th><th>鎵�鍦� DLL</th><th>鑱岃矗</th></tr>
+    <tr><td>Engine锛堝簭鍒楀寲/搴忓垪鎵ц锛�</td><td><code>OpenTap.dll</code></td><td>TestPlan 鎵ц銆佹彃浠跺璞$敓鍛藉懆鏈熴�乆ML 搴忓垪鍖�</td></tr>
+    <tr><td>PluginSearcher</td><td><code>OpenTap.dll</code>锛堝唴缃� Mono.Cecil锛�</td><td>涓嶅姞杞� CLR 绫诲瀷鍗冲彲瑙f瀽绋嬪簭闆嗙殑鎻掍欢鍏冩暟鎹紙蹇�佹敮鎸佸欢杩熷姞杞斤級</td></tr>
+    <tr><td>PackageManager / Image</td><td><code>OpenTap.Package.dll</code></td><td>鍖呭畨瑁呫�佷緷璧栬В鏋愩�佷笅杞姐�佸嵏杞�</td></tr>
+    <tr><td>CLI</td><td><code>tap.dll</code> / <code>tap.exe</code></td><td><code>tap package install / run / plan</code> 绛夊懡浠ゅ叆鍙�</td></tr>
+    <tr><td>鍩虹姝ラ鍖�</td><td><code>OpenTap.Plugins.BasicSteps.dll</code></td><td>Delay銆丩oop銆両f銆丼cpi 浠櫒鎺у埗绛夐�氱敤 TestStep</td></tr>
+</table>
+
+<div class="info">
+    <strong>瀹夎鐩綍甯冨眬锛堝疄娴嬪畼鏂� OpenTAP 鍖咃級锛�</strong>
+    鏍稿績寮曟搸 DLL锛�<code>tap.dll</code>銆�<code>OpenTap.dll</code>銆�<code>OpenTap.Package.dll</code>锛夋斁鍦ㄦ牴鐩綍锛�
+    <strong>姣忎釜绗笁鏂瑰寘鐨勬枃浠惰闅旂鍒拌嚜宸辩殑瀛愮洰褰�</strong> <code>Packages/&lt;鍖呭悕&gt;/</code>锛堝 <code>Packages/OpenTAP/OpenTap.Plugins.BasicSteps.dll</code>锛夛紝鍗歌浇鍖呮椂鎸夋竻鍗曞垹闄よ繖浜涙枃浠讹紝澶╃劧閬垮厤鏂囦欢鍐茬獊銆�
+</div>
+
+<!-- ============================================================ -->
+<h2 id="s2">2. Instrument 鎶借薄娣卞叆瑙f瀽</h2>
+
+<h3>绫诲眰娆�</h3>
+<div class="mermaid">
+classDiagram
+    class IResource {
+        <<interface>>
+        +string Name
+        +bool Enabled
+        +Open()
+        +Close()
+    }
+    class Resource {
+        <<abstract>>
+        +string Name
+        +virtual bool Enabled
+        +virtual Open()
+        +virtual Close()
+    }
+    class IInstrument { <<interface>> }
+    class Instrument {
+        <<abstract>>
+        Instrument() 榛樿Name= INST
+    }
+    class ScpiInstrument {
+        +IdnQuery
+        +Query/Write
+        +Connection 绫诲瀷
+        +Open/Close 瀹炵幇
+    }
+    class Dut {
+        <<abstract>>
+        琚祴浠舵ā鍨�
+    }
+    IResource <|-- Resource
+    IResource <.. IInstrument
+    IInstrument <|.. Instrument
+    Resource <|-- Instrument
+    Instrument <|-- ScpiInstrument
+    Resource <|-- Dut
+</code></pre>
+</div>
+
+<ul>
+    <li><strong><code>Resource</code>锛堟娊璞″熀绫伙級</strong>锛氱粺涓�"鍙版灦璧勬簮"妯″瀷 鈥斺�� 鍚嶇О鍞竴銆佸彲鍚敤/绂佺敤銆�<code>Open()</code>/<code>Close()</code> 鐢熷懡鍛ㄦ湡銆侷nstrument 涓� DUT 閮界户鎵垮畠銆�</li>
+    <li><strong><code>Instrument : Resource, IInstrument</code></strong>锛氭簮鐮佷粎 ~20 琛岋紙楠岃瘉鑷� GitHub opentap/opentap Engine/Instrument.cs锛夛紝鏋勯�犲嚱鏁伴粯璁� <code>Name="INST"</code>銆傛淳鐢熺被閲嶅啓 <code>Open/Close</code> 瀹屾垚纭欢杩炴帴銆�</li>
+    <li><strong><code>ScpiInstrument</code></strong>锛圫CPI 鎻掍欢鍖呮彁渚涳級锛氭渶甯哥敤鐨勪华鍣ㄥ熀绫伙紝灏佽 SCPI 鍗忚鏍堬細
+        <ul>
+            <li>IDN 鏌ヨ锛�*IDN? 鑷姩璇嗗埆鍘傚晢/鍨嬪彿/鍥轰欢锛�</li>
+            <li>澶氫紶杈撳眰锛歏ISA锛圞eysight/NI锛夈�丷aw TCP/Socket銆丼erial銆乁SB-TMC銆丟PIB銆丠iSLIP</li>
+            <li>鍒嗗眰鍗忚妯″瀷锛圠ayer锛夛細鍙湪 Message/Resource 灞傛彃鍏ユ棩蹇椼�佽秴鏃躲�侀噸璇曠瓥鐣�</li>
+        </ul>
+    </li>
+    <li><strong>杩炴帴閰嶇疆鎸佷箙鍖�</strong>锛�9.23+ 寮曞叆 <code>BenchStore</code>/<code>ResourceSettings</code> 浣撶郴锛屽皢浠櫒鐨勫湴鍧�銆佽秴鏃躲�佸埆鍚嶄粠娴嬭瘯搴忓垪涓墺绂绘垚鍙版灦绾ч厤缃紙瀵瑰簲鏃х増 <code>InstrumentSettings.xml</code> 鏂囦欢锛夈��</li>
+</ul>
+
+<div class="highlight">
+<strong>涓庝綘浠� <code>IDeviceDriver</code> 鐨勫叧閿樊寮傦細</strong>OpenTAP 鐨� Instrument 瀵硅薄鍚屾椂鎵挎媴"椹卞姩 + 杩炴帴閰嶇疆 + 鐢熷懡鍛ㄦ湡"涓夌瑙掕壊锛屼笖鐢卞簭鍒楀寲鍣ㄥ湪鍙嶅簭鍒楀寲 TestPlan 鏃�<strong>鑷姩鎸夌被鍨嬪悕浠庢彃浠跺浘璋卞垱寤哄疄渚�</strong>銆備綘浠殑 <code>CanDriverAdapter(deviceId, busName, nodeIndex)</code> 鍒欐槸宸ュ巶鏄惧紡鏋勯�狅紝閰嶇疆鏉ヨ嚜 SQLite 鐨� <code>DeviceDefinition</code> 琛ㄣ��
+</div>
+
+<!-- ============================================================ -->
+<h2 id="s3">3. 娴嬭瘯姝ラ濡備綍寮曠敤浠櫒</h2>
+
+<pre><code><span class="cmt">// OpenTAP 椋庢牸鐨� TestStep 寮曠敤浠櫒锛堢紪杈戝櫒鑷姩娓叉煋涓轰笅鎷夋锛�</span>
+<span class="kwd">public class</span> PowerOnStep : TestStep
+{
+    <span class="cmt">// 浠讳綍鏆撮湶 Instrument 灞炴�х殑 TestStep锛岀紪杈戝櫒鏄剧ず鍙�変华鍣ㄥ垪琛紱</span>
+    <span class="cmt">// 鍒楄〃鏉ユ簮 = PluginSearcher 鎵弿鍑虹殑鎵�鏈夐潪鎶借薄 Instrument 瀛愮被瀹炰緥锛堟潵鑷� settings store锛�</span>
+    <span class="kwd">public</span> ScpiInstrument PowerSupply { <span class="kwd">get</span>; <span class="kwd">set</span>; }
+    <span class="kwd">public double</span> Voltage { <span class="kwd">get</span>; <span class="kwd">set</span>; } = 12.0;
+
+    <span class="kwd">public override void</span> Run()
+    {
+        <span class="kwd">using</span> <span class="kwd">var</span> _ = SynchronizationManager.RequestLock(PowerSupply, TimeSpan.FromSeconds(10));
+        PowerSupply.Write($&quot;VOLT {Voltage:F2}&quot;);
+        PowerSupply.Write(&quot;OUTP ON&quot;);
+        <span class="kwd">var</span> readback = PowerSupply.QueryDouble(&quot;MEAS:VOLT?&quot;);
+        <span class="kwd">if</span> (Math.Abs(readback - Voltage) &gt; 0.5)
+            Upwards.Find(Voltage, readback).Fail(&quot;鐢靛帇鍋忓樊杩囧ぇ&quot;);
+    }
+}</code></pre>
+
+<table>
+    <tr><th>鏈哄埗</th><th>璇存槑</th></tr>
+    <tr><td>灞炴�х被鍨嬪嵆閫夋嫨鍣�</td><td><code>public Instrument X</code> 灞炴�у湪缂栬緫鍣�/CLI 涓覆鏌撴垚浠櫒涓嬫媺妗嗭紱[ResourceProperty] 绛� Attribute 鍙檺鍒跺�欓�夌被鍨嬶紙鍙垪 CAN / 鍙垪鐢垫簮锛�</td></tr>
+    <tr><td>鑷姩 Open/Close</td><td>TestPlanRun 寮�濮嬫椂寮曟搸瀵规墍鏈� Enabled 鐨� Instrument 璋� <code>Open()</code>锛堟噿鎵撳紑锛夛紝缁撴潫鍚� <code>Close()</code>锛涙楠や唬鐮佷笉鍏冲績杩炴帴缁嗚妭</td></tr>
+    <tr><td>骞跺彂淇濇姢</td><td><code>SynchronizationManager.RequestLock(resource, timeout)</code> 鎻愪緵杩涚▼鍐呭鍚屼竴浠櫒鐨勪簰鏂ラ攣锛涜法杩涚▼浜掓枼 OpenTAP <strong>涓嶆彁渚�</strong>锛岄渶澶栭儴浠茶锛堣 搂9锛�</td></tr>
+    <tr><td>搴忓垪鍖�</td><td>TestPlan XML 閲屼繚瀛樼殑鏄华鍣� <code>Name</code> 寮曠敤锛堥潪瀹炰緥锛夛紝杩愯鏃舵寜鍚嶅瓧瑙f瀽鍒� settings store 涓厤缃殑瀹炰緥</td></tr>
+</table>
+
+<!-- ============================================================ -->
+<h2 id="s4">4. 鍖咃紙Package锛夋満鍒跺叏鏅�</h2>
+
+<div class="card">
+<strong>鍖呮枃浠舵湰璐細</strong><code>.opentap</code> 鏂囦欢灏辨槸涓�涓� <strong>ZIP 鍘嬬缉鍖�</strong>锛屾牴鐩綍鍚� <code>package.xml</code> 娓呭崟锛屽叾浣欎负杞借嵎鏂囦欢锛圖LL銆侀厤缃�佹枃妗g瓑锛夈�傛竻鍗曞0鏄庝簡鍖呭悕銆佽涔夊寲鐗堟湰銆佸钩鍙扮害鏉熴�佷緷璧栧叧绯诲拰鏂囦欢閮ㄧ讲甯冨眬銆�
+</div>
+
+<div class="mermaid">
+graph LR
+    subgraph 鍖呮枃浠�
+        Z[".opentap (ZIP)"] --> PX["package.xml 娓呭崟"]
+        Z --> PL["杞借嵎鏂囦欢"]
+    end
+    subgraph 浠撳簱
+        REPO["packages.opentap.io<br/>(瀹樻柟 NuGet 椋庢牸浠撳簱)"]
+        PRIV["绉佹湁浠撳簱<br/>tap repo add"]
+    end
+    PLAT["Developer's Platform<br/>(妗岄潰鐗堝寘娴忚鍣�/CI)"] --> REPO
+    REPO -->|tap package install| IMG["Image = 瀹夎鐩綍<br/>鐘舵�� + 宸茶鍖呮竻鍗�"]
+    PRIV -->|鍚屽崗璁畖 IMG
+    PX --> IMG
+    IMG -->|閮ㄧ讲鍒皘 FILES["鏍圭洰褰� + Packages/&lt;name&gt;/<br/>+ Dependencies/"]
+    IMG -->|鍗歌浇| DEL["鎸夋竻鍗曞垹闄ゆ枃浠�<br/>锛堜笉褰卞搷鍏朵粬鍖咃級"]
+</div>
+
+<h3>鏍稿績 CLI 鍛戒护</h3>
+<pre><code><span class="cmt"># 鍒楀嚭鍙畨瑁� / 宸插畨瑁�</span>
+tap package list
+tap package list -i
+
+<span class="cmt"># 瀹夎锛堝彲鎸囧畾浠撳簱銆佺増鏈�侀�氶亾锛�</span>
+tap package install "Developer's System CE" -y
+tap package install MyCanDriver -v 2.1.0 -c candidate
+tap package install Keysight.34461A -s https://packages.opentap.io
+
+<span class="cmt"># 浠庢簮鐮佸伐绋嬫瀯寤哄寘</span>
+tap package create package.xml
+
+<span class="cmt"># 绠$悊绉佹湁浠撳簱婧�</span>
+tap repo add http://192.168.1.50/opentap-repo
+tap repo list
+
+<span class="cmt"># 淇 / 搴忓垪鍖� / 浼氳瘽</span>
+tap package recover
+tap package serialize-package / deserialize-package</code></pre>
+
+<table>
+    <tr><th>鐗规��</th><th>鏈哄埗</th></tr>
+    <tr><td>鍖呴殧绂诲畨瑁�</td><td>鍖呮枃浠堕儴缃插埌 <code>Packages/&lt;鍖呭悕&gt;/</code>锛屽悓鍚� DLL 涓嶅悓鐗堟湰鍙叡瀛橈紙寮曟搸鎸夊寘娓呭崟鍔犺浇锛�</td></tr>
+    <tr><td>骞冲彴/鏋舵瀯鍖哄垎</td><td><code>OS="Windows|Linux|MacOS"</code>銆�<code>Architecture="x64|x86|arm"</code>锛屾竻鍗曞唴鍙寜鏉′欢鍖呭惈涓嶅悓鍘熺敓渚濊禆锛堝畼鏂瑰寘鐢� <code>$(Architecture)</code> 鍙橀噺鍒囧垎 libgit2 鐨� .dll/.so/.dylib锛�</td></tr>
+    <tr><td>瀹夎閽╁瓙</td><td><code>PackageActionExtensions</code> 鍙湪 pre/post install 鎵ц澶栭儴鍛戒护锛堝畼鏂瑰寘鐢� <code>chmod +x tap</code> 淇� Linux 鏉冮檺锛�</td></tr>
+    <tr><td>閫氶亾锛圕hannels锛�</td><td>release / candidate / alpha锛屽悓涓�鍖呭彲鎸変笉鍚岄�氶亾鍙戝竷锛汣I 鍦烘櫙閿佸畾閫氶亾鍗冲彲鎺у埗鏇存柊鑺傚</td></tr>
+    <tr><td>鑷姩鏇存柊</td><td><code>tap package install --force</code> 鎴栨闈㈢増鍖呮祻瑙堝櫒锛涚増鏈瘮杈冧娇鐢ㄤ弗鏍� SemVer 2.0</td></tr>
+</table>
+
+<!-- ============================================================ -->
+<h2 id="s5">5. package.xml 娓呭崟鏂囦欢璇﹁В</h2>
+
+<p>浠ヤ笅楠ㄦ灦鎻愮偧鑷� <strong>瀹樻柟 OpenTAP 鍖呯殑鐪熷疄 package.xml</strong>锛圙itHub opentap/opentap@main锛夛細</p>
+
+<pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
+&lt;Package Name="MyCompany.CanDriver"
+         xmlns="http://opentap.io/schemas/package"
+         Version="$(GitVersion)"          <span class="cmt">&lt;!-- MSBuild 椋庢牸鍙橀噺娉ㄥ叆 --&gt;</span>
+         OS="$(Platform)" Architecture="$(Architecture)"&gt;
+
+  &lt;Description&gt;CAN 鎬荤嚎浠櫒椹卞姩鎻掍欢锛圥CAN/铏氭嫙鎬荤嚎锛�&lt;/Description&gt;
+  &lt;Status&gt;Released&lt;/Status&gt;
+  &lt;Organisation&gt;鎴戝徃&lt;/Organisation&gt;
+  &lt;SourceUrl&gt;https://git.internal/CanDriver&lt;/SourceUrl&gt;
+  &lt;SourceLicense&gt;Proprietary&lt;/SourceLicense&gt;
+  &lt;Owner&gt;MyCompany&lt;/Owner&gt;
+
+  <span class="cmt">&lt;!-- 鈶� 鍙橀噺涓庢潯浠讹紙MSBuild 琛ㄨ揪寮忥級--&gt;</span>
+  &lt;Variables&gt;
+    &lt;ArchitectureCondition Condition="$(Architecture) == ''"&gt;x64&lt;/Architecture&gt;
+    &lt;PlatformCondition Condition="$(Platform) == ''"&gt;Windows&lt;/Platform&gt;
+  &lt;/Variables&gt;
+
+  <span class="cmt">&lt;!-- 鈶� 渚濊禆锛氭寚鍚戝叾浠�"鍖�"锛堢増鏈寖鍥�/蹇呴渶/鎺ㄨ崘锛�--&gt;</span>
+  &lt;Dependencies&gt;
+    &lt;PackageDependency Name="OpenTAP" Version="9.31.0" Action="Required"/&gt;
+    &lt;PackageDependency Name="Keysight.SCPI" Version="9.x" Action="Optional"/&gt;
+  &lt;/Dependencies&gt;
+
+  <span class="cmt">&lt;!-- 鈶� 鏂囦欢锛氬畨瑁呰矾寰� / 婧愯矾寰� / 鍏冩暟鎹搷浣� --&gt;</span>
+  &lt;Files&gt;
+    <span class="cmt">&lt;!-- 鎻掍欢 DLL 鏀捐繘鍖呴殧绂荤洰褰� --&gt;</span>
+    &lt;File Path="Packages/MyCompany.CanDriver/CanDriverPlugin.dll"&gt;
+      &lt;SetAssemblyInfo Attributes="Version"/&gt;   <span class="cmt">&lt;!-- 鑷姩鍐欏叆绋嬪簭闆嗙増鏈彿 --&gt;</span>
+    &lt;/File&gt;
+    &lt;File Path="Packages/MyCompany.CanDriver/peak_pcans.dll" SourcePath="native/pcans.dll"/&gt;
+    &lt;File Path="Docs/**" SourcePath="doc/"/&gt;                    <span class="cmt">&lt;!-- glob --&gt;</span>
+  &lt;/Files&gt;
+
+  <span class="cmt">&lt;!-- 鈶� 骞冲彴宸紓鍖� --&gt;</span>
+  &lt;Files Condition="$(Platform) == Linux"&gt;
+    &lt;File Path="Packages/MyCompany.CanDriver/libpcans.so"/&gt;
+  &lt;/Files&gt;
+&lt;/Package&gt;</code></pre>
+
+<table>
+    <tr><th>鍏冪礌</th><th>浣滅敤</th></tr>
+    <tr><td><code>Package</code> 鏍瑰睘鎬�</td><td>Name/Version/OS/Architecture锛屾敮鎸� <code>$(鍙橀噺)</code> + <code>Condition</code></td></tr>
+    <tr><td><code>Dependencies</code> / <code>PackageDependency</code></td><td>澹版槑瀵瑰叾浠栧寘鐨勬渶灏忕増鏈姹傦紱Action = Required / Recommended / Optional</td></tr>
+    <tr><td><code>PluginDependencies</code></td><td>澹版槑杩愯鏃� .NET 绋嬪簭闆嗕緷璧栵紙闈炲寘绾э級锛岀敤浜庡姞杞介『搴忎笌鍐茬獊鎻愮ず</td></tr>
+    <tr><td><code>Files</code> / <code>File</code></td><td>閮ㄧ讲甯冨眬锛�<code>Path</code>锛堢洰鏍囷級+ <code>SourcePath</code>锛堟簮锛夛紝鍙甫 <code>Action="Install|WriteCode"</code>銆�<code>SetAssemblyInfo</code>锛堝啓鐗堟湰/鍏徃鍏冩暟鎹級銆�<code>SignCertificate</code>锛� Authenticode 绛惧悕锛�</td></tr>
+    <tr><td><code>PackageActionExtensions</code></td><td>瀹夎鍓嶅悗鎵ц澶栭儴鍙墽琛�/鑴氭湰锛堝鏉冮檺淇銆侀┍鍔ㄥ畨瑁呭櫒锛�</td></tr>
+    <tr><td><code>Variables/Condition</code></td><td>涓�浠芥竻鍗曡法骞冲彴澶嶇敤锛屾瀯寤烘椂鎸夊彉閲忚鍓枃浠堕泦</td></tr>
+    <tr><td><code>TypeTags</code></td><td>缁欐彃浠剁被鎵撴爣绛撅紝缂栬緫鍣ㄥ彲鎸� tag 杩囨护锛堝 "PowerSupply" tag 鍙樉绀虹數婧愶級</td></tr>
+</table>
+
+<!-- ============================================================ -->
+<h2 id="s6">6. 渚濊禆瑙f瀽涓庣増鏈ā鍨�</h2>
+
+<ul>
+    <li><strong>SemVer 2.0</strong>锛氬寘鐗堟湰涓ユ牸閬靛惊 <code>MAJOR.MINOR.PATCH</code> + 棰勫彂甯冩爣璇嗭紙<code>-alpha.1</code>锛夈��</li>
+    <li><strong>瑙f瀽鍣�</strong>锛�<code>OpenTap.Package</code> 鍐呯疆姹傝В鍣紝澶勭悊 <code>瀹夎 A 鈫� A 渚濊禆 B 鈮�2.0 鈫� 宸茶 B 1.3 鈫� 鐢熸垚"鍗囩骇 B"璁″垝</code>锛涘鍖呬氦鍙変緷璧栫敤鍥炴函鎼滅储姹傛渶灏忓彉鏇撮泦銆�</li>
+    <li><strong>闄嶇骇淇濇姢</strong>锛�<code>install</code> 榛樿鎷掔粷闄嶇骇宸插畨瑁呭寘锛岄櫎闈� <code>--force</code>銆�</li>
+    <li><strong>鍐茬獊澶勭悊</strong>锛氬悓涓�鏂囦欢琚袱涓寘澹版槑 鈫� 鍚庤�呭畨瑁呮姤閿欐彁绀� ownership 鍐茬獊锛涢�氳繃 <code>Packages/&lt;name&gt;/</code> 鐩綍绾﹀畾鍩烘湰鍙伩鍏嶃��</li>
+    <li><strong>OpenTAP 鍐呮牳鐗堟湰鍏煎</strong>锛氭墍鏈夊寘閮戒緷璧� <code>OpenTAP</code> 鍖呮湰韬紱鍐呮牳鍗囩骇鍚庢棫鍖呮寜 <code>&lt;PackageDependency Version="9.31.0"&gt;</code> 鐨勬渶灏忕増鏈尮閰嶄繚鎸佸吋瀹癸紝9.x 淇濇寔 ABI 鎵胯銆�</li>
+</ul>
+
+<!-- ============================================================ -->
+<h2 id="s7">7. 椹卞姩鎻掍欢寮�鍙�-鍒嗗彂-瀹夎宸ヤ綔娴�</h2>
+
+<div class="mermaid">
+sequenceDiagram
+    participant Dev as 椹卞姩寮�鍙戣��
+    participant VS as VS / dotnet CLI
+    participant Tap as tap CLI
+    participant Repo as 鍖呬粨搴�
+    participant User as 鐜板満宸ョ▼甯�
+
+    Dev->>VS: NuGet 寮曠敤 OpenTap / OpenTap.Package SDK
+    Dev->>VS: 缂栧啓 `class MyCanInstrument : Instrument`
+    VS->>VS: dotnet build 鈫� 鐢熸垚 DLL
+    Dev->>Tap: tap package create package.xml
+    Tap->>Tap: 鏍¢獙娓呭崟 + ZIP 鎵撳寘 鈫� MyCan.opentap
+    Dev->>Repo: 涓婁紶鍒扮鏈変粨搴� (HTTP 鏈嶅姟鍣�/鏂囦欢鍏变韩)
+    User->>Tap: tap repo add http://鍐呯綉浠撳簱
+    User->>Tap: tap package install MyCan -y
+    Tap->>Repo: 瑙f瀽渚濊禆 鈫� 涓嬭浇 .opentap
+    Tap->>Tap: 鎸夋竻鍗曢儴缃插埌 Packages/MyCan/
+    Note over User: 閲嶅惎缂栬緫鍣�/CLI锛屾柊浠櫒鑷姩鍑虹幇鍦ㄤ笅鎷夊垪琛�
+</div>
+
+<h3>寮�鍙戠幆澧冧緷璧�</h3>
+<ul>
+    <li>NuGet 鍖咃細<code>OpenTap</code>銆�<code>OpenTap.Package</code>锛堟彁渚� SDK 寮曠敤锛岀紪璇戞湡锛�</li>
+    <li>VS 鎵╁睍锛�<em>OpenTAP Project Templates</em>锛堝惈 Instrument 鎻掍欢椤圭洰妯℃澘锛�</li>
+    <li>璋冭瘯鏂瑰紡锛氭妸缂栬瘧浜х墿 DLL 鐩存帴鎷峰埌瀹夎鐩綍 <code>Packages/xxx/</code>锛屽惎鍔� <code>tap ui</code>锛堟闈㈢増锛夋垨浣犱滑鑷繁鐨勭紪杈戝櫒瀹夸富璋冭瘯</li>
+    <li>娉ㄦ剰锛�<strong>鎻掍欢 SDK 鏄� netstandard2.0/net472 鍙岀洰鏍�</strong>锛屼笌浣犱滑 .NET Framework 4.7.2 涓荤▼搴忓吋瀹�</li>
+</ul>
+
+<!-- ============================================================ -->
+<h2 id="s8">8. Image API锛氬畨瑁呯洰褰曠姸鎬佺鐞�</h2>
+
+<p>OpenTAP 9.15+ 寮曞叆 <code>OpenTap.Package.Image</code> 姒傚康锛屾妸"瀹夎鐩綍褰撳墠鐘舵��"鎶借薄鎴愬璞★細</p>
+
+<pre><code><span class="cmt">// 绋嬪簭鍖栫鐞嗕竴涓� OpenTAP 瀹夎鐩綍锛圕LI 搴曞眰灏辨槸瀹冿級</span>
+<span class="kwd">var</span> image = <span class="kwd">new</span> Image(<span class="str">"C:/Program Files/OpenTAP"</span>);
+image.InstallPackage(<span class="str">"MyCompany.CanDriver"</span>, <span class="str">"latest"</span>, <span class="str">"release"</span>);
+image.QueryAvailable(<span class="str">"CAN"</span>);           <span class="cmt">// 鍒楀嚭鍊欓�夊寘</span>
+image.UninstallPackage(<span class="str">"OldDriver"</span>);    <span class="cmt">// 鎸夋竻鍗曠簿纭垹闄�</span></code></pre>
+
+<div class="info">瀵逛綘浠殑浠峰�硷細鏈潵濡傛灉鍋�"HMI 鍐呭祵椹卞姩甯傚満"锛屽彲浠ョ洿鎺ヨ皟 Image API 瀹炵幇<strong>鐣岄潰閲岀偣鍑犱笅瀹屾垚椹卞姩鍗囩骇</strong>锛屾棤闇�杩愮淮浠嬪叆銆�</div>
+
+<!-- ============================================================ -->
+<h2 id="s9">9. 涓� TapProject 鐜版湁鏋舵瀯鐨勬槧灏勪笌宸窛</h2>
+
+<h3>9.1 姒傚康瀵圭収琛�</h3>
+<table>
+    <tr><th>TapProject 鐜版湁</th><th>OpenTAP 瀵瑰簲鐗�</th><th>鍖归厤搴�</th></tr>
+    <tr><td>IDeviceDriver + DriverFactory switch</td><td>Instrument 瀛愮被 + PluginSearcher 鍙嶅皠鍙戠幇</td><td>鉁� 鐩存帴鏇挎崲</td></tr>
+    <tr><td>DeviceConfig锛圫QLite DeviceDefinition锛�</td><td>BenchStore / ResourceSettings锛圶ML settings store锛�</td><td>鈿狅笍 闇�瑕佸弻鍚戝悓姝ラ�傞厤鍣�</td></tr>
+    <tr><td>IResourceManager 棰勭害 + ResourceOwnerToken 绉熺害</td><td>SynchronizationManager锛堜粎杩涚▼鍐呴攣锛�</td><td>鉂� OpenTAP 娌℃湁璺ㄨ繘绋�/璺ㄤ細璇濅徊瑁侊紝<strong>蹇呴』淇濈暀浣犱滑鐨�</strong></td></tr>
+    <tr><td>IAutoDeviceFacade + IAutoDeviceLease锛圥er-Step锛�</td><td>TestStep 灞炴�х粦瀹� Instrument + RequestLock</td><td>鉁� 璇箟绛変环锛岀绾︽洿缁�</td></tr>
+    <tr><td>HMI 鎻掍欢 PluginLoader锛圵PF UI锛�</td><td>鏃犲搴旓紙OpenTAP 涓嶇 UI锛�</td><td>鈥� 淇濇寔鐙珛</td></tr>
+    <tr><td>椹卞姩鍒嗗彂=鎷� DLL+閲嶇紪璇�</td><td>.opentap 鍖� + tap package install + 绉佹湁浠撳簱</td><td>鉁� 鏈鏀归�犳牳蹇冩敹鐩�</td></tr>
+</table>
+
+<h3>9.2 妗ユ帴璁捐锛氬弻杞ㄥ苟琛�</h3>
+<div class="mermaid">
+graph TB
+    subgraph 缁熶竴灞俒"Aging.Infrastructure锛堜繚鐣欙級"]
+        F["IAutoDeviceFacade"]
+        L["IAutoDeviceLease"]
+        RM["IResourceManager锛堣法浼氳瘽浠茶锛�"]
+    end
+    subgraph 閫傞厤灞俒"鏂板锛欴river 閫傞厤"]
+        REG["DriverRegistry<br/>鍙嶅皠鎵弿 Drivers/*.dll<br/>锛堥樁娈典竴锛岃嚜鐮旇交閲忥級"]
+        BRIDGE["TapInstrumentBridge<br/>OpenTAP Instrument 鈫� IDeviceDriver<br/>锛堥樁娈典簩锛屽彲閫夛級"]
+    end
+    subgraph 椹卞姩鐢熸�乕"涓ょ椹卞姩褰㈡�佸苟瀛�"]
+        D1["鑷爺椹卞姩<br/>IDeviceDriverProvider<br/>鈫� 鎵� .opentap 鍖呭垎鍙�"]
+        D2["绗笁鏂� OpenTAP 浠櫒鍖�<br/>Keysight/NationalInstruments<br/>鈫� tap package install 鐩存帴鐢�"]
+    end
+    F --> RM
+    F --> REG
+    REG --> D1
+    BRIDGE --> D2
+    BRIDGE --> REG
+</div>
+
+<h3>9.3 涓変釜鍏抽敭宸窛涓庡绛�</h3>
+<table>
+    <tr><th>宸窛</th><th>褰卞搷</th><th>瀵圭瓥</th></tr>
+    <tr><td>OpenTAP 鏃犵敓浜�/缁存姢浜掓枼浠茶</td><td>鍏ㄨ嚜鍔ㄤ笌鎵嬪姩璋冭瘯鍙兘鎾炶溅锛堟鏄綘浠仛绉熺害鐨勫姩鏈猴級</td><td>淇濈暀 IResourceManager锛屽湪 Instrument.Open() 閲岃皟鐢� Reserve锛汣lose() 閲� Release</td></tr>
+    <tr><td>浠櫒閰嶇疆鍙屾簮锛圫QLite vs settings store锛�</td><td>娉ㄥ唽椤垫敼绔偣銆佸簭鍒楅噷鐢ㄦ棫鍦板潃</td><td>浠� DeviceConfig 涓哄敮涓�鐪熸簮锛屽啓涓�涓鍑哄櫒鐢熸垚 <code>InstrumentSettings.xml</code>锛涙垨鍙嶅悜瀵煎叆</td></tr>
+    <tr><td>浣犱滑鐨� HMI 瀹夸富 鈮� OpenTAP Editor</td><td>浠櫒涓嬫媺妗嗗湪 WPF 閲屼笉浼氳嚜鍔ㄥ嚭鐜�</td><td>浣犱滑鐨� DeviceEditModal 浠� DriverRegistry/PluginManager 鏋氫妇绫诲瀷濉厖 ComboBox锛堝凡鏈� ForceRefreshForTest 妯″紡锛屽悓鐞嗭級</td></tr>
+</table>
+
+<!-- ============================================================ -->
+<h2 id="s10">10. 钀藉湴璺嚎寤鸿涓庢垚鏈瘎浼�</h2>
+
+<table>
+    <tr><th>闃舵</th><th>鍋氫粈涔�</th><th>宸ヤ綔閲�</th><th>鏀剁泭</th></tr>
+    <tr>
+        <td><strong>闃舵 0锛堝凡瀹屾垚锛�</strong></td>
+        <td>AutoDeviceFacade + Lease + 绫诲瀷鍖� CAN 鏈嶅姟</td>
+        <td>鈥�</td>
+        <td>璋冪敤浣撻獙宸茶В鍐�</td>
+    </tr>
+    <tr>
+        <td><strong>闃舵 1</strong></td>
+        <td>鑷爺 <code>IDeviceDriverProvider</code> + <code>DriverRegistry</code> 鍙嶅皠鎵弿 <code>Drivers/*.dll</code>锛�<br>CAN 椹卞姩鎷嗘垚鐙珛椤圭洰锛堜涪 DLL 鍏嶇紪璇戜富绋嬪簭锛�</td>
+        <td>~2-3 浜烘棩</td>
+        <td>瑙e喅"鍔犻┍鍔ㄥ繀椤婚噸缂栬瘧"鐨� 80% 鐥涚偣锛涙妧鏈爤鏃犲紩鍏�</td>
+    </tr>
+    <tr>
+        <td><strong>闃舵 2</strong></td>
+        <td>缁欐瘡涓┍鍔ㄥ伐绋嬪姞 <code>package.xml</code>锛岀敤 <code>tap package create</code> 浜у嚭 <code>.opentap</code>锛涙惌鍐呯綉绉佹湁浠撳簱锛堟枃浠舵湇鍔″櫒鍗冲彲锛�</td>
+        <td>~2 浜烘棩</td>
+        <td>鐗堟湰鍖栧垎鍙戙�佷緷璧栨鏌ャ�佺幇鍦� <code>tap package install</code> 涓�閿</td>
+    </tr>
+    <tr>
+        <td><strong>闃舵 3锛堝彲閫夛級</strong></td>
+        <td><code>TapInstrumentBridge</code>锛氭柊鐪熺‖浠朵华鍣ㄧ洿鎺ュ啓 <code>Instrument</code> 瀛愮被璧� OpenTAP 鐢熸�侊紱妗ユ帴鍥� IDeviceDriver 澶嶇敤绉熺害</td>
+        <td>~5-10 浜烘棩</td>
+        <td>鍙洿鎺ュ鐢� Keysight NI-DMM銆丳ickering 寮�鍏崇瓑鏁扮櫨涓幇鎴愬畼鏂瑰寘锛�<strong>鐪佸幓鑷爺 SCPI 椹卞姩</strong></td>
+    </tr>
+    <tr>
+        <td><strong>闃舵 4锛堣繙鏈燂級</strong></td>
+        <td>HMI 鍐呭祵"椹卞姩绠$悊鍣�"椤甸潰璋� Image API 鍋氱晫闈㈢骇鍗囩骇</td>
+        <td>~3 浜烘棩</td>
+        <td>杩愮淮鑷姩鍖�</td>
+    </tr>
+</table>
+
+<div class="warn">
+<strong>椋庨櫓鎻愮ず锛�</strong>
+<ul>
+    <li>闃舵 1 鍙嶅皠鍔犺浇鑻ョ敤 <code>Assembly.LoadFrom</code> 浼氶攣鏂囦欢瀵艰嚧鏃犳硶鐑浛鎹紱寤鸿 <code>AssemblyLoadContext</code>锛�.NET Core 椋庢牸锛宯et472 鏃犳 API 鈫� 閫�鍖栦负 <code>AppDomain</code> 闅旂鎴栨帴鍙�"閲嶅惎鐢熸晥"锛夈��</li>
+    <li>OpenTAP 9.31 鐨� netstandard2.0 鎻掍欢 SDK 鍦� net472 杩愯姝e父锛屼絾 <strong>涓嶈鍋囪</strong>鍏跺寘绠$悊鍣ㄤ細绠$悊 net472 涓荤▼搴忊�斺�斿畠绠$悊鐨勬槸 OpenTAP 瀹夎鐩綍锛涗綘浠富绋嬪簭鑻ヨ鍒╃敤 .opentap锛岄渶瑕佹妸寮曟搸瑁呮垚涓�涓�"宓屽叆寮� OpenTAP 鐩綍"銆�</li>
+    <li>绉佹湁鍖呬粨搴撴棤閴存潈鏃舵敞鎰忓唴缃戦殧绂伙紱瀹樻柟浠撳簱鍦板潃鍙� <code>tap repo remove</code> 绂佺敤澶栫綉璁块棶銆�</li>
+</ul>
+</div>
+
+<!-- ============================================================ -->
+<h2 id="s11">11. 缁撹</h2>
+
+<div class="success">
+<ol>
+    <li><strong>OpenTAP 鐨� Instrument 鏄�"璧勬簮鍨嬫彃浠�"</strong>锛氱户鎵� <code>Instrument : Resource</code> 鍗宠嚜鍔ㄨ幏寰楀彂鐜般�佸簭鍒楀寲缁戝畾銆佺敓鍛藉懆鏈熸墭绠★紱SCPI 鍦烘櫙鏈夊紑绠卞嵆鐢ㄧ殑 <code>ScpiInstrument</code>銆�</li>
+    <li><strong>鎻掍欢鍖咃紙.opentap锛夋槸鍒嗗彂鍗曞厓鑰岄潪寮曠敤鍗曞厓</strong>锛歓IP + package.xml锛屼緷璧栬В鏋愮敤 SemVer锛屽钩鍙板樊寮傚寲闈犳潯浠跺彉閲忥紱瀹夎鍒� <code>Packages/&lt;name&gt;/</code> 闅旂鐩綍锛屽嵏杞界簿纭寜娓呭崟銆�</li>
+    <li><strong>"鍏嶉噸缂栬瘧鍔犻┍鍔�"涓ゆ潯璺兘鑳借蛋</strong>锛氳交閲忚嚜鐮� DriverRegistry锛堥樁娈� 1锛岀珛鍒昏鏁堬級锛屾垨鎷ユ姳 OpenTAP 鍖呯敓鎬侊紙闃舵 2/3锛岄暱鏈熸敹鐩婂ぇ锛屽彲鐧藉珫鍘傚晢瀹樻柟椹卞姩锛夈��</li>
+    <li><strong>浣犱滑鐨� IResourceManager 绉熺害浣撶郴鏄� OpenTAP 缂哄け鐨勮兘鍔�</strong>锛屾敼閫犱腑搴斾繚鐣欏苟鍓嶇Щ鍒� Instrument.Open()/Close() 閽╁瓙锛岃�屼笉鏄鏇夸唬銆�</li>
+    <li><strong>鎺ㄨ崘缁勫悎</strong>锛氶樁娈� 1 鍏堣锛�2-3 浜烘棩瑙e喅涓荤棝鐐癸級鈫� 闃舵 2 涓婄鏈変粨搴擄紙鍐� 2 浜烘棩锛夆啋 鎸夌湡瀹炵‖浠堕渶姹傚喅瀹氭槸鍚﹁繘闃舵 3銆�</li>
+</ol>
+</div>
+
+<footer>
+    OpenTAP Instrument + 鎻掍欢鍖呮満鍒跺垎鏋� 路 TapProject 椹卞姩鐑彃鎷旇皟鐮� 路 2026-11-03<br>
+    鍙傝�冿細opentap.io 鏂囨。銆乬ithub.com/opentap/opentap锛坧ackage.xml / Engine/Instrument.cs 婧愮爜瀹炴祴锛�
+</footer>
+
+<script>
+    mermaid.initialize({ 
+        startOnLoad: true, theme: 'default', securityLevel: 'loose',
+        fontFamily: 'Segoe UI, Microsoft YaHei, sans-serif',
+        flowchart: { curve: 'basis', padding: 16 },
+        sequence: { showSequenceNumbers: false, actorMargin: 50 }
+    });
+</script>
+
+</body>
+</html>

--
Gitblit v1.9.1