将Feature/XP.Common和Feature/XP.Hardware分支合并至Develop/XP.forHardwareAndCommon,完善XPapp注册和相关硬件类库通用类库功能。

This commit is contained in:
QI Mingxuan
2026-04-16 17:31:13 +08:00
parent 6ec4c3ddaa
commit 2bd6e566c3
581 changed files with 74600 additions and 222 deletions
+245
View File
@@ -0,0 +1,245 @@
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(),
_ => 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;
// 验证配置 | 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>
/// 加载 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 地址 | 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");
}
}
}
@@ -0,0 +1,138 @@
using System.Collections.Generic;
using XP.Hardware.Detector.Abstractions.Enums;
namespace XP.Hardware.Detector.Config
{
/// <summary>
/// 探测器通用配置基类 | Detector common configuration base class
/// 包含所有探测器的通用配置参数
/// </summary>
public class DetectorConfig
{
/// <summary>
/// 探测器类型 | Detector type
/// </summary>
public DetectorType Type { get; set; }
/// <summary>
/// IP 地址 | IP address
/// </summary>
public string IP { get; set; }
/// <summary>
/// 端口号 | Port number
/// </summary>
public int Port { get; set; }
/// <summary>
/// 图像存储路径 | Image save path
/// </summary>
public string SavePath { get; set; }
/// <summary>
/// 是否自动保存图像 | Whether to auto save images
/// </summary>
public bool AutoSave { get; set; }
/// <summary>
/// 获取支持的 Binning 选项(显示名称 → 索引)| Get supported binning options (display name → index)
/// 子类可重写以提供不同的选项列表
/// </summary>
public virtual List<BinningOption> GetSupportedBinnings()
{
return new List<BinningOption>
{
new BinningOption("1×1", 0),
new BinningOption("2×2", 1),
};
}
/// <summary>
/// 获取支持的 PGA(灵敏度)选项 | Get supported PGA (sensitivity) options
/// 子类可重写以提供不同的选项列表
/// </summary>
public virtual List<int> GetSupportedPgaValues()
{
return new List<int> { 2, 3, 4, 5, 6, 7 };
}
/// <summary>
/// 获取各 Binning 模式下的最大帧率 | Get max frame rate for each binning mode
/// 子类可重写以提供不同的限制
/// </summary>
public virtual decimal GetMaxFrameRate(int binningIndex)
{
return 15m;
}
/// <summary>
/// 获取指定 Binning 模式下的图像规格(像素尺寸、分辨率)| Get image spec for given binning mode
/// 子类可重写以提供不同的映射关系
/// </summary>
/// <param name="binningIndex">Binning 索引 | Binning index</param>
/// <returns>图像规格 | Image specification</returns>
public virtual BinningImageSpec GetImageSpec(int binningIndex)
{
return new BinningImageSpec(0.139, 0.139, 3072, 3060);
}
}
/// <summary>
/// Binning 模式下的图像规格 | Image specification for binning mode
/// 包含像素尺寸和图像分辨率,供重建 PC 使用
/// </summary>
public class BinningImageSpec
{
/// <summary>
/// X 方向像素尺寸(mm| Pixel size in X direction (mm)
/// </summary>
public double PixelX { get; }
/// <summary>
/// Y 方向像素尺寸(mm| Pixel size in Y direction (mm)
/// </summary>
public double PixelY { get; }
/// <summary>
/// 图像宽度(像素)| Image width (pixels)
/// </summary>
public int ImageWidth { get; }
/// <summary>
/// 图像高度(像素)| Image height (pixels)
/// </summary>
public int ImageHeight { get; }
public BinningImageSpec(double pixelX, double pixelY, int imageWidth, int imageHeight)
{
PixelX = pixelX;
PixelY = pixelY;
ImageWidth = imageWidth;
ImageHeight = imageHeight;
}
}
/// <summary>
/// Binning 选项模型 | Binning option model
/// </summary>
public class BinningOption
{
/// <summary>
/// 显示名称 | Display name
/// </summary>
public string DisplayName { get; }
/// <summary>
/// 索引值 | Index value
/// </summary>
public int Index { get; }
public BinningOption(string displayName, int index)
{
DisplayName = displayName;
Index = index;
}
public override string ToString() => DisplayName;
}
}
@@ -0,0 +1,56 @@
using System.Collections.Generic;
using XP.Hardware.Detector.Abstractions.Enums;
namespace XP.Hardware.Detector.Config
{
/// <summary>
/// iRay 探测器配置类 | iRay detector configuration class
/// 包含 iRay 专属的配置参数
/// </summary>
public class IRayDetectorConfig : DetectorConfig
{
/// <summary>
/// 默认增益值 | Default gain value
/// </summary>
public double DefaultGain { get; set; } = 1.0;
/// <summary>
/// 采集模式 | Acquisition mode
/// </summary>
public AcquisitionMode AcquisitionMode { get; set; } = AcquisitionMode.Continuous;
/// <summary>
/// iRay 支持 1×1、2×2、3×3、4×4 四种 Binning | iRay supports 1×1, 2×2, 3×3, 4×4 binning
/// </summary>
public override List<BinningOption> GetSupportedBinnings()
{
return new List<BinningOption>
{
new BinningOption("1×1", 0),
new BinningOption("2×2", 1),
new BinningOption("3×3", 2),
new BinningOption("4×4", 3),
};
}
/// <summary>
/// iRay PGA 范围 1-8 | iRay PGA range 1-8
/// </summary>
public override List<int> GetSupportedPgaValues()
{
return new List<int> { 1, 2, 3, 4, 5, 6, 7, 8 };
}
/// <summary>
/// iRay 各 Binning 模式最大帧率 | iRay max frame rate per binning mode
/// </summary>
public override decimal GetMaxFrameRate(int binningIndex) => binningIndex switch
{
0 => 15m, // 1×1
1 => 30m, // 2×2
2 => 45m, // 3×3
3 => 60m, // 4×4
_ => 15m
};
}
}
@@ -0,0 +1,94 @@
using System.Collections.Generic;
using XP.Hardware.Detector.Abstractions.Enums;
namespace XP.Hardware.Detector.Config
{
/// <summary>
/// Varex 探测器配置类 | Varex detector configuration class
/// 包含 Varex 专属的配置参数
/// </summary>
public class VarexDetectorConfig : DetectorConfig
{
/// <summary>
/// Binning 模式 | Binning mode
/// </summary>
public BinningMode BinningMode { get; set; } = BinningMode.Bin1x1;
/// <summary>
/// 增益模式 | Gain mode
/// </summary>
public GainMode GainMode { get; set; } = GainMode.Low;
/// <summary>
/// 曝光时间(毫秒)| Exposure time (milliseconds)
/// </summary>
public uint ExposureTime { get; set; } = 100;
/// <summary>
/// ROI 起始 X 坐标 | ROI start X coordinate
/// </summary>
public uint RoiX { get; set; } = 0;
/// <summary>
/// ROI 起始 Y 坐标 | ROI start Y coordinate
/// </summary>
public uint RoiY { get; set; } = 0;
/// <summary>
/// ROI 宽度 | ROI width
/// </summary>
public uint RoiWidth { get; set; } = 0;
/// <summary>
/// ROI 高度 | ROI height
/// </summary>
public uint RoiHeight { get; set; } = 0;
/// <summary>
/// Varex 支持 1×1、2×2、4×4 三种 Binning | Varex supports 1×1, 2×2, 4×4 binning
/// </summary>
public override List<BinningOption> GetSupportedBinnings()
{
return new List<BinningOption>
{
new BinningOption("1×1", 0),
new BinningOption("2×2", 1),
new BinningOption("3×3", 2),
new BinningOption("4×4", 3),
};
}
/// <summary>
/// Varex PGA 范围 2-7 | Varex PGA range 2-7
/// </summary>
public override List<int> GetSupportedPgaValues()
{
return new List<int> { 2, 3, 4, 5, 6, 7 };
}
/// <summary>
/// Varex 各 Binning 模式最大帧率 | Varex max frame rate per binning mode
/// </summary>
public override decimal GetMaxFrameRate(int binningIndex) => binningIndex switch
{
0 => 15m, // 1×1
1 => 30m, // 2×2
2 => 45m, // 3×3
3 => 60m, // 4×4
_ => 15m
};
/// <summary>
/// Varex 4343N 各 Binning 模式的图像规格 | Varex 4343N image spec per binning mode
/// 像素尺寸和分辨率映射关系,供重建 PC 使用
/// </summary>
public override BinningImageSpec GetImageSpec(int binningIndex) => binningIndex switch
{
0 => new BinningImageSpec(0.139, 0.139, 3072, 3060), // 1×1
1 => new BinningImageSpec(0.278, 0.278, 1536, 1530), // 2×2
2 => new BinningImageSpec(0.417, 0.417, 1024, 1020), // 3×3
3 => new BinningImageSpec(0.556, 0.556, 768, 765), // 4×4
_ => new BinningImageSpec(0.139, 0.139, 3072, 3060)
};
}
}