Files
XplorePlane/XP.Hardware.Detector/Config/ConfigLoader.cs
T
QI Mingxuan 4943bc16b7 已合并 PR 90: 探测器直方图和优化合并至开发分支
1、重构探测器Hardware.Detector模块,统一设备调用接口,支持多探测器兼容,优化设备连接状态判断逻辑,新增校正帧数可配置功能。
2、优化Varex探测器校正流程,修复内存缓冲区对齐问题,增加指针、分辨率有效性校验,校正期间屏蔽帧回调、自动启停采集,规避SDK冲突与程序崩溃问题。
3、开发通用图像灰度直方图控件,优化资源释放逻辑。
2026-05-22 08:51:50 +08:00

282 lines
12 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Configuration;
using System.IO;
using System.Net;
using XP.Hardware.Detector.Abstractions;
using XP.Hardware.Detector.Abstractions.Enums;
namespace XP.Hardware.Detector.Config
{
/// <summary>
/// 配置加载器 | Configuration loader
/// 从 App.config 读取探测器配置并验证参数有效性
/// </summary>
public static class ConfigLoader
{
/// <summary>
/// 加载配置 | Load configuration
/// </summary>
/// <returns>配置结果 | Configuration result</returns>
public static DetectorResult<DetectorConfig> LoadConfiguration()
{
try
{
// 读取探测器类型 | Read detector type
string typeStr = ConfigurationManager.AppSettings["Detector:Type"];
if (string.IsNullOrEmpty(typeStr))
{
return DetectorResult<DetectorConfig>.Failure("配置文件中未找到 Detector:Type | Detector:Type not found in configuration");
}
if (!Enum.TryParse<DetectorType>(typeStr, true, out var detectorType))
{
return DetectorResult<DetectorConfig>.Failure($"无效的探测器类型:{typeStr} | Invalid detector type: {typeStr}");
}
// 根据类型创建配置对象 | Create configuration object based on type
DetectorConfig config = detectorType switch
{
DetectorType.Varex => LoadVarexConfiguration(),
DetectorType.IRay => LoadIRayConfiguration(),
DetectorType.Simulated => LoadSimulatedConfiguration(),
_ => throw new NotSupportedException($"不支持的探测器类型:{detectorType} | Unsupported detector type: {detectorType}")
};
// 加载通用配置 | Load common configuration
config.Type = detectorType;
config.IP = ConfigurationManager.AppSettings["Detector:IP"] ?? "127.0.0.1";
config.Port = int.TryParse(ConfigurationManager.AppSettings["Detector:Port"], out var port) ? port : 5000;
config.SavePath = ConfigurationManager.AppSettings["Detector:SavePath"] ?? Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Images");
config.AutoSave = bool.TryParse(ConfigurationManager.AppSettings["Detector:AutoSave"], out var autoSave) && autoSave;
// 加载校正帧数配置(钳位到 1-128| Load correction frame count config (clamp to 1-128)
if (int.TryParse(ConfigurationManager.AppSettings["Detector:Correction:DarkFrameCount"], out var darkFrames))
{
config.DarkCorrectionFrameCount = Math.Clamp(darkFrames, 1, 128);
}
if (int.TryParse(ConfigurationManager.AppSettings["Detector:Correction:GainFrameCount"], out var gainFrames))
{
config.GainCorrectionFrameCount = Math.Clamp(gainFrames, 1, 128);
}
// 验证配置 | Validate configuration
var validationResult = ValidateConfiguration(config);
if (!validationResult.IsSuccess)
{
return DetectorResult<DetectorConfig>.Failure(validationResult.ErrorMessage);
}
return DetectorResult<DetectorConfig>.Success(config, "配置加载成功 | Configuration loaded successfully");
}
catch (Exception ex)
{
return DetectorResult<DetectorConfig>.Failure($"加载配置异常 | Load configuration exception: {ex.Message}", ex);
}
}
/// <summary>
/// 加载 Varex 配置 | Load Varex configuration
/// </summary>
private static VarexDetectorConfig LoadVarexConfiguration()
{
var config = new VarexDetectorConfig();
// 读取 Binning 模式 | Read binning mode
string binningStr = ConfigurationManager.AppSettings["Detector:Varex:BinningMode"];
if (!string.IsNullOrEmpty(binningStr) && Enum.TryParse<BinningMode>(binningStr, true, out var binningMode))
{
config.BinningMode = binningMode;
}
// 读取增益模式 | Read gain mode
string gainStr = ConfigurationManager.AppSettings["Detector:Varex:GainMode"];
if (!string.IsNullOrEmpty(gainStr) && Enum.TryParse<GainMode>(gainStr, true, out var gainMode))
{
config.GainMode = gainMode;
}
// 读取曝光时间 | Read exposure time
if (uint.TryParse(ConfigurationManager.AppSettings["Detector:Varex:ExposureTime"], out var exposureTime))
{
config.ExposureTime = exposureTime;
}
// 读取 ROI 参数 | Read ROI parameters
if (uint.TryParse(ConfigurationManager.AppSettings["Detector:Varex:ROI_X"], out var roiX))
{
config.RoiX = roiX;
}
if (uint.TryParse(ConfigurationManager.AppSettings["Detector:Varex:ROI_Y"], out var roiY))
{
config.RoiY = roiY;
}
if (uint.TryParse(ConfigurationManager.AppSettings["Detector:Varex:ROI_Width"], out var roiWidth))
{
config.RoiWidth = roiWidth;
}
if (uint.TryParse(ConfigurationManager.AppSettings["Detector:Varex:ROI_Height"], out var roiHeight))
{
config.RoiHeight = roiHeight;
}
return config;
}
/// <summary>
/// 加载软件模拟探测器配置 | Load simulated detector configuration
/// </summary>
private static SimulatedDetectorConfig LoadSimulatedConfiguration()
{
var config = new SimulatedDetectorConfig();
if (int.TryParse(ConfigurationManager.AppSettings["Detector:Simulated:Width"], out var w) && w > 0)
config.Width = w;
if (int.TryParse(ConfigurationManager.AppSettings["Detector:Simulated:Height"], out var h) && h > 0)
config.Height = h;
if (double.TryParse(ConfigurationManager.AppSettings["Detector:Simulated:FrameRateFps"],
System.Globalization.NumberStyles.Any,
System.Globalization.CultureInfo.InvariantCulture, out var fps) && fps > 0)
config.FrameRateFps = fps;
return config;
}
/// <summary>
/// 加载 iRay 配置 | Load iRay configuration
/// </summary>
private static IRayDetectorConfig LoadIRayConfiguration()
{
var config = new IRayDetectorConfig();
// 读取默认增益 | Read default gain
if (double.TryParse(ConfigurationManager.AppSettings["Detector:IRay:DefaultGain"], out var defaultGain))
{
config.DefaultGain = defaultGain;
}
// 读取采集模式 | Read acquisition mode
string modeStr = ConfigurationManager.AppSettings["Detector:IRay:AcquisitionMode"];
if (!string.IsNullOrEmpty(modeStr) && Enum.TryParse<AcquisitionMode>(modeStr, true, out var acquisitionMode))
{
config.AcquisitionMode = acquisitionMode;
}
return config;
}
/// <summary>
/// 保存探测器参数到 App.config | Save detector parameters to App.config
/// </summary>
/// <param name="binningIndex">Binning 索引 | Binning index</param>
/// <param name="pga">PGA 灵敏度值 | PGA sensitivity value</param>
/// <param name="frameRate">帧率 | Frame rate</param>
/// <param name="avgFrames">帧合并数 | Average frame count</param>
public static void SaveParameters(int binningIndex, int pga, decimal frameRate, int avgFrames)
{
var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
SetAppSetting(config, "Detector:BinningIndex", binningIndex.ToString());
SetAppSetting(config, "Detector:PGA", pga.ToString());
SetAppSetting(config, "Detector:FrameRate", frameRate.ToString(System.Globalization.CultureInfo.InvariantCulture));
SetAppSetting(config, "Detector:AvgFrames", avgFrames.ToString());
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection("appSettings");
}
/// <summary>
/// 加载已保存的探测器参数 | Load saved detector parameters
/// </summary>
/// <returns>参数元组(binningIndex, pga, frameRate, avgFrames),加载失败返回 null | Parameter tuple, null if failed</returns>
public static (int binningIndex, int pga, decimal frameRate, int avgFrames)? LoadSavedParameters()
{
try
{
string binStr = ConfigurationManager.AppSettings["Detector:BinningIndex"];
string pgaStr = ConfigurationManager.AppSettings["Detector:PGA"];
string frStr = ConfigurationManager.AppSettings["Detector:FrameRate"];
string avgStr = ConfigurationManager.AppSettings["Detector:AvgFrames"];
if (string.IsNullOrEmpty(binStr) || string.IsNullOrEmpty(pgaStr) ||
string.IsNullOrEmpty(frStr) || string.IsNullOrEmpty(avgStr))
{
return null;
}
if (int.TryParse(binStr, out var binning) &&
int.TryParse(pgaStr, out var pgaVal) &&
decimal.TryParse(frStr, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out var fr) &&
int.TryParse(avgStr, out var avg))
{
return (binning, pgaVal, fr, avg);
}
}
catch
{
// 忽略加载异常 | Ignore load exception
}
return null;
}
/// <summary>
/// 设置 AppSettings 键值 | Set AppSettings key-value
/// </summary>
private static void SetAppSetting(Configuration config, string key, string value)
{
if (config.AppSettings.Settings[key] != null)
{
config.AppSettings.Settings[key].Value = value;
}
else
{
config.AppSettings.Settings.Add(key, value);
}
}
/// <summary>
/// 验证配置参数 | Validate configuration parameters
/// </summary>
private static DetectorResult ValidateConfiguration(DetectorConfig config)
{
// 模拟探测器不需要网络连接,跳过 IP/端口验证 | Simulated detector skips IP/port validation
if (config.Type != DetectorType.Simulated)
{
// 验证 IP 地址 | Validate IP address
if (!IPAddress.TryParse(config.IP, out _))
{
return DetectorResult.Failure($"无效的 IP 地址:{config.IP} | Invalid IP address: {config.IP}");
}
// 验证端口范围 | Validate port range
if (config.Port < 1 || config.Port > 65535)
{
return DetectorResult.Failure($"无效的端口号:{config.Port},必须在 1-65535 之间 | Invalid port: {config.Port}, must be between 1-65535");
}
}
// 验证存储路径 | Validate save path
if (string.IsNullOrWhiteSpace(config.SavePath))
{
return DetectorResult.Failure("存储路径不能为空 | Save path cannot be empty");
}
try
{
// 尝试创建目录以验证路径有效性 | Try to create directory to validate path
if (!Directory.Exists(config.SavePath))
{
Directory.CreateDirectory(config.SavePath);
}
}
catch (Exception ex)
{
return DetectorResult.Failure($"无效的存储路径:{config.SavePath},错误:{ex.Message} | Invalid save path: {config.SavePath}, error: {ex.Message}");
}
return DetectorResult.Success("配置验证通过 | Configuration validation passed");
}
}
}