Files
XplorePlane/XP.Hardware.RaySource/Documents/GUIDENCE.md
T

681 lines
21 KiB
Markdown
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.
# 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 中注册
```csharp
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` 时会自动执行:
1. 初始化灯丝寿命服务(建表、异常恢复、重算累计寿命)
2. 检查灯丝寿命预警(≥90% 弹出模态对话框)
---
## 3. 配置文件设置 | Configuration File Setup
`App.config` 中添加 X 射线源配置:
```xml
<?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 注入服务
```csharp
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 初始化射线源
```csharp
// 方式一:分步初始化 | 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 开启/关闭射线
```csharp
// 开启射线 | 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
```csharp
// 设置电压(范围由配置文件定义,默认 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
```csharp
// TXI 开启/关闭
_raySourceService.TxiOn();
_raySourceService.TxiOff();
// 暖机
_raySourceService.WarmUp();
// 训机
_raySourceService.Training();
// 灯丝校准
_raySourceService.FilamentCalibration();
// 全部电压自动定心
_raySourceService.AutoCenter();
// 设置功率模式(1=Micro Focus2=High Power
_raySourceService.SetPowerMode(1); // 微焦点模式
_raySourceService.SetPowerMode(2); // 高功率模式
```
注意:TXI、暖机、训机、灯丝校准、自动定心、功率模式切换等操作需要射线源已连接变量(`IsConnected == true`)。
---
## 7. 状态监控和错误处理 | Status Monitoring and Error Handling
### 7.1 读取系统状态
```csharp
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 检查和清除错误
```csharp
// 检查错误
XRayResult errorResult = _raySourceService.CheckErrors();
// 清除错误
XRayResult clearResult = _raySourceService.ClearErrors();
```
### 7.3 状态属性
```csharp
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 射线源状态变化事件
```csharp
_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 系统状态更新事件
```csharp
_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 错误事件
```csharp
_eventAggregator.GetEvent<ErrorOccurredEvent>()
.Subscribe(OnErrorOccurred, ThreadOption.UIThread);
private void OnErrorOccurred(string errorMessage)
{
_logger.Error(null, "射线源错误: {Error}", errorMessage);
}
```
### 8.4 操作结果事件
```csharp
_eventAggregator.GetEvent<OperationResultEvent>()
.Subscribe(OnOperationResult, ThreadOption.UIThread);
private void OnOperationResult(OperationResultData data)
{
// data.OperationName - 操作名称
// data.IsSuccess - 是否成功
// data.Message - 结果消息
}
```
### 8.5 PVI 变量连接状态事件
```csharp
_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 手动查询
```csharp
// 获取实时累计使用秒数(含当前运行时长)
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
```csharp
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 参数范围验证
```csharp
// 服务层自动校验参数范围,超出范围返回错误结果
XRayResult result = _raySourceService.SetVoltage(300f); // 超出 225kV 上限
// result.Success == false
// result.ErrorMessage == "电压参数超出范围:20-225kV"
```
### 11.2 紧急关闭优先级
紧急关闭具有最高优先级,可以在任何状态下执行:
```csharp
// 紧急关闭:依次关闭射线 → 完全关闭设备 → 状态重置为 Unavailable
_raySourceService.EmergencyShutdown();
```
### 11.3 业务规则校验
- 未初始化禁止操作(所有操作前检查 `IsInitialized`
- 防重复开启/关闭(双重检查锁定模式)
- 异常断联自动检测(状态变为 Unavailable 时重置标志位)
### 11.4 实时调节支持
连接射线源后,无论射线是否开启,都可以实时调节电压和电流。
---
## 12. 异常处理 | Exception Handling
### 12.1 XRayResult 结果处理
所有操作返回 `XRayResult` 对象:
```csharp
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` 进行结构化日志记录:
```csharp
// 各层日志模块名称
_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 进程未清理
**解决方案**:
1. 确认 Host 可执行文件和 BR.AN.PviServices.dll 已正确部署
2. 检查 `App.config` 中的 PLC 连接参数
3. 使用 `ping` 命令测试 PLC 网络连接
4. 查看日志中 Host 进程 PID 和管道连接状态
5. 手动终止残留的 `XP.Hardware.RaySource.Comet.Host.exe` 进程
### 14.2 射线无法开启
**可能原因**:
- 射线源未初始化或变量未连接
- 设备处于错误状态
- 互锁信号未满足
**解决方案**:
1. 确认 `IsInitialized == true``IsConnected == true`
2. 调用 `CheckErrors()` 检查错误状态
3. 检查设备互锁信号
### 14.3 电压电流设置失败
**可能原因**:
- 参数超出配置范围
- 射线源未初始化
- IPC 管道已断开
**解决方案**:
1. 验证参数在有效范围内
2. 检查 `IsInitialized` 状态
3. 查看日志中 IPC 通信状态
### 14.4 Host 进程异常退出
**可能原因**:
- BR.AN.PviServices.dll 缺失或版本不匹配
- PVI Service 未正确安装
- Host 进程内存异常
**解决方案**:
1. 检查 Host 目录下 DLL 文件完整性
2. 确认 B&R Automation Studio 和 PVI Services 已安装
3. 查看 Host 进程 stderr 日志输出
### 14.5 灯丝寿命数据异常
**可能原因**:
- SerialNumber 配置为空
- SQLite 数据库文件损坏
- 异常断电导致未关闭记录
**解决方案**:
1. 确认 `App.config``RaySource:SerialNumber` 已配置
2. 检查数据库文件完整性
3. 服务初始化时会自动恢复未关闭记录(标记为异常中断,DurationSeconds=0
---
## 15. 注意事项 | Notes
1. **线程安全**: `IRaySourceService` 是单例,内部使用 `lock` 保护关键操作
2. **同步 API**: 所有 `IXRaySource``IRaySourceService` 方法为同步方法,ViewModel 中通过 `Task.Run` 包装避免阻塞 UI
3. **InitializeAndConnectAsync**: 唯一的异步便捷方法,内部通过 `Task.Run` 包装同步调用
4. **实时调节**: 连接后可随时调节电压电流,无论射线是否开启
5. **资源释放**: 应用退出时务必调用 `Dispose()` 释放资源(会触发紧急关闭和 Host 进程终止)
6. **事件订阅**: 记得在 ViewModel 销毁时取消事件订阅
7. **配置验证**: 启动前自动验证配置参数的有效性
8. **日志记录**: 所有关键操作都有详细的结构化日志记录
9. **错误处理**: 始终检查 `XRayResult.Success` 并处理错误
10. **Host 进程**: CometHostManager 会自动清理残留进程并管理 Host 生命周期
---
## 16. 文档索引 | Documentation Index
- **[GUIDENCE.md](./GUIDENCE.md)** - 本文档,详细使用指南
- **[README.md](./README.md)** - 项目概述和快速参考
- **[ProjectStructure.md](./ProjectStructure.md)** - 项目结构详解和调用链路
- **[README_RaySourceOperateView.md](./README_RaySourceOperateView.md)** - 操作视图使用说明
- **[App.config.example](./App.config.example)** - 配置文件示例
---
**最后更新 | Last Updated**: 2026-03-26