21 KiB
21 KiB
X 射线源模块使用指南 | X-Ray Source Module Usage Guide
1. 模块概述 | Module Overview
XP.Hardware.RaySource 是 XplorePlane X 射线检测系统的核心硬件控制模块,负责与工业 X 射线源设备进行通讯和控制。该模块采用策略模式设计,通过 Named Pipe IPC 进程隔离架构与 .NET Framework 4.8 Host 子进程通信,支持多种 X 射线源型号的统一管理。
核心特性 | Key Features
- 支持多种 X 射线源型号(当前支持 Comet 225kV)
- 基于 Named Pipe IPC 的进程隔离架构(.NET 8 ↔ .NET Framework 4.8)
- 完整的设备生命周期管理(初始化、连接变量、暖机、训机、灯丝校准、自动定心、开关射线)
- 电压电流精确控制(20-225kV / 10-1000μA)
- TXI 开关控制、功率模式切换(Micro Focus / High Power)
- 实时状态监控和错误检测
- 灯丝寿命管理(使用时长记录、累计统计、预警提醒)
- 基于 Prism 事件聚合器的松耦合通讯
- 安全机制:紧急关闭优先级、参数范围验证、双重检查锁定
2. 模块注册 | Module Registration
X 射线源模块已通过 Prism 的模块化系统注册,在应用启动时自动加载。
在 App.xaml.cs 中注册
using Prism.Modularity;
using XP.Hardware.RaySource.Module;
protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
{
// 注册 X 射线源模块 | Register X-Ray Source module
moduleCatalog.AddModule<RaySourceModule>();
base.ConfigureModuleCatalog(moduleCatalog);
}
模块自动注册的服务
| 服务 | 类型 | 生命周期 | 说明 |
|---|---|---|---|
RaySourceConfig |
实例 | 单例 | 配置对象(从 App.config 加载) |
IRaySourceFactory → RaySourceFactory |
接口→实现 | 单例 | 射线源工厂 |
IRaySourceService → RaySourceService |
接口→实现 | 单例 | 射线源业务服务 |
IFilamentLifetimeService → FilamentLifetimeService |
接口→实现 | 单例 | 灯丝寿命管理服务 |
模块初始化行为
模块 OnInitialized 时会自动执行:
- 初始化灯丝寿命服务(建表、异常恢复、重算累计寿命)
- 检查灯丝寿命预警(≥90% 弹出模态对话框)
3. 配置文件设置 | Configuration File Setup
在 App.config 中添加 X 射线源配置:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<!-- 射线源类型 | Ray Source Type -->
<add key="RaySource:SourceType" value="Comet225" />
<!-- PVI 通讯参数 | PVI Communication Parameters -->
<add key="RaySource:PlcIpAddress" value="192.168.12.10" />
<add key="RaySource:PlcPort" value="11159" />
<add key="RaySource:StationNumber" value="1" />
<add key="RaySource:PortNumber" value="11" />
<add key="RaySource:CpuName" value="cpu" />
<add key="RaySource:ConnectionTimeout" value="5000" />
<!-- 硬件参数范围 | Hardware Parameter Ranges -->
<add key="RaySource:MinVoltage" value="20" />
<add key="RaySource:MaxVoltage" value="225" />
<add key="RaySource:MinCurrent" value="10" />
<add key="RaySource:MaxCurrent" value="1000" />
<!-- 操作超时配置 | Operation Timeout Configuration -->
<add key="RaySource:InitializationTimeout" value="30000" />
<add key="RaySource:WarmUpTimeout" value="300000" />
<add key="RaySource:StartUpTimeout" value="180000" />
<add key="RaySource:AutoCenterTimeout" value="120000" />
<add key="RaySource:FilamentAdjustTimeout" value="120000" />
<add key="RaySource:GeneralOperationTimeout" value="10000" />
<!-- 灯丝寿命管理配置 | Filament Lifetime Management Configuration -->
<add key="RaySource:SerialNumber" value="SN08602861" />
<add key="RaySource:TotalLifeThreshold" value="1000" />
</appSettings>
</configuration>
4. 在 ViewModel 中使用 | Usage in ViewModel
4.1 注入服务
using Prism.Commands;
using Prism.Events;
using Prism.Mvvm;
using XP.Common.Logging.Interfaces;
using XP.Hardware.RaySource.Abstractions;
using XP.Hardware.RaySource.Abstractions.Enums;
using XP.Hardware.RaySource.Abstractions.Events;
using XP.Hardware.RaySource.Config;
using XP.Hardware.RaySource.Services;
namespace YourNamespace.ViewModels
{
public class YourViewModel : BindableBase
{
private readonly IRaySourceService _raySourceService;
private readonly IEventAggregator _eventAggregator;
private readonly ILoggerService _logger;
public YourViewModel(
IRaySourceService raySourceService,
IEventAggregator eventAggregator,
ILoggerService logger)
{
_raySourceService = raySourceService;
_eventAggregator = eventAggregator;
_logger = logger.ForModule("YourViewModel");
// 订阅事件 | Subscribe to events
SubscribeEvents();
}
private void SubscribeEvents()
{
_eventAggregator.GetEvent<RaySourceStatusChangedEvent>()
.Subscribe(OnRaySourceStatusChanged, ThreadOption.UIThread);
_eventAggregator.GetEvent<StatusUpdatedEvent>()
.Subscribe(OnStatusUpdated, ThreadOption.UIThread);
_eventAggregator.GetEvent<ErrorOccurredEvent>()
.Subscribe(OnErrorOccurred, ThreadOption.UIThread);
_eventAggregator.GetEvent<OperationResultEvent>()
.Subscribe(OnOperationResult, ThreadOption.UIThread);
_eventAggregator.GetEvent<VariablesConnectedEvent>()
.Subscribe(OnVariablesConnected, ThreadOption.UIThread);
}
private void OnRaySourceStatusChanged(RaySourceStatus newStatus)
{
_logger.Info("射线源状态变化: {Status}", newStatus);
}
private void OnStatusUpdated(SystemStatusData data)
{
_logger.Debug("状态更新: 电压={Voltage}kV, 电流={Current}μA",
data.ActualVoltage, data.ActualCurrent);
}
private void OnErrorOccurred(string errorMessage)
{
_logger.Error(null, "错误发生: {Error}", errorMessage);
}
private void OnOperationResult(OperationResultData data)
{
_logger.Info("操作 {Op} {Result}: {Msg}",
data.OperationName, data.IsSuccess ? "成功" : "失败", data.Message);
}
private void OnVariablesConnected(bool isConnected)
{
_logger.Info("变量连接状态: {Connected}", isConnected);
}
}
}
4.2 初始化射线源
// 方式一:分步初始化 | Step-by-step initialization
public void InitializeRaySource()
{
// 步骤1:初始化(启动 Host 进程,建立 IPC 连接)
XRayResult result = _raySourceService.Initialize();
if (!result.Success)
{
_logger.Error(null, "初始化失败: {Error}", result.ErrorMessage);
return;
}
// 步骤2:连接变量(创建和激活 PVI 变量)
XRayResult connectResult = _raySourceService.ConnectVariables();
if (!connectResult.Success)
{
_logger.Error(null, "连接变量失败: {Error}", connectResult.ErrorMessage);
}
}
// 方式二:异步一键初始化 | Async one-step initialization
public async Task AutoInitializeAsync()
{
XRayResult result = await _raySourceService.InitializeAndConnectAsync();
if (result.Success)
{
_logger.Info("自动初始化完成");
}
}
4.3 开启/关闭射线
// 开启射线 | Turn on X-ray
public void TurnOnXRay()
{
if (!_raySourceService.IsInitialized || !_raySourceService.IsConnected)
{
_logger.Warn("射线源未就绪");
return;
}
XRayResult result = _raySourceService.TurnOn();
if (result.Success)
{
_logger.Info("射线已开启");
}
}
// 关闭射线 | Turn off X-ray
public void TurnOffXRay()
{
XRayResult result = _raySourceService.TurnOff();
if (result.Success)
{
_logger.Info("射线已关闭");
}
}
// 紧急关闭(最高优先级,任何状态下可执行)| Emergency shutdown
public void EmergencyShutdown()
{
_raySourceService.EmergencyShutdown();
}
// 断开连接(保留实例以便重连)| Disconnect
public void Disconnect()
{
_raySourceService.Disconnect();
}
5. 电压电流控制 | Voltage and Current Control
// 设置电压(范围由配置文件定义,默认 20-225kV)
XRayResult result = _raySourceService.SetVoltage(100f);
// 设置电流(范围由配置文件定义,默认 10-1000μA)
XRayResult result = _raySourceService.SetCurrent(500f);
// 读取实际电压
XRayResult voltageResult = _raySourceService.ReadVoltage();
if (voltageResult.Success)
{
float voltage = voltageResult.GetFloat();
}
// 读取实际电流
XRayResult currentResult = _raySourceService.ReadCurrent();
if (currentResult.Success)
{
float current = currentResult.GetFloat();
}
6. 设备操作 | Device Operations
// TXI 开启/关闭
_raySourceService.TxiOn();
_raySourceService.TxiOff();
// 暖机
_raySourceService.WarmUp();
// 训机
_raySourceService.Training();
// 灯丝校准
_raySourceService.FilamentCalibration();
// 全部电压自动定心
_raySourceService.AutoCenter();
// 设置功率模式(1=Micro Focus,2=High Power)
_raySourceService.SetPowerMode(1); // 微焦点模式
_raySourceService.SetPowerMode(2); // 高功率模式
注意:TXI、暖机、训机、灯丝校准、自动定心、功率模式切换等操作需要射线源已连接变量(IsConnected == true)。
7. 状态监控和错误处理 | Status Monitoring and Error Handling
7.1 读取系统状态
XRayResult result = _raySourceService.ReadSystemStatus();
if (result.Success && result.Data is SystemStatusData statusData)
{
// statusData 包含全量状态信息:
// - SetVoltage / ActualVoltage(设定/实际电压)
// - SetCurrent / ActualCurrent(设定/实际电流)
// - IsXRayOn(射线开启状态)
// - WarmUpStatus / VacuumStatus / StartUpStatus(暖机/真空/启动状态)
// - AutoCenterStatus / FilamentAdjustStatus(自动定心/灯丝调整状态)
// - IsInterlockActive(连锁状态)
// - WatchdogStatus / PowerMode / TxiStatus(看门狗/功率模式/TXI状态)
}
7.2 检查和清除错误
// 检查错误
XRayResult errorResult = _raySourceService.CheckErrors();
// 清除错误
XRayResult clearResult = _raySourceService.ClearErrors();
7.3 状态属性
bool isInitialized = _raySourceService.IsInitialized; // 是否已初始化
bool isConnected = _raySourceService.IsConnected; // PVI 变量是否已连接
bool isXRayOn = _raySourceService.IsXRayOn; // 射线是否开启
RaySourceStatus status = _raySourceService.CurrentStatus; // 当前状态(三态)
8. Prism 事件通讯 | Prism Event Communication
模块使用 Prism 事件聚合器实现跨模块通讯,支持以下事件:
8.1 射线源状态变化事件
_eventAggregator.GetEvent<RaySourceStatusChangedEvent>()
.Subscribe(OnRaySourceStatusChanged, ThreadOption.UIThread);
private void OnRaySourceStatusChanged(RaySourceStatus newStatus)
{
// newStatus: Unavailable(-1) / Closed(0) / Opened(1)
switch (newStatus)
{
case RaySourceStatus.Unavailable:
// 射线源不可用(未初始化或连接丢失)
break;
case RaySourceStatus.Closed:
// 射线源已连接,射线关闭
break;
case RaySourceStatus.Opened:
// 射线源已连接,射线开启
break;
}
}
8.2 系统状态更新事件
_eventAggregator.GetEvent<StatusUpdatedEvent>()
.Subscribe(OnStatusUpdated, ThreadOption.UIThread);
private void OnStatusUpdated(SystemStatusData data)
{
// 全量状态数据,由 Host 进程定期推送
float actualVoltage = data.ActualVoltage;
float actualCurrent = data.ActualCurrent;
bool isXRayOn = data.IsXRayOn;
string warmUpStatus = data.WarmUpStatus;
// ... 更多字段见 SystemStatusData 定义
}
8.3 错误事件
_eventAggregator.GetEvent<ErrorOccurredEvent>()
.Subscribe(OnErrorOccurred, ThreadOption.UIThread);
private void OnErrorOccurred(string errorMessage)
{
_logger.Error(null, "射线源错误: {Error}", errorMessage);
}
8.4 操作结果事件
_eventAggregator.GetEvent<OperationResultEvent>()
.Subscribe(OnOperationResult, ThreadOption.UIThread);
private void OnOperationResult(OperationResultData data)
{
// data.OperationName - 操作名称
// data.IsSuccess - 是否成功
// data.Message - 结果消息
}
8.5 PVI 变量连接状态事件
_eventAggregator.GetEvent<VariablesConnectedEvent>()
.Subscribe(OnVariablesConnected, ThreadOption.UIThread);
private void OnVariablesConnected(bool isConnected)
{
// true = PVI 变量已连接,射线源准备就绪
// false = PVI 变量已断开
}
9. 灯丝寿命管理 | Filament Lifetime Management
9.1 自动联动
灯丝寿命管理与射线源开关自动联动:
- 射线源开启(TurnOn)→ 自动开始记录灯丝使用时长
- 射线源关闭(TurnOff / Disconnect / EmergencyShutdown)→ 自动停止记录并累加统计
- 异常断联 → 下次初始化时自动恢复未关闭的记录
9.2 手动查询
// 获取实时累计使用秒数(含当前运行时长)
double totalSeconds = _filamentLifetimeService.GetCurrentTotalLifeSeconds();
// 获取寿命百分比(0-100)
double percentage = _filamentLifetimeService.GetLifetimePercentage();
// 获取阈值秒数
double thresholdSeconds = _filamentLifetimeService.GetThresholdSeconds();
// 检查是否需要预警(≥90%)
bool shouldWarn = _filamentLifetimeService.ShouldShowLifetimeWarning();
9.3 数据持久化
灯丝寿命数据通过 SQLite 持久化,包含两张表:
RaySourceFilamentLifetimeStatistics:累计统计表(按序列号唯一)RaySourceFilamentUsageLogs:使用流水表(每次开关记录一条)
10. 在应用退出时释放资源 | Release Resources on Application Exit
protected override void OnExit(ExitEventArgs e)
{
Log.Information("XplorePlane 主应用退出");
// 释放射线源资源 | Release X-ray source resources
try
{
var raySourceService = Container.Resolve<IRaySourceService>();
raySourceService?.Dispose();
Log.Information("射线源资源已成功释放");
}
catch (Exception ex)
{
Log.Error(ex, "射线源资源释放失败,忽略该错误继续退出");
}
Log.CloseAndFlush();
base.OnExit(e);
}
11. 安全机制 | Safety Mechanisms
11.1 参数范围验证
// 服务层自动校验参数范围,超出范围返回错误结果
XRayResult result = _raySourceService.SetVoltage(300f); // 超出 225kV 上限
// result.Success == false
// result.ErrorMessage == "电压参数超出范围:20-225kV"
11.2 紧急关闭优先级
紧急关闭具有最高优先级,可以在任何状态下执行:
// 紧急关闭:依次关闭射线 → 完全关闭设备 → 状态重置为 Unavailable
_raySourceService.EmergencyShutdown();
11.3 业务规则校验
- 未初始化禁止操作(所有操作前检查
IsInitialized) - 防重复开启/关闭(双重检查锁定模式)
- 异常断联自动检测(状态变为 Unavailable 时重置标志位)
11.4 实时调节支持
连接射线源后,无论射线是否开启,都可以实时调节电压和电流。
12. 异常处理 | Exception Handling
12.1 XRayResult 结果处理
所有操作返回 XRayResult 对象:
XRayResult result = _raySourceService.TurnOn();
if (result.Success)
{
var data = result.Data; // 获取返回数据
}
else
{
string error = result.ErrorMessage; // 获取错误消息
_logger.Error(null, "操作失败: {Error}", error);
}
12.2 IPC 通信异常
当 Host 进程崩溃或管道断开时:
CometIpcClient设置_isPipeConnected = false,阻止后续命令发送- 返回
null响应,服务层转换为错误结果 - 推送
Disconnected状态,触发 UI 更新
13. 日志记录 | Logging
模块使用 ILoggerService 进行结构化日志记录:
// 各层日志模块名称
_logger = logger.ForModule("RaySource.Service"); // 服务层
_logger = logger.ForModule("RaySource.Factory"); // 工厂层
_logger = logger.ForModule<Comet225RaySource>(); // 适配器层
_logger = logger.ForModule<CometIpcClient>(); // IPC 客户端
_logger = logger.ForModule<CometHostManager>(); // Host 管理器
_logger = logger.ForModule("RaySource.ViewModel"); // 操作视图模型
_logger = logger.ForModule("RaySource.ConfigVM"); // 配置视图模型
_logger = logger.ForModule<FilamentLifetimeService>(); // 灯丝寿命服务
日志级别
- Debug: 详细调试信息(IPC 消息收发、电压电流读取等)
- Info: 一般信息(初始化成功、射线开启、状态变更等)
- Warn: 警告信息(参数超出范围、重复操作、异常恢复等)
- Error: 错误信息(操作失败、通讯异常、IPC 超时等)
- Fatal: 致命错误(系统崩溃等)
14. 故障排查 | Troubleshooting
14.1 初始化失败
可能原因:
- Host 可执行文件未找到(检查
{主程序目录}/Host/XP.Hardware.RaySource.Comet.Host.exe) - PLC IP 地址或端口配置错误
- PLC 未启动或网络不通
- Named Pipe 连接超时
- 残留的 Host 进程未清理
解决方案:
- 确认 Host 可执行文件和 BR.AN.PviServices.dll 已正确部署
- 检查
App.config中的 PLC 连接参数 - 使用
ping命令测试 PLC 网络连接 - 查看日志中 Host 进程 PID 和管道连接状态
- 手动终止残留的
XP.Hardware.RaySource.Comet.Host.exe进程
14.2 射线无法开启
可能原因:
- 射线源未初始化或变量未连接
- 设备处于错误状态
- 互锁信号未满足
解决方案:
- 确认
IsInitialized == true且IsConnected == true - 调用
CheckErrors()检查错误状态 - 检查设备互锁信号
14.3 电压电流设置失败
可能原因:
- 参数超出配置范围
- 射线源未初始化
- IPC 管道已断开
解决方案:
- 验证参数在有效范围内
- 检查
IsInitialized状态 - 查看日志中 IPC 通信状态
14.4 Host 进程异常退出
可能原因:
- BR.AN.PviServices.dll 缺失或版本不匹配
- PVI Service 未正确安装
- Host 进程内存异常
解决方案:
- 检查 Host 目录下 DLL 文件完整性
- 确认 B&R Automation Studio 和 PVI Services 已安装
- 查看 Host 进程 stderr 日志输出
14.5 灯丝寿命数据异常
可能原因:
- SerialNumber 配置为空
- SQLite 数据库文件损坏
- 异常断电导致未关闭记录
解决方案:
- 确认
App.config中RaySource:SerialNumber已配置 - 检查数据库文件完整性
- 服务初始化时会自动恢复未关闭记录(标记为异常中断,DurationSeconds=0)
15. 注意事项 | Notes
- 线程安全:
IRaySourceService是单例,内部使用lock保护关键操作 - 同步 API: 所有
IXRaySource和IRaySourceService方法为同步方法,ViewModel 中通过Task.Run包装避免阻塞 UI - InitializeAndConnectAsync: 唯一的异步便捷方法,内部通过
Task.Run包装同步调用 - 实时调节: 连接后可随时调节电压电流,无论射线是否开启
- 资源释放: 应用退出时务必调用
Dispose()释放资源(会触发紧急关闭和 Host 进程终止) - 事件订阅: 记得在 ViewModel 销毁时取消事件订阅
- 配置验证: 启动前自动验证配置参数的有效性
- 日志记录: 所有关键操作都有详细的结构化日志记录
- 错误处理: 始终检查
XRayResult.Success并处理错误 - Host 进程: CometHostManager 会自动清理残留进程并管理 Host 生命周期
16. 文档索引 | Documentation Index
- GUIDENCE.md - 本文档,详细使用指南
- README.md - 项目概述和快速参考
- ProjectStructure.md - 项目结构详解和调用链路
- README_RaySourceOperateView.md - 操作视图使用说明
- App.config.example - 配置文件示例
最后更新 | Last Updated: 2026-03-26