From de4a7121db409f9c23fb1eeea8d2ddf8479f7bb2 Mon Sep 17 00:00:00 2001 From: "zhengxuan.zhang" Date: Thu, 21 May 2026 17:15:27 +0800 Subject: [PATCH] =?UTF-8?q?=E8=99=9A=E6=8B=9F=E6=A8=A1=E5=BC=8F=E4=B8=8B?= =?UTF-8?q?=20=E8=B7=B3=E8=BF=87=E8=81=94=E9=94=81=EF=BC=88Interlock?= =?UTF-8?q?=EF=BC=89=E6=A3=80=E6=9F=A5=EF=BC=8C=E5=9B=A0=E4=B8=BA=E8=99=9A?= =?UTF-8?q?=E6=8B=9F=E6=A8=A1=E5=BC=8F=E6=B2=A1=E6=9C=89=E7=9C=9F=E5=AE=9E?= =?UTF-8?q?=E5=AE=89=E5=85=A8=E9=97=A8=E4=BF=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + .../Module/MotionControlModule.cs | 14 ++++++++------ .../Services/MotionControlService.cs | 8 ++++++-- .../Implementations/SimulatedXRaySource.cs | 2 ++ .../ViewModels/RaySourceOperateViewModel.cs | 14 ++++++++++---- 5 files changed, 27 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 6d8de7a..f1d6278 100644 --- a/README.md +++ b/README.md @@ -108,3 +108,4 @@ dotnet build XplorePlane.sln -c Release - [x] 主界面硬件栏相机设置按钮 - [x] 打通与硬件层的调用流程 - [x] 打通与图像层的调用流程 +- [ ] CNC的执行、存储逻辑的开发测试 diff --git a/XP.Hardware.MotionControl/Module/MotionControlModule.cs b/XP.Hardware.MotionControl/Module/MotionControlModule.cs index 2c84fcb..7770809 100644 --- a/XP.Hardware.MotionControl/Module/MotionControlModule.cs +++ b/XP.Hardware.MotionControl/Module/MotionControlModule.cs @@ -69,17 +69,19 @@ namespace XP.Hardware.MotionControl.Module // Initialize LocalizationHelper to use ILocalizationService for string lookup (supports Fallback Chain) LocalizationHelper.Initialize(localizationService); - // 仅在非虚拟模式下启动 PLC 状态轮询 | Only start PLC polling when not in simulated mode + // 启动状态轮询(虚拟模式和 PLC 模式均需要,用于驱动 UI 位置更新事件) + // Start status polling (needed for both simulated and PLC modes to drive UI position update events) + var motionService = containerProvider.Resolve(); + motionService.StartPolling(); + var motionSystem = containerProvider.Resolve(); - if (motionSystem is not SimulatedMotionSystem) + if (motionSystem is SimulatedMotionSystem) { - var motionService = containerProvider.Resolve(); - motionService.StartPolling(); - System.Console.WriteLine("[MotionControlModule] PLC 轮询已启动 | PLC polling started"); + System.Console.WriteLine("[MotionControlModule] [Simulated] 轮询已启动(虚拟模式)| Polling started (simulated mode)"); } else { - System.Console.WriteLine("[MotionControlModule] [Simulated] 跳过 PLC 轮询 | Skipping PLC polling (simulated mode)"); + System.Console.WriteLine("[MotionControlModule] PLC 轮询已启动 | PLC polling started"); } System.Console.WriteLine("[MotionControlModule] 模块已初始化 | Module initialized"); diff --git a/XP.Hardware.MotionControl/Services/MotionControlService.cs b/XP.Hardware.MotionControl/Services/MotionControlService.cs index 97fe3a1..d26b701 100644 --- a/XP.Hardware.MotionControl/Services/MotionControlService.cs +++ b/XP.Hardware.MotionControl/Services/MotionControlService.cs @@ -11,6 +11,7 @@ using XP.Hardware.MotionControl.Abstractions; using XP.Hardware.MotionControl.Abstractions.Enums; using XP.Hardware.MotionControl.Abstractions.Events; using XP.Hardware.MotionControl.Config; +using XP.Hardware.MotionControl.Implementations; using XP.Hardware.Plc.Abstractions; namespace XP.Hardware.MotionControl.Services @@ -105,8 +106,11 @@ namespace XP.Hardware.MotionControl.Services /// private void OnPollingTick(object state) { - // PLC 未连接时跳过轮询 | Skip polling when PLC is not connected - if (!_plcService.IsConnected) return; + // 虚拟运动系统不依赖 PLC 连接 | Simulated motion system does not depend on PLC connection + bool isSimulated = _motionSystem is SimulatedMotionSystem; + + // PLC 未连接时跳过轮询(虚拟模式除外)| Skip polling when PLC is not connected (except simulated mode) + if (!isSimulated && !_plcService.IsConnected) return; // 连续错误过多时降频:每50次轮询才尝试一次 | Throttle when too many consecutive errors if (_pollErrorCount > 3) diff --git a/XP.Hardware.RaySource/Implementations/SimulatedXRaySource.cs b/XP.Hardware.RaySource/Implementations/SimulatedXRaySource.cs index a6d4c2a..e696540 100644 --- a/XP.Hardware.RaySource/Implementations/SimulatedXRaySource.cs +++ b/XP.Hardware.RaySource/Implementations/SimulatedXRaySource.cs @@ -65,6 +65,8 @@ namespace XP.Hardware.RaySource.Implementations public override XRayResult ConnectVariables() { _isConnected = true; + _eventAggregator.GetEvent().Publish(true); + _eventAggregator.GetEvent().Publish(RaySourceStatus.Closed); _logger.Info("[Simulated] PVI 变量连接成功"); return XRayResult.Ok(); } diff --git a/XP.Hardware.RaySource/ViewModels/RaySourceOperateViewModel.cs b/XP.Hardware.RaySource/ViewModels/RaySourceOperateViewModel.cs index 6f1e3a4..5d1fae1 100644 --- a/XP.Hardware.RaySource/ViewModels/RaySourceOperateViewModel.cs +++ b/XP.Hardware.RaySource/ViewModels/RaySourceOperateViewModel.cs @@ -70,11 +70,14 @@ namespace XP.Hardware.RaySource.ViewModels { get { + var isSimulated = _config.SourceType.Equals("Simulated", System.StringComparison.OrdinalIgnoreCase); + var suffix = isSimulated ? "\n(虚拟模式)" : ""; + return RaySourceStatus switch { RaySourceStatus.Unavailable => $"{_localizationService.GetString("RaySource_StatusUnavailable")}", - RaySourceStatus.Closed => _localizationService.GetString("RaySource_StatusClosed"), - RaySourceStatus.Opened => _localizationService.GetString("RaySource_StatusOpened"), + RaySourceStatus.Closed => (_localizationService.GetString("RaySource_StatusClosed") ?? "已关闭") + suffix, + RaySourceStatus.Opened => (_localizationService.GetString("RaySource_StatusOpened") ?? "已开启") + suffix, _ => _localizationService.GetString("RaySource_StatusUnavailable") }; } @@ -477,11 +480,14 @@ namespace XP.Hardware.RaySource.ViewModels } /// - /// 开启命令是否可执行(仅关闭状态且连锁激活时可执行)| Can execute turn on command (only when closed and interlock active) + /// 开启命令是否可执行(仅关闭状态且连锁激活时可执行,虚拟模式跳过联锁检查) + /// Can execute turn on command (only when closed and interlock active; simulated mode skips interlock check) /// private bool CanExecuteTurnOn() { - return !_isOperating && _isVariablesConnected && IsInterlockActive && RaySourceStatus == RaySourceStatus.Closed && _raySourceService.IsInitialized; + var isSimulated = _config.SourceType.Equals("Simulated", System.StringComparison.OrdinalIgnoreCase); + var interlockOk = isSimulated || IsInterlockActive; + return !_isOperating && _isVariablesConnected && interlockOk && RaySourceStatus == RaySourceStatus.Closed && _raySourceService.IsInitialized; } ///