using Aging.Infrastructure.Contracts;
using CommunityToolkit.Mvvm.ComponentModel;
using HMI.Base;
using HMI.Core.Util;
using HMI.UI.Util;
using log4net;
using Plugin.DeviceDebug.Model;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
namespace Plugin.DeviceDebug
{
///
/// 硬件调试插件(壳):装配并持有共享基础设施(会话管理器/设备服务/配置库路径),
/// 以 TabControl 承载多个 ,支持同时调试多个设备,
/// 每个 Tab 拥有独立会话与维护租约。设备下拉仅列出尚未打开的设备。
///
[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;
private string _deviceConfigDbPath;
// 全量设备("id [kind]")与已打开标签映射(deviceId → TabItem)
private readonly List _allDevices = new();
private readonly Dictionary _openTabs = new(StringComparer.OrdinalIgnoreCase);
[ObservableProperty] private ObservableCollection _deviceList = new();
[ObservableProperty] private string _selectedDevice;
public DeviceDebug()
{
DataContext = this;
InitializeComponent();
}
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);
var container = new UtilContainer();
_deviceManager = container.GetUtil("DeviceManager");
_deviceService = container.GetUtil("DeviceService");
_resourceManager = container.GetUtil("ResourceManager");
_sessionManager = new DebugSessionManager(_debugModel, _resourceManager);
_deviceConfigDbPath = Path.Combine(BaseFolder, "data.db");
log.Info("硬件调试模块初始化完成");
}
catch (Exception ex)
{
log.Error("硬件调试模块初始化失败", ex);
ToastHelper.Error($"硬件调试初始化失败: {ex.Message}");
}
}
private void SimpleMaskControl_Loaded(object sender, RoutedEventArgs e)
{
LoadDeviceList();
Loaded -= SimpleMaskControl_Loaded;
}
private void RfhBtn_Click(object sender, RoutedEventArgs e) => LoadDeviceList();
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");
_allDevices.Clear();
foreach (System.Data.DataRow row in dt.Rows)
_allDevices.Add($"{row["DeviceId"]} [{row["Kind"]}]");
RefreshAvailableList();
log.Info($"加载设备列表完成,共 {_allDevices.Count} 个设备");
}
catch (Exception ex)
{
log.Error("加载设备列表失败", ex);
ToastHelper.Error($"加载设备列表失败: {ex.Message}");
}
}
/// 下拉仅列出未打开的设备(一会一设备)。
private void RefreshAvailableList()
{
var avail = _allDevices
.Where(d => !_openTabs.ContainsKey(ParseDeviceId(d)))
.ToList();
DeviceList = new ObservableCollection(avail);
}
private static string ParseDeviceId(string selection)
{
if (string.IsNullOrEmpty(selection)) return string.Empty;
int idx = selection.IndexOf(" [");
return idx > 0 ? selection.Substring(0, idx) : selection;
}
private static 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;
}
private void AddDeviceBtn_Click(object sender, RoutedEventArgs e)
{
try
{
if (string.IsNullOrEmpty(SelectedDevice))
{
ToastHelper.Warning("请先在设备下拉中选择设备");
return;
}
string deviceId = ParseDeviceId(SelectedDevice);
string kind = ParseDeviceKind(SelectedDevice);
// 已打开则聚焦其 Tab(防御性:下拉本已过滤)
if (_openTabs.TryGetValue(deviceId, out var existing))
{
debugTabs.SelectedItem = existing;
SelectedDevice = null;
return;
}
var tabContent = new DeviceDebugTab();
tabContent.Initialize(_debugModel, _sessionManager, _deviceManager, _deviceService,
_deviceConfigDbPath, deviceId, kind);
var tab = new TabItem { Header = deviceId, Content = tabContent, Tag = deviceId };
debugTabs.Items.Add(tab);
debugTabs.SelectedItem = tab;
_openTabs[deviceId] = tab;
RefreshAvailableList();
SelectedDevice = null;
log.Info($"已加入调试设备: {deviceId}(当前 {debugTabs.Items.Count} 个标签)");
}
catch (Exception ex)
{
log.Error("加入调试设备失败", ex);
ToastHelper.Error($"加入调试失败: {ex.Message}");
}
}
private void CloseTabBtn_Click(object sender, RoutedEventArgs e)
{
try
{
if (debugTabs.SelectedItem is not TabItem tab) return;
string deviceId = tab.Tag as string ?? "";
if (tab.Content is DeviceDebugTab content)
content.CloseSessionSilently(); // 关闭即释放维护租约,杜绝泄漏
debugTabs.Items.Remove(tab);
if (!string.IsNullOrEmpty(deviceId)) _openTabs.Remove(deviceId);
RefreshAvailableList();
log.Info($"已关闭调试标签并释放会话: {deviceId}");
}
catch (Exception ex)
{
log.Error("关闭调试标签失败", ex);
ToastHelper.Error($"关闭失败: {ex.Message}");
}
}
}
}