From b544d5cccd76735e034c8055918a50927b437474 Mon Sep 17 00:00:00 2001
From: wenxiangchao <wenxiangchao@ihengxin.com.cn>
Date: 星期二, 10 十一月 2026 08:29:04 +0800
Subject: [PATCH] fix: 维护模式重复进入失败与按钮灰死 + Broker 并发验证用例
---
Plugin.DeviceDebug/Panels/CanDebugPanel.xaml.cs | 558 ++++++++-----------------------------------------------
1 files changed, 88 insertions(+), 470 deletions(-)
diff --git a/Plugin.DeviceDebug/Panels/CanDebugPanel.xaml.cs b/Plugin.DeviceDebug/Panels/CanDebugPanel.xaml.cs
index aa8a60b..59b314b 100644
--- a/Plugin.DeviceDebug/Panels/CanDebugPanel.xaml.cs
+++ b/Plugin.DeviceDebug/Panels/CanDebugPanel.xaml.cs
@@ -1,44 +1,25 @@
-using Aging.Infrastructure.Drivers;
using log4net;
using Plugin.DeviceDebug.Entity;
using System;
-using System.Collections.ObjectModel;
-using System.Globalization;
-using System.Linq;
-using System.Threading;
using System.Windows;
using System.Windows.Controls;
-using System.Windows.Media;
-using System.Windows.Threading;
namespace Plugin.DeviceDebug.Panels
{
/// <summary>
- /// CAN 甯ф樉绀烘ā鍨�
- /// </summary>
- public class CanFrameDisplay
- {
- public DateTime Timestamp { get; set; }
- public string FrameId { get; set; } = string.Empty;
- public int Dlc { get; set; }
- public string Data { get; set; } = string.Empty;
- public string Direction { get; set; } = string.Empty; // TX / RX
- public string Source { get; set; } = string.Empty;
- }
-
- /// <summary>
- /// CanDebugPanel.xaml 鐨勪氦浜掗�昏緫
+ /// CAN 璋冭瘯闈㈡澘澶氶�氶亾澹筹細浠� TabControl 鎵胯浇鑻ュ共 <see cref="CanChannelView"/>锛�
+ /// 鏀寔鍚屽睆骞跺垪澶氫釜 CAN 閫氶亾鐙珛鏀跺彂锛堥獙鏀跺満鏅� 4锛夈��
+ /// 瀵瑰淇濇寔涓庢棫鍗曢潰鏉夸竴鑷寸殑灞炴�у绾︼紙DeviceId/InitialBusName/InitialNodeIndex/
+ /// AutoConnectOnLoad/ExistingDriver/IsMaintenanceMode/OnCommandExecute锛夛紝
+ /// DeviceDebug 閫夎澶囨椂杩欎簺閰嶇疆琚浆鍙戝埌"璁惧閫氶亾"锛堥涓� Tab锛夈��
/// </summary>
public partial class CanDebugPanel : UserControl
{
private static readonly ILog log = LogManager.GetLogger(typeof(CanDebugPanel));
- /// <summary>
- /// 鏄惁涓虹淮鎶ゆā寮忥紙鎺у埗杈撳叆鍙敤鎬э級
- /// </summary>
public static readonly DependencyProperty IsMaintenanceModeProperty =
DependencyProperty.Register(nameof(IsMaintenanceMode), typeof(bool), typeof(CanDebugPanel),
- new PropertyMetadata(false));
+ new PropertyMetadata(false, OnMaintenanceModeChanged));
public bool IsMaintenanceMode
{
@@ -46,498 +27,135 @@
set => SetValue(IsMaintenanceModeProperty, value);
}
- /// <summary>
- /// 鍛戒护鎵ц浜嬩欢
- /// </summary>
+ private static void OnMaintenanceModeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var panel = (CanDebugPanel)d;
+ if (panel._deviceChannel != null)
+ panel._deviceChannel.IsMaintenanceMode = (bool)e.NewValue;
+ }
+
+ /// <summary>鍛戒护鎵ц浜嬩欢锛堜换涓�閫氶亾瑙﹀彂鍧囦笂鎶涳紝渚� DeviceDebug 缁熶竴澶勭悊锛�</summary>
public event EventHandler<DebugCommand>? OnCommandExecute;
- /// <summary>
- /// 鎺ユ敹甯у垪琛�
- /// </summary>
- public ObservableCollection<CanFrameDisplay> ReceivedFrames { get; } = new();
+ private CanChannelView? _deviceChannel;
+ private int _manualSeq;
- /// <summary>
- /// CAN 椹卞姩閫傞厤鍣�
- /// </summary>
- private CanDriverAdapter? _driver;
-
- /// <summary>
- /// 杞瀹氭椂鍣紙鐢ㄤ簬妫�鏌ユ帴鏀堕偖绠憋級
- /// </summary>
- private DispatcherTimer? _pollTimer;
-
- /// <summary>
- /// 鏄惁宸茶繛鎺�
- /// </summary>
- private bool _isConnected;
-
- /// <summary>
- /// 璁惧ID锛堜粠 DeviceDebug 浼犲叆锛岄潰鏉胯嚜鍔ㄦ嫾鎺� deviceId锛�
- /// </summary>
- public string DeviceId
- {
- get => _deviceId;
- set
- {
- _deviceId = value;
- if (!string.IsNullOrEmpty(value))
- {
- // 灏嗚澶嘔D鍓嶇紑鎷兼帴鍒伴粯璁よ澶囨爣璇嗕腑锛岄伩鍏嶄笌妯℃嫙鍣ㄩ潰鏉块噸鍚�
- UpdateDeviceIdDisplay();
- }
- }
- }
+ // 寰呰浆鍙戝埌璁惧閫氶亾鐨勯厤缃紙鍙兘鏃╀簬閫氶亾鍒涘缓锛�
private string _deviceId = string.Empty;
-
- /// <summary>
- /// 浠庤澶� Endpoint 瑙f瀽鍑虹殑鎬荤嚎鍚嶇О
- /// </summary>
- public string InitialBusName { get; set; }
-
- /// <summary>
- /// 浠庤澶� Endpoint 瑙f瀽鍑虹殑鑺傜偣缂栧彿
- /// </summary>
- public int? InitialNodeIndex { get; set; }
-
- /// <summary>
- /// 鏄惁鑷姩杩炴帴锛堜粠 DeviceDebug 鎵撳紑鏃�=true锛�
- /// </summary>
- public bool AutoConnectOnLoad { get; set; }
+ private string _initialBusName;
+ private int? _initialNodeIndex;
+ private bool _autoConnectOnLoad;
+ private Aging.Infrastructure.Contracts.IDeviceDriver? _existingDriver;
public CanDebugPanel()
{
InitializeComponent();
- receiveList.ItemsSource = ReceivedFrames;
- InitializePollTimer();
- Loaded += CanDebugPanel_Loaded;
}
- private void CanDebugPanel_Loaded(object sender, RoutedEventArgs e)
+ /// <summary>璁惧ID锛堣浆鍙戝埌璁惧閫氶亾锛�</summary>
+ public string DeviceId
{
- Loaded -= CanDebugPanel_Loaded;
-
- // 浠庤澶囦俊鎭垵濮嬪寲鎬荤嚎/鑺傜偣杈撳叆
- if (!string.IsNullOrEmpty(InitialBusName))
- {
- busNameInput.Text = InitialBusName;
- }
- if (InitialNodeIndex.HasValue)
- {
- nodeIndexInput.Text = InitialNodeIndex.Value.ToString();
- }
-
- // 鑷姩杩炴帴
- if (AutoConnectOnLoad)
- {
- Dispatcher.BeginInvoke(new Action(() =>
- {
- try { DoConnect(); }
- catch (Exception ex) { log.Warn($"鑷姩杩炴帴澶辫触: {ex.Message}"); }
- }), DispatcherPriority.Background);
- }
+ get => _deviceId;
+ set { _deviceId = value; EnsureDeviceChannel().DeviceId = value; }
}
- private void UpdateDeviceIdDisplay()
+ /// <summary>鎬荤嚎鍚嶇О锛堣浆鍙戝埌璁惧閫氶亾锛�</summary>
+ public string InitialBusName
{
- if (!string.IsNullOrEmpty(_deviceId) && busNameInput != null)
- {
- // 淇濈暀榛樿鎬荤嚎鍚嶏紝浠呰褰� deviceId 浠ヤ緵鏃ュ織浣跨敤
- log.Info($"[CanDebugPanel] 鍏宠仈璁惧: {_deviceId}");
- }
+ get => _initialBusName;
+ set { _initialBusName = value; EnsureDeviceChannel().InitialBusName = value; }
}
- /// <summary>
- /// 鍒濆鍖栬疆璇㈠畾鏃跺櫒
- /// </summary>
- private void InitializePollTimer()
+ /// <summary>鑺傜偣缂栧彿锛堣浆鍙戝埌璁惧閫氶亾锛�</summary>
+ public int? InitialNodeIndex
{
- _pollTimer = new DispatcherTimer
- {
- Interval = TimeSpan.FromMilliseconds(100) // 100ms 杞涓�娆�
- };
- _pollTimer.Tick += PollTimer_Tick;
+ get => _initialNodeIndex;
+ set { _initialNodeIndex = value; EnsureDeviceChannel().InitialNodeIndex = value; }
}
- /// <summary>
- /// 杞瀹氭椂鍣ㄥ洖璋� - 浠呮洿鏂扮粺璁′俊鎭紙甯ф樉绀虹敱浜嬩欢椹卞姩锛�
- /// </summary>
- private void PollTimer_Tick(object? sender, EventArgs e)
+ /// <summary>鍔犺浇鍗宠嚜鍔ㄨ繛鎺ワ紙杞彂鍒拌澶囬�氶亾锛�</summary>
+ public bool AutoConnectOnLoad
{
- if (!_isConnected || _driver == null) return;
-
- try
- {
- // 鏇存柊缁熻
- UpdateStats();
- }
- catch (Exception ex)
- {
- log.Error($"杞缁熻鏇存柊澶辫触: {ex.Message}");
- }
+ get => _autoConnectOnLoad;
+ set { _autoConnectOnLoad = value; EnsureDeviceChannel().AutoConnectOnLoad = value; }
}
- /// <summary>
- /// 杩炴帴鎸夐挳鐐瑰嚮
- /// </summary>
- private void ConnectBtn_Click(object sender, RoutedEventArgs e)
+ /// <summary>澶栭儴宸叉敞鍐岄┍鍔紙杞彂鍒拌澶囬�氶亾锛屽叡浜澶囧鐢ㄥ涓婚�氳矾锛�</summary>
+ public Aging.Infrastructure.Contracts.IDeviceDriver? ExistingDriver
{
- try
- {
- DoConnect();
- }
- catch (Exception ex)
- {
- log.Error($"CAN 杩炴帴澶辫触: {ex.Message}", ex);
- MessageBox.Show($"杩炴帴澶辫触: {ex.Message}", "閿欒", MessageBoxButton.OK, MessageBoxImage.Error);
- UpdateConnectionStatus(false);
- }
+ get => _existingDriver;
+ set { _existingDriver = value; EnsureDeviceChannel().ExistingDriver = value; }
}
- /// <summary>
- /// 瀹為檯杩炴帴閫昏緫锛堜粠 UI 鎴栬嚜鍔ㄨ繛鎺ヨ皟鐢級
- /// </summary>
- private void DoConnect()
+ /// <summary>鎯版�у垱寤�"璁惧閫氶亾"锛堥涓� Tab锛夛紝骞舵寕鎺ュ懡浠や簨浠朵笌褰撳墠缁存姢鎬併��</summary>
+ private CanChannelView EnsureDeviceChannel()
{
- if (_isConnected) return;
+ if (_deviceChannel != null) return _deviceChannel;
- string busName = busNameInput.Text.Trim();
- if (!int.TryParse(nodeIndexInput.Text.Trim(), out int nodeIndex))
- {
- throw new ArgumentException("鑺傜偣缂栧彿鏍煎紡閿欒");
- }
-
- // 浼樺厛浣跨敤 DeviceDebug 浼犲叆鐨勮澶� ID锛屽惁鍒欒嚜鍔ㄧ敓鎴愪竴涓�
- string deviceId = string.IsNullOrEmpty(_deviceId)
- ? $"CAN_Test_{nodeIndex}_{DateTime.Now:HHmmss}"
- : _deviceId;
-
- _driver = new CanDriverAdapter(deviceId, busName, nodeIndex);
-
- // 璁㈤槄椹卞姩鐨勫抚鎺ユ敹浜嬩欢锛堝嵆鏃舵樉绀烘帴鏀跺埌鐨勫抚锛�
- _driver.DriverFrameReceived += OnDriverFrameReceived;
-
- // 杩炴帴
- _driver.ConnectAsync(CancellationToken.None).GetAwaiter().GetResult();
- _isConnected = true;
-
- // 妯℃嫙鍣ㄦā寮忎笅锛岃繛鎺ュ悗鑷姩鍚敤缁存姢妯″紡锛堝厑璁稿彂閫侊級
- IsMaintenanceMode = true;
- if (maintenanceToggleBtn != null)
- {
- maintenanceToggleBtn.IsChecked = true;
- maintenanceToggleBtn.IsEnabled = true;
- }
-
- // 鏇存柊 UI
- UpdateConnectionStatus(true);
- _pollTimer?.Start();
-
- log.Info($"CAN 椹卞姩宸茶繛鎺�: Bus={busName}, Node={nodeIndex}, DeviceId={deviceId}");
+ _deviceChannel = new CanChannelView();
+ WireChannel(_deviceChannel, MakeHeader(_deviceId, _initialBusName, _initialNodeIndex));
+ // 搴旂敤宸插埌杈剧殑缁存姢鎬�
+ _deviceChannel.IsMaintenanceMode = IsMaintenanceMode;
+ var devTab = MakeTab(_deviceChannel);
+ devTab.Header = MakeHeader(_deviceId, _initialBusName, _initialNodeIndex);
+ channelTabs.Items.Add(devTab);
+ return _deviceChannel;
}
- /// <summary>
- /// 椹卞姩甯ф帴鏀朵簨浠跺鐞� - 鍗虫椂鏄剧ず鎺ユ敹鍒扮殑甯�
- /// </summary>
- private void OnDriverFrameReceived(object? sender, CanSimulator.CanFrame frame)
+ private void WireChannel(CanChannelView view, string header)
{
- try
- {
- // 鍒ゆ柇鏂瑰悜锛氬鏋滃抚鐨勬潵婧愭槸褰撳墠鑺傜偣锛屽垯涓鸿嚜鍔ㄥ搷搴旓紙鏄剧ず涓� RX锛�
- string direction = "RX";
- string source = frame.SourceNodeId;
-
- AddReceivedFrame(
- frame.FrameIdHex,
- frame.DataHex,
- direction,
- source
- );
-
- log.Debug($"[鍗虫椂鏄剧ず] 鎺ユ敹甯�: {frame}");
- }
- catch (Exception ex)
- {
- log.Error($"鍗虫椂鏄剧ず甯уけ璐�: {ex.Message}", ex);
- }
+ view.OnCommandExecute += (s, e) => OnCommandExecute?.Invoke(this, e);
}
- /// <summary>
- /// 鏂紑鎸夐挳鐐瑰嚮
- /// </summary>
- private void DisconnectBtn_Click(object sender, RoutedEventArgs e)
+ private TabItem MakeTab(CanChannelView view)
{
- try
- {
- _pollTimer?.Stop();
- if (_driver != null)
- {
- _driver.DriverFrameReceived -= OnDriverFrameReceived;
- _driver.DisconnectAsync().GetAwaiter().GetResult();
- _driver.Dispose();
- }
- _driver = null;
- _isConnected = false;
- IsMaintenanceMode = false;
-
- UpdateConnectionStatus(false);
- log.Info("CAN 椹卞姩宸叉柇寮�");
- }
- catch (Exception ex)
- {
- log.Error($"CAN 鏂紑澶辫触: {ex.Message}", ex);
- }
+ // 澶嶇敤瑙嗗浘鑷韩鐨勬爣棰樺尯涓嶆樉绀鸿澶囧悕锛岃繖閲岀敤 Tab 澶存爣娉ㄩ�氶亾韬唤
+ return new TabItem { Content = view };
}
- /// <summary>
- /// 娣锋潅妯″紡鎸夐挳鐐瑰嚮
- /// </summary>
- private void PromiscuousBtn_Click(object sender, RoutedEventArgs e)
+ private static string MakeHeader(string deviceId, string bus, int? node)
{
- if (!_isConnected || _driver == null) return;
-
- try
- {
- _driver.QueryAsync("PROMISCUOUS", CancellationToken.None).GetAwaiter().GetResult();
- log.Info("宸茶缃贩鏉傛ā寮忥紙鎺ユ敹鎵�鏈夊抚锛�");
- MessageBox.Show("宸茶缃贩鏉傛ā寮忥紝灏嗘帴鏀舵墍鏈� CAN 甯�", "鎻愮ず", MessageBoxButton.OK, MessageBoxImage.Information);
- }
- catch (Exception ex)
- {
- log.Error($"璁剧疆娣锋潅妯″紡澶辫触: {ex.Message}");
- }
+ string id = string.IsNullOrEmpty(deviceId) ? "閫氶亾" : deviceId;
+ if (!string.IsNullOrEmpty(bus))
+ return $"{id} @{bus}:{node}";
+ return id;
}
- /// <summary>
- /// 缁存姢妯″紡鍒囨崲鎸夐挳鐐瑰嚮
- /// </summary>
- private void MaintenanceToggleBtn_Click(object sender, RoutedEventArgs e)
+ /// <summary>鎵嬪姩娣诲姞涓�涓彲缂栬緫鐨勭┖鐧介�氶亾锛圠ocal TCP 鐩磋繛锛岀敤鎴疯嚜濉�荤嚎/鑺傜偣鍚庤繛鎺ワ級銆�</summary>
+ private void AddChannelBtn_Click(object sender, RoutedEventArgs e)
{
- bool isOn = maintenanceToggleBtn.IsChecked == true;
- IsMaintenanceMode = isOn;
-
- if (isOn)
- {
- maintenanceToggleBtn.Content = "缁存姢妯″紡: 寮�";
- maintenanceToggleBtn.Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#4CAF50"));
- log.Info("缁存姢妯″紡宸插紑鍚紙鍙彂閫� CAN 甯э級");
- }
- else
- {
- maintenanceToggleBtn.Content = "缁存姢妯″紡: 鍏�";
- maintenanceToggleBtn.Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#9E9E9E"));
- log.Info("缁存姢妯″紡宸插叧闂紙鍙鐩戞帶锛�");
- }
+ var view = new CanChannelView { AutoConnectOnLoad = false };
+ _manualSeq++;
+ string header = $"CAN 閫氶亾 #{_manualSeq}"; // 鎵嬪姩閫氶亾鍏蜂綋鎬荤嚎/鑺傜偣鐢辩敤鎴烽〉鍐呭~鍐欙紝鏍囩涓嶉璁�
+ WireChannel(view, header);
+ var tab = MakeTab(view);
+ tab.Header = header;
+ channelTabs.Items.Add(tab);
+ channelTabs.SelectedItem = tab;
+ log.Info($"[CanDebugPanel] 鎵嬪姩娣诲姞閫氶亾 {header}");
}
- /// <summary>
- /// 鑷姩鍝嶅簲妯″紡鍒囨崲鎸夐挳鐐瑰嚮
- /// </summary>
- private void AutoResponseToggleBtn_Click(object sender, RoutedEventArgs e)
+ /// <summary>鍏抽棴褰撳墠閫変腑鐨勯�氶亾锛堣澶囬�氶亾涓嶅彲鍏抽棴锛岄伩鍏嶈閫�鍑� DeviceDebug 浼氳瘽瑙嗗浘锛夈��</summary>
+ private void CloseChannelBtn_Click(object sender, RoutedEventArgs e)
{
- if (!_isConnected || _driver == null) return;
-
- try
+ if (channelTabs.SelectedItem is not TabItem tab) return;
+ if (tab.Content == _deviceChannel)
{
- bool isOn = autoResponseToggleBtn.IsChecked == true;
-
- // 閫氳繃椹卞姩鍙戦�佸懡浠ゅ惎鐢�/绂佺敤鑷姩鍝嶅簲
- string cmd = isOn ? "AUTO_RESPONSE:ON" : "AUTO_RESPONSE:OFF";
- _driver.QueryAsync(cmd, CancellationToken.None).GetAwaiter().GetResult();
-
- if (isOn)
- {
- autoResponseToggleBtn.Content = "鑷姩鍝嶅簲: 寮�";
- autoResponseToggleBtn.Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FF9800"));
- log.Info("鑷姩鍝嶅簲妯″紡宸插紑鍚紙鏀跺埌甯у皢鑷姩鍥炲锛�");
- }
- else
- {
- autoResponseToggleBtn.Content = "鑷姩鍝嶅簲: 鍏�";
- autoResponseToggleBtn.Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#9E9E9E"));
- log.Info("鑷姩鍝嶅簲妯″紡宸插叧闂�");
- }
+ MessageBox.Show("璁惧閫氶亾涓嶅彲鍦ㄦ鍏抽棴锛岃浠庤澶囬�夋嫨鍒囨崲銆�", "鎻愮ず",
+ MessageBoxButton.OK, MessageBoxImage.Information);
+ return;
}
- catch (Exception ex)
- {
- log.Error($"鍒囨崲鑷姩鍝嶅簲妯″紡澶辫触: {ex.Message}");
- MessageBox.Show($"鍒囨崲澶辫触: {ex.Message}", "閿欒", MessageBoxButton.OK, MessageBoxImage.Error);
- }
+ if (tab.Content is CanChannelView view)
+ view.DisconnectInternalSafe();
+ channelTabs.Items.Remove(tab);
}
- /// <summary>
- /// 鏇存柊杩炴帴鐘舵�佹樉绀�
- /// </summary>
- private void UpdateConnectionStatus(bool connected)
+ /// <summary>鏇存柊璁惧閫氶亾 Tab 澶达紙鍦ㄩ厤缃綈澶囧悗璋冪敤涓�娆″嵆鍙級銆�</summary>
+ public void RefreshDeviceHeader()
{
- _isConnected = connected;
- if (connected)
- {
- statusIndicator.Fill = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#4CAF50"));
- statusText.Text = "宸茶繛鎺�";
- connectBtn.IsEnabled = false;
- disconnectBtn.IsEnabled = true;
- promiscuousBtn.IsEnabled = true;
- maintenanceToggleBtn.IsEnabled = true;
- autoResponseToggleBtn.IsEnabled = true;
- busNameInput.IsEnabled = false;
- nodeIndexInput.IsEnabled = false;
- }
- else
- {
- statusIndicator.Fill = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#9E9E9E"));
- statusText.Text = "鏈繛鎺�";
- connectBtn.IsEnabled = true;
- disconnectBtn.IsEnabled = false;
- promiscuousBtn.IsEnabled = false;
- maintenanceToggleBtn.IsEnabled = false;
- autoResponseToggleBtn.IsEnabled = false;
- busNameInput.IsEnabled = true;
- nodeIndexInput.IsEnabled = true;
- }
- }
-
- /// <summary>
- /// 鏇存柊缁熻淇℃伅
- /// </summary>
- private void UpdateStats()
- {
- if (_driver == null) return;
-
- try
- {
- var status = _driver.GetStatus();
- var response = _driver.QueryAsync("STATUS", CancellationToken.None).GetAwaiter().GetResult();
- // 瑙f瀽鐘舵��: "STATUS:Node=..., Active=True, Rx=0, Tx=0, Err=0, Mailbox=0|Bus=..."
- statsText.Text = $"TX: {GetStatValue(response, "Tx")} RX: {GetStatValue(response, "Rx")} Err: {GetStatValue(response, "Err")}";
- }
- catch
- {
- // 蹇界暐缁熻鏇存柊澶辫触
- }
- }
-
- /// <summary>
- /// 浠庣姸鎬佸瓧绗︿覆涓彁鍙栨暟鍊煎��
- /// </summary>
- private string GetStatValue(string statusStr, string key)
- {
- try
- {
- var parts = statusStr.Split(',');
- foreach (var part in parts)
- {
- var kv = part.Trim().Split('=');
- if (kv.Length == 2 && kv[0].Trim() == key)
- {
- return kv[1].Trim();
- }
- }
- }
- catch { }
- return "0";
- }
-
- /// <summary>
- /// 娣诲姞鎺ユ敹甯�
- /// </summary>
- public void AddReceivedFrame(string frameId, string data, string direction = "RX", string source = "")
- {
- try
- {
- var frame = new CanFrameDisplay
- {
- Timestamp = DateTime.Now,
- FrameId = frameId,
- Dlc = data.Split(new[] { ' ', '-' }, StringSplitOptions.RemoveEmptyEntries).Length,
- Data = data,
- Direction = direction,
- Source = source
- };
-
- Application.Current.Dispatcher.Invoke(() =>
- {
- ReceivedFrames.Insert(0, frame);
-
- // 闄愬埗鏄剧ず鏁伴噺
- if (ReceivedFrames.Count > 500)
- {
- var toRemove = ReceivedFrames.Skip(500).ToList();
- foreach (var item in toRemove)
- {
- ReceivedFrames.Remove(item);
- }
- }
- });
- }
- catch (Exception ex)
- {
- log.Error($"娣诲姞鎺ユ敹甯уけ璐�: {ex.Message}", ex);
- }
- }
-
- /// <summary>
- /// 鍙戦�佹寜閽偣鍑�
- /// </summary>
- private void SendBtn_Click(object sender, RoutedEventArgs e)
- {
- try
- {
- if (!IsMaintenanceMode)
- {
- MessageBox.Show("褰撳墠涓哄彧璇绘ā寮忥紝鏃犳硶鍙戦�佹暟鎹�", "鎻愮ず", MessageBoxButton.OK, MessageBoxImage.Warning);
- return;
- }
-
- if (!_isConnected || _driver == null)
- {
- MessageBox.Show("璇峰厛杩炴帴 CAN 鎬荤嚎", "鎻愮ず", MessageBoxButton.OK, MessageBoxImage.Warning);
- return;
- }
-
- string frameIdStr = frameIdInput.Text.Trim();
- string dataStr = dataInput.Text.Trim();
-
- // 楠岃瘉甯� ID
- uint frameId = CanSimulator.CanFrame.ParseFrameId(frameIdStr);
-
- // 楠岃瘉鏁版嵁
- byte[] dataBytes = CanSimulator.CanFrame.ParseData(dataStr);
- if (dataBytes.Length > 8)
- {
- MessageBox.Show("鏁版嵁闀垮害涓嶈兘瓒呰繃 8 瀛楄妭", "閿欒", MessageBoxButton.OK, MessageBoxImage.Error);
- return;
- }
-
- // 閫氳繃椹卞姩鍙戦��
- string command = $"SEND:{frameIdStr}:{dataStr}";
- var response = _driver.SendCommandAsync(command, CancellationToken.None).GetAwaiter().GetResult();
-
- // 娣诲姞鍒版樉绀哄垪琛紙TX锛�
- AddReceivedFrame($"0x{frameId:X3}", BitConverter.ToString(dataBytes).Replace("-", " "), "TX", "LOCAL");
-
- log.Info($"鍙戦�� CAN 甯�: ID=0x{frameId:X3}, Data={BitConverter.ToString(dataBytes)}, Response={response}");
- }
- catch (Exception ex)
- {
- log.Error($"鍙戦�� CAN 甯уけ璐�: {ex.Message}", ex);
- MessageBox.Show($"鍙戦�佸け璐�: {ex.Message}", "閿欒", MessageBoxButton.OK, MessageBoxImage.Error);
- }
- }
-
- /// <summary>
- /// 娓呯┖鎸夐挳鐐瑰嚮
- /// </summary>
- private void ClearBtn_Click(object sender, RoutedEventArgs e)
- {
- try
- {
- ReceivedFrames.Clear();
- log.Info("娓呯┖ CAN 鎺ユ敹璁板綍");
- }
- catch (Exception ex)
- {
- log.Error($"娓呯┖鎺ユ敹璁板綍澶辫触: {ex.Message}", ex);
- }
+ if (_deviceChannel == null || channelTabs.Items.Count == 0) return;
+ if (channelTabs.Items[0] is TabItem t)
+ t.Header = MakeHeader(_deviceId, _initialBusName, _initialNodeIndex);
}
}
}
--
Gitblit v1.9.1