| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798 |
- 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
- {
- /// <summary>
- /// 设置页 ViewModel(partial 拆分):
- /// 本文件 = 导航/通讯/调试 + 构造函数 + 全部命令声明;
- /// 相机/机器人/光源/全局变量/系统设置分别位于 SettingViewModel.*.cs。
- /// </summary>
- 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<ICommunication> Communications { get; }
- public ObservableCollection<CommunicationTypeInfo> CommunicationTypes { get; }
- public ObservableCollection<CommunicationTypeInfo> PlcTypes { get; }
- /// <summary>当前Tab下显示的通讯列表</summary>
- public ObservableCollection<ICommunication> 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;
- /// <summary>
- /// PropertyGrid 绑定对象 - 直接返回当前选中的配置对象
- /// 基础Tab 和 PLCTab 使用不同的 Info 子类,PropertyGrid 自动只显示对应属性
- /// </summary>
- public object PropertyGridSelectedObject => _selectedCommunication;
- /// <summary>
- /// PropertyGrid 是否可用(未选中或已连接时禁用)
- /// </summary>
- 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); }
- }
- /// <summary>基础通讯类型列表(供基础Tab添加用)</summary>
- public ObservableCollection<CommunicationTypeInfo> BasicCommTypes { get; }
- private CommunicationTypeInfo _selectedPlcType;
- public CommunicationTypeInfo SelectedPlcType
- {
- get { return _selectedPlcType; }
- set { SetProperty(ref _selectedPlcType, value); }
- }
- #endregion
- #region 视觉引擎与主页画面
- /// <summary>可用视觉引擎(启动时反射探测:VisionPro / VM / Halcon ...)</summary>
- public System.Collections.Generic.IReadOnlyList<TeamAAS.Vision.IVisualEngine> AvailableEngines
- => TeamAAS.Vision.VisualEngineManager.Instance.Engines;
- private TeamAAS.Vision.IVisualEngine _selectedEngine;
- /// <summary>当前选中的视觉引擎(一键切换:主页画面/标定页随引擎变化)</summary>
- 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();
- }
- }
- /// <summary>按当前配置重建主页画面布局、重注册画面框并保存配置</summary>
- 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));
- /// <summary>主页画面数可选规格:均能被最优行列算法精确铺满(无空白框)</summary>
- public int[] HomePageFrameOptions { get; } = { 1, 2, 4, 6, 9 };
- /// <summary>主页画面框水平排列(HomeFrameArrange=1)</summary>
- public bool IsHorizontalArrange
- {
- get => (App.SystemConfig?.Vision?.HomeFrameArrange ?? 1) == 1;
- set { if (value && App.SystemConfig?.Vision != null) App.SystemConfig.Vision.HomeFrameArrange = 1; }
- }
- /// <summary>主页画面框垂直排列(HomeFrameArrange=2)</summary>
- 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;
- /// <summary>品牌专属调试页(由 [Communication] 特性 DebugPageType 创建);null = 使用通用通讯测试面板</summary>
- public object CurrentCommunicationDebugPage
- {
- get { return _currentCommunicationDebugPage; }
- private set
- {
- SetProperty(ref _currentCommunicationDebugPage, value);
- }
- }
- private ICommunication _debugPageDevice;
- /// <summary>
- /// 按选中的设备刷新专属调试页;设备实例未变化时不重建(保留页面状态)。
- /// </summary>
- 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<object> FeederDirectionCommand { get; }
- public DelegateCommand StopFeederActionCommand { get; }
- public DelegateCommand ExecuteActionCommand { get; }
- public DelegateCommand DownloadParamCommand { get; }
- #region 序列集命令
- public DelegateCommand AddSequenceCommand { get; }
- public DelegateCommand DeleteSequenceCommand { get; }
- public DelegateCommand RenameSequenceCommand { get; }
- public DelegateCommand<string> AddSequenceStepCommand { get; }
- public DelegateCommand MoveUpStepCommand { get; }
- public DelegateCommand MoveDownStepCommand { get; }
- public DelegateCommand DeleteStepCommand { get; }
- public DelegateCommand ExecuteSequenceCommand { get; }
- public DelegateCommand StopSequenceCommand { get; }
- #endregion
- #endregion
- #region 光源命令
- public DelegateCommand LightConnectCommand { get; }
- public DelegateCommand LightDisconnectCommand { get; }
- public DelegateCommand LightTurnOnAllCommand { get; }
- public DelegateCommand LightTurnOffAllCommand { get; }
- public DelegateCommand LightSetBrightnessCommand { get; }
- public DelegateCommand LightReadBrightnessCommand { get; }
- public DelegateCommand LightRefreshDevicesCommand { get; }
- #endregion
- #region 通讯命令
- public DelegateCommand AddCommunicationCommand { get; }
- public DelegateCommand DeleteCommunicationCommand { get; }
- public DelegateCommand ConnectCommunicationCommand { get; }
- public DelegateCommand DisconnectCommunicationCommand { get; }
- public DelegateCommand SaveCommunicationsCommand { get; }
- public DelegateCommand RefreshCommunicationCommand { get; }
- public DelegateCommand ConnectAllCommand { get; }
- public DelegateCommand DisconnectAllCommand { get; }
- #endregion
- public SettingViewModel(ICameraManager cameraManager, IRobotManager robotManager,
- CommunicationManager communicationManager, IFeederManager feederManager)
- {
- _cameraManager = cameraManager;
- _robotManager = robotManager;
- _communicationManager = communicationManager;
- _feederManager = feederManager;
- Cameras = new ObservableCollection<TeamAAS.Camera.Models.CameraInfo>();
- SdkStatus = new ObservableCollection<SdkStatusItem>();
- Robots = new ObservableCollection<RobotInfo>();
- Feeders = new ObservableCollection<TeamAAS.Feeder.Models.FeederInfo>();
- Communications = new ObservableCollection<ICommunication>();
- DisplayedCommunications = new ObservableCollection<ICommunication>();
- CommunicationTypes = new ObservableCollection<CommunicationTypeInfo>();
- PlcTypes = new ObservableCollection<CommunicationTypeInfo>();
- BasicCommTypes = new ObservableCollection<CommunicationTypeInfo>();
- // 相机命令
- SearchDevicesCommand = new DelegateCommand(OpenSearchDialog);
- DeleteCameraCommand = new DelegateCommand(DeleteCamera);
- ConnectCommand = new DelegateCommand(async () => await ConnectAsync());
- DisconnectCommand = new DelegateCommand(Disconnect);
- StartGrabbingCommand = new DelegateCommand(StartGrabbing);
- StopGrabbingCommand = new DelegateCommand(StopGrabbing);
- SaveCameraConfigCommand = new DelegateCommand(SaveCameraConfig);
- // 机器人命令
- AddRobotCommand = new DelegateCommand(AddRobot);
- DeleteRobotCommand = new DelegateCommand(DeleteRobot);
- ConnectRobotCommand = new DelegateCommand(async () => await ConnectRobotAsync());
- DisconnectRobotCommand = new DelegateCommand(DisconnectRobot);
- SaveRobotConfigCommand = new DelegateCommand(SaveRobotConfig);
- // 供料器命令
- AddFeederCommand = new DelegateCommand(AddFeeder);
- DeleteFeederCommand = new DelegateCommand(DeleteFeeder, () => HasSelectedFeeder);
- SaveFeederConfigCommand = new DelegateCommand(SaveFeederConfig);
- ConnectFeederCommand = new DelegateCommand(async () => await ConnectFeederAsync());
- DisconnectFeederCommand = new DelegateCommand(DisconnectFeeder);
- ToggleBacklightCommand = new DelegateCommand(ToggleBacklight);
- FeederDirectionCommand = new DelegateCommand<object>(async (p) => await ExecuteDirectionAsync(Convert.ToInt32(p)));
- StopFeederActionCommand = new DelegateCommand(async () => await StopFeederAsync());
- ExecuteActionCommand = new DelegateCommand(async () => await ExecuteCurrentActionAsync());
- DownloadParamCommand = new DelegateCommand(async () => await DownloadFeederParamsAsync());
- AddSequenceCommand = new DelegateCommand(AddSequence);
- DeleteSequenceCommand = new DelegateCommand(DeleteSequence);
- RenameSequenceCommand = new DelegateCommand(RenameSequence);
- AddSequenceStepCommand = new DelegateCommand<string>(AddSequenceStep);
- MoveUpStepCommand = new DelegateCommand(MoveUpStep);
- MoveDownStepCommand = new DelegateCommand(MoveDownStep);
- DeleteStepCommand = new DelegateCommand(DeleteStep);
- ExecuteSequenceCommand = new DelegateCommand(async () => await ExecuteSequenceAsync());
- StopSequenceCommand = new DelegateCommand(StopSequence);
- // 光源命令
- LightConnectCommand = new DelegateCommand(async () => await LightConnectAsync());
- LightDisconnectCommand = new DelegateCommand(LightDisconnect);
- LightTurnOnAllCommand = new DelegateCommand(async () => await LightTurnOnAllAsync());
- LightTurnOffAllCommand = new DelegateCommand(async () => await LightTurnOffAllAsync());
- LightSetBrightnessCommand = new DelegateCommand(async () => await LightSetBrightnessAsync());
- LightReadBrightnessCommand = new DelegateCommand(async () => await LightReadBrightnessAsync());
- LightRefreshDevicesCommand = new DelegateCommand(RefreshLightSerialDevices);
- // 通讯命令
- AddCommunicationCommand = new DelegateCommand(AddCommunication);
- DeleteCommunicationCommand = new DelegateCommand(DeleteCommunication);
- ConnectCommunicationCommand = new DelegateCommand(async () => await ConnectCommunicationAsync());
- DisconnectCommunicationCommand = new DelegateCommand(DisconnectCommunication);
- SaveCommunicationsCommand = new DelegateCommand(SaveCommunications);
- RefreshCommunicationCommand = new DelegateCommand(RefreshCommunications);
- ConnectAllCommand = new DelegateCommand(ConnectAll);
- DisconnectAllCommand = new DelegateCommand(DisconnectAll);
- // 全局变量命令
- SaveGlobalVarsCommand = new DelegateCommand(SaveGlobalVars);
- InitGlobalVarEditor();
- // 通用设置命令
- SaveSystemConfigCommand = new DelegateCommand(SaveSystemConfig);
- LoadSystemConfigCommand = new DelegateCommand(LoadSystemConfig);
- // 语言设置命令
- RefreshLanguagesCommand = new DelegateCommand(RefreshLanguages);
- // 全局事件配置命令
- SaveGlobalEventConfigCommand = new DelegateCommand(SaveGlobalEventConfig);
- LoadGlobalEventConfigCommand = new DelegateCommand(LoadGlobalEventConfig);
- AddHeartbeatCommand = new DelegateCommand(AddHeartbeat);
- RemoveHeartbeatCommand = new DelegateCommand<HeartbeatConfig>(RemoveHeartbeat);
- AddProductSwitchEventCommand = new DelegateCommand(AddProductSwitchEvent);
- RemoveProductSwitchEventCommand = new DelegateCommand<ProductSwitchEvent>(RemoveProductSwitchEvent);
- }
- /// <summary>
- /// 首次导航到设置页时延迟加载(UI 先渲染,数据后台加载)
- /// </summary>
- public void DelayedLoad()
- {
- try { LoadSdkStatus(); } catch { }
- try { LoadCommunicationTypes(); } catch { }
- try { LoadPlcTypes(); } catch { }
- try { LoadBasicCommTypes(); } catch { }
- try { RefreshCommunications(); } catch { }
- try { RefreshLightSerialDevices(); } catch { }
- try { InitLightModelOptions(); } catch { }
- try { RefreshCameraList(); } catch { }
- try { RefreshRobotList(); } catch { }
- try { RefreshFeederList(); } catch { }
- try { RefreshRecipeList(); } catch { }
- try { InitGlobalVarEditor(); } catch { }
- try { TeamAAS.FlowEditor.Execution.ResultRegistry.RefreshGlobals(); } catch { }
- try { LoadSystemConfig(); } catch { }
- try { LoadGlobalEventConfig(); } catch { }
- try { InitializeLanguageSettings(); } catch { }
- }
- private void InitLightModelOptions()
- {
- LightModelDisplayOptions.Clear();
- foreach (LightModel model in Enum.GetValues(typeof(LightModel)))
- {
- var field = typeof(LightModel).GetField(model.ToString());
- var attr = field?.GetCustomAttributes(typeof(System.ComponentModel.DescriptionAttribute), false)
- .OfType<System.ComponentModel.DescriptionAttribute>()
- .FirstOrDefault();
- string display = attr?.Description ?? model.ToString();
- LightModelDisplayOptions.Add(new LightModelDisplay { Model = model, Display = display });
- }
- SelectedLightModelItem = LightModelDisplayOptions.FirstOrDefault();
- }
- #region 通讯基础操作
- private void LoadCommunicationTypes()
- {
- CommunicationTypes.Clear();
- try
- {
- var types = _communicationManager.GetAvailableTypes();
- foreach (var t in types)
- {
- CommunicationTypes.Add(t);
- }
- AddTypeKey = CommunicationTypes.FirstOrDefault()?.TypeKey ?? "";
- }
- catch (Exception ex)
- {
- CommMessage = $"加载通讯类型失败: {ex.Message}";
- }
- }
- private void LoadPlcTypes()
- {
- PlcTypes.Clear();
- try
- {
- var types = _communicationManager.GetPlcTypes();
- foreach (var t in types)
- {
- PlcTypes.Add(t);
- }
- }
- catch (Exception ex)
- {
- CommMessage = $"加载 PLC 协议类型失败: {ex.Message}";
- }
- }
- private void LoadBasicCommTypes()
- {
- BasicCommTypes.Clear();
- try
- {
- var types = _communicationManager.GetBasicTypes();
- foreach (var t in types)
- {
- BasicCommTypes.Add(t);
- }
- }
- catch { }
- }
- private void RefreshCommunications()
- {
- Communications.Clear();
- try
- {
- foreach (var comm in _communicationManager.Devices)
- {
- Communications.Add(comm);
- }
- }
- catch (Exception ex)
- {
- CommMessage = $"加载通讯列表失败: {ex.Message}";
- }
- UpdateDisplayedCommunications();
- RefreshLightSerialDevices();
- }
- private void UpdateDisplayedCommunications()
- {
- DisplayedCommunications.Clear();
- var list = Communications.ToList();
- if (IsBasicTab)
- {
- foreach (var c in list)
- {
- if (c is PlcCommunicationBase) continue;
- DisplayedCommunications.Add(c);
- }
- }
- else if (IsPlcTab)
- {
- foreach (var c in list)
- {
- if (c is PlcCommunicationBase)
- DisplayedCommunications.Add(c);
- }
- }
- RaisePropertyChanged(nameof(DisplayedCommunications));
- }
- private void AddCommunication()
- {
- try
- {
- string typeKey;
- string baseName;
- if (IsPlcTab)
- {
- var plcType = SelectedPlcType;
- if (plcType == null)
- {
- DialogHelper.ShowWarning("请先选择 PLC 协议类型");
- return;
- }
- typeKey = plcType.TypeKey;
- baseName = "PLC" + (DisplayedCommunications.Count + 1);
- }
- else
- {
- if (string.IsNullOrWhiteSpace(AddTypeKey))
- {
- DialogHelper.ShowWarning("请先选择通讯类型");
- return;
- }
- typeKey = AddTypeKey;
- baseName = _communicationManager.GetTypeInfo(typeKey)?.DisplayName ?? "通讯" + (DisplayedCommunications.Count + 1);
- }
- var index = Communications.Count + 1;
- var name = GetUniqueCommunicationName(baseName + index);
- var device = _communicationManager.Create(typeKey, Guid.NewGuid(), name, index);
- _communicationManager.Register(device);
- Communications.Add(device);
- UpdateDisplayedCommunications();
- SelectedCommunication = device;
- CommMessage = $"已添加 {device.Name}";
- RefreshLightSerialDevices();
- }
- catch (Exception ex)
- {
- DialogHelper.ShowError("添加通讯失败", ex);
- }
- }
- private string GetUniqueCommunicationName(string baseName)
- {
- var names = new HashSet<string>(
- Communications.Select(c => c.Name),
- StringComparer.OrdinalIgnoreCase);
- if (!names.Contains(baseName)) return baseName;
- int n = 1;
- string candidate;
- do
- {
- candidate = $"{baseName}({n})";
- n++;
- } while (names.Contains(candidate));
- return candidate;
- }
- private void DeleteCommunication()
- {
- if (SelectedCommunication == null) return;
- if (!DialogHelper.ConfirmYesNo(
- $"确认删除 \"{SelectedCommunication.Name}\" 吗?",
- "确认删除"))
- {
- return;
- }
- var toRemove = SelectedCommunication;
- try
- {
- _communicationManager.Remove(toRemove.Id);
- }
- catch (Exception ex)
- {
- System.Diagnostics.Debug.WriteLine($"移除通讯设备异常: {ex.Message}");
- }
- Communications.Remove(toRemove);
- DisplayedCommunications.Remove(toRemove);
- for (int i = 0; i < Communications.Count; i++)
- {
- Communications[i].Index = i + 1;
- }
- SelectedCommunication = null;
- RefreshLightSerialDevices();
- }
- private async Task ConnectCommunicationAsync()
- {
- if (SelectedCommunication == null) return;
- try
- {
- await SelectedCommunication.ConnectAsync();
- UpdateDebugMode();
- RaisePropertyChanged(nameof(IsPropertyGridEnabled));
- CommMessage = SelectedCommunication.IsConnected ? $"已连接 {SelectedCommunication.Name}" : $"连接失败 {SelectedCommunication.Name}";
- }
- catch (Exception ex)
- {
- CommMessage = $"连接异常: {ex.Message}";
- }
- }
- private void DisconnectCommunication()
- {
- if (SelectedCommunication == null) return;
- try
- {
- SelectedCommunication.Disconnect();
- RaisePropertyChanged(nameof(IsPropertyGridEnabled));
- CommMessage = $"已断开 {SelectedCommunication.Name}";
- }
- catch (Exception ex)
- {
- CommMessage = $"断开异常: {ex.Message}";
- }
- }
- private void ConnectAll()
- {
- try
- {
- foreach (var device in Communications)
- {
- try { device.Connect(); } catch { }
- }
- CommMessage = "已连接所有设备";
- }
- catch (Exception ex)
- {
- CommMessage = $"批量连接异常: {ex.Message}";
- }
- }
- private void DisconnectAll()
- {
- try
- {
- foreach (var device in Communications)
- {
- try { device.Disconnect(); } catch { }
- }
- CommMessage = "已断开所有设备";
- }
- catch (Exception ex)
- {
- CommMessage = $"批量断开异常: {ex.Message}";
- }
- }
- private void SaveCommunications()
- {
- try
- {
- if (_communicationManager.SaveConfig())
- CommMessage = "通讯配置已保存";
- else
- DialogHelper.ShowError("通讯配置保存失败,请查看日志");
- }
- catch (Exception ex)
- {
- DialogHelper.ShowError("保存通讯配置失败", ex);
- }
- }
- #endregion
- #region 通讯调试
- private void UpdateDebugMode()
- {
- if (_subscribedDevice != null)
- {
- _subscribedDevice.DataReceivedEvent -= OnDataReceived;
- _subscribedDevice = null;
- }
- if (_selectedCommunication == null)
- {
- IsPlcDebugMode = false;
- return;
- }
- IsPlcDebugMode = _selectedCommunication is PlcCommunicationBase;
- var comm = _communicationManager.Get(_selectedCommunication.Id);
- if (comm != null)
- {
- _subscribedDevice = comm;
- _subscribedDevice.DataReceivedEvent += OnDataReceived;
- }
- RefreshCommunicationDebugPage();
- }
- private void OnDataReceived(object sender, string data)
- {
- var comm = _selectedCommunication as BindableCommunicationBase;
- if (comm == null) return;
- Application.Current.Dispatcher.Invoke(() =>
- {
- comm.AppendLog($"RX: {data}");
- });
- }
- #endregion
- }
- }
|