diff --git a/XplorePlane/Models/CncModels.cs b/XplorePlane/Models/CncModels.cs
index 5672544..56c1014 100644
--- a/XplorePlane/Models/CncModels.cs
+++ b/XplorePlane/Models/CncModels.cs
@@ -46,7 +46,8 @@ namespace XplorePlane.Models
/// 参考点节点 | Reference point node
public record ReferencePointNode(
Guid Id, int Index, string Name,
- double XM, double YM, double ZT, double ZD, double TiltD, double Dist
+ double XM, double YM, double ZT, double ZD, double TiltD, double Dist,
+ bool IsRayOn, double Voltage, double Current
) : CncNode(Id, Index, CncNodeType.ReferencePoint, Name);
/// 保存节点(含图像)| Save node with image
@@ -113,4 +114,4 @@ namespace XplorePlane.Models
DateTime UpdatedAt,
IReadOnlyList Nodes
);
-}
\ No newline at end of file
+}
diff --git a/XplorePlane/Services/Cnc/CncProgramService.cs b/XplorePlane/Services/Cnc/CncProgramService.cs
index c7f9524..eabad59 100644
--- a/XplorePlane/Services/Cnc/CncProgramService.cs
+++ b/XplorePlane/Services/Cnc/CncProgramService.cs
@@ -6,6 +6,7 @@ using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using XP.Common.Logging.Interfaces;
+using XP.Hardware.RaySource.Services;
using XplorePlane.Models;
using XplorePlane.Services.AppState;
@@ -20,6 +21,7 @@ namespace XplorePlane.Services.Cnc
public class CncProgramService : ICncProgramService
{
private readonly IAppStateService _appStateService;
+ private readonly IRaySourceService _raySourceService;
private readonly ILoggerService _logger;
// ── 序列化配置 | Serialization options ──
@@ -32,12 +34,15 @@ namespace XplorePlane.Services.Cnc
public CncProgramService(
IAppStateService appStateService,
+ IRaySourceService raySourceService,
ILoggerService logger)
{
ArgumentNullException.ThrowIfNull(appStateService);
+ ArgumentNullException.ThrowIfNull(raySourceService);
ArgumentNullException.ThrowIfNull(logger);
_appStateService = appStateService;
+ _raySourceService = raySourceService;
_logger = logger.ForModule();
_logger.Info("CncProgramService 已初始化 | CncProgramService initialized");
@@ -344,6 +349,7 @@ namespace XplorePlane.Services.Cnc
private ReferencePointNode CreateReferencePointNode(Guid id, int index)
{
var motion = _appStateService.MotionState;
+ var raySource = _appStateService.RaySourceState;
return new ReferencePointNode(
id, index, $"参考点_{index}",
XM: motion.XM,
@@ -351,7 +357,10 @@ namespace XplorePlane.Services.Cnc
ZT: motion.ZT,
ZD: motion.ZD,
TiltD: motion.TiltD,
- Dist: motion.Dist);
+ Dist: motion.Dist,
+ IsRayOn: raySource.IsOn,
+ Voltage: raySource.Voltage,
+ Current: TryReadCurrent());
}
/// 创建保存节点(含图像)| Create save node with image
@@ -382,5 +391,24 @@ namespace XplorePlane.Services.Cnc
id, index, $"保存位置_{index}",
MotionState: _appStateService.MotionState);
}
+ private double TryReadCurrent()
+ {
+ try
+ {
+ var result = _raySourceService.ReadCurrent();
+ if (result?.Success == true)
+ {
+ return result.GetFloat();
+ }
+
+ _logger.Warn("Failed to read ray source current, ReferencePoint node will use 0");
+ }
+ catch (Exception ex)
+ {
+ _logger.Warn("Failed to read ray source current: {Message}", ex.Message);
+ }
+
+ return 0d;
+ }
}
-}
\ No newline at end of file
+}
diff --git a/XplorePlane/ViewModels/Cnc/CncEditorViewModel.cs b/XplorePlane/ViewModels/Cnc/CncEditorViewModel.cs
index 325c9c2..c1cdc9c 100644
--- a/XplorePlane/ViewModels/Cnc/CncEditorViewModel.cs
+++ b/XplorePlane/ViewModels/Cnc/CncEditorViewModel.cs
@@ -173,7 +173,7 @@ namespace XplorePlane.ViewModels.Cnc
if (_currentProgram == null)
{
_logger.Warn("无法插入节点:当前无程序 | Cannot insert node: no current program");
- return;
+ ExecuteNewProgram();
}
try
@@ -365,7 +365,7 @@ namespace XplorePlane.ViewModels.Cnc
var sb = new StringBuilder();
// CSV 表头 | CSV header
- sb.AppendLine("Index,NodeType,Name,XM,YM,ZT,ZD,TiltD,Dist,Voltage_kV,Power_W,RayOn,DetectorConnected,FrameRate,Resolution,ImageFile,MarkerType,MarkerX,MarkerY,DialogTitle,DialogMessage,DelayMs,Pipeline");
+ sb.AppendLine("Index,NodeType,Name,XM,YM,ZT,ZD,TiltD,Dist,Voltage_kV,Current_uA,Power_W,RayOn,DetectorConnected,FrameRate,Resolution,ImageFile,MarkerType,MarkerX,MarkerY,DialogTitle,DialogMessage,DelayMs,Pipeline");
var inv = CultureInfo.InvariantCulture;
@@ -373,11 +373,11 @@ namespace XplorePlane.ViewModels.Cnc
{
var row = node switch
{
- ReferencePointNode rp => $"{rp.Index},{rp.NodeType},{Esc(rp.Name)},{rp.XM.ToString(inv)},{rp.YM.ToString(inv)},{rp.ZT.ToString(inv)},{rp.ZD.ToString(inv)},{rp.TiltD.ToString(inv)},{rp.Dist.ToString(inv)},,,,,,,,,,,,,,",
+ ReferencePointNode rp => $"{rp.Index},{rp.NodeType},{Esc(rp.Name)},{rp.XM.ToString(inv)},{rp.YM.ToString(inv)},{rp.ZT.ToString(inv)},{rp.ZD.ToString(inv)},{rp.TiltD.ToString(inv)},{rp.Dist.ToString(inv)},{rp.Voltage.ToString(inv)},{rp.Current.ToString(inv)},,{rp.IsRayOn},,,,,,,,,,",
- SaveNodeWithImageNode sni => $"{sni.Index},{sni.NodeType},{Esc(sni.Name)},{sni.MotionState.XM.ToString(inv)},{sni.MotionState.YM.ToString(inv)},{sni.MotionState.ZT.ToString(inv)},{sni.MotionState.ZD.ToString(inv)},{sni.MotionState.TiltD.ToString(inv)},{sni.MotionState.Dist.ToString(inv)},{sni.RaySourceState.Voltage.ToString(inv)},{sni.RaySourceState.Power.ToString(inv)},{sni.RaySourceState.IsOn},{sni.DetectorState.IsConnected},{sni.DetectorState.FrameRate.ToString(inv)},{Esc(sni.DetectorState.Resolution)},{Esc(sni.ImageFileName)},,,,,,",
+ SaveNodeWithImageNode sni => $"{sni.Index},{sni.NodeType},{Esc(sni.Name)},{sni.MotionState.XM.ToString(inv)},{sni.MotionState.YM.ToString(inv)},{sni.MotionState.ZT.ToString(inv)},{sni.MotionState.ZD.ToString(inv)},{sni.MotionState.TiltD.ToString(inv)},{sni.MotionState.Dist.ToString(inv)},{sni.RaySourceState.Voltage.ToString(inv)},,{sni.RaySourceState.Power.ToString(inv)},{sni.RaySourceState.IsOn},{sni.DetectorState.IsConnected},{sni.DetectorState.FrameRate.ToString(inv)},{Esc(sni.DetectorState.Resolution)},{Esc(sni.ImageFileName)},,,,,,",
- SaveNodeNode sn => $"{sn.Index},{sn.NodeType},{Esc(sn.Name)},{sn.MotionState.XM.ToString(inv)},{sn.MotionState.YM.ToString(inv)},{sn.MotionState.ZT.ToString(inv)},{sn.MotionState.ZD.ToString(inv)},{sn.MotionState.TiltD.ToString(inv)},{sn.MotionState.Dist.ToString(inv)},{sn.RaySourceState.Voltage.ToString(inv)},{sn.RaySourceState.Power.ToString(inv)},{sn.RaySourceState.IsOn},{sn.DetectorState.IsConnected},{sn.DetectorState.FrameRate.ToString(inv)},{Esc(sn.DetectorState.Resolution)},,,,,,,",
+ SaveNodeNode sn => $"{sn.Index},{sn.NodeType},{Esc(sn.Name)},{sn.MotionState.XM.ToString(inv)},{sn.MotionState.YM.ToString(inv)},{sn.MotionState.ZT.ToString(inv)},{sn.MotionState.ZD.ToString(inv)},{sn.MotionState.TiltD.ToString(inv)},{sn.MotionState.Dist.ToString(inv)},{sn.RaySourceState.Voltage.ToString(inv)},,{sn.RaySourceState.Power.ToString(inv)},{sn.RaySourceState.IsOn},{sn.DetectorState.IsConnected},{sn.DetectorState.FrameRate.ToString(inv)},{Esc(sn.DetectorState.Resolution)},,,,,,,",
SavePositionNode sp => $"{sp.Index},{sp.NodeType},{Esc(sp.Name)},{sp.MotionState.XM.ToString(inv)},{sp.MotionState.YM.ToString(inv)},{sp.MotionState.ZT.ToString(inv)},{sp.MotionState.ZD.ToString(inv)},{sp.MotionState.TiltD.ToString(inv)},{sp.MotionState.Dist.ToString(inv)},,,,,,,,,,,,,,",
@@ -466,4 +466,4 @@ namespace XplorePlane.ViewModels.Cnc
.Publish(new CncProgramChangedPayload(ProgramName ?? string.Empty, IsModified));
}
}
-}
\ No newline at end of file
+}
diff --git a/XplorePlane/ViewModels/Main/MainViewModel.cs b/XplorePlane/ViewModels/Main/MainViewModel.cs
index 2a97744..f3a633e 100644
--- a/XplorePlane/ViewModels/Main/MainViewModel.cs
+++ b/XplorePlane/ViewModels/Main/MainViewModel.cs
@@ -10,6 +10,7 @@ using System.IO;
using System.Windows;
using System.Windows.Media.Imaging;
using XplorePlane.Events;
+using XplorePlane.ViewModels.Cnc;
using XplorePlane.Views;
using XplorePlane.Views.Cnc;
using XP.Common.Logging.Interfaces;
@@ -23,6 +24,8 @@ namespace XplorePlane.ViewModels
private readonly ILoggerService _logger;
private readonly IContainerProvider _containerProvider;
private readonly IEventAggregator _eventAggregator;
+ private readonly CncEditorViewModel _cncEditorViewModel;
+ private readonly CncPageView _cncPageView;
private string _licenseInfo = "当前时间";
public string LicenseInfo
@@ -51,6 +54,17 @@ namespace XplorePlane.ViewModels
public DelegateCommand OpenLibraryVersionsCommand { get; }
public DelegateCommand OpenUserManualCommand { get; }
public DelegateCommand OpenCameraSettingsCommand { get; }
+ public DelegateCommand NewCncProgramCommand { get; }
+ public DelegateCommand SaveCncProgramCommand { get; }
+ public DelegateCommand LoadCncProgramCommand { get; }
+ public DelegateCommand InsertReferencePointCommand { get; }
+ public DelegateCommand InsertSavePositionCommand { get; }
+ public DelegateCommand InsertCompleteProgramCommand { get; }
+ public DelegateCommand InsertInspectionMarkerCommand { get; }
+ public DelegateCommand InsertInspectionModuleCommand { get; }
+ public DelegateCommand InsertSaveNodeCommand { get; }
+ public DelegateCommand InsertPauseDialogCommand { get; }
+ public DelegateCommand InsertWaitDelayCommand { get; }
// 硬件命令
public DelegateCommand AxisResetCommand { get; }
@@ -94,6 +108,8 @@ namespace XplorePlane.ViewModels
_logger = logger?.ForModule() ?? throw new ArgumentNullException(nameof(logger));
_containerProvider = containerProvider ?? throw new ArgumentNullException(nameof(containerProvider));
_eventAggregator = eventAggregator ?? throw new ArgumentNullException(nameof(eventAggregator));
+ _cncEditorViewModel = _containerProvider.Resolve();
+ _cncPageView = new CncPageView { DataContext = _cncEditorViewModel };
NavigationTree = new ObservableCollection