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 化 + 多设备并发调试 + 后台生命周期管理
---
Plugin.IntegrationTest/MainWindow.xaml.cs | 469 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 443 insertions(+), 26 deletions(-)
diff --git a/Plugin.IntegrationTest/MainWindow.xaml.cs b/Plugin.IntegrationTest/MainWindow.xaml.cs
index 3e80e2d..995ecc0 100644
--- a/Plugin.IntegrationTest/MainWindow.xaml.cs
+++ b/Plugin.IntegrationTest/MainWindow.xaml.cs
@@ -8,8 +8,12 @@
using System.Windows;
using System.Windows.Media;
using System.Windows.Threading;
+using Aging.Infrastructure;
+using Aging.Infrastructure.Contracts;
using Aging.Infrastructure.Drivers;
+using Aging.Infrastructure.Services;
using CanSimulator;
+using HMI.Core.Util;
using log4net;
using Plugin.DeviceConfig.Entity;
using Plugin.DeviceConfig.Model;
@@ -38,6 +42,14 @@
private CanBusSimulator? _canBus;
private CanDebugPanel? _canDebugPanel;
+ // V3.0锛欴eviceBroker 瀹夸富瀛愯繘绋嬶紙瀛樺湪 Broker 璁惧鏃惰嚜鍔ㄦ媺璧凤級
+ private System.Diagnostics.Process? _brokerProcess;
+
+ // 鑷姩鍖栨祴璇曟湇鍔�
+ private IAutoDeviceFacade? _autoFacade;
+ private ICanBusService? _canBusService;
+ private CancellationTokenSource? _autoCts;
+
public MainWindow()
{
InitializeComponent();
@@ -51,9 +63,22 @@
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
- // 娓呯悊 CAN 妯℃嫙鍣�
- _canBus?.Dispose();
- CanDriverAdapter.ResetAllBuses();
+ // 鍙栨秷姝e湪杩愯鐨勮嚜鍔ㄥ寲娴嬭瘯
+ try { _autoCts?.Cancel(); } catch { }
+
+ // 鍋滄 DeviceBroker 瀹夸富锛堝叾鎸佹湁鐨勭墿鐞嗕細璇濋殢杩涚▼閫�鍑洪噴鏀撅紝绉熺害闈� TTL 杩囨湡+浜哄伐鍥炴敹锛�
+ try
+ {
+ if (_brokerProcess != null && !_brokerProcess.HasExited)
+ {
+ _brokerProcess.Kill();
+ _brokerProcess.WaitForExit(3000);
+ }
+ _brokerProcess?.Dispose();
+ }
+ catch { }
+
+ // CAN 妯℃嫙鍣ㄥ凡澶栭儴鍖栦负鐙珛鏈嶅姟杩涚▼锛屾湰杩涚▼鏃犺繘绋嬪唴鎬荤嚎闇�娓呯悊
// 涓嶅垹闄ゆ祴璇曠洰褰曪紝淇濈暀鏁版嵁浠ヤ究閲嶅惎鍚庢仮澶�
// 锛堝闇�鎵嬪姩閲嶇疆锛屼娇鐢ㄥ伐鍏锋爮涓殑 "閲嶇疆鏁版嵁" 鎸夐挳锛�
@@ -74,22 +99,26 @@
try
{
- // 鍒濆鍖栦华鍣ㄤ华琛ㄦ敞鍐屾彃浠�
+ // 鍒濆鍖栦华鍣ㄤ华琛ㄦ敞鍐屾彃浠讹紙寤哄簱 data.db锛�
_deviceConfigPlugin = new Plugin.DeviceConfig.DeviceConfig();
_deviceConfigPlugin.SetBaseFolder(_testDir);
_deviceConfigPlugin.SetLogger(_testLog);
_deviceConfigPlugin.InitFinish();
deviceConfigHost.Child = _deviceConfigPlugin;
- // 鍒濆鍖栫‖浠惰皟璇曟彃浠�
+ // 棰勭疆 CAN 娴嬭瘯璁惧锛堝繀椤诲湪鍩虹璁炬柦鍒濆鍖栧墠鍐欏叆锛孊ootstrapper 鎹娉ㄥ唽浠g悊椹卞姩锛�
+ SeedPresetCanDevices();
+
+ // 鍒濆鍖栧熀纭�璁炬柦 & 鑷姩鍖栨湇鍔★紙蹇呴』鍦� DeviceDebug.InitFinish 涔嬪墠锛�
+ // 瀹冧粠 UtilContainer 鎷夊彇 DeviceManager/ResourceManager锛屾敞鍐屽湪 Bootstrapper.Initialize 瀹屾垚锛�
+ InitializeAutoServices();
+
+ // 鍒濆鍖栫‖浠惰皟璇曟彃浠讹紙姝ゆ椂鍩虹璁炬柦鏈嶅姟宸插氨缁紝缁存姢绉熺害/椹卞姩澶嶇敤閾捐矾鍙敤锛�
_deviceDebugPlugin = new Plugin.DeviceDebug.DeviceDebug();
_deviceDebugPlugin.SetBaseFolder(_testDir);
_deviceDebugPlugin.SetLogger(_testLog);
_deviceDebugPlugin.InitFinish();
deviceDebugHost.Child = _deviceDebugPlugin;
-
- // 棰勭疆 CAN 娴嬭瘯璁惧锛堟柟渚跨洿鎺ラ獙璇侀┍鍔ㄤ笌闈㈡澘锛�
- SeedPresetCanDevices();
// 鍒锋柊鎻掍欢鍐呴儴鍒楄〃锛堥渶鎵嬪姩璋冪敤鎻掍欢鏂规硶锛�
_deviceConfigPlugin.ForceRefreshForTest();
@@ -107,7 +136,8 @@
Log(" 2. 宸查缃� CAN-001 (CAN_BUS_1:0) 鍜� CAN-002 (CAN_BUS_1:1) 渚涙祴璇�");
Log(" 3. 鍒囨崲鍒� '纭欢璋冭瘯' Tab锛岄�夋嫨 CAN-001 浼氳嚜鍔ㄦ墦寮� CAN 闈㈡澘骞惰繛鎺ユ�荤嚎");
Log(" 4. 鍒囨崲鍒� 'CAN 妯℃嫙鍣�' Tab 鍙墜鍔ㄦ帶鍒舵�荤嚎鎴栧彟涓�涓妭鐐瑰彂閫佹暟鎹�");
- Log(" 5. 鍙殢鏃剁偣鍑� '杩愯鑷姩鍖栨祴璇�' 楠岃瘉鏍稿績閫昏緫");
+ Log(" 5. 鍒囨崲鍒� '鍏ㄨ嚜鍔ㄦ祴璇�' Tab 鍙綋楠屾柟妗� B+C 鐨勮嚜鍔ㄥ寲姝ラ");
+ Log(" 6. 鍙殢鏃剁偣鍑� '杩愯鑷姩鍖栨祴璇�' 楠岃瘉鏍稿績閫昏緫");
}
catch (Exception ex)
{
@@ -628,6 +658,402 @@
}
}
+ #region 鍏ㄨ嚜鍔ㄦ祴璇曪紙鏂规 B+C锛�
+
+ /// <summary>
+ /// 鍒濆鍖栬嚜鍔ㄥ寲鏈嶅姟锛�
+ /// 1) 鍚姩 Infrastructure Bootstrapper锛圧esourceManager/DeviceManager/DeviceService/AutoDeviceFacade/CanBusService锛�
+ /// 2) 涓洪缃� CAN 璁惧娉ㄥ唽椹卞姩
+ /// 3) 灏嗚澶囧垪琛ㄥ~鍒� UI 涓嬫媺妗�
+ /// </summary>
+ private void InitializeAutoServices()
+ {
+ try
+ {
+ // 鍒濆鍖栧熀纭�璁炬柦锛堝箓绛夛紝宸插垵濮嬪寲鏃惰嚜鍔ㄨ烦杩囷級
+ string dbPath = Path.Combine(_testDir, "data.db");
+ try { InfrastructureBootstrapper.Initialize(dbPath); }
+ catch (Exception ex) { Log($"[WARN] Bootstrapper 鍒濆鍖栧紓甯�: {ex.Message}"); }
+
+ // 浠� UtilContainer 鎷夊彇鏈嶅姟瀹炰緥
+ var container = new UtilContainer();
+ _autoFacade = container.GetUtil<IAutoDeviceFacade>("AutoDeviceFacade");
+ _canBusService = container.GetUtil<ICanBusService>("CanBusService");
+
+ // 涓洪缃澶囨敞鍐岄┍鍔紙鑷姩鍚姩 CAN 鎬荤嚎锛�
+ RegisterCanDriver("CAN-001", "CAN_BUS_1:0");
+ RegisterCanDriver("CAN-002", "CAN_BUS_1:1");
+
+ // 鍒濆鍖栬澶囦笅鎷夊垪琛�
+ autoTxDeviceCombo.ItemsSource = new[] { "CAN-001", "CAN-002" };
+ autoRxDeviceCombo.ItemsSource = new[] { "CAN-002", "CAN-001" };
+ autoTxDeviceCombo.SelectedIndex = 0;
+ autoRxDeviceCombo.SelectedIndex = 0;
+
+ if (_autoFacade != null && _canBusService != null)
+ {
+ Log("[INFO] AutoDeviceFacade 鍜� CanBusService 宸插氨缁�");
+ Log("[INFO] CAN-001 / CAN-002 椹卞姩宸叉敞鍐�");
+ }
+ else
+ {
+ Log("[ERROR] 鑷姩鍖栨湇鍔℃湭姝g‘鍒濆鍖栵紝鍏ㄨ嚜鍔ㄦ祴璇� Tab 涓嶅彲鐢�");
+ autoRunBtn.IsEnabled = false;
+ }
+
+ // V3.0锛氳嫢閰嶇疆搴撳瓨鍦� Broker 鍩熻澶囷紝鑷姩鎷夎捣 DeviceBroker.exe 瀹夸富
+ TryStartDeviceBroker();
+ }
+ catch (Exception ex)
+ {
+ Log($"[ERROR] 鍒濆鍖栬嚜鍔ㄥ寲鏈嶅姟澶辫触: {ex.Message}");
+ Log(ex.StackTrace ?? "");
+ autoRunBtn.IsEnabled = false;
+ }
+ }
+
+ /// <summary>
+ /// V3.0锛氳嫢 data.db 涓瓨鍦� ExecutionMode=Broker 鐨勮澶囷紝鑷姩鎷夎捣 DeviceBroker.exe 瀹夸富瀛愯繘绋嬨��
+ /// 瀹夸富榛樿鍙傛暟鎸囧悜鏈幆澧冨悓涓� data.db/arb.db锛堝悓鏈轰徊瑁佸煙锛夛紱鎵句笉鍒板彲鎵ц鏂囦欢鏃堕檷绾т负璀﹀憡锛�
+ /// Broker 璁惧灏嗘姤 BROKER_UNREACHABLE锛孡ocal 璁惧涓嶅彈褰卞搷銆�
+ /// </summary>
+ private void TryStartDeviceBroker()
+ {
+ try
+ {
+ var model = new DeviceConfigModel();
+ string dbPath = Path.Combine(_testDir, "data.db");
+ if (!File.Exists(dbPath)) return;
+ model.InitDatabase(dbPath);
+ var brokerDevices = model.GetAllDevices()
+ .Where(d => d.ExecutionMode == Plugin.DeviceConfig.Entity.ExecutionModeKind.Broker)
+ .ToList();
+ if (brokerDevices.Count == 0)
+ {
+ Log("[INFO] 鏃� Broker 鍩熻澶囷紝鏈惎鍔� DeviceBroker 瀹夸富");
+ return;
+ }
+
+ string exe = FindDeviceBrokerExe();
+ if (exe == null)
+ {
+ Log("[WARN] 鏈壘鍒� DeviceBroker.exe锛孊roker 璁惧閾捐矾涓嶅彲鐢紙璇锋瀯寤� DeviceBroker 宸ョ▼锛�");
+ return;
+ }
+
+ var psi = new System.Diagnostics.ProcessStartInfo(exe)
+ {
+ Arguments = $"--db \"{dbPath}\" --arb \"{Path.Combine(_testDir, "arb.db")}\" --broker broker-b01",
+ UseShellExecute = false,
+ CreateNoWindow = true,
+ };
+ _brokerProcess = System.Diagnostics.Process.Start(psi);
+ Log($"[INFO] DeviceBroker 瀹夸富宸插惎鍔� (PID={_brokerProcess?.Id})锛孊roker 璁惧: " +
+ string.Join(", ", brokerDevices.Select(d => d.DeviceId)));
+ }
+ catch (Exception ex)
+ {
+ Log($"[WARN] 鍚姩 DeviceBroker 澶辫触: {ex.Message}");
+ }
+ }
+
+ private static string FindDeviceBrokerExe()
+ {
+ string baseDir = AppDomain.CurrentDomain.BaseDirectory;
+ var candidates = new[]
+ {
+ Path.Combine(baseDir, "DeviceBroker.exe"),
+ Path.Combine(baseDir, @"DeviceBroker\DeviceBroker.exe"),
+ Path.GetFullPath(Path.Combine(baseDir, @"..\..\..\..\DeviceBroker\bin\Debug\net472\DeviceBroker.exe")),
+ Path.GetFullPath(Path.Combine(baseDir, @"..\..\..\DeviceBroker\bin\Debug\net472\DeviceBroker.exe")),
+ };
+ foreach (var c in candidates)
+ {
+ try { if (File.Exists(c)) return c; } catch { }
+ }
+ return null;
+ }
+
+ /// <summary>
+ /// 鍚� DeviceManager 娉ㄥ唽 CAN 椹卞姩锛堜娇鐢� DriverFactory锛�
+ /// </summary>
+ private void RegisterCanDriver(string deviceId, string endpoint)
+ {
+ try
+ {
+ InfrastructureBootstrapper.RegisterDevice(deviceId, "CAN", endpoint);
+ }
+ catch (Exception ex)
+ {
+ Log($"[WARN] 娉ㄥ唽璁惧 {deviceId} 椹卞姩澶辫触: {ex.Message}");
+ }
+ }
+
+ /// <summary>
+ /// 杩愯鑷姩鍖栨楠わ紙灏佽瀹屾暣娴佺▼锛氬紑鎬荤嚎 鈫� 绉熺害 鈫� 鍙戦�� 鈫� 鍥炴敹 鈫� 閲婃斁锛�
+ /// </summary>
+ private async void AutoRunBtn_Click(object sender, RoutedEventArgs e)
+ {
+ if (_autoFacade == null || _canBusService == null)
+ {
+ AutoLog("[ERROR] 鏈嶅姟鏈垵濮嬪寲");
+ return;
+ }
+
+ string txDevice = autoTxDeviceCombo.SelectedItem as string ?? "CAN-001";
+ string rxDevice = autoRxDeviceCombo.SelectedItem as string ?? "CAN-002";
+
+ if (!int.TryParse(autoLoopCount.Text, out int loops) || loops <= 0)
+ {
+ AutoLog("[ERROR] 寰幆娆℃暟蹇呴』涓烘鏁存暟");
+ return;
+ }
+ if (!int.TryParse(autoInterval.Text, out int intervalMs) || intervalMs < 0)
+ {
+ intervalMs = 200;
+ }
+
+ // 纭繚鎬荤嚎宸插惎鍔紙浣跨敤 CAN-001 椹卞姩鏃朵細鑷姩鍚姩锛�
+ EnsureBusRunning();
+
+ // 鍚敤涓鎸夐挳
+ autoRunBtn.IsEnabled = false;
+ autoStopBtn.IsEnabled = true;
+ autoProgress.Maximum = loops;
+ autoProgress.Value = 0;
+ _autoCts = new CancellationTokenSource();
+ var ct = _autoCts.Token;
+
+ AutoLog("鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲");
+ AutoLog($" CAN 鑰佸寲鑷姩鍖栨楠ゅ紑濮�");
+ AutoLog($" 鍙戦�佽澶�: {txDevice}, 鐩爣璁惧: {rxDevice}");
+ AutoLog($" 寰幆娆℃暟: {loops}, 甯ч棿闅�: {intervalMs}ms");
+ AutoLog("鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲");
+
+ int successCount = 0;
+ int failCount = 0;
+ var swTotal = System.Diagnostics.Stopwatch.StartNew();
+
+ // ===== 鏂规 B锛氫綔鐢ㄥ煙绉熺害锛堜竴娆$敵璇凤紝澶氭浣跨敤锛� =====
+ try
+ {
+ using var lease = await _autoFacade.AcquireAsync(txDevice, "CAN_Aging", ct);
+ AutoLog($"[绉熺害] 宸茶幏寰� {txDevice} 浣滅敤鍩熺绾�: Session={lease.SessionId.Substring(0, 8)}, 鏃跺埢 {lease.AcquiredAt:HH:mm:ss.fff}");
+
+ // ===== 鏂规 C锛氫娇鐢ㄧ被鍨嬪寲鏈嶅姟 =====
+ // 鐩爣璁惧鍏堝惎鐢ㄨ嚜鍔ㄥ搷搴旓紙浠ヤ究鍥炵幆楠岃瘉锛�
+ using var rxLease = await _autoFacade.AcquireAsync(rxDevice, "CAN_Aging_Rx", ct);
+ AutoLog($"[绉熺害] 宸茶幏寰� {rxDevice} 浣滅敤鍩熺绾�: Session={rxLease.SessionId.Substring(0, 8)}");
+ await _canBusService.SetAutoResponseAsync(rxLease, true, ct);
+ AutoLog($"[閰嶇疆] 宸蹭负 {rxDevice} 鍚敤鑷姩鍝嶅簲妯″紡");
+
+ for (int i = 0; i < loops; i++)
+ {
+ if (ct.IsCancellationRequested) break;
+
+ uint frameId = (uint)(0x100 + i);
+ byte[] payload = new byte[] { (byte)i, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x5A };
+
+ // 鍙戦�侊紙璧� txDevice 绉熺害锛�
+ bool sent = await _canBusService.SendFrameAsync(lease, frameId, payload, ct);
+ AutoLog($"[T+{i,3:D3}] TX {frameId:X3} | {BitConverter.ToString(payload).Replace("-", " ")} {(sent ? "鉁�" : "鉁�")}");
+
+ // 鎺ユ敹鍥炲搷锛堣蛋 rxDevice 绉熺害锛�
+ await Task.Delay(intervalMs, ct);
+ var echo = await _canBusService.ReceiveFrameAsync(rxLease, ct);
+
+ if (echo != null)
+ {
+ AutoLog($"[R+{i,3:D3}] RX {echo.FrameIdHex} | {echo.DataHex} 鍖归厤={(echo.FrameId == frameId ? "鉁�" : "鉁�")}");
+ if (echo.FrameId == frameId && echo.Data.SequenceEqual(payload)) successCount++;
+ else failCount++;
+ }
+ else
+ {
+ AutoLog($"[R+{i,3:D3}] RX 鏃犲洖鍝�");
+ failCount++;
+ }
+
+ autoProgress.Value = i + 1;
+ autoProgressText.Text = $"{i + 1}/{loops} 瀹屾垚";
+ }
+
+ // 鏀跺熬锛氬叧闂嚜鍔ㄥ搷搴�
+ await _canBusService.SetAutoResponseAsync(rxLease, false, ct);
+ AutoLog($"[閰嶇疆] 宸蹭负 {rxDevice} 鍏抽棴鑷姩鍝嶅簲妯″紡");
+ }
+ catch (OperationCanceledException)
+ {
+ AutoLog("[涓] 鐢ㄦ埛鎵嬪姩涓娴嬭瘯");
+ }
+ catch (TimeoutException ex)
+ {
+ AutoLog($"[澶辫触] 绉熺害鐢宠瓒呮椂: {ex.Message}");
+ failCount++;
+ }
+ catch (InvalidOperationException ex)
+ {
+ AutoLog($"[澶辫触] 璧勬簮鍐茬獊: {ex.Message}");
+ failCount++;
+ }
+ catch (Exception ex)
+ {
+ AutoLog($"[寮傚父] {ex.GetType().Name}: {ex.Message}");
+ failCount++;
+ }
+ finally
+ {
+ swTotal.Stop();
+ // 浣跨敤 lease.Dispose() 浼氳嚜鍔ㄩ噴鏀剧绾︼紝鏃犻渶鎵嬪姩鍐欎唬鐮�
+ _autoCts?.Dispose();
+ _autoCts = null;
+
+ AutoLog("");
+ AutoLog("鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲");
+ AutoLog($" 姝ラ瀹屾垚 | 鎴愬姛 {successCount} | 澶辫触 {failCount} | 鎬昏�楁椂 {swTotal.ElapsedMilliseconds}ms");
+ AutoLog($" 绉熺害宸茶嚜鍔ㄩ噴鏀撅紙using 浣滅敤鍩熺粨鏉燂級");
+ AutoLog("鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲");
+
+ autoRunBtn.IsEnabled = true;
+ autoStopBtn.IsEnabled = false;
+ autoProgressText.Text = "灏辩华";
+ }
+ }
+
+ /// <summary>
+ /// 鍏ㄨ嚜鍔烽�愯澶囦竴娆℃敹鍙戯細妯℃嫙 TestPlan 鐨� TestStep锛屽 CAN-001~004 閫愪竴
+ /// 閫氳繃绫诲瀷鍖栨湇鍔�/闂ㄩ潰璋冪敤 CAN 椹卞姩锛屽畬鎴愨�滃彂閫佸懡浠も啋鎺ユ敹鍥炴樉鈥濅竴娆″畬鏁村線杩斻��
+ /// 渚濊禆鎬荤嚎搴旂瓟鍣紙BUS_ECHO锛変娇鍗曡澶囪嚜鍙戣嚜鏀讹紝鏃犻渶瀵圭璁惧銆�
+ /// </summary>
+ private async void PerDeviceCanTest_Click(object sender, RoutedEventArgs e)
+ {
+ if (_autoFacade == null || _canBusService == null)
+ {
+ AutoLog("[ERROR] 鏈嶅姟鏈垵濮嬪寲");
+ return;
+ }
+
+ var devices = new[] { "CAN-001", "CAN-002", "CAN-003", "CAN-004" };
+ perDeviceBtn.IsEnabled = false;
+ autoStopBtn.IsEnabled = true;
+ _autoCts = new CancellationTokenSource();
+ var ct = _autoCts.Token;
+ autoProgress.Maximum = devices.Length * 3 + 2;
+ autoProgress.Value = 0;
+
+ int passed = 0, failed = 0;
+ var sw = System.Diagnostics.Stopwatch.StartNew();
+ AutoLog("鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲");
+ AutoLog(" 鍏ㄨ嚜鍔烽�愯澶囦竴娆℃敹鍙戯紙妯℃嫙 TestPlan TestStep锛�");
+ AutoLog("鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲");
+
+ // 鍏ㄥ眬鍓嶇疆锛氬惎鐢ㄦ�荤嚎搴旂瓟鍣紙浣挎瘡娆″彂閫侀兘鑳芥敹鍒板洖鏄撅級
+ await RunStepAsync("鍏ㄥ眬", "鍚敤鎬荤嚎搴旂瓟鍣� BUS_ECHO:ON", async () =>
+ (await _autoFacade.QueryAsync(devices[0], "BUS_ECHO:ON", ct)).Success,
+ ok => { if (ok) passed++; else failed++; autoProgress.Value++; });
+
+ for (int idx = 0; idx < devices.Length; idx++)
+ {
+ if (ct.IsCancellationRequested) break;
+ string dev = devices[idx];
+ uint frameId = (uint)(0x300 + idx);
+ byte[] payload = new byte[] { (byte)idx, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
+
+ // TestStep 1锛氬彂閫佸懡浠ゅ抚锛圤neShot锛氬唴閮� 棰勭害鈫掓墽琛屸啋閲婃斁锛�
+ await RunStepAsync(dev, $"鍙戦�� 0x{frameId:X3}", async () =>
+ await _canBusService.SendFrameAsync(dev, frameId, payload, ct),
+ ok => { if (ok) passed++; else failed++; autoProgress.Value++; });
+
+ // TestStep 2锛氳Е鍙戝涓� drain锛圔roker 璁惧鍥炴樉缁忔鎹庡甫鍥炲鎴风缂撳啿锛�
+ await RunStepAsync(dev, "瑙﹀彂鍥炴樉鎹庡甫(STATUS)", async () =>
+ (await _autoFacade.QueryAsync(dev, "STATUS", ct)).Success,
+ ok => { if (ok) passed++; else failed++; autoProgress.Value++; });
+
+ // TestStep 3锛氭帴鏀跺洖鏄惧苟鏍¢獙甯� ID
+ await RunStepAsync(dev, "鎺ユ敹骞舵牎楠屽洖鏄�", async () =>
+ {
+ for (int t = 0; t < 10; t++)
+ {
+ var recv = await _canBusService.ReceiveFrameAsync(dev, ct);
+ if (recv != null)
+ {
+ bool match = recv.FrameId == frameId;
+ AutoLog($" [{dev}] RX {recv.FrameIdHex} | {recv.DataHex} 鍖归厤={(match ? "鉁�" : "鉁�")}");
+ return match;
+ }
+ await Task.Delay(80, ct);
+ }
+ AutoLog($" [{dev}] 鏈敹鍒板洖鏄�");
+ return false;
+ },
+ ok => { if (ok) passed++; else failed++; autoProgress.Value++; });
+ }
+
+ // 鍏ㄥ眬鏀跺熬锛氬叧闂�荤嚎搴旂瓟鍣�
+ await RunStepAsync("鍏ㄥ眬", "鍏抽棴鎬荤嚎搴旂瓟鍣� BUS_ECHO:OFF", async () =>
+ (await _autoFacade.QueryAsync(devices[0], "BUS_ECHO:OFF", ct)).Success,
+ ok => { if (ok) passed++; else failed++; autoProgress.Value++; });
+
+ sw.Stop();
+ AutoLog("鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�");
+ AutoLog($" 瀹屾垚 | 閫氳繃 {passed} | 澶辫触 {failed} | 鑰楁椂 {sw.ElapsedMilliseconds}ms");
+ AutoLog("鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲鈺愨晲");
+ autoProgressText.Text = $"閫氳繃 {passed} / 澶辫触 {failed}";
+ perDeviceBtn.IsEnabled = true;
+ autoStopBtn.IsEnabled = false;
+ _autoCts?.Dispose();
+ _autoCts = null;
+ }
+
+ /// <summary>妯℃嫙 TestPlan 鐨� TestStep锛氬懡鍚嶆楠� + 鏂█ + 璁板綍閫氳繃/澶辫触銆�</summary>
+ private async Task RunStepAsync(string device, string name, Func<Task<bool>> body, Action<bool> onDone)
+ {
+ AutoLog($"鈻� [TestStep] {device} :: {name}");
+ bool ok;
+ try { ok = await body(); }
+ catch (OperationCanceledException) { AutoLog(" [涓] 鐢ㄦ埛鍙栨秷"); throw; }
+ catch (Exception ex) { ok = false; AutoLog($" 寮傚父: {ex.Message}"); }
+ AutoLog($" {(ok ? "PASS 鉁�" : "FAIL 鉁�")}");
+ onDone(ok);
+ }
+
+ /// <summary>
+ /// 涓褰撳墠鑷姩鍖栨祴璇�
+ /// </summary>
+ private void AutoStopBtn_Click(object sender, RoutedEventArgs e)
+ {
+ _autoCts?.Cancel();
+ AutoLog("[涓] 宸插彂閫佸彇娑堣姹�...");
+ }
+
+ /// <summary>
+ /// 娓呯┖鑷姩鍖栨棩蹇�
+ /// </summary>
+ private void AutoClearLog_Click(object sender, RoutedEventArgs e)
+ {
+ autoLog.Clear();
+ }
+
+ /// <summary>
+ /// 鎬荤嚎鐢卞閮� CanSimulatorServer 鎵樼锛屾湰鍦版棤闇�鍐嶅惎鍔ㄨ繘绋嬪唴鎬荤嚎锛堜繚鐣欑┖瀹炵幇鍏煎鏃ц皟鐢級銆�
+ /// </summary>
+ private void EnsureBusRunning() { }
+
+ /// <summary>
+ /// 鍚戣嚜鍔ㄥ寲鏃ュ織鍖鸿拷鍔犳棩蹇�
+ /// </summary>
+ private void AutoLog(string msg)
+ {
+ string line = $"{DateTime.Now:HH:mm:ss.fff} {msg}";
+ Dispatcher.Invoke(() =>
+ {
+ autoLog.AppendText(line + Environment.NewLine);
+ autoLog.ScrollToEnd();
+ });
+ }
+
+ #endregion
+
#region CAN 妯℃嫙鍣�
/// <summary>
@@ -663,25 +1089,17 @@
return;
}
- // 閫氳繃 DriverFactory 鍒涘缓 CAN 椹卞姩鏉ュ惎鍔ㄦ�荤嚎
+ // 鎬荤嚎鐢卞閮ㄦā鎷熷櫒鏈嶅姟鎵樼锛氭澶勪粎楠岃瘉涓�涓妭鐐瑰彲鎺ュ叆锛堣繛閫氭�ф帰娴嬶級
var driver = DriverFactory.CreateDriver("CAN_SIM_0", "CAN", $"{busName}:0");
driver.ConnectAsync(CancellationToken.None).GetAwaiter().GetResult();
- // 鑾峰彇鎬荤嚎瀹炰緥
- var buses = CanDriverAdapter.GetAllBuses();
- if (buses.TryGetValue(busName, out var bus))
- {
- _canBus = bus;
- bus.Start();
+ // 鏇存柊 UI
+ canBusIndicator.Fill = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#4CAF50"));
+ canBusStatusText.Text = $"宸叉帴鍏ュ閮ㄦā鎷熷櫒 ({busName})";
+ canStartBtn.IsEnabled = false;
+ canStopBtn.IsEnabled = true;
- // 鏇存柊 UI
- canBusIndicator.Fill = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#4CAF50"));
- canBusStatusText.Text = $"杩愯涓� ({busName})";
- canStartBtn.IsEnabled = false;
- canStopBtn.IsEnabled = true;
-
- Log($"[CAN] 鎬荤嚎 {busName} 宸插惎鍔�");
- }
+ Log($"[CAN] 宸茶繛鎺ュ閮ㄦā鎷熷櫒鎬荤嚎 {busName}");
}
catch (Exception ex)
{
@@ -720,7 +1138,6 @@
{
try
{
- CanDriverAdapter.ResetAllBuses();
_canBus = null;
// 鏇存柊 UI
@@ -729,7 +1146,7 @@
canStartBtn.IsEnabled = true;
canStopBtn.IsEnabled = false;
- Log("[CAN] 鎵�鏈夋�荤嚎宸查噸缃�");
+ Log("[CAN] 鏈湴鐘舵�佸凡閲嶇疆锛堝閮ㄦā鎷熷櫒鎬荤嚎涓嶅彈褰卞搷锛�");
}
catch (Exception ex)
{
--
Gitblit v1.9.1