From 9d1660270272180cd71147d6ddd53d1382643d2e Mon Sep 17 00:00:00 2001
From: wenxiangchao <wenxiangchao@ihengxin.com.cn>
Date: 星期一, 02 十一月 2026 18:00:14 +0800
Subject: [PATCH] merge: 并入远程 Initial commit 作为历史根节点
---
Plugin.DeviceDebug/DeviceDebug.xaml.cs | 668 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 668 insertions(+), 0 deletions(-)
diff --git a/Plugin.DeviceDebug/DeviceDebug.xaml.cs b/Plugin.DeviceDebug/DeviceDebug.xaml.cs
new file mode 100644
index 0000000..dc82505
--- /dev/null
+++ b/Plugin.DeviceDebug/DeviceDebug.xaml.cs
@@ -0,0 +1,668 @@
+using Aging.Infrastructure.Contracts;
+using CommunityToolkit.Mvvm.ComponentModel;
+using HMI.Base;
+using HMI.Core.Util;
+using HMI.UI.Util;
+using log4net;
+using Plugin.DeviceDebug.Entity;
+using Plugin.DeviceDebug.Model;
+using Plugin.DeviceDebug.Panels;
+using System;
+using System.Collections.ObjectModel;
+using System.IO;
+using System.Linq;
+using System.Threading;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Media;
+
+namespace Plugin.DeviceDebug
+{
+ /// <summary>
+ /// DeviceDebug.xaml 鐨勪氦浜掗�昏緫
+ /// </summary>
+ [ObservableObject]
+ public partial class DeviceDebug : SimpleMaskControl
+ {
+ private static readonly ILog _log = LogManager.GetLogger(typeof(DeviceDebug));
+ private DeviceDebugModel _debugModel;
+ private DebugSessionManager _sessionManager;
+
+ // 鍩虹璁炬柦灞傛湇鍔�
+ private IDeviceManager? _deviceManager;
+ private IDeviceService? _deviceService;
+ private IResourceManager? _resourceManager;
+
+ // 璁惧閰嶇疆鏁版嵁搴撹矾寰勶紙涓� DeviceConfig 鎻掍欢鍏变韩锛�
+ private string _deviceConfigDbPath;
+
+ [ObservableProperty] private ObservableCollection<string> _deviceList = new();
+ [ObservableProperty] private string _selectedDevice;
+ [ObservableProperty] private DebugSession _currentSession;
+ [ObservableProperty] private ObservableCollection<DebugOperation> _operationLogs = new();
+ [ObservableProperty] private string _connectionStateText = "鏈繛鎺�";
+ [ObservableProperty] private string _sessionStateText = "";
+ [ObservableProperty] private string _reservationStatusText = "";
+ [ObservableProperty] private string _currentDeviceId = "";
+ [ObservableProperty] private string _currentDeviceKind = "";
+ [ObservableProperty] private string _currentEffectiveVersion = "";
+ [ObservableProperty] private string _currentEndpoint = "";
+ [ObservableProperty] private string _currentDriverType = "";
+ [ObservableProperty] private Brush _connectionBrush = new SolidColorBrush(Colors.Gray);
+ [ObservableProperty] private Brush _sessionStateBrush = new SolidColorBrush(Colors.Gray);
+ [ObservableProperty] private bool _canEnterMaintenance;
+ [ObservableProperty] private bool _canExitMaintenance;
+ [ObservableProperty] private bool _hasDevice;
+
+ // 缂撳瓨褰撳墠閫変腑鐨勮澶囩被鍨�
+ private string _currentDeviceKindStr;
+
+ public DeviceDebug()
+ {
+ DataContext = this;
+ InitializeComponent();
+ }
+
+ /// <summary>
+ /// 寮哄埗鍒锋柊璁惧鍒楄〃锛堜緵闆嗘垚娴嬭瘯棰勭疆璁惧鍚庤皟鐢級
+ /// </summary>
+ public void ForceRefreshForTest()
+ {
+ try { LoadDeviceList(); }
+ catch (Exception ex) { _log.Error("ForceRefreshForTest Error.", ex); }
+ }
+
+ public override void InitFinish()
+ {
+ base.InitFinish();
+ try
+ {
+ // 鍒濆鍖栬皟璇曟暟鎹簱
+ _debugModel = new DeviceDebugModel();
+ string dbPath = Path.Combine(BaseFolder, "debug.db");
+ _debugModel.InitDatabase(dbPath);
+
+ // 浠� UtilContainer 鑾峰彇鍩虹璁炬柦鏈嶅姟
+ var container = new UtilContainer();
+ _deviceManager = container.GetUtil<IDeviceManager>("DeviceManager");
+ _deviceService = container.GetUtil<IDeviceService>("DeviceService");
+ _resourceManager = container.GetUtil<IResourceManager>("ResourceManager");
+
+ // 鍒涘缓浼氳瘽绠$悊鍣紙浼犲叆 ResourceManager锛�
+ _sessionManager = new DebugSessionManager(_debugModel, _resourceManager);
+
+ // 璁惧閰嶇疆鏁版嵁搴撹矾寰勶紙涓� DeviceConfig 鍏变韩锛�
+ _deviceConfigDbPath = Path.Combine(BaseFolder, "data.db");
+
+ log.Info("纭欢璋冭瘯妯″潡鍒濆鍖栧畬鎴�");
+ }
+ catch (Exception ex)
+ {
+ log.Error("纭欢璋冭瘯妯″潡鍒濆鍖栧け璐�", ex);
+ ToastHelper.Error($"纭欢璋冭瘯鍒濆鍖栧け璐�: {ex.Message}");
+ }
+ }
+
+ /// <summary>
+ /// 鍔犺浇璁惧鍒楄〃
+ /// </summary>
+ private void LoadDeviceList()
+ {
+ try
+ {
+ if (!File.Exists(_deviceConfigDbPath))
+ {
+ log.Warn($"璁惧閰嶇疆鏁版嵁搴撲笉瀛樺湪: {_deviceConfigDbPath}");
+ ToastHelper.Warning("璁惧閰嶇疆鏁版嵁搴撲笉瀛樺湪锛岃鍏堝湪璁惧閰嶇疆妯″潡涓坊鍔犺澶�");
+ return;
+ }
+
+ var sqliteHelper = new SqliteHelper(_deviceConfigDbPath);
+ var dt = sqliteHelper.GetDataTable("SELECT DeviceId, Kind FROM DeviceDefinition ORDER BY DeviceId");
+
+ var list = new ObservableCollection<string>();
+ foreach (System.Data.DataRow row in dt.Rows)
+ {
+ string deviceId = row["DeviceId"].ToString();
+ string kind = row["Kind"].ToString();
+ list.Add($"{deviceId} [{kind}]");
+ }
+
+ DeviceList = list;
+ log.Info($"鍔犺浇璁惧鍒楄〃瀹屾垚锛屽叡 {list.Count} 涓澶�");
+ }
+ catch (Exception ex)
+ {
+ log.Error("鍔犺浇璁惧鍒楄〃澶辫触", ex);
+ ToastHelper.Error($"鍔犺浇璁惧鍒楄〃澶辫触: {ex.Message}");
+ }
+ }
+
+ /// <summary>
+ /// 瑙f瀽璁惧閫夋嫨瀛楃涓诧紝鑾峰彇 DeviceId
+ /// </summary>
+ private string ParseDeviceId(string selection)
+ {
+ if (string.IsNullOrEmpty(selection)) return string.Empty;
+ int idx = selection.IndexOf(" [");
+ return idx > 0 ? selection.Substring(0, idx) : selection;
+ }
+
+ /// <summary>
+ /// 瑙f瀽璁惧閫夋嫨瀛楃涓诧紝鑾峰彇 Kind
+ /// </summary>
+ private string ParseDeviceKind(string selection)
+ {
+ if (string.IsNullOrEmpty(selection)) return string.Empty;
+ int start = selection.IndexOf(" [");
+ int end = selection.IndexOf("]");
+ if (start >= 0 && end > start)
+ return selection.Substring(start + 2, end - start - 2);
+ return string.Empty;
+ }
+
+ /// <summary>
+ /// 鍔犺浇璁惧璇︾粏淇℃伅
+ /// </summary>
+ private void LoadDeviceInfo(string deviceId)
+ {
+ try
+ {
+ if (!File.Exists(_deviceConfigDbPath)) return;
+
+ var sqliteHelper = new SqliteHelper(_deviceConfigDbPath);
+ var dt = sqliteHelper.GetDataTable(
+ $"SELECT DeviceId, Kind, EffectiveVersion, Endpoint, DriverType FROM DeviceDefinition WHERE DeviceId = '{deviceId}'");
+
+ if (dt.Rows.Count > 0)
+ {
+ var row = dt.Rows[0];
+ CurrentDeviceId = row["DeviceId"].ToString();
+ CurrentDeviceKind = row["Kind"].ToString();
+ CurrentEffectiveVersion = row["EffectiveVersion"]?.ToString() ?? "";
+ CurrentEndpoint = row["Endpoint"]?.ToString() ?? "";
+ CurrentDriverType = row["DriverType"]?.ToString() ?? "";
+
+ // 缂撳瓨璁惧绫诲瀷
+ _currentDeviceKindStr = CurrentDeviceKind;
+ }
+ }
+ catch (Exception ex)
+ {
+ log.Error($"鍔犺浇璁惧淇℃伅澶辫触: {deviceId}", ex);
+ }
+ }
+
+ /// <summary>
+ /// 閫夋嫨璁惧鏃讹細鎵撳紑浼氳瘽锛圧eadOnly锛夛紝鍔犺浇瀵瑰簲闈㈡澘
+ /// </summary>
+ private void OnDeviceSelected()
+ {
+ try
+ {
+ if (string.IsNullOrEmpty(SelectedDevice))
+ {
+ HasDevice = false;
+ panelContainer.Content = new TextBlock
+ {
+ Text = "璇烽�夋嫨璁惧",
+ HorizontalAlignment = HorizontalAlignment.Center,
+ VerticalAlignment = VerticalAlignment.Center,
+ FontSize = 16,
+ Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#999"))
+ };
+ return;
+ }
+
+ string deviceId = ParseDeviceId(SelectedDevice);
+ string kind = ParseDeviceKind(SelectedDevice);
+
+ // 鍔犺浇璁惧璇︾粏淇℃伅
+ LoadDeviceInfo(deviceId);
+
+ HasDevice = true;
+
+ // 鎵撳紑浼氳瘽锛圧eadOnly锛�
+ CurrentSession = _sessionManager.OpenSession(deviceId, "", "operator", CurrentEffectiveVersion);
+
+ // 閫氳繃 DeviceManager 杩炴帴璁惧
+ if (_deviceManager != null)
+ {
+ try
+ {
+ _deviceManager.ConnectAsync(deviceId, CancellationToken.None)
+ .GetAwaiter().GetResult();
+ ConnectionStateText = "宸茶繛鎺�";
+ ConnectionBrush = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#4CAF50"));
+ }
+ catch (Exception ex)
+ {
+ log.Warn($"閫氳繃 DeviceManager 杩炴帴璁惧澶辫触: {ex.Message}");
+ ConnectionStateText = "杩炴帴澶辫触";
+ ConnectionBrush = new SolidColorBrush(Colors.OrangeRed);
+ }
+ }
+
+ // 鍔犺浇鎿嶄綔鏃ュ織
+ LoadOperationLogs();
+
+ // 鏇存柊鎸夐挳鐘舵��
+ UpdateButtonStates();
+
+ // 鍔犺浇瀵瑰簲闈㈡澘
+ LoadPanel(kind);
+
+ log.Info($"宸查�夋嫨璁惧: {deviceId}, 绫诲瀷: {kind}");
+ }
+ catch (Exception ex)
+ {
+ log.Error("閫夋嫨璁惧澶辫触", ex);
+ ToastHelper.Error($"閫夋嫨璁惧澶辫触: {ex.Message}");
+ }
+ }
+
+ /// <summary>
+ /// 鏍规嵁璁惧绫诲瀷鍔犺浇瀵瑰簲鐨勮皟璇曢潰鏉�
+ /// </summary>
+ private void LoadPanel(string deviceKind)
+ {
+ try
+ {
+ UIElement panel = null;
+
+ switch (deviceKind)
+ {
+ case "PowerSupply":
+ var powerPanel = new PowerSupplyDebugPanel();
+ powerPanel.IsMaintenanceMode = CurrentSession?.State == DebugSessionState.MaintenanceActive;
+ powerPanel.OnCommandExecute += Panel_OnCommandExecute;
+ panel = powerPanel;
+ break;
+ case "CanDevice":
+ var canPanel = new CanDebugPanel
+ {
+ DeviceId = CurrentDeviceId,
+ InitialBusName = ParseCanBusName(CurrentEndpoint),
+ InitialNodeIndex = ParseCanNodeIndex(CurrentEndpoint),
+ AutoConnectOnLoad = true
+ };
+ canPanel.IsMaintenanceMode = CurrentSession?.State == DebugSessionState.MaintenanceActive;
+ canPanel.OnCommandExecute += Panel_OnCommandExecute;
+ panel = canPanel;
+ break;
+ case "PlcDevice":
+ var plcPanel = new PlcDebugPanel();
+ plcPanel.IsMaintenanceMode = CurrentSession?.State == DebugSessionState.MaintenanceActive;
+ plcPanel.OnCommandExecute += Panel_OnCommandExecute;
+ panel = plcPanel;
+ break;
+ default:
+ panel = new TextBlock
+ {
+ Text = $"涓嶆敮鎸佺殑璁惧绫诲瀷: {deviceKind}",
+ HorizontalAlignment = HorizontalAlignment.Center,
+ VerticalAlignment = VerticalAlignment.Center,
+ FontSize = 14,
+ Foreground = new SolidColorBrush(Colors.OrangeRed)
+ };
+ break;
+ }
+
+ panelContainer.Content = panel;
+ }
+ catch (Exception ex)
+ {
+ log.Error($"鍔犺浇璋冭瘯闈㈡澘澶辫触: {deviceKind}", ex);
+ ToastHelper.Error($"鍔犺浇闈㈡澘澶辫触: {ex.Message}");
+ }
+ }
+
+ /// <summary>
+ /// 闈㈡澘鍛戒护鎵ц浜嬩欢澶勭悊
+ /// </summary>
+ private void Panel_OnCommandExecute(object sender, DebugCommand command)
+ {
+ try
+ {
+ if (CurrentSession == null)
+ {
+ ToastHelper.Warning("璇峰厛閫夋嫨璁惧");
+ return;
+ }
+
+ // 楠岃瘉鍛戒护鏉冮檺
+ if (!_sessionManager.ValidateCommand(CurrentSession.SessionId, command))
+ {
+ ToastHelper.Warning("褰撳墠浼氳瘽鐘舵�佷笉鍏佽鎵ц姝ゆ搷浣滐紝璇峰厛杩涘叆缁存姢妯″紡");
+ return;
+ }
+
+ // 閫氳繃 DeviceService 鎵ц瀹為檯鍛戒护
+ if (_deviceService != null)
+ {
+ ExecuteViaDeviceService(command);
+ }
+ else
+ {
+ // 闄嶇骇妯″紡锛氬熀纭�璁炬柦鏈垵濮嬪寲鏃朵繚鐣欏師鏈夎涓�
+ log.Warn("DeviceService 鏈垵濮嬪寲锛屼娇鐢ㄩ檷绾фā寮忚褰曞懡浠�");
+ ExecuteFallback(command);
+ }
+ }
+ catch (Exception ex)
+ {
+ log.Error($"鎵ц鍛戒护澶辫触: {command.CommandType}", ex);
+ ToastHelper.Error($"鍛戒护鎵ц澶辫触: {ex.Message}");
+
+ // 璁板綍澶辫触鎿嶄綔
+ var operation = new DebugOperation
+ {
+ SessionId = CurrentSession?.SessionId ?? "",
+ CommandType = command.CommandType,
+ Parameters = SerializeParameters(command),
+ Outcome = "Failed",
+ ErrorMessage = ex.Message,
+ Timestamp = DateTime.Now
+ };
+ _debugModel.RecordOperation(operation);
+ OperationLogs.Insert(0, operation);
+ }
+ }
+
+ /// <summary>
+ /// 閫氳繃 DeviceService 鎵ц璁惧鍛戒护
+ /// </summary>
+ private void ExecuteViaDeviceService(DebugCommand command)
+ {
+ try
+ {
+ var ownerToken = new ResourceOwnerToken(
+ OwnerType.Maintenance,
+ CurrentSession.SessionId);
+
+ var deviceCommand = BuildDeviceCommand(command);
+
+ var result = _deviceService.ExecuteCommandAsync(
+ command.DeviceId,
+ deviceCommand,
+ ownerToken,
+ CancellationToken.None).GetAwaiter().GetResult();
+
+ var operation = new DebugOperation
+ {
+ SessionId = CurrentSession.SessionId,
+ CommandType = command.CommandType,
+ Parameters = SerializeParameters(command),
+ Outcome = result.Success ? "Success" : "Failed",
+ DeviceReadback = result.Readback ?? "",
+ ErrorCode = result.ErrorCode ?? "",
+ ErrorMessage = result.ErrorMessage ?? "",
+ Timestamp = DateTime.Now
+ };
+
+ _debugModel.RecordOperation(operation);
+ OperationLogs.Insert(0, operation);
+
+ if (result.Success)
+ ToastHelper.Success($"鍛戒护 {command.CommandType} 鎵ц鎴愬姛");
+ else
+ ToastHelper.Warning($"鍛戒护鎵ц澶辫触: {result.ErrorMessage}");
+
+ log.Info($"鎵ц鍛戒护: {command.CommandType}, 璁惧: {command.DeviceId}, 缁撴灉: {(result.Success ? "鎴愬姛" : "澶辫触")}");
+ }
+ catch (Exception ex)
+ {
+ log.Error($"DeviceService 鎵ц鍛戒护澶辫触: {ex.Message}", ex);
+ ToastHelper.Error($"璁惧閫氫俊澶辫触: {ex.Message}");
+
+ var operation = new DebugOperation
+ {
+ SessionId = CurrentSession.SessionId,
+ CommandType = command.CommandType,
+ Parameters = SerializeParameters(command),
+ Outcome = "Failed",
+ ErrorMessage = ex.Message,
+ Timestamp = DateTime.Now
+ };
+ _debugModel.RecordOperation(operation);
+ OperationLogs.Insert(0, operation);
+ }
+ }
+
+ /// <summary>
+ /// 闄嶇骇妯″紡锛氭棤 DeviceService 鏃剁殑鍚庡澶勭悊
+ /// </summary>
+ private void ExecuteFallback(DebugCommand command)
+ {
+ var operation = new DebugOperation
+ {
+ SessionId = CurrentSession.SessionId,
+ CommandType = command.CommandType,
+ Parameters = SerializeParameters(command),
+ Outcome = "Success",
+ Timestamp = DateTime.Now
+ };
+
+ _debugModel.RecordOperation(operation);
+ OperationLogs.Insert(0, operation);
+
+ ToastHelper.Success($"鍛戒护 {command.CommandType} 宸插彂閫侊紙闄嶇骇妯″紡锛�");
+ log.Info($"[闄嶇骇妯″紡] 鎵ц鍛戒护: {command.CommandType}, 璁惧: {command.DeviceId}");
+ }
+
+ /// <summary>
+ /// 鏍规嵁鍛戒护绫诲瀷鏋勫缓瀹為檯璁惧鍛戒护瀛楃涓�
+ /// </summary>
+ private string BuildDeviceCommand(DebugCommand command)
+ {
+ if (command is PowerSetCommand psc)
+ {
+ return $"VOLT {psc.Voltage};CURR {psc.CurrentLimit};OUTP {(psc.Output ? "ON" : "OFF")}";
+ }
+ else if (command is PowerMeasureCommand)
+ {
+ return "MEAS:ALL?";
+ }
+ else if (command is CanSendCommand csc)
+ {
+ return $"CAN:SEND {csc.Frame}";
+ }
+ else if (command is PlcWriteCommand pwc)
+ {
+ return $"WRITE:{pwc.IoAddress}:{(pwc.Value ? "TRUE" : "FALSE")}";
+ }
+ return command.CommandType;
+ }
+
+ /// <summary>
+ /// 搴忓垪鍖栧懡浠ゅ弬鏁颁负JSON瀛楃涓�
+ /// </summary>
+ private string SerializeParameters(DebugCommand command)
+ {
+ try
+ {
+ switch (command)
+ {
+ case PowerSetCommand psc:
+ return $"{{Voltage:{psc.Voltage},CurrentLimit:{psc.CurrentLimit},Output:{psc.Output}}}";
+ case PowerMeasureCommand _:
+ return "{}";
+ case CanSendCommand csc:
+ return $"{{Frame:{csc.Frame},Data:{BitConverter.ToString(csc.Data)}}}";
+ case PlcWriteCommand pwc:
+ return $"{{IoAddress:{pwc.IoAddress},Value:{pwc.Value}}}";
+ default:
+ return "{}";
+ }
+ }
+ catch
+ {
+ return "{}";
+ }
+ }
+
+ /// <summary>
+ /// 鍔犺浇鎿嶄綔鏃ュ織
+ /// </summary>
+ private void LoadOperationLogs()
+ {
+ try
+ {
+ if (CurrentSession == null) return;
+
+ var ops = _debugModel.GetOperationsBySession(CurrentSession.SessionId);
+ OperationLogs = new ObservableCollection<DebugOperation>(ops.Take(100));
+ }
+ catch (Exception ex)
+ {
+ log.Error("鍔犺浇鎿嶄綔鏃ュ織澶辫触", ex);
+ }
+ }
+
+ /// <summary>
+ /// 鏇存柊鎸夐挳鍚敤鐘舵��
+ /// </summary>
+ private void UpdateButtonStates()
+ {
+ if (CurrentSession == null)
+ {
+ CanEnterMaintenance = false;
+ CanExitMaintenance = false;
+ SessionStateText = "";
+ return;
+ }
+
+ var state = CurrentSession.State;
+ CanEnterMaintenance = state == DebugSessionState.ReadOnly;
+ CanExitMaintenance = state == DebugSessionState.MaintenanceActive;
+
+ // 鏇存柊浼氳瘽鐘舵�佹枃鏈拰棰滆壊
+ SessionStateText = state.ToString();
+ SessionStateBrush = state switch
+ {
+ DebugSessionState.ReadOnly => new SolidColorBrush((Color)ColorConverter.ConvertFromString("#2196F3")),
+ DebugSessionState.MaintenanceActive => new SolidColorBrush((Color)ColorConverter.ConvertFromString("#4CAF50")),
+ DebugSessionState.Faulted => new SolidColorBrush(Colors.Red),
+ DebugSessionState.RecoveryRequired => new SolidColorBrush(Colors.Orange),
+ _ => new SolidColorBrush(Colors.Gray)
+ };
+
+ // 鏇存柊闈㈡澘鐨勭淮鎶ゆā寮�
+ if (panelContainer.Content is PowerSupplyDebugPanel powerPanel)
+ powerPanel.IsMaintenanceMode = state == DebugSessionState.MaintenanceActive;
+ else if (panelContainer.Content is CanDebugPanel canPanel)
+ canPanel.IsMaintenanceMode = state == DebugSessionState.MaintenanceActive;
+ else if (panelContainer.Content is PlcDebugPanel plcPanel)
+ plcPanel.IsMaintenanceMode = state == DebugSessionState.MaintenanceActive;
+ }
+
+ #region 浜嬩欢澶勭悊
+
+ private void SimpleMaskControl_Loaded(object sender, RoutedEventArgs e)
+ {
+ LoadDeviceList();
+ Loaded -= SimpleMaskControl_Loaded;
+ }
+
+ private void DeviceSelector_SelectionChanged(object sender, SelectionChangedEventArgs e)
+ {
+ OnDeviceSelected();
+ }
+
+ private void RfhBtn_Click(object sender, RoutedEventArgs e)
+ {
+ LoadDeviceList();
+ }
+
+ private void EnterMaintenanceBtn_Click(object sender, RoutedEventArgs e)
+ {
+ try
+ {
+ if (CurrentSession == null) return;
+
+ // 璇锋眰缁存姢妯″紡
+ if (_sessionManager.RequestMaintenance(CurrentSession.SessionId))
+ {
+ // 婵�娲荤淮鎶ゆā寮�
+ _sessionManager.ActivateMaintenance(CurrentSession.SessionId);
+ UpdateButtonStates();
+
+ // 閲嶆柊鍔犺浇闈㈡澘浠ユ洿鏂癐sMaintenanceMode
+ LoadPanel(CurrentDeviceKind);
+
+ ToastHelper.Success("宸茶繘鍏ョ淮鎶ゆ帶鍒舵ā寮�");
+ log.Info($"浼氳瘽 {CurrentSession.SessionId} 杩涘叆缁存姢妯″紡");
+ }
+ else
+ {
+ ToastHelper.Warning("鏃犳硶杩涘叆缁存姢妯″紡锛岃妫�鏌ヨ澶囩姸鎬�");
+ }
+ }
+ catch (Exception ex)
+ {
+ log.Error("杩涘叆缁存姢妯″紡澶辫触", ex);
+ ToastHelper.Error($"杩涘叆缁存姢妯″紡澶辫触: {ex.Message}");
+ }
+ }
+
+ private void ExitMaintenanceBtn_Click(object sender, RoutedEventArgs e)
+ {
+ try
+ {
+ if (CurrentSession == null) return;
+
+ if (MsgBoxHelper.WarnMessage(Window.GetWindow(this), "纭畾瑕侀��鍑虹淮鎶ゆā寮忓悧锛�") == MessageBoxResult.OK)
+ {
+ _sessionManager.CloseSession(CurrentSession.SessionId);
+ CurrentSession = null;
+ UpdateButtonStates();
+
+ // 娓呯┖闈㈡澘
+ panelContainer.Content = new TextBlock
+ {
+ Text = "璇烽�夋嫨璁惧",
+ HorizontalAlignment = HorizontalAlignment.Center,
+ VerticalAlignment = VerticalAlignment.Center,
+ FontSize = 16,
+ Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#999"))
+ };
+
+ HasDevice = false;
+ SelectedDevice = null;
+
+ ToastHelper.Success("宸查��鍑虹淮鎶ゆā寮�");
+ log.Info("宸查��鍑虹淮鎶ゆā寮�");
+ }
+ }
+ catch (Exception ex)
+ {
+ log.Error("閫�鍑虹淮鎶ゆā寮忓け璐�", ex);
+ ToastHelper.Error($"閫�鍑虹淮鎶ゆā寮忓け璐�: {ex.Message}");
+ }
+ }
+
+ /// <summary>
+ /// 浠� CAN Endpoint 瑙f瀽鎬荤嚎鍚嶇О锛堟牸寮�: 鎬荤嚎鍚�:鑺傜偣缂栧彿锛�
+ /// </summary>
+ private string ParseCanBusName(string endpoint)
+ {
+ if (string.IsNullOrEmpty(endpoint)) return "CAN_BUS_1";
+ int idx = endpoint.IndexOf(':');
+ return idx > 0 ? endpoint.Substring(0, idx) : endpoint;
+ }
+
+ /// <summary>
+ /// 浠� CAN Endpoint 瑙f瀽鑺傜偣缂栧彿
+ /// </summary>
+ private int? ParseCanNodeIndex(string endpoint)
+ {
+ if (string.IsNullOrEmpty(endpoint)) return 0;
+ int idx = endpoint.IndexOf(':');
+ if (idx > 0 && idx < endpoint.Length - 1 && int.TryParse(endpoint.Substring(idx + 1), out int n))
+ return n;
+ return 0;
+ }
+
+ #endregion
+ }
+}
--
Gitblit v1.9.1