using System; using System.Threading; using System.Threading.Tasks; using Prism.Events; using XP.Hardware.Detector.Abstractions; using XP.Hardware.Detector.Abstractions.Enums; using XP.Hardware.Detector.Config; using XP.Hardware.Detector.Factories; using XP.Common.Logging.Interfaces; namespace XP.Hardware.Detector.Services { /// /// 探测器服务实现 | Detector service implementation /// 单例模式,封装业务逻辑,屏蔽厂商差异 /// public class DetectorService : IDetectorService, IDisposable { private readonly IDetectorFactory _factory; private readonly IEventAggregator _eventAggregator; private readonly ILoggerService _logger; private readonly object _lock = new object(); private IAreaDetector _detector; private DetectorConfig _config; private DetectorResult _lastError; private bool _disposed = false; /// /// 当前探测器状态 | Current detector status /// public DetectorStatus Status { get { lock (_lock) { return _detector?.Status ?? DetectorStatus.Uninitialized; } } } /// /// 当前探测器类型 | Current detector type /// public DetectorType? Type { get { lock (_lock) { return _detector?.Type; } } } /// /// 探测器是否已连接 | Whether detector is connected /// public bool IsConnected { get { lock (_lock) { if (_detector == null) return false; var status = _detector.Status; return status == DetectorStatus.Ready || status == DetectorStatus.Acquiring || status == DetectorStatus.Correcting; } } } /// /// 构造函数 | Constructor /// /// 探测器工厂 | Detector factory /// 事件聚合器 | Event aggregator /// 日志服务 | Logger service public DetectorService(IDetectorFactory factory, IEventAggregator eventAggregator, ILoggerService logger = null) { _factory = factory ?? throw new ArgumentNullException(nameof(factory)); _eventAggregator = eventAggregator ?? throw new ArgumentNullException(nameof(eventAggregator)); _logger = logger?.ForModule("DetectorService"); _logger?.Info("DetectorService 实例已创建 | DetectorService instance created"); } /// /// 初始化探测器 | Initialize detector /// /// 取消令牌 | Cancellation token /// 操作结果 | Operation result public async Task InitializeAsync(CancellationToken cancellationToken = default) { // 若已连接,先断开再重连 | If already connected, disconnect first then reconnect bool alreadyConnected; lock (_lock) { alreadyConnected = _detector != null; } if (alreadyConnected) { _logger?.Info("探测器已连接,先断开再重新初始化 | Detector already connected, disconnecting before reinitializing"); await DisconnectAsync(); } try { _logger?.Info("开始初始化探测器服务 | Starting to initialize detector service"); // 加载配置 | Load configuration _logger?.Debug("加载配置文件 | Loading configuration file"); var configResult = ConfigLoader.LoadConfiguration(); if (!configResult.IsSuccess) { _lastError = configResult; _logger?.Error(null, $"加载配置失败 | Failed to load configuration: {configResult.ErrorMessage}"); return configResult; } _logger?.Info($"配置加载成功,探测器类型:{configResult.Data.Type} | Configuration loaded successfully, detector type: {configResult.Data.Type}"); // 保存配置引用 | Save config reference _config = configResult.Data; // 创建探测器实例 | Create detector instance _logger?.Debug("创建探测器实例 | Creating detector instance"); var createResult = _factory.CreateDetector(configResult.Data); if (!createResult.IsSuccess) { _lastError = createResult; _logger?.Error(createResult.Exception, $"创建探测器实例失败 | Failed to create detector instance: {createResult.ErrorMessage}"); return DetectorResult.Failure(createResult.ErrorMessage, createResult.Exception, createResult.ErrorCode); } lock (_lock) { _detector = createResult.Data; } // 初始化探测器 | Initialize detector _logger?.Debug("初始化探测器硬件 | Initializing detector hardware"); var initResult = await _detector.InitializeAsync(cancellationToken); if (!initResult.IsSuccess) { _lastError = initResult; _logger?.Error(initResult.Exception, $"初始化探测器硬件失败 | Failed to initialize detector hardware: {initResult.ErrorMessage}"); } else { _logger?.Info("探测器服务初始化成功 | Detector service initialized successfully"); } return initResult; } catch (Exception ex) { var errorMsg = $"初始化服务失败 | Failed to initialize service: {ex.Message}"; _logger?.Error(ex, errorMsg); var errorResult = DetectorResult.Failure(errorMsg, ex, -1); _lastError = errorResult; return errorResult; } } /// /// 断开探测器连接 | Disconnect detector /// public async Task DisconnectAsync() { try { IAreaDetector detector; lock (_lock) { detector = _detector; if (detector == null) { _logger?.Warn("探测器未连接,无需断开 | Detector not connected, no need to disconnect"); return DetectorResult.Success("探测器未连接 | Detector not connected"); } } _logger?.Info("开始断开探测器连接 | Starting to disconnect detector"); // 如果正在采集,先停止 | If acquiring, stop first if (detector.Status == DetectorStatus.Acquiring) { _logger?.Info("探测器正在采集,先停止采集 | Detector is acquiring, stopping first"); await detector.StopAcquisitionAsync(); } // 释放探测器资源 | Dispose detector resources lock (_lock) { _detector?.Dispose(); _detector = null; } _config = null; _logger?.Info("探测器已断开连接 | Detector disconnected"); return DetectorResult.Success("探测器已断开连接 | Detector disconnected"); } catch (Exception ex) { var errorMsg = $"断开探测器连接异常 | Disconnect detector exception: {ex.Message}"; _logger?.Error(ex, errorMsg); // 强制清理 | Force cleanup lock (_lock) { _detector?.Dispose(); _detector = null; } _config = null; var errorResult = DetectorResult.Failure(errorMsg, ex, -1); _lastError = errorResult; return errorResult; } } /// /// 启动连续采集 | Start continuous acquisition /// /// 取消令牌 | Cancellation token /// 操作结果 | Operation result public async Task StartAcquisitionAsync(CancellationToken cancellationToken = default) { try { _logger?.Info("服务层:启动连续采集 | Service layer: Starting continuous acquisition"); var detector = GetDetectorOrThrow(); var result = await detector.StartAcquisitionAsync(cancellationToken); if (!result.IsSuccess) { _lastError = result; _logger?.Error(result.Exception, $"启动采集失败 | Failed to start acquisition: {result.ErrorMessage}"); } return result; } catch (Exception ex) { var errorMsg = $"服务层启动采集异常 | Service layer start acquisition exception: {ex.Message}"; _logger?.Error(ex, errorMsg); var errorResult = DetectorResult.Failure(errorMsg, ex, -1); _lastError = errorResult; return errorResult; } } /// /// 停止采集 | Stop acquisition /// /// 取消令牌 | Cancellation token /// 操作结果 | Operation result public async Task StopAcquisitionAsync(CancellationToken cancellationToken = default) { try { _logger?.Info("服务层:停止采集 | Service layer: Stopping acquisition"); var detector = GetDetectorOrThrow(); var result = await detector.StopAcquisitionAsync(cancellationToken); if (!result.IsSuccess) { _lastError = result; _logger?.Error(result.Exception, $"停止采集失败 | Failed to stop acquisition: {result.ErrorMessage}"); } return result; } catch (Exception ex) { var errorMsg = $"服务层停止采集异常 | Service layer stop acquisition exception: {ex.Message}"; _logger?.Error(ex, errorMsg); var errorResult = DetectorResult.Failure(errorMsg, ex, -1); _lastError = errorResult; return errorResult; } } /// /// 单帧采集 | Single frame acquisition /// /// 取消令牌 | Cancellation token /// 操作结果 | Operation result public async Task AcquireSingleFrameAsync(CancellationToken cancellationToken = default) { try { _logger?.Debug("服务层:单帧采集 | Service layer: Single frame acquisition"); var detector = GetDetectorOrThrow(); var result = await detector.AcquireSingleFrameAsync(cancellationToken); if (!result.IsSuccess) { _lastError = result; _logger?.Error(result.Exception, $"单帧采集失败 | Failed to acquire single frame: {result.ErrorMessage}"); } return result; } catch (Exception ex) { var errorMsg = $"服务层单帧采集异常 | Service layer single frame acquisition exception: {ex.Message}"; _logger?.Error(ex, errorMsg); var errorResult = DetectorResult.Failure(errorMsg, ex, -1); _lastError = errorResult; return errorResult; } } /// /// 暗场校正 | Dark field correction /// /// 采集帧数 | Frame count /// 取消令牌 | Cancellation token /// 操作结果 | Operation result public async Task DarkCorrectionAsync(int frameCount = 10, CancellationToken cancellationToken = default) { try { _logger?.Info("服务层:执行暗场校正,帧数:{FrameCount} | Service layer: Executing dark correction, frame count: {FrameCount}", frameCount); var detector = GetDetectorOrThrow(); // 如果正在采集,先停止(XISL SDK 不允许采集中执行校正)| Stop acquisition first if running bool wasAcquiring = detector.Status == DetectorStatus.Acquiring; if (wasAcquiring) { _logger?.Info("探测器正在采集,先停止采集再执行暗场校正 | Detector is acquiring, stopping before dark correction"); var stopResult = await detector.StopAcquisitionAsync(cancellationToken); if (!stopResult.IsSuccess) { _lastError = stopResult; _logger?.Error(stopResult.Exception, "停止采集失败,无法执行暗场校正:{Message} | Failed to stop acquisition, cannot perform dark correction: {Message}", stopResult.ErrorMessage); return DetectorResult.Failure($"停止采集失败,无法执行暗场校正 | Failed to stop acquisition: {stopResult.ErrorMessage}"); } } var result = await detector.DarkCorrectionAsync(frameCount, cancellationToken); if (!result.IsSuccess) { _lastError = result; _logger?.Error(result.Exception, "暗场校正失败:{Message} | Dark correction failed: {Message}", result.ErrorMessage); } // 如果之前在采集,恢复采集 | Resume acquisition if it was running before if (wasAcquiring) { _logger?.Info("暗场校正完成,恢复连续采集 | Dark correction done, resuming continuous acquisition"); var startResult = await detector.StartAcquisitionAsync(cancellationToken); if (!startResult.IsSuccess) { _logger?.Warn("恢复采集失败:{Message} | Failed to resume acquisition: {Message}", startResult.ErrorMessage); } } return result; } catch (Exception ex) { var errorMsg = $"服务层暗场校正异常 | Service layer dark correction exception: {ex.Message}"; _logger?.Error(ex, errorMsg); var errorResult = DetectorResult.Failure(errorMsg, ex, -1); _lastError = errorResult; return errorResult; } } /// /// 增益校正(亮场校正)| Gain correction (bright field correction) /// /// 采集帧数 | Frame count /// 取消令牌 | Cancellation token /// 操作结果 | Operation result public async Task GainCorrectionAsync(int frameCount = 10, CancellationToken cancellationToken = default) { try { _logger?.Info("服务层:执行亮场校正,帧数:{FrameCount} | Service layer: Executing gain correction, frame count: {FrameCount}", frameCount); var detector = GetDetectorOrThrow(); // 如果正在采集,先停止(XISL SDK 不允许采集中执行校正)| Stop acquisition first if running bool wasAcquiring = detector.Status == DetectorStatus.Acquiring; if (wasAcquiring) { _logger?.Info("探测器正在采集,先停止采集再执行亮场校正 | Detector is acquiring, stopping before gain correction"); var stopResult = await detector.StopAcquisitionAsync(cancellationToken); if (!stopResult.IsSuccess) { _lastError = stopResult; _logger?.Error(stopResult.Exception, "停止采集失败,无法执行亮场校正:{Message} | Failed to stop acquisition, cannot perform gain correction: {Message}", stopResult.ErrorMessage); return DetectorResult.Failure($"停止采集失败,无法执行亮场校正 | Failed to stop acquisition: {stopResult.ErrorMessage}"); } } var result = await detector.GainCorrectionAsync(frameCount, cancellationToken); if (!result.IsSuccess) { _lastError = result; _logger?.Error(result.Exception, "亮场校正失败:{Message} | Gain correction failed: {Message}", result.ErrorMessage); } // 如果之前在采集,恢复采集 | Resume acquisition if it was running before if (wasAcquiring) { _logger?.Info("亮场校正完成,恢复连续采集 | Gain correction done, resuming continuous acquisition"); var startResult = await detector.StartAcquisitionAsync(cancellationToken); if (!startResult.IsSuccess) { _logger?.Warn("恢复采集失败:{Message} | Failed to resume acquisition: {Message}", startResult.ErrorMessage); } } return result; } catch (Exception ex) { var errorMsg = $"服务层亮场校正异常 | Service layer gain correction exception: {ex.Message}"; _logger?.Error(ex, errorMsg); var errorResult = DetectorResult.Failure(errorMsg, ex, -1); _lastError = errorResult; return errorResult; } } /// /// 坏像素校正 | Bad pixel correction /// /// 取消令牌 | Cancellation token /// 操作结果 | Operation result public async Task BadPixelCorrectionAsync(CancellationToken cancellationToken = default) { try { _logger?.Info("服务层:执行坏像素校正 | Service layer: Executing bad pixel correction"); var detector = GetDetectorOrThrow(); // 如果正在采集,先停止(XISL SDK 不允许采集中执行校正)| Stop acquisition first if running bool wasAcquiring = detector.Status == DetectorStatus.Acquiring; if (wasAcquiring) { _logger?.Info("探测器正在采集,先停止采集再执行坏像素校正 | Detector is acquiring, stopping before bad pixel correction"); var stopResult = await detector.StopAcquisitionAsync(cancellationToken); if (!stopResult.IsSuccess) { _lastError = stopResult; _logger?.Error(stopResult.Exception, "停止采集失败,无法执行坏像素校正:{Message} | Failed to stop acquisition, cannot perform bad pixel correction: {Message}", stopResult.ErrorMessage); return DetectorResult.Failure($"停止采集失败,无法执行坏像素校正 | Failed to stop acquisition: {stopResult.ErrorMessage}"); } } var result = await detector.BadPixelCorrectionAsync(cancellationToken); if (!result.IsSuccess) { _lastError = result; _logger?.Error(result.Exception, "坏像素校正失败:{Message} | Bad pixel correction failed: {Message}", result.ErrorMessage); } // 如果之前在采集,恢复采集 | Resume acquisition if it was running before if (wasAcquiring) { _logger?.Info("坏像素校正完成,恢复连续采集 | Bad pixel correction done, resuming continuous acquisition"); var startResult = await detector.StartAcquisitionAsync(cancellationToken); if (!startResult.IsSuccess) { _logger?.Warn("恢复采集失败:{Message} | Failed to resume acquisition: {Message}", startResult.ErrorMessage); } } return result; } catch (Exception ex) { var errorMsg = $"服务层坏像素校正异常 | Service layer bad pixel correction exception: {ex.Message}"; _logger?.Error(ex, errorMsg); var errorResult = DetectorResult.Failure(errorMsg, ex, -1); _lastError = errorResult; return errorResult; } } /// /// 执行自动校正(暗场+增益+坏像素)| Execute auto correction (dark + gain + bad pixel) /// /// 采集帧数 | Frame count /// 取消令牌 | Cancellation token /// 操作结果 | Operation result public async Task AutoCorrectionAsync(int frameCount = 10, CancellationToken cancellationToken = default) { try { _logger?.Info("服务层:执行自动校正,帧数:{FrameCount} | Service layer: Executing auto correction, frame count: {FrameCount}", frameCount); var detector = GetDetectorOrThrow(); var result = await detector.AutoCorrectionAsync(frameCount, cancellationToken); if (!result.IsSuccess) { _lastError = result; _logger?.Error(result.Exception, "自动校正失败:{Message} | Auto correction failed: {Message}", result.ErrorMessage); } return result; } catch (Exception ex) { var errorMsg = $"服务层自动校正异常 | Service layer auto correction exception: {ex.Message}"; _logger?.Error(ex, errorMsg); var errorResult = DetectorResult.Failure(errorMsg, ex, -1); _lastError = errorResult; return errorResult; } } /// /// 应用探测器参数(Binning/PGA/帧率统一下发)| Apply detector parameters (Binning/PGA/FrameRate) /// public async Task ApplyParametersAsync(int binningIndex, int pga, decimal frameRate, CancellationToken cancellationToken = default) { try { _logger?.Info("服务层:应用参数,Binning={Binning},PGA={PGA},帧率={FrameRate} | Service layer: Applying parameters", binningIndex, pga, frameRate); var detector = GetDetectorOrThrow(); // 如果正在采集,先停止 | Stop acquisition first if running bool wasAcquiring = detector.Status == DetectorStatus.Acquiring; if (wasAcquiring) { _logger?.Info("探测器正在采集,先停止采集再应用参数 | Detector is acquiring, stopping before applying parameters"); var stopResult = await detector.StopAcquisitionAsync(cancellationToken); if (!stopResult.IsSuccess) { _lastError = stopResult; _logger?.Error(stopResult.Exception, "停止采集失败,无法应用参数:{Message} | Failed to stop acquisition, cannot apply parameters: {Message}", stopResult.ErrorMessage); return DetectorResult.Failure($"停止采集失败,无法应用参数 | Failed to stop acquisition, cannot apply parameters: {stopResult.ErrorMessage}"); } } // 通过统一接口下发参数(不依赖具体探测器类型)| Apply parameters via unified interface (no dependency on specific detector type) var result = await detector.ApplyParametersAsync(binningIndex, pga, frameRate, cancellationToken); if (!result.IsSuccess) { _lastError = result; _logger?.Error(result.Exception, "应用参数失败:{Message} | Apply parameters failed: {Message}", result.ErrorMessage); } else { _logger?.Info("参数应用成功 | Parameters applied successfully"); } // 如果之前在采集,恢复采集 | Resume acquisition if it was running before if (wasAcquiring) { _logger?.Info("参数应用完成,恢复连续采集 | Parameters applied, resuming continuous acquisition"); var startResult = await detector.StartAcquisitionAsync(cancellationToken); if (!startResult.IsSuccess) { _logger?.Warn("恢复采集失败:{Message}(参数已成功应用)| Failed to resume acquisition: {Message} (parameters were applied successfully)", startResult.ErrorMessage); } } return result; } catch (Exception ex) { var errorMsg = $"服务层应用参数异常 | Service layer apply parameters exception: {ex.Message}"; _logger?.Error(ex, errorMsg); var errorResult = DetectorResult.Failure(errorMsg, ex, -1); _lastError = errorResult; return errorResult; } } /// /// 保存当前配置到文件 | Save current configuration to file /// public void SaveParameters(int binningIndex, int pga, decimal frameRate, int avgFrames) { try { _logger?.Info("保存探测器参数,Binning={Binning},PGA={PGA},帧率={FrameRate},帧合并={AvgFrames} | Saving detector parameters", binningIndex, pga, frameRate, avgFrames); ConfigLoader.SaveParameters(binningIndex, pga, frameRate, avgFrames); _logger?.Info("探测器参数保存成功 | Detector parameters saved successfully"); } catch (Exception ex) { _logger?.Error(ex, "保存探测器参数失败:{Message} | Failed to save detector parameters: {Message}", ex.Message); } } /// /// 获取探测器信息 | Get detector information /// /// 探测器信息 | Detector information public DetectorInfo GetInfo() { var detector = GetDetectorOrThrow(); return detector.GetInfo(); } /// /// 获取最后的错误信息 | Get last error information /// /// 错误结果 | Error result public DetectorResult GetLastError() { return _lastError ?? DetectorResult.Success(); } /// /// 获取当前探测器配置 | Get current detector configuration /// 未初始化时尝试从配置文件加载(仅读取配置,不创建探测器实例) /// public DetectorConfig GetCurrentConfig() { if (_config != null) return _config; // 未初始化时,尝试从配置文件加载以提供 UI 选项 | If not initialized, try loading from config for UI options try { var configResult = ConfigLoader.LoadConfiguration(); if (configResult.IsSuccess) { _config = configResult.Data; return _config; } } catch { // 忽略加载异常,返回 null | Ignore load exception, return null } return null; } /// /// 获取当前探测器的校正能力描述 | Get correction capabilities of current detector /// 未初始化时返回基于配置文件的默认值 /// public CorrectionCapabilities GetCorrectionCapabilities() { lock (_lock) { if (_detector != null) { return _detector.GetCorrectionCapabilities(); } } // 未初始化时从配置文件构建默认值 | Build default from config when not initialized var config = GetCurrentConfig(); return new CorrectionCapabilities { DarkFrameCount = config?.DarkCorrectionFrameCount ?? 64, GainFrameCount = config?.GainCorrectionFrameCount ?? 64 }; } /// /// 获取探测器实例或抛出异常 | Get detector instance or throw exception /// /// 探测器实例 | Detector instance /// 探测器未初始化 | Detector not initialized private IAreaDetector GetDetectorOrThrow() { lock (_lock) { if (_detector == null) { throw new InvalidOperationException("探测器未初始化,请先调用 InitializeAsync | Detector not initialized, please call InitializeAsync first"); } return _detector; } } /// /// 释放资源 | Dispose resources /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// /// 释放资源 | Dispose resources /// /// 是否释放托管资源 | Whether to dispose managed resources protected virtual void Dispose(bool disposing) { if (!_disposed) { if (disposing) { // 带超时保护的资源释放,避免退出时无限阻塞 // Dispose with timeout protection to avoid infinite blocking on exit const int disposeTimeoutMs = 5000; // 5 秒总超时 | 5 seconds total timeout try { IAreaDetector detector; lock (_lock) { detector = _detector; } if (detector != null) { // 仅在正在采集时才停止采集 | Only stop acquisition if currently acquiring if (detector.Status == DetectorStatus.Acquiring) { _logger?.Info("Dispose:探测器正在采集,尝试停止 | Dispose: Detector is acquiring, attempting to stop"); using var cts = new CancellationTokenSource(disposeTimeoutMs); var stopTask = Task.Run(async () => await detector.StopAcquisitionAsync(cts.Token), cts.Token); if (!stopTask.Wait(disposeTimeoutMs)) { _logger?.Warn("Dispose:停止采集超时,强制继续释放 | Dispose: Stop acquisition timeout, forcing cleanup"); } } // 直接释放探测器资源(不再调用 DisconnectAsync 避免重复停止) // Directly dispose detector resources (skip DisconnectAsync to avoid redundant stop) lock (_lock) { _detector?.Dispose(); _detector = null; } _config = null; _logger?.Info("Dispose:探测器资源已释放 | Dispose: Detector resources disposed"); } } catch (OperationCanceledException) { _logger?.Warn("Dispose:操作已取消,强制释放资源 | Dispose: Operation cancelled, forcing resource cleanup"); lock (_lock) { _detector?.Dispose(); _detector = null; } _config = null; } catch (AggregateException ex) { _logger?.Warn($"Dispose:聚合异常,强制释放资源 | Dispose: Aggregate exception, forcing cleanup: {ex.InnerException?.Message ?? ex.Message}"); lock (_lock) { _detector?.Dispose(); _detector = null; } _config = null; } catch (Exception ex) { _logger?.Error(ex, "Dispose:释放探测器资源异常 | Dispose: Exception disposing detector resources"); lock (_lock) { try { _detector?.Dispose(); } catch { /* 忽略 | Ignore */ } _detector = null; } _config = null; } } _disposed = true; } } } }