将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
@@ -0,0 +1,37 @@
<?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" />
<!-- 外部程序配置 | External Program Configuration -->
<add key="RaySource:AdvanceExePath" value="C:\Program Files (x86)\Feinfocus\FXEControl_3.1.1.65\FXEControl.exe" />
<add key="RaySource:HostExePath" value="" />
<!-- 操作超时配置 | 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>
+680
View File
@@ -0,0 +1,680 @@
# 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
@@ -0,0 +1,310 @@
# XP.Hardware.RaySource 项目结构文档
## 1. 项目概览
| 项目 | 框架 | 类型 | 命名空间 | 程序集名称 |
|------|------|------|----------|-----------|
| XP.Hardware.RaySource | .NET 8.0 (net8.0-windows7.0) | WPF 类库 | `XP.Hardware.RaySource.*` | XP.Hardware.RaySource |
| XP.Hardware.RaySource.Comet.Host | .NET Framework 4.8 | WinForms 控制台 | `XP.Hardware.RaySource.Comet.Host` | XP.Hardware.RaySource.Comet.Host |
| XP.Hardware.RaySource.Comet.Messages | netstandard2.0 | 类库 | `XP.Hardware.RaySource.Comet.Messages` | XP.Hardware.RaySource.Comet.Messages |
## 2. 版本信息
### XP.Hardware.RaySource
- 目标框架:`net8.0-windows7.0`
- SDK 风格项目
- NuGet 依赖:
- `Prism.Wpf` 9.0.537
- `System.Configuration.ConfigurationManager` 8.0.0
- `Telerik.UI.for.Wpf.NetCore.Xaml` 2024.1.408
- 项目引用:
- `XP.Common`(日志、数据库、多语言基础设施)
- `XP.Hardware.RaySource.Comet.Messages`IPC 消息定义)
### XP.Hardware.RaySource.Comet.Host
- 目标框架:`.NET Framework 4.8`
- WinForms 进程(因依赖 B&R PVI Services COM 组件,无法迁移到 .NET 8)
- 外部依赖:
- `BR.AN.PviServices.dll`Version 1.1.0.0,贝加莱 PVI 通讯库)
- `Newtonsoft.Json`JSON 序列化)
- 项目引用:
- `XP.Hardware.RaySource.Comet.Messages`IPC 消息定义)
### XP.Hardware.RaySource.Comet.Messages
- 目标框架:`netstandard2.0`(跨框架共享)
- 定义 IPC 命令和响应消息类型
- 被 RaySource.NET 8)和 Comet.Host.NET Framework 4.8)共同引用
## 3. 引用关系
```
┌─────────────────────────────────────────────────────────────┐
│ XP.Hardware.RaySource (.NET 8.0 WPF 类库) │
│ │
│ ProjectReference ──► XP.Common │
│ ProjectReference ──► XP.Hardware.RaySource.Comet.Messages │
│ │
│ NuGet: Prism.Wpf, Telerik, ConfigurationManager │
└────────────────────┬────────────────────────────────────────┘
│ Named Pipe IPC(进程间通信)
┌─────────────────────────────────────────────────────────────┐
│ XP.Hardware.RaySource.Comet.Host (.NET Framework 4.8) │
│ │
│ ProjectReference ──► XP.Hardware.RaySource.Comet.Messages │
│ 外部引用 ──► BR.AN.PviServices.dll(贝加莱 PVI 通讯库) │
│ NuGet: Newtonsoft.Json │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ XP.Hardware.RaySource.Comet.Messages (netstandard2.0) │
│ │
│ 共享消息库,定义 IPC 命令和响应类型 │
│ 被 RaySource 和 Comet.Host 共同引用 │
│ NuGet: Newtonsoft.Json │
└─────────────────────────────────────────────────────────────┘
```
### 进程隔离架构说明
RaySource.NET 8)通过 Named Pipe 与 Comet.Host.NET Framework 4.8)进行进程间通信。之所以采用这种架构,是因为 `BR.AN.PviServices.dll`(贝加莱 PVI 通讯库)仅支持 .NET Framework,无法直接在 .NET 8 中使用。因此将 PVI 通讯层隔离到独立的 .NET Framework 4.8 Host 子进程中,通过 Named Pipe 双管道模式实现跨框架通信。
`Comet.Messages` 作为 `netstandard2.0` 共享库,定义了两端通信的命令和响应消息格式,确保序列化/反序列化的一致性。
## 4. XP.Hardware.RaySource 项目结构
```
XP.Hardware.RaySource/
├── Abstractions/ # 抽象层(接口、基类、枚举、事件)
│ ├── Enums/
│ │ └── RaySourceStatus.cs # 射线源状态枚举(Unavailable=-1 / Closed=0 / Opened=1
│ ├── Events/
│ │ ├── ErrorOccurredEvent.cs # 错误触发事件(PubSubEvent<string>
│ │ ├── OperationResultEvent.cs # 操作结果事件(PubSubEvent<OperationResultData>
│ │ ├── RaySourceStatusChangedEvent.cs # 射线源状态变更事件(PubSubEvent<RaySourceStatus>
│ │ ├── StatusUpdatedEvent.cs # 系统状态更新事件(PubSubEvent<SystemStatusData>
│ │ └── VariablesConnectedEvent.cs # PVI 变量连接状态事件(PubSubEvent<bool>
│ ├── IRaySourceFactory.cs # 射线源工厂接口
│ ├── IXRaySource.cs # 射线源策略接口(核心接口,同步方法)
│ ├── XRayResult.cs # 操作结果封装类(Ok/Error 静态工厂方法)
│ └── XRaySourceBase.cs # 射线源抽象基类(含 Dispose 模式)
├── Config/
│ ├── ConfigLoader.cs # 配置加载器(支持加载和保存到 App.config
│ └── RaySourceConfig.cs # 射线源配置实体类(含验证方法)
├── Converters/
│ ├── RaySourceOperateConverter.cs # WPF 值转换器(状态→径向渐变色/边框色/启用状态)
│ └── FilamentLifetimeColorConverter.cs # 灯丝寿命百分比→颜色(绿/黄/红)
├── Factories/
│ └── RaySourceFactory.cs # 射线源工厂实现(创建 CometHostManager + CometIpcClient + Comet225RaySource
├── Implementations/
│ ├── Comet225RaySource.cs # Comet 225kV 射线源适配器(委托 IPC 客户端和 Host 管理器)
│ ├── CometHostManager.cs # Host 进程生命周期管理器(启动/监控/关闭子进程)
│ └── CometIpcClient.cs # Named Pipe IPC 客户端(双管道通信,消息收发)
├── Module/
│ └── RaySourceModule.cs # Prism 模块入口(DI 注册 + 灯丝寿命初始化 + 预警检查)
├── Services/
│ ├── IRaySourceService.cs # 射线源业务服务接口(含 InitializeAndConnectAsync
│ ├── RaySourceService.cs # 射线源业务服务实现(单例,业务规则校验 + 灯丝寿命联动)
│ ├── IFilamentLifetimeService.cs # 灯丝寿命管理服务接口
│ └── FilamentLifetimeService.cs # 灯丝寿命管理服务实现(SQLite 持久化)
├── ViewModels/
│ ├── RaySourceConfigViewModel.cs # 配置视图模型(初始化/连接/断开/设备状态监控/灯丝寿命进度条)
│ └── RaySourceOperateViewModel.cs # 操作视图模型(开关/电压电流调节/自动初始化)
├── Views/
│ ├── RaySourceConfigView.xaml(.cs) # 配置视图(设备状态面板 + 功能按钮 + 灯丝寿命进度条)
│ ├── RaySourceConfigWindow.xaml(.cs) # 配置窗口(包裹 ConfigView 的独立窗口)
│ └── RaySourceOperateView.xaml(.cs) # 操作视图(腰圆状态指示器 + 开关按钮 + 电压电流滑块)
└── Documents/ # 文档目录
```
## 5. 调用链路详解
### 5.1 整体架构(适配器模式 + IPC 进程隔离 + 事件驱动)
```
┌──────────────┐ ┌──────────────────┐ ┌───────────────────┐ ┌────────────────┐ ┌──────────────┐
│ ViewModel │───►│ RaySourceService │───►│ Comet225RaySource │───►│ CometIpcClient │───►│ Host 进程 │
│ (UI 层) │ │ (业务服务层) │ │ (适配器层) │ │ (IPC 通信层) │ │ (PVI 通讯层) │
└──────────────┘ └──────────────────┘ └───────────────────┘ └────────────────┘ └──────────────┘
▲ ▲ │ │
│ │ │ │
└────────── Prism EventAggregator ◄──────────────────────────────────┘◄─── Named Pipe ──────┘
(推送消息路由为 Prism 事件)
```
### 5.2 调用流程
#### 初始化流程
```
1. RaySourceModule.RegisterTypes()
→ 注册 RaySourceConfig(从 App.config 加载)
→ 注册 IRaySourceFactory → RaySourceFactory(单例)
→ 注册 IRaySourceService → RaySourceService(单例)
→ 注册 IFilamentLifetimeService → FilamentLifetimeService(单例)
2. RaySourceModule.OnInitialized()
→ FilamentLifetimeService.Initialize()(建表、异常恢复、重算累计寿命)
→ 检查灯丝寿命预警(≥90% 弹出对话框)
3. ViewModel 调用 IRaySourceService.Initialize()
→ RaySourceService.Initialize()
→ 验证配置参数
→ IRaySourceFactory.CreateRaySource("Comet225")
→ new CometHostManager(logger, config)
→ new CometIpcClient(config, eventAggregator, logger)
→ new Comet225RaySource(hostManager, ipcClient, logger)
→ Comet225RaySource.Initialize()
→ CometHostManager.EnsureRunning() // 启动 Host 子进程
→ 清理残留进程 → 启动新进程 → 等待 Named Pipe 就绪
→ CometIpcClient.Initialize()
→ Connect() // 连接双管道
→ SendCommand(InitializeCommand) // 发送初始化命令
→ Host 端执行 PVI Service/CPU 连接
→ 等待 ServiceConnected 推送确认
```
#### 变量连接流程
```
4. ViewModel 调用 IRaySourceService.ConnectVariables()
→ RaySourceService.ConnectVariables()
→ Comet225RaySource.ConnectVariables()
→ CometIpcClient.ConnectVariables()
→ SendCommand(ConnectVariablesCommand)
→ Host 端执行:CreateVariables → ActivateVariables → BindEventHandlers
→ Host 推送 VariablesConnected → RaySourceConnected
→ CometIpcClient 路由推送为 Prism 事件
→ VariablesConnectedEvent(true)
→ RaySourceStatusChangedEvent(Closed)
```
#### 操作流程(以开启射线为例)
```
5. ViewModel.ExecuteTurnOn()
→ RaySourceService.TurnOn() // 业务规则校验(状态检查、防重复、双重检查锁定)
→ Comet225RaySource.TurnOn() // 适配器层
→ CometIpcClient.TurnOn() // IPC 通信层
→ SendCommand(TurnOnCommand) // 序列化为 JSON,写入命令管道
→ Host 端执行 PVI 变量写入
→ Host 返回响应 → CometIpcClient 接收
→ 更新状态为 Opened
→ 发布 RaySourceStatusChangedEvent
→ FilamentLifetimeService.StartFilamentUsage() // 记录灯丝使用开始
```
#### 状态反馈流程(事件驱动)
```
6. Host 端 PVI 变量值变化
→ Host 构造推送消息(StatusChanged / XRayStateChanged / ErrorOccurred 等)
→ 写入响应管道
→ CometIpcClient.ReceiveLoop() 接收
→ 识别为推送消息(IsPush=true
→ HandlePushMessage() 路由到对应 Prism 事件
→ StatusUpdatedEvent(全量状态数据)
→ RaySourceStatusChangedEvent(三态变更)
→ ErrorOccurredEvent(错误信息)
→ VariablesConnectedEvent(连接状态)
→ ViewModel 通过事件订阅更新 UI
```
### 5.3 IPC 通信机制
#### Named Pipe 双管道模式
| 管道名称 | 方向 | 用途 |
|----------|------|------|
| `XP.Hardware.RaySource.Comet.Cmd` | 客户端 → Host | 命令管道(写入命令 JSON) |
| `XP.Hardware.RaySource.Comet.Rsp` | Host → 客户端 | 响应管道(接收响应和推送) |
#### 消息类型
- **命令消息**:客户端发送,Host 处理后返回响应(请求-响应模式)
- **推送消息**:Host 主动推送状态变化(`IsPush=true`),包括:
- `StatusChanged`:全量状态数据(电压/电流/各子系统状态)
- `XRayStateChanged`:射线开关状态变化
- `ErrorOccurred`:错误信息
- `ConnectionStateChanged`:连接状态变化(ServiceConnected / VariablesConnected / RaySourceConnected / Disconnected
- `Log`:Host 端日志转发(按级别映射到主进程 ILoggerService
#### 超时机制
- 命令超时:35000ms(大于 Host 端 PVI 连接超时 30s
- 管道连接超时:使用 `RaySourceConfig.ConnectionTimeout`(默认 5000ms
- Host 进程关闭超时:5000ms(超时则强制终止)
### 5.4 日志桥接机制
Host 进程(.NET Framework 4.8)通过 Named Pipe 推送日志消息到主进程。`CometIpcClient` 接收 `LogResponse` 推送后,根据 `Level` 字段映射到 `ILoggerService` 对应方法:
```
Host 端日志 → LogResponseJSON)→ Named Pipe → CometIpcClient.HandleLogPush()
→ Level="Debug" → _logger.Debug(message, args)
→ Level="Info" → _logger.Info(message, args)
→ Level="Warn" → _logger.Warn(message, args)
→ Level="Error" → _logger.Error(null, message, args)
→ Level="Fatal" → _logger.Fatal(null, message, args)
```
## 6. 灯丝寿命管理架构
### 6.1 数据库表结构
#### RaySourceFilamentLifetimeStatistics(累计统计表)
| 字段 | 类型 | 说明 |
|------|------|------|
| Id | INTEGER PK | 自增主键 |
| SourceType | TEXT | 射线源类型 |
| SerialNumber | TEXT | 序列号(唯一索引) |
| TotalLifeSeconds | REAL | 累计使用秒数 |
| LastUpdateTime | TEXT | 最后更新时间(ISO 8601 |
#### RaySourceFilamentUsageLogs(使用流水表)
| 字段 | 类型 | 说明 |
|------|------|------|
| Id | INTEGER PK | 自增主键 |
| SourceType | TEXT | 射线源类型 |
| SerialNumber | TEXT | 序列号 |
| StartTime | TEXT | 开始时间(ISO 8601 |
| EndTime | TEXT | 结束时间(可为 NULL |
| DurationSeconds | REAL | 持续秒数 |
| Status | INTEGER | 0=正常,1=异常中断 |
### 6.2 灯丝寿命联动
- 射线源开启(TurnOn)→ `StartFilamentUsage()`:插入流水记录
- 射线源关闭(TurnOff)→ `StopFilamentUsage()`:事务更新流水记录 + 累加统计表
- 断开连接 / 紧急关闭 → `StopFilamentUsage()`:同上
- 异常断联 → 下次初始化时 `RecoverUnclosedRecords()`:将未关闭记录标记为异常中断
### 6.3 预警机制
- 模块初始化时检查灯丝寿命百分比
- 百分比 ≥ 90% 时弹出模态预警对话框
- ConfigView 中显示灯丝寿命进度条(60 秒定时刷新)
- 进度条颜色:< 80% 绿色,80%-89% 黄色,≥ 90% 红色
## 7. 设计模式总结
| 模式 | 应用位置 | 说明 |
|------|---------|------|
| 策略模式 | `IXRaySource``Comet225RaySource` | 支持多种射线源实现的可扩展架构 |
| 工厂模式 | `IRaySourceFactory``RaySourceFactory` | 根据配置类型创建对应射线源实例 |
| 适配器模式 | `Comet225RaySource` | 将 IPC 通信适配为 IXRaySource 接口 |
| 进程隔离 | `CometHostManager` + `CometIpcClient` | 通过 Named Pipe 实现 .NET 8 与 .NET Framework 4.8 跨框架通信 |
| 事件驱动 | Prism EventAggregator + IPC 推送 | 解耦 PVI 通讯层与 UI 层的状态同步 |
| 依赖注入 | Prism DI 容器 | 通过 RaySourceModule 注册所有服务 |
| 单例模式 | RaySourceService、RaySourceFactory、FilamentLifetimeService | 全局唯一的服务和工厂实例 |
| 双重检查锁定 | RaySourceService.TurnOn/TurnOff | 防止并发重复操作 |
---
**最后更新 | Last Updated**: 2026-03-26
+413
View File
@@ -0,0 +1,413 @@
# XP.Hardware.RaySource
工业 X 射线源控制模块 | Industrial X-Ray Source Control Module
---
## 项目概述 | Project Overview
XP.Hardware.RaySource 是 XplorePlane X 射线检测系统的核心硬件控制模块,负责与工业 X 射线源设备进行通讯和控制。该模块采用策略模式和工厂模式设计,支持多种 X 射线源型号的统一管理,提供完整的设备生命周期控制和安全机制。
### 主要特性 | Key Features
- 支持多种 X 射线源型号(当前支持 Comet 225kV
- 基于 Named Pipe IPC 的进程隔离架构(.NET 8 主进程 ↔ .NET Framework 4.8 Host 进程)
- 完整的设备生命周期管理(初始化、连接变量、暖机、训机、灯丝校准、自动定心、开关射线)
- 精确的电压电流控制(20-225kV / 10-1000μA
- 实时状态监控和错误检测
- 基于 Prism 事件聚合器的松耦合跨模块通讯
- 安全机制:紧急关闭优先级、参数范围验证
- 灯丝寿命管理:使用时长记录、累计统计、预警提醒
- TXI 开关控制、功率模式切换(Micro Focus / High Power
- 完整的日志记录和异常处理
---
## 框架架构 | Architecture
```
XP.Hardware.RaySource/
├── Abstractions/ # 抽象层 | Abstraction Layer
│ ├── IXRaySource.cs # 策略接口(同步方法)
│ ├── XRaySourceBase.cs # 抽象基类
│ ├── XRayResult.cs # 结果封装类
│ ├── IRaySourceFactory.cs # 工厂接口
│ ├── Enums/ # 枚举定义
│ │ └── RaySourceStatus.cs # 三态枚举(Unavailable/Closed/Opened
│ └── Events/ # Prism 事件定义
│ ├── StatusUpdatedEvent.cs # 系统状态更新事件
│ ├── ErrorOccurredEvent.cs # 错误触发事件
│ ├── OperationResultEvent.cs # 操作结果事件
│ ├── RaySourceStatusChangedEvent.cs # 射线源状态变更事件
│ └── VariablesConnectedEvent.cs # PVI 变量连接状态事件
├── Implementations/ # 实现层 | Implementation Layer
│ ├── Comet225RaySource.cs # Comet 225kV 适配器(委托 IPC 客户端)
│ ├── CometHostManager.cs # Host 进程生命周期管理器
│ └── CometIpcClient.cs # Named Pipe IPC 客户端
├── Factories/ # 工厂层 | Factory Layer
│ └── RaySourceFactory.cs # 射线源工厂
├── Services/ # 业务服务层 | Service Layer
│ ├── IRaySourceService.cs # 服务接口
│ ├── RaySourceService.cs # 服务实现(单例)
│ ├── IFilamentLifetimeService.cs # 灯丝寿命服务接口
│ └── FilamentLifetimeService.cs # 灯丝寿命服务实现
├── Config/ # 配置层 | Configuration Layer
│ ├── RaySourceConfig.cs # 配置实体
│ └── ConfigLoader.cs # 配置加载器(支持保存)
├── Module/ # Prism 模块 | Prism Module
│ └── RaySourceModule.cs # 模块注册
├── ViewModels/ # 视图模型 | View Models
│ ├── RaySourceConfigViewModel.cs # 配置视图模型(初始化/连接/断开/设备状态监控/灯丝寿命)
│ └── RaySourceOperateViewModel.cs # 操作视图模型(开关/电压电流调节)
├── Views/ # WPF 视图 | WPF Views
│ ├── RaySourceConfigView.xaml # 配置视图(设备状态面板)
│ ├── RaySourceConfigWindow.xaml # 配置窗口(包裹 ConfigView
│ └── RaySourceOperateView.xaml # 操作视图(开关/滑块)
├── Converters/ # WPF 值转换器 | WPF Value Converters
│ ├── RaySourceOperateConverter.cs # 状态→颜色/边框色/启用状态
│ └── FilamentLifetimeColorConverter.cs # 灯丝寿命百分比→颜色
└── Documents/ # 文档 | Documentation
├── README.md # 项目说明(本文档)
├── ProjectStructure.md # 项目结构详解
├── GUIDENCE.md # 使用指南
├── README_RaySourceOperateView.md # 操作视图说明
└── App.config.example # 配置文件示例
```
### 设计模式 | Design Patterns
- **策略模式**`IXRaySource` 接口定义统一操作,支持多种设备实现
- **工厂模式**`IRaySourceFactory` 根据设备类型动态创建实例
- **适配器模式**`Comet225RaySource` 将 IPC 通信适配为 `IXRaySource` 接口
- **进程隔离**:通过 `CometHostManager` + `CometIpcClient` 实现 .NET 8 与 .NET Framework 4.8 的跨框架通信
- **模板方法模式**`XRaySourceBase` 提供基础实现框架
- **单例模式**`IRaySourceService``IFilamentLifetimeService` 作为全局单例
- **依赖注入**:通过 Prism 容器管理服务生命周期
- **事件聚合器**:使用 Prism `IEventAggregator` 实现松耦合通讯
### IPC 进程隔离架构 | IPC Process Isolation Architecture
```
┌──────────────────────────────────────────────────────────────────────┐
│ .NET 8 主进程 (XP.Hardware.RaySource) │
│ │
│ ViewModel → RaySourceService → Comet225RaySource │
│ │ │
│ CometHostManager(管理 Host 进程生命周期)│
│ CometIpcClientNamed Pipe 双管道通信) │
│ │ │
│ NamedPipe: Cmd(写入)/ Rsp(读取) │
└──────────────────────────────┬───────────────────────────────────────┘
│ Named Pipe IPC
┌──────────────────────────────┴───────────────────────────────────────┐
│ .NET Framework 4.8 Host 进程 (Comet.Host) │
│ │
│ CometPviClient ← BR.AN.PviServices.dll │
│ (PVI 通讯层,直接操作 PLC 变量) │
└──────────────────────────────────────────────────────────────────────┘
```
---
## 核心功能 | Core Features
### 1. 设备生命周期管理 | Device Lifecycle Management
```csharp
// 初始化射线源(类型从配置文件读取)
XRayResult result = _raySourceService.Initialize();
// 连接 PVI 变量并启动实时状态通讯
XRayResult connectResult = _raySourceService.ConnectVariables();
// 异步执行初始化 + 连接变量的完整流程
XRayResult autoResult = await _raySourceService.InitializeAndConnectAsync();
// 开启射线
_raySourceService.TurnOn();
// 关闭射线
_raySourceService.TurnOff();
// 紧急关闭(最高优先级)
_raySourceService.EmergencyShutdown();
// 断开连接(保留实例以便重连)
_raySourceService.Disconnect();
```
### 2. 电压电流控制 | Voltage and Current Control
```csharp
// 设置电压(20-225kV
_raySourceService.SetVoltage(100f);
// 设置电流(10-1000μA
_raySourceService.SetCurrent(500f);
// 读取实际电压
XRayResult voltageResult = _raySourceService.ReadVoltage();
float voltage = voltageResult.GetFloat();
// 读取实际电流
XRayResult currentResult = _raySourceService.ReadCurrent();
float current = currentResult.GetFloat();
```
### 3. 设备操作 | Device Operations
```csharp
// TXI 开启/关闭
_raySourceService.TxiOn();
_raySourceService.TxiOff();
// 暖机
_raySourceService.WarmUp();
// 训机
_raySourceService.Training();
// 灯丝校准
_raySourceService.FilamentCalibration();
// 全部电压自动定心
_raySourceService.AutoCenter();
// 设置功率模式(1=Micro Focus2=High Power
_raySourceService.SetPowerMode(1);
```
### 4. 状态监控 | Status Monitoring
```csharp
// 读取系统状态
_raySourceService.ReadSystemStatus();
// 检查错误
_raySourceService.CheckErrors();
// 清除错误
_raySourceService.ClearErrors();
// 检查状态属性
bool isInitialized = _raySourceService.IsInitialized;
bool isConnected = _raySourceService.IsConnected;
bool isXRayOn = _raySourceService.IsXRayOn;
RaySourceStatus status = _raySourceService.CurrentStatus;
```
### 5. 灯丝寿命管理 | Filament Lifetime Management
```csharp
// 初始化灯丝寿命服务(模块启动时自动调用)
_filamentLifetimeService.Initialize();
// 获取累计使用秒数
double totalSeconds = _filamentLifetimeService.GetCurrentTotalLifeSeconds();
// 获取寿命百分比
double percentage = _filamentLifetimeService.GetLifetimePercentage();
// 检查是否需要预警(≥90%
bool shouldWarn = _filamentLifetimeService.ShouldShowLifetimeWarning();
```
### 6. 事件通讯 | Event Communication
```csharp
// 订阅射线源状态变化事件(三态:Unavailable/Closed/Opened
_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);
// 订阅 PVI 变量连接状态事件
_eventAggregator.GetEvent<VariablesConnectedEvent>()
.Subscribe(OnVariablesConnected, ThreadOption.UIThread);
```
---
## 技术要求 | Technical Requirements
### 运行环境 | Runtime Environment
- **.NET 8.0** (net8.0-windows7.0)
- **Windows 操作系统**WPF 依赖)
- **Visual Studio 2022** 或更高版本
### 核心依赖 | Core Dependencies
| 依赖库 | 版本 | 用途 |
|--------|------|------|
| **Prism.Wpf** | 9.0.537 | MVVM 框架和依赖注入 |
| **Telerik UI for WPF** | 2024.1.408 | UI 控件库 |
| **System.Configuration.ConfigurationManager** | 8.0.0 | 配置文件管理 |
| **XP.Common** | - | 日志、数据库、多语言基础设施 |
| **XP.Hardware.RaySource.Comet.Messages** | - | IPC 消息定义(netstandard2.0 共享库) |
### 关联项目 | Related Projects
| 项目 | 框架 | 用途 |
|------|------|------|
| **XP.Hardware.RaySource.Comet.Host** | .NET Framework 4.8 | Host 子进程,运行 B&R PVI 通讯 |
| **XP.Hardware.RaySource.Comet.Messages** | netstandard2.0 | IPC 命令/响应消息定义 |
---
## 快速开始 | Quick Start
### 1. 配置文件设置
参见 [App.config.example](./App.config.example)
### 2. 注册模块
`App.xaml.cs` 中:
```csharp
protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
{
moduleCatalog.AddModule<RaySourceModule>();
}
```
### 3. 使用服务
在 ViewModel 中注入并使用:
```csharp
public class YourViewModel : BindableBase
{
private readonly IRaySourceService _raySourceService;
private readonly IEventAggregator _eventAggregator;
public YourViewModel(
IRaySourceService raySourceService,
IEventAggregator eventAggregator)
{
_raySourceService = raySourceService;
_eventAggregator = eventAggregator;
_eventAggregator.GetEvent<RaySourceStatusChangedEvent>()
.Subscribe(OnStatusChanged, ThreadOption.UIThread);
}
public void Initialize()
{
XRayResult result = _raySourceService.Initialize();
if (result.Success)
{
_raySourceService.ConnectVariables();
}
}
}
```
---
## 配置参数说明 | Configuration Parameters
| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| SourceType | string | Comet225 | 射线源类型 |
| PlcIpAddress | string | 192.168.12.10 | PLC IP 地址 |
| PlcPort | int | 11159 | PLC 端口号 |
| StationNumber | int | 1 | 源站号 |
| PortNumber | int | 11 | 源端口号 |
| CpuName | string | cpu | CPU 名称 |
| ConnectionTimeout | int | 5000 | 连接超时(毫秒)|
| MinVoltage | float | 20 | 最小电压(kV|
| MaxVoltage | float | 225 | 最大电压(kV|
| MinCurrent | float | 10 | 最小电流(μA|
| MaxCurrent | float | 1000 | 最大电流(μA|
| AdvanceExePath | string | FXEControl.exe 路径 | 高级设置外部程序路径 |
| HostExePath | string | 空(自动查找) | Host 进程可执行文件路径 |
| InitializationTimeout | int | 30000 | 初始化超时(毫秒)|
| WarmUpTimeout | int | 300000 | 暖机超时(5分钟)|
| StartUpTimeout | int | 180000 | 启动超时(3分钟)|
| AutoCenterTimeout | int | 120000 | 自动定心超时(2分钟)|
| FilamentAdjustTimeout | int | 120000 | 灯丝调整超时(2分钟)|
| GeneralOperationTimeout | int | 10000 | 一般操作超时(毫秒)|
| SerialNumber | string | 空 | 射线源序列号(灯丝寿命管理) |
| TotalLifeThreshold | int | 1000 | 灯丝总寿命阈值(小时) |
---
## 安全机制 | Safety Mechanisms
### 1. 参数范围验证
所有参数在设置前都会进行范围验证,超出范围返回错误结果。
### 2. 紧急关闭优先级
紧急关闭具有最高优先级,可以在任何状态下执行,会依次关闭射线、完全关闭设备。
### 3. 业务规则校验
- 未初始化禁止操作
- 防重复开启/关闭(双重检查锁定)
- 异常断联自动检测和状态重置
### 4. 灯丝寿命预警
灯丝使用时长达到阈值 90% 时,系统自动弹出预警对话框。
---
## 文档索引 | Documentation Index
- **[README.md](./README.md)** - 本文档,项目概述和快速参考
- **[ProjectStructure.md](./ProjectStructure.md)** - 项目结构详解和调用链路
- **[GUIDENCE.md](./GUIDENCE.md)** - 详细使用指南,包含完整代码示例
- **[README_RaySourceOperateView.md](./README_RaySourceOperateView.md)** - 操作视图使用说明
- **[App.config.example](./App.config.example)** - 配置文件示例
---
## 故障排查 | Troubleshooting
### 初始化失败
- 检查 Host 进程可执行文件是否存在(默认路径:`{主程序目录}/Host/XP.Hardware.RaySource.Comet.Host.exe`
- 检查 PLC IP 地址和端口配置
- 确认 PLC 网络连接正常
- 查看日志中 Named Pipe 连接状态
### 射线无法开启
- 确认已成功初始化并连接变量(`IsInitialized && IsConnected`
- 检查设备错误状态
- 验证互锁信号
### 电压电流设置失败
- 验证参数在有效范围内
- 确认射线源已初始化
- 检查 IPC 管道连接状态
### Host 进程异常
- 检查 Host 进程是否正常启动(查看日志中 PID 信息)
- 确认 BR.AN.PviServices.dll 已正确部署到 Host 目录
- 检查是否有残留的 Host 进程(CometHostManager 会自动清理)
详细故障排查请参考 [GUIDENCE.md](./GUIDENCE.md) 第 14 节。
---
## 许可证 | License
本模块是 XplorePlane 项目的一部分,遵循项目整体许可协议。
---
**最后更新 | Last Updated**: 2026-03-26
@@ -0,0 +1,378 @@
# RaySourceOperateView 使用说明
## 概述
`RaySourceOperateView` 是射线源操作和监控面板,提供射线源开关控制、电压电流实时调节和状态监控功能。
## 架构设计
### MVVM 模式
- **View**: `RaySourceOperateView.xaml` - WPF 用户控件界面
- **ViewModel**: `RaySourceOperateViewModel.cs` - 视图模型,处理业务逻辑
- **Model**: `RaySourceStatus.cs` - 射线源状态枚举(Unavailable / Closed / Opened
### 依赖注入
ViewModel 通过构造函数注入以下依赖:
- `IRaySourceService` - 射线源业务服务
- `IEventAggregator` - Prism 事件聚合器
- `RaySourceConfig` - 射线源配置
- `ILoggerService` - 日志服务
- `ILocalizationService` - 多语言服务
## 功能特性
### 1. 状态监控
- **腰圆状态指示器**
- 灰色径向渐变 = 射线源不可用(Unavailable
- 绿色径向渐变 (#8BC34A#4CAF50) = 射线源已关闭(Closed
- 红色径向渐变 (#FF8A80#F44336) = 射线源已开启(Opened
- **呼吸闪烁动画**:射线源开启时,状态指示器播放呼吸闪烁动画(透明度 1.0 → 0.6 循环,周期约 1.5 秒)
- **实时状态文本**:通过 `ILocalizationService` 获取多语言状态文字
### 2. 射线源控制
- **开启射线源按钮**
- 仅在 Closed 状态、已初始化且变量已连接时可用
- 调用 `IRaySourceService.TurnOn()`
- 按钮文字通过多语言绑定:`{loc:Localization RaySource_TurnOnButton}`
- **关闭射线源按钮**
- 仅在 Opened 状态、已初始化且变量已连接时可用
- 调用 `IRaySourceService.TurnOff()`
- 按钮文字通过多语言绑定:`{loc:Localization RaySource_TurnOffButton}`
- **配置按钮**
- 打开 `RaySourceConfigWindow`(射线源配置窗口)
- 窗口已存在时激活而非重复创建
- **高级/设置按钮**
- 启动外部高级设置程序(`FXEControl.exe`
- 如果程序已运行则将窗口置前
- 使用 `ProcessHelper.StartOrActivate()` 实现
### 3. 电压调节
- **滑块范围**:从配置文件读取(默认 20-225 kV)
- **双向绑定**:滑块和数值输入框绑定同一属性 `VoltageValue`,使用 `Mode=TwoWay`
- **延迟拖拽**:滑块使用 `IsDeferredDraggingEnabled="True"`,松手时才提交值
- **手动提交**:通过 `ApplyVoltageCommand` 提交电压值到硬件(滑块松手/输入框失焦时触发)
- **启用条件**:仅在服务已初始化且变量已连接时可调节(`IsSlidersEnabled`
- **范围显示**:滑块下方显示最小值和最大值
- **实际值显示**:右上角显示当前实际电压值
### 4. 电流调节
- **滑块范围**:从配置文件读取(默认 10-1000 μA)
- **双向绑定**:滑块和数值输入框绑定同一属性 `CurrentValue`,使用 `Mode=TwoWay`
- **延迟拖拽**:滑块使用 `IsDeferredDraggingEnabled="True"`,松手时才提交值
- **手动提交**:通过 `ApplyCurrentCommand` 提交电流值到硬件
- **启用条件**:仅在服务已初始化且变量已连接时可调节(`IsSlidersEnabled`
- **范围显示**:滑块下方显示最小值和最大值
- **实际值显示**:右上角显示当前实际电流值
### 5. 自动初始化
- ViewModel 提供 `AutoInitializeAsync()` 方法
- 由 View 的 `Loaded` 事件触发,仅执行一次
- 异步执行 `InitializeAndConnectAsync()`(初始化 + 连接变量)
- 如果已初始化且变量已连接则跳过
## 关联视图:RaySourceConfigView
`RaySourceConfigView` 是射线源配置和设备状态监控面板,通过 `RaySourceConfigWindow` 包裹为独立窗口。
### ConfigView 功能
- **设备信息**:显示射线源类型和连接状态(颜色编码:灰色=未连接,橙色=已初始化,绿色=变量已连接)
- **操作按钮**:初始化 / 连接变量 / 断开(三列等宽布局)
- **设备状态面板**:暖机/真空/启动/自动定心/灯丝校准/射线开启/连锁/看门狗/TXI/功率模式
- **TXI 控制**TXI ON / TXI OFF 按钮
- **功率模式切换**High Power / Micro Focus 按钮
- **功能设置按钮**:暖机设置 / 训机设置 / 灯丝校准 / 自动定心(四列等宽布局,带确认对话框和进度条窗口)
- **灯丝寿命进度条**:显示灯丝使用百分比(60 秒定时刷新),颜色随百分比变化(绿/黄/红)
### ConfigView 依赖注入
- `IRaySourceService` - 射线源业务服务
- `IEventAggregator` - Prism 事件聚合器
- `RaySourceConfig` - 射线源配置
- `ILoggerService` - 日志服务
- `ILocalizationService` - 多语言服务
- `IFilamentLifetimeService` - 灯丝寿命管理服务
## 多语言支持
### XAML 中使用
```xml
xmlns:loc="clr-namespace:XP.Common.Localization.Extensions;assembly=XP.Common"
<TextBlock Text="{loc:Localization RaySource_VoltageLabel}"/>
<telerik:RadButton Content="{loc:Localization RaySource_TurnOnButton}"/>
```
### ViewModel 中使用
```csharp
_localizationService.GetString("RaySource_StatusClosed")
```
### 资源键列表
#### OperateView 资源键
| 资源键 | 中文 | 英文 |
|--------|------|------|
| RaySource_VoltageLabel | 电压(kV | Voltage (kV) |
| RaySource_CurrentLabel | 电流(μA | Current (μA) |
| RaySource_ActualValueLabel | 当前值: {0} | Actual: {0} |
| RaySource_TurnOnButton | 开启射线源 | Turn On X-Ray |
| RaySource_TurnOffButton | 关闭射线源 | Turn Off X-Ray |
| RaySource_AdvanceButton | 高级 | Advance |
| RaySource_ConfigButton | 配置 | Config |
| RaySource_StatusUnavailable | 射线源\n不可用 | X-Ray\nUnavailable |
| RaySource_StatusClosed | 射线源\n已关闭 | X-Ray\nClosed |
| RaySource_StatusOpened | 射线源\n已开启 | X-Ray\nOpened |
#### ConfigView 资源键
| 资源键 | 中文 | 英文 |
|--------|------|------|
| RaySource_SourceTypeLabel | 射线源类型 | Source Type |
| RaySource_InitializeButton | 初始化 | Initialize |
| RaySource_ConnectVariablesButton | 连接变量 | Connect Variables |
| RaySource_DisconnectButton | 断开 | Disconnect |
| RaySource_WarmUpLabel | 暖机 | Warm-up |
| RaySource_VacuumLabel | 真空 | Vacuum |
| RaySource_StartUpLabel | 启动 | Startup |
| RaySource_AutoCenterLabel | 自动定心 | Auto-center |
| RaySource_FilamentLabel | 灯丝校准 | Filament |
| RaySource_XRayOnLabel | 射线 | X-Ray |
| RaySource_InterlockLabel | 连锁 | Interlock |
| RaySource_WatchdogLabel | 看门狗 | Watchdog |
| RaySource_TxiStatusLabel | TXI | TXI |
| RaySource_TxiOnButton | TXI ON | TXI ON |
| RaySource_TxiOffButton | TXI OFF | TXI OFF |
| RaySource_PowerModeLabel | 功率模式 | Power Mode |
| RaySource_HighPowerButton | High Power | High Power |
| RaySource_MicroFocusButton | Micro Focus | Micro Focus |
| RaySource_WarmUpSettingButton | 暖机设置 | Warm-up |
| RaySource_TrainingSettingButton | 训机设置 | Training |
| RaySource_FilamentCalibrationButton | 灯丝校准 | Filament Cal. |
| RaySource_AutoCenterSettingButton | 自动定心 | Auto-center |
| RaySource_FilamentLifetimeLabel | 灯丝寿命 | Filament Life |
| RaySource_ConfigWindowTitle | 射线源配置 | X-Ray Source Config |
> 注意:多语言仅在应用启动时加载,无需运行时热切换。
## 呼吸闪烁动画
射线源开启时,状态指示器播放呼吸闪烁动画,增强视觉警示效果。
### 动画定义
```xml
<Storyboard x:Key="BreathingAnimation" RepeatBehavior="Forever">
<DoubleAnimation Storyboard.TargetProperty="Opacity"
From="1.0" To="0.6" Duration="0:0:0.75"
AutoReverse="True"/>
</Storyboard>
```
### 触发机制
通过 `DataTrigger` 监听 `RaySourceStatus` 属性:
- 当状态变为 `Opened` 时,自动开始动画
- 当状态离开 `Opened` 时,自动停止动画
## 事件订阅
### OperateViewModel 订阅事件
1. **RaySourceStatusChangedEvent**:射线源状态变更(三态)
- 更新 `RaySourceStatus` 属性和按钮/滑块启用状态
- 异常断联时重置变量连接状态
2. **StatusUpdatedEvent**:系统状态更新
- 更新实际电压和电流值(仅在值真正变化时更新,避免无意义赋值)
- 同步服务层权威状态
3. **ErrorOccurredEvent**:错误发生
- 显示错误消息对话框
4. **OperationResultEvent**:操作结果
- 操作失败时显示警告消息
5. **VariablesConnectedEvent**:变量连接状态变更
- 更新 `IsVariablesConnected` 属性
- 连接成功时主动读取最新设备状态
### ConfigViewModel 订阅事件
1. **RaySourceStatusChangedEvent**:刷新初始化状态和命令可执行状态
2. **StatusUpdatedEvent**:刷新设备状态面板所有字段
3. **VariablesConnectedEvent**:刷新连接状态和命令可执行状态
## 数据绑定
### OperateView 状态绑定
```xml
<!-- 状态指示器背景色(径向渐变)-->
Background="{Binding RaySourceStatus, Converter={StaticResource StatusToColorConverter}}"
<!-- 状态指示器边框色 -->
BorderBrush="{Binding RaySourceStatus, Converter={StaticResource StatusToBorderColorConverter}}"
<!-- 状态文本(多语言)-->
Text="{Binding StatusText}"
```
### OperateView 命令绑定
```xml
<telerik:RadButton Content="{loc:Localization RaySource_TurnOnButton}" Command="{Binding TurnOnCommand}"/>
<telerik:RadButton Content="{loc:Localization RaySource_TurnOffButton}" Command="{Binding TurnOffCommand}"/>
<telerik:RadButton Content="{loc:Localization RaySource_AdvanceButton}" Command="{Binding SettingsCommand}"/>
<telerik:RadButton Content="{loc:Localization RaySource_ConfigButton}" Command="{Binding ConfigCommand}"/>
```
### OperateView 滑块绑定
```xml
<!-- 电压滑块(延迟拖拽模式)-->
<telerik:RadSlider Minimum="{Binding VoltageMin}" Maximum="{Binding VoltageMax}"
Value="{Binding VoltageValue, Mode=TwoWay}"
IsDeferredDraggingEnabled="True"
IsEnabled="{Binding IsSlidersEnabled}"/>
<!-- 电压数值输入框 -->
<telerik:RadNumericUpDown Minimum="{Binding VoltageMin}" Maximum="{Binding VoltageMax}"
Value="{Binding VoltageValue, Mode=TwoWay}"
IsEnabled="{Binding IsSlidersEnabled}" NumberDecimalDigits="1"/>
```
## 转换器
### 1. RaySourceStatusToColorConverter
`RaySourceStatus` 枚举转换为径向渐变背景色:
- `Unavailable` → 灰色渐变(#E0E0E0#BDBDBD
- `Closed` → 绿色渐变(#8BC34A#4CAF50
- `Opened` → 红色渐变(#FF8A80#F44336
### 2. RaySourceStatusToBorderColorConverter
`RaySourceStatus` 枚举转换为边框色:
- `Unavailable`#9E9E9E
- `Closed`#2E7D32
- `Opened`#C62828
### 3. FilamentLifetimeColorConverter
将灯丝寿命百分比转换为进度条颜色:
- < 80% → 绿色 (#4CAF50)
- 80%-89% → 黄色 (#FFC107)
- ≥ 90% → 红色 (#E53935)
## 业务规则
### 安全规则
1. **未初始化禁止操作**:所有操作前检查 `IsInitialized``IsVariablesConnected`
2. **参数范围校验**:电压和电流值必须在配置的范围内
3. **操作失败回滚**:设置失败时恢复滑块到实际值(仅当实际值在有效范围内时)
4. **连接丢失处理**:连接丢失时状态设为 `Unavailable`,重置变量连接状态,禁用所有操作
5. **设备反馈保护**`IsUpdatingFromDevice` 标志防止设备反馈更新时误触发写入
### 状态管理
- 状态变更通过事件驱动,确保 UI 与硬件状态同步
- 使用 `RaisePropertyChanged` 通知 UI 更新
- 命令的 `CanExecute` 自动监听状态变化
- 三态管理:Unavailable → Closed → Opened
## 使用示例
### 在独立窗口中使用
```csharp
var raySourceView = _containerProvider.Resolve<RaySourceOperateView>();
var window = new Window
{
Title = "射线源操作",
Content = raySourceView,
SizeToContent = SizeToContent.WidthAndHeight,
ResizeMode = ResizeMode.NoResize,
WindowStartupLocation = WindowStartupLocation.CenterOwner,
Owner = Application.Current.MainWindow
};
window.ShowDialog();
```
### 在主窗口 Region 中加载
```xml
<ContentControl prism:RegionManager.RegionName="RaySourceOperateRegion" />
```
```csharp
_regionManager.RequestNavigate("RaySourceOperateRegion", "RaySourceOperateView");
```
## XAML 命名空间引用
```xml
xmlns:local="clr-namespace:XP.Hardware.RaySource.Views"
xmlns:converters="clr-namespace:XP.Hardware.RaySource.Converters"
xmlns:enums="clr-namespace:XP.Hardware.RaySource.Abstractions.Enums"
xmlns:loc="clr-namespace:XP.Common.Localization.Extensions;assembly=XP.Common"
xmlns:prism="http://prismlibrary.com/"
xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
```
## 注意事项
1. **线程安全**:所有事件处理使用 `ThreadOption.UIThread` 确保在 UI 线程执行
2. **资源释放**ViewModel 实现 `IDisposable`,在 Dispose 时取消事件订阅、断开射线源连接、关闭配置窗口
3. **同步操作**:硬件操作为同步方法,ViewModel 中直接调用(不阻塞 UI 因为操作通过 IPC 快速返回)
4. **错误处理**:所有操作包含 try-catch,确保异常不会导致程序崩溃
5. **多语言**:所有界面文字通过 `{loc:Localization}``ILocalizationService` 获取,无硬编码文字
6. **动画性能**:呼吸闪烁动画使用 WPF Storyboard,性能开销极低
7. **日志规范**:使用 `_logger.ForModule("RaySource.ViewModel")` 和结构化日志消息
8. **自动初始化**OperateView 加载时自动执行 `AutoInitializeAsync()`,仅执行一次
9. **配置窗口**:通过 ConfigCommand 打开,单例模式(已存在时激活而非重复创建)
## 故障排查
### 按钮不可用
- 检查 `IsInitialized``IsVariablesConnected` 状态
- 检查 `RaySourceStatus` 是否正确
- 查看命令的 `CanExecute` 逻辑
### 滑块不可用
- 确认服务已初始化且变量已连接(`IsSlidersEnabled`
### 实际值不更新
- 确认已订阅 `StatusUpdatedEvent`
- 检查 Host 进程是否正常推送状态
- 验证 `ThreadOption.UIThread` 设置
### 设置值不生效
- 检查 `ApplyVoltageCommand` / `ApplyCurrentCommand` 是否正确触发
- 查看业务规则校验逻辑
- 确认 IPC 管道连接正常
### 多语言文字不显示
- 确认 XP.Common 资源文件中已添加对应的资源键
- 检查 XAML 中 `xmlns:loc` 命名空间引用是否正确
### 动画不播放
- 确认 `RaySourceStatus` 已变为 `Opened`
- 检查 `enums` 命名空间引用是否正确
### 状态显示为"不可用"
- 检查射线源服务连接状态
- 确认 Host 进程是否正常运行
- 查看日志中是否有连接丢失的警告信息
---
**最后更新 | Last Updated**: 2026-03-26