新增CNC执行数据源的生成
This commit is contained in:
@@ -1,12 +1,17 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Media.Imaging;
|
||||
using XP.Common.GeneralForm.Views;
|
||||
using XP.Common.Logging.Interfaces;
|
||||
using XplorePlane.Models;
|
||||
using XplorePlane.Services.InspectionResults;
|
||||
using XplorePlane.Services.MainViewport;
|
||||
using XplorePlane.ViewModels;
|
||||
|
||||
namespace XplorePlane.Services.Cnc
|
||||
{
|
||||
@@ -17,11 +22,22 @@ namespace XplorePlane.Services.Cnc
|
||||
{
|
||||
private readonly IInspectionResultStore _store;
|
||||
private readonly ILoggerService _logger;
|
||||
private readonly IMainViewportService _mainViewportService;
|
||||
private readonly IPipelineExecutionService _pipelineExecutionService;
|
||||
private readonly IImageProcessingService _imageProcessingService;
|
||||
|
||||
public CncExecutionService(IInspectionResultStore store, ILoggerService logger)
|
||||
public CncExecutionService(
|
||||
IInspectionResultStore store,
|
||||
ILoggerService logger,
|
||||
IMainViewportService mainViewportService,
|
||||
IPipelineExecutionService pipelineExecutionService,
|
||||
IImageProcessingService imageProcessingService)
|
||||
{
|
||||
_store = store ?? throw new ArgumentNullException(nameof(store));
|
||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
_mainViewportService = mainViewportService;
|
||||
_pipelineExecutionService = pipelineExecutionService;
|
||||
_imageProcessingService = imageProcessingService;
|
||||
}
|
||||
|
||||
public async Task ExecuteAsync(CncProgram program, IProgress<CncNodeExecutionProgress> progress, CancellationToken cancellationToken)
|
||||
@@ -32,6 +48,10 @@ namespace XplorePlane.Services.Cnc
|
||||
|
||||
int inspectionNodeCount = program.Nodes.OfType<InspectionModuleNode>().Count();
|
||||
|
||||
// 获取当前源图像(用于 run/source.bmp)
|
||||
var sourceImage = _mainViewportService?.LatestManualImage as BitmapSource
|
||||
?? _mainViewportService?.CurrentDisplayImage as BitmapSource;
|
||||
|
||||
Guid runId;
|
||||
try
|
||||
{
|
||||
@@ -41,7 +61,21 @@ namespace XplorePlane.Services.Cnc
|
||||
NodeCount = inspectionNodeCount,
|
||||
StartedAt = DateTime.UtcNow
|
||||
};
|
||||
await _store.BeginRunAsync(runRecord);
|
||||
|
||||
InspectionAssetWriteRequest sourceAsset = null;
|
||||
if (sourceImage != null)
|
||||
{
|
||||
sourceAsset = new InspectionAssetWriteRequest
|
||||
{
|
||||
AssetType = InspectionAssetType.RunSourceImage,
|
||||
Content = EncodeBitmapToBmp(sourceImage),
|
||||
FileFormat = "bmp",
|
||||
Width = sourceImage.PixelWidth,
|
||||
Height = sourceImage.PixelHeight
|
||||
};
|
||||
}
|
||||
|
||||
await _store.BeginRunAsync(runRecord, sourceAsset);
|
||||
runId = runRecord.RunId;
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -90,24 +124,7 @@ namespace XplorePlane.Services.Cnc
|
||||
case InspectionModuleNode inspectionNode:
|
||||
try
|
||||
{
|
||||
var nodeResult = new InspectionNodeResult
|
||||
{
|
||||
RunId = runId,
|
||||
NodeId = inspectionNode.Id,
|
||||
NodeIndex = inspectionNode.Index,
|
||||
NodeName = inspectionNode.Name
|
||||
};
|
||||
|
||||
PipelineExecutionSnapshot pipelineSnapshot = inspectionNode.Pipeline != null
|
||||
? new PipelineExecutionSnapshot
|
||||
{
|
||||
RunId = runId,
|
||||
NodeId = inspectionNode.Id,
|
||||
PipelineName = inspectionNode.Pipeline.Name
|
||||
}
|
||||
: null;
|
||||
|
||||
await _store.AppendNodeResultAsync(nodeResult, pipelineSnapshot: pipelineSnapshot);
|
||||
await ExecuteInspectionNodeAsync(runId, inspectionNode, sourceImage, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -162,6 +179,127 @@ namespace XplorePlane.Services.Cnc
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ExecuteInspectionNodeAsync(
|
||||
Guid runId,
|
||||
InspectionModuleNode inspectionNode,
|
||||
BitmapSource sourceImage,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var nodeResult = new InspectionNodeResult
|
||||
{
|
||||
RunId = runId,
|
||||
NodeId = inspectionNode.Id,
|
||||
NodeIndex = inspectionNode.Index,
|
||||
NodeName = inspectionNode.Name,
|
||||
PipelineName = inspectionNode.Pipeline?.Name ?? string.Empty
|
||||
};
|
||||
|
||||
PipelineExecutionSnapshot pipelineSnapshot = null;
|
||||
if (inspectionNode.Pipeline != null)
|
||||
{
|
||||
var pipelineJson = JsonSerializer.Serialize(inspectionNode.Pipeline);
|
||||
pipelineSnapshot = new PipelineExecutionSnapshot
|
||||
{
|
||||
RunId = runId,
|
||||
NodeId = inspectionNode.Id,
|
||||
PipelineName = inspectionNode.Pipeline.Name,
|
||||
PipelineDefinitionJson = pipelineJson
|
||||
};
|
||||
}
|
||||
|
||||
// 构建资产列表
|
||||
var assets = new System.Collections.Generic.List<InspectionAssetWriteRequest>();
|
||||
|
||||
// input.bmp — 当前源图像
|
||||
if (sourceImage != null)
|
||||
{
|
||||
assets.Add(new InspectionAssetWriteRequest
|
||||
{
|
||||
AssetType = InspectionAssetType.NodeInputImage,
|
||||
Content = EncodeBitmapToBmp(sourceImage),
|
||||
FileFormat = "bmp",
|
||||
Width = sourceImage.PixelWidth,
|
||||
Height = sourceImage.PixelHeight
|
||||
});
|
||||
}
|
||||
|
||||
// result_overlay.bmp — 执行流水线后的结果图像
|
||||
if (_pipelineExecutionService != null && inspectionNode.Pipeline?.Nodes?.Count > 0 && sourceImage != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var pipelineNodes = BuildPipelineNodeViewModels(inspectionNode.Pipeline);
|
||||
var resultImage = await _pipelineExecutionService.ExecutePipelineAsync(
|
||||
pipelineNodes, sourceImage, null, cancellationToken);
|
||||
|
||||
if (resultImage != null)
|
||||
{
|
||||
assets.Add(new InspectionAssetWriteRequest
|
||||
{
|
||||
AssetType = InspectionAssetType.NodeResultImage,
|
||||
Content = EncodeBitmapToBmp(resultImage),
|
||||
FileFormat = "bmp",
|
||||
Width = resultImage.PixelWidth,
|
||||
Height = resultImage.PixelHeight
|
||||
});
|
||||
nodeResult.Status = InspectionNodeStatus.Succeeded;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.ForModule<CncExecutionService>().Warn(
|
||||
"Pipeline execution failed for node '{0}': {1}", inspectionNode.Name, ex.Message);
|
||||
nodeResult.Status = InspectionNodeStatus.Failed;
|
||||
}
|
||||
}
|
||||
|
||||
await _store.AppendNodeResultAsync(nodeResult, pipelineSnapshot: pipelineSnapshot, assets: assets);
|
||||
}
|
||||
|
||||
private System.Collections.Generic.IEnumerable<ViewModels.PipelineNodeViewModel> BuildPipelineNodeViewModels(PipelineModel pipeline)
|
||||
{
|
||||
var nodes = new System.Collections.Generic.List<ViewModels.PipelineNodeViewModel>();
|
||||
if (pipeline?.Nodes == null) return nodes;
|
||||
|
||||
foreach (var nodeModel in pipeline.Nodes.OrderBy(n => n.Order))
|
||||
{
|
||||
var displayName = _imageProcessingService?.GetProcessorDisplayName(nodeModel.OperatorKey) ?? nodeModel.OperatorKey;
|
||||
var vm = new ViewModels.PipelineNodeViewModel(nodeModel.OperatorKey, displayName, string.Empty)
|
||||
{
|
||||
Order = nodeModel.Order,
|
||||
IsEnabled = nodeModel.IsEnabled
|
||||
};
|
||||
|
||||
// 加载参数定义并恢复保存的值
|
||||
if (_imageProcessingService != null)
|
||||
{
|
||||
var paramDefs = _imageProcessingService.GetProcessorParameters(nodeModel.OperatorKey);
|
||||
if (paramDefs != null)
|
||||
{
|
||||
foreach (var def in paramDefs)
|
||||
{
|
||||
var paramVm = new ViewModels.ProcessorParameterVM(def);
|
||||
if (nodeModel.Parameters != null && nodeModel.Parameters.TryGetValue(def.Name, out var saved))
|
||||
paramVm.Value = saved;
|
||||
vm.Parameters.Add(paramVm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nodes.Add(vm);
|
||||
}
|
||||
return nodes;
|
||||
}
|
||||
|
||||
private static byte[] EncodeBitmapToBmp(BitmapSource bitmap)
|
||||
{
|
||||
using var ms = new MemoryStream();
|
||||
var encoder = new BmpBitmapEncoder();
|
||||
encoder.Frames.Add(BitmapFrame.Create(bitmap));
|
||||
encoder.Save(ms);
|
||||
return ms.ToArray();
|
||||
}
|
||||
|
||||
private static async Task ExecuteWaitDelayWithProgressAsync(WaitDelayNode waitNode, CancellationToken cancellationToken)
|
||||
{
|
||||
int totalMs = waitNode.DelayMilliseconds;
|
||||
|
||||
Reference in New Issue
Block a user