using log4net;
using Plugin.DeviceDebug.Entity;
using System;
using System.Windows;
using System.Windows.Controls;
namespace Plugin.DeviceDebug.Panels
{
///
/// CAN 调试面板多通道壳:以 TabControl 承载若干 ,
/// 支持同屏并列多个 CAN 通道独立收发(验收场景 4)。
/// 对外保持与旧单面板一致的属性契约(DeviceId/InitialBusName/InitialNodeIndex/
/// AutoConnectOnLoad/ExistingDriver/IsMaintenanceMode/OnCommandExecute),
/// DeviceDebug 选设备时这些配置被转发到"设备通道"(首个 Tab)。
///
public partial class CanDebugPanel : UserControl
{
private static readonly ILog log = LogManager.GetLogger(typeof(CanDebugPanel));
public static readonly DependencyProperty IsMaintenanceModeProperty =
DependencyProperty.Register(nameof(IsMaintenanceMode), typeof(bool), typeof(CanDebugPanel),
new PropertyMetadata(false, OnMaintenanceModeChanged));
public bool IsMaintenanceMode
{
get => (bool)GetValue(IsMaintenanceModeProperty);
set => SetValue(IsMaintenanceModeProperty, value);
}
private static void OnMaintenanceModeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var panel = (CanDebugPanel)d;
if (panel._deviceChannel != null)
panel._deviceChannel.IsMaintenanceMode = (bool)e.NewValue;
}
/// 命令执行事件(任一通道触发均上抛,供 DeviceDebug 统一处理)
public event EventHandler? OnCommandExecute;
private CanChannelView? _deviceChannel;
private int _manualSeq;
// 待转发到设备通道的配置(可能早于通道创建)
private string _deviceId = string.Empty;
private string _initialBusName;
private int? _initialNodeIndex;
private bool _autoConnectOnLoad;
private Aging.Infrastructure.Contracts.IDeviceDriver? _existingDriver;
public CanDebugPanel()
{
InitializeComponent();
}
/// 设备ID(转发到设备通道)
public string DeviceId
{
get => _deviceId;
set { _deviceId = value; EnsureDeviceChannel().DeviceId = value; }
}
/// 总线名称(转发到设备通道)
public string InitialBusName
{
get => _initialBusName;
set { _initialBusName = value; EnsureDeviceChannel().InitialBusName = value; }
}
/// 节点编号(转发到设备通道)
public int? InitialNodeIndex
{
get => _initialNodeIndex;
set { _initialNodeIndex = value; EnsureDeviceChannel().InitialNodeIndex = value; }
}
/// 加载即自动连接(转发到设备通道)
public bool AutoConnectOnLoad
{
get => _autoConnectOnLoad;
set { _autoConnectOnLoad = value; EnsureDeviceChannel().AutoConnectOnLoad = value; }
}
/// 外部已注册驱动(转发到设备通道,共享设备复用宿主通路)
public Aging.Infrastructure.Contracts.IDeviceDriver? ExistingDriver
{
get => _existingDriver;
set { _existingDriver = value; EnsureDeviceChannel().ExistingDriver = value; }
}
/// 惰性创建"设备通道"(首个 Tab),并挂接命令事件与当前维护态。
private CanChannelView EnsureDeviceChannel()
{
if (_deviceChannel != null) return _deviceChannel;
_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;
}
private void WireChannel(CanChannelView view, string header)
{
view.OnCommandExecute += (s, e) => OnCommandExecute?.Invoke(this, e);
}
private TabItem MakeTab(CanChannelView view)
{
// 复用视图自身的标题区不显示设备名,这里用 Tab 头标注通道身份
return new TabItem { Content = view };
}
private static string MakeHeader(string deviceId, string bus, int? node)
{
string id = string.IsNullOrEmpty(deviceId) ? "通道" : deviceId;
if (!string.IsNullOrEmpty(bus))
return $"{id} @{bus}:{node}";
return id;
}
/// 手动添加一个可编辑的空白通道(Local TCP 直连,用户自填总线/节点后连接)。
private void AddChannelBtn_Click(object sender, RoutedEventArgs e)
{
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}");
}
/// 关闭当前选中的通道(设备通道不可关闭,避免误退出 DeviceDebug 会话视图)。
private void CloseChannelBtn_Click(object sender, RoutedEventArgs e)
{
if (channelTabs.SelectedItem is not TabItem tab) return;
if (tab.Content == _deviceChannel)
{
MessageBox.Show("设备通道不可在此关闭,请从设备选择切换。", "提示",
MessageBoxButton.OK, MessageBoxImage.Information);
return;
}
if (tab.Content is CanChannelView view)
view.DisconnectInternalSafe();
channelTabs.Items.Remove(tab);
}
/// 更新设备通道 Tab 头(在配置齐备后调用一次即可)。
public void RefreshDeviceHeader()
{
if (_deviceChannel == null || channelTabs.Items.Count == 0) return;
if (channelTabs.Items[0] is TabItem t)
t.Header = MakeHeader(_deviceId, _initialBusName, _initialNodeIndex);
}
}
}