using Prism.Commands;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using System.Windows;
using TeamAAS.Camera.Interfaces;
using TeamAAS.Communication;
using TeamAAS.Communication.Base;
using TeamAAS.Communication.Config;
using TeamAAS.Communication.Interfaces;
using TeamAAS.Communication.LightSources;
using TeamAAS.Communication.Models;
using TeamAAS.Feeder.Interfaces;
using TeamAAS.Robot.Interfaces;
using TeamAAS.Robot.Models;
using TeamAAS.Views;
namespace TeamAAS.ViewModels
{
///
/// 设置页 ViewModel(partial 拆分):
/// 本文件 = 导航/通讯/调试 + 构造函数 + 全部命令声明;
/// 相机/机器人/光源/全局变量/系统设置分别位于 SettingViewModel.*.cs。
///
public partial class SettingViewModel : TeamAAS.BindableBase
{
private readonly ICameraManager _cameraManager;
private readonly IRobotManager _robotManager;
private readonly IFeederManager _feederManager;
private readonly CommunicationManager _communicationManager;
[DllImport("gdi32.dll")]
private static extern bool DeleteObject(IntPtr hObject);
#region 导航
private string _selectedSection = "Camera";
public string SelectedSection
{
get { return _selectedSection; }
set
{
if (SetProperty(ref _selectedSection, value))
{
RaisePropertyChanged(nameof(IsBasicTab));
RaisePropertyChanged(nameof(IsPlcTab));
RaisePropertyChanged(nameof(IsCommSection));
RaisePropertyChanged(nameof(CommTabDisplayText));
UpdateDisplayedCommunications();
RaisePropertyChanged(nameof(PropertyGridSelectedObject));
UpdateDebugMode();
if (value == "Light")
{
RefreshLightSerialDevices();
}
if (value == "ProductData")
{
RefreshDatabaseHost();
}
if (value == "GlobalVariable")
{
// 进入全局变量页:从 live 列表克隆 Global 变量到编辑器
InitGlobalVarEditor();
}
}
}
}
#endregion
#region 通讯管理 - 基础属性
public bool IsCommSection => SelectedSection == "BasicComm" || SelectedSection == "PlcComm";
public bool IsBasicTab => SelectedSection == "BasicComm";
public bool IsPlcTab => SelectedSection == "PlcComm";
public string CommTabDisplayText => IsBasicTab ? "基础通讯设备" : "PLC通讯设备";
public ObservableCollection Communications { get; }
public ObservableCollection CommunicationTypes { get; }
public ObservableCollection PlcTypes { get; }
/// 当前Tab下显示的通讯列表
public ObservableCollection DisplayedCommunications { get; }
private ICommunication _selectedCommunication;
public ICommunication SelectedCommunication
{
get { return _selectedCommunication; }
set
{
var old = _selectedCommunication as System.ComponentModel.INotifyPropertyChanged;
if (old != null) old.PropertyChanged -= OnSelectedDevicePropertyChanged;
SetProperty(ref _selectedCommunication, value);
var now = _selectedCommunication as System.ComponentModel.INotifyPropertyChanged;
if (now != null) now.PropertyChanged += OnSelectedDevicePropertyChanged;
RaisePropertyChanged(nameof(IsTcpClientSelected));
RaisePropertyChanged(nameof(IsTcpServerSelected));
RaisePropertyChanged(nameof(IsSerialSelected));
RaisePropertyChanged(nameof(IsUdpSelected));
RaisePropertyChanged(nameof(IsWebSelected));
RaisePropertyChanged(nameof(IsPlcSelected));
RaisePropertyChanged(nameof(HasSelectedCommunication));
RaisePropertyChanged(nameof(PropertyGridSelectedObject));
RaisePropertyChanged(nameof(IsPropertyGridEnabled));
UpdateDebugMode();
}
}
private void OnSelectedDevicePropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(ICommunication.IsConnected))
{
RaisePropertyChanged(nameof(IsPropertyGridEnabled));
UpdateDebugMode();
}
}
public bool HasSelectedCommunication => _selectedCommunication != null;
///
/// PropertyGrid 绑定对象 - 直接返回当前选中的配置对象
/// 基础Tab 和 PLCTab 使用不同的 Info 子类,PropertyGrid 自动只显示对应属性
///
public object PropertyGridSelectedObject => _selectedCommunication;
///
/// PropertyGrid 是否可用(未选中或已连接时禁用)
///
public bool IsPropertyGridEnabled => _selectedCommunication != null && !_selectedCommunication.IsConnected;
private bool IsType(string typeKey) => SelectedCommunication?.TypeKey?.Contains(typeKey) ?? false;
public bool IsTcpClientSelected => IsType("TcpClientCommunication");
public bool IsTcpServerSelected => IsType("TcpServerCommunication");
public bool IsSerialSelected => IsType("SerialCommunication");
public bool IsUdpSelected => IsType("UdpCommunication");
public bool IsWebSelected => IsType("WebCommunication");
public bool IsPlcSelected => SelectedCommunication is PlcCommunicationBase;
private string _addTypeKey = "";
public string AddTypeKey
{
get { return _addTypeKey; }
set { SetProperty(ref _addTypeKey, value); }
}
private string _commMessage = "";
public string CommMessage
{
get { return _commMessage; }
set { SetProperty(ref _commMessage, value); }
}
/// 基础通讯类型列表(供基础Tab添加用)
public ObservableCollection BasicCommTypes { get; }
private CommunicationTypeInfo _selectedPlcType;
public CommunicationTypeInfo SelectedPlcType
{
get { return _selectedPlcType; }
set { SetProperty(ref _selectedPlcType, value); }
}
#endregion
#region 视觉引擎与主页画面
/// 可用视觉引擎(启动时反射探测:VisionPro / VM / Halcon ...)
public System.Collections.Generic.IReadOnlyList AvailableEngines
=> TeamAAS.Vision.VisualEngineManager.Instance.Engines;
private TeamAAS.Vision.IVisualEngine _selectedEngine;
/// 当前选中的视觉引擎(一键切换:主页画面/标定页随引擎变化)
public TeamAAS.Vision.IVisualEngine SelectedEngine
{
get
{
return _selectedEngine
?? TeamAAS.Vision.VisualEngineManager.Instance.Current
?? TeamAAS.Vision.VisualEngineManager.Instance.GetOrLoad(App.SystemConfig?.Vision?.EngineName);
}
set
{
if (value == null) return;
_selectedEngine = value;
RaisePropertyChanged(nameof(SelectedEngine));
if (!TeamAAS.Vision.VisualEngineManager.Instance.SetCurrent(value.EngineName)) return;
App.SystemConfig.Vision.EngineName = value.EngineName;
ApplyVisionLayout();
App.SaveSystemConfig();
}
}
/// 按当前配置重建主页画面布局、重注册画面框并保存配置
private void ApplyVisionLayout()
{
var vision = App.SystemConfig.Vision;
var engine = TeamAAS.Vision.VisualEngineManager.Instance.Current;
engine?.ApplyHomeLayout(vision.HomePageFrameCount, vision.HomeFrameArrange);
TeamAAS.Vision.VisualFrameManager.Clear();
for (int i = 0; i < vision.HomePageFrameCount; i++)
TeamAAS.Vision.VisualFrameManager.Register($"home:{i + 1}", vision.GetFrameName(i), "Home");
// 主页 VM 不一定存活,布局数据已持久化;主页下次导航时按配置重建
App.SaveSystemConfig();
}
private DelegateCommand _applyVisionLayoutCommand;
public DelegateCommand ApplyVisionLayoutCommand
=> _applyVisionLayoutCommand ?? (_applyVisionLayoutCommand = new DelegateCommand(ApplyVisionLayout));
/// 主页画面数可选规格:均能被最优行列算法精确铺满(无空白框)
public int[] HomePageFrameOptions { get; } = { 1, 2, 4, 6, 9 };
/// 主页画面框水平排列(HomeFrameArrange=1)
public bool IsHorizontalArrange
{
get => (App.SystemConfig?.Vision?.HomeFrameArrange ?? 1) == 1;
set { if (value && App.SystemConfig?.Vision != null) App.SystemConfig.Vision.HomeFrameArrange = 1; }
}
/// 主页画面框垂直排列(HomeFrameArrange=2)
public bool IsVerticalArrange
{
get => (App.SystemConfig?.Vision?.HomeFrameArrange ?? 1) == 2;
set { if (value && App.SystemConfig?.Vision != null) App.SystemConfig.Vision.HomeFrameArrange = 2; }
}
#endregion
#region 通讯调试
private ICommunication _subscribedDevice;
private bool _isPlcDebugMode;
public bool IsPlcDebugMode
{
get { return _isPlcDebugMode; }
set { SetProperty(ref _isPlcDebugMode, value); }
}
private object _currentCommunicationDebugPage;
/// 品牌专属调试页(由 [Communication] 特性 DebugPageType 创建);null = 使用通用通讯测试面板
public object CurrentCommunicationDebugPage
{
get { return _currentCommunicationDebugPage; }
private set
{
SetProperty(ref _currentCommunicationDebugPage, value);
}
}
private ICommunication _debugPageDevice;
///
/// 按选中的设备刷新专属调试页;设备实例未变化时不重建(保留页面状态)。
///
private void RefreshCommunicationDebugPage()
{
var comm = _selectedCommunication;
if (comm == _debugPageDevice && (comm != null || _currentCommunicationDebugPage == null))
return;
(_currentCommunicationDebugPage as TeamAAS.Communication.UI.ICommunicationDebugPage)?.UnbindCommunication();
_debugPageDevice = null;
CurrentCommunicationDebugPage = null;
if (comm == null) return;
try
{
var page = TeamAAS.Communication.UI.CommunicationDebugPageFactory.Create(comm);
if (page == null) return;
_debugPageDevice = comm;
CurrentCommunicationDebugPage = page;
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"加载通讯调试页失败: {ex.Message}");
}
}
#endregion
#region 相机命令
public DelegateCommand SearchDevicesCommand { get; }
public DelegateCommand DeleteCameraCommand { get; }
public DelegateCommand ConnectCommand { get; }
public DelegateCommand DisconnectCommand { get; }
public DelegateCommand StartGrabbingCommand { get; }
public DelegateCommand StopGrabbingCommand { get; }
public DelegateCommand SaveCameraConfigCommand { get; }
#endregion
#region 机器人命令
public DelegateCommand AddRobotCommand { get; }
public DelegateCommand DeleteRobotCommand { get; }
public DelegateCommand ConnectRobotCommand { get; }
public DelegateCommand DisconnectRobotCommand { get; }
public DelegateCommand SaveRobotConfigCommand { get; }
#endregion
#region 供料器命令
public DelegateCommand AddFeederCommand { get; }
public DelegateCommand DeleteFeederCommand { get; }
public DelegateCommand SaveFeederConfigCommand { get; }
public DelegateCommand ConnectFeederCommand { get; }
public DelegateCommand DisconnectFeederCommand { get; }
public DelegateCommand ToggleBacklightCommand { get; }
public DelegateCommand