1169 lines
41 KiB
C#
1169 lines
41 KiB
C#
using BR.AN.PviServices;
|
||
using System;
|
||
using System.Text;
|
||
using System.Threading;
|
||
using System.Windows.Forms;
|
||
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
|
||
|
||
// 解决 BR.AN.PviServices.Exception 与 System.Exception 的歧义
|
||
using Exception = System.Exception;
|
||
|
||
namespace XP.Hardware.RaySource.Comet
|
||
{
|
||
/// <summary>
|
||
/// Comet PVI 通讯客户端静态类
|
||
/// 封装 BR.AN.PviServices 的所有直接调用
|
||
/// 包含:Service/CPU 连接管理、Variable 创建/激活/绑定、ValueChanged 回调处理
|
||
/// </summary>
|
||
public static class CometPviClient
|
||
{
|
||
#region 日志回调委托
|
||
|
||
/// <summary>
|
||
/// 日志回调委托(由 .NET 8 层注入)
|
||
/// </summary>
|
||
private static Action<CometLogLevel, string, object[]> _logger;
|
||
|
||
#endregion
|
||
|
||
#region PVI 核心对象
|
||
|
||
private static Service _service;
|
||
private static Cpu _cpu;
|
||
|
||
#endregion
|
||
|
||
#region 连接参数
|
||
|
||
private static string _ipAddress;
|
||
private static int _port;
|
||
private static string _cpuName;
|
||
private static int _sourcePort;
|
||
private static int _stationNumber;
|
||
|
||
#endregion
|
||
|
||
#region 连接状态
|
||
|
||
private static bool _isConnected;
|
||
private static bool _isVariablesConnected;
|
||
private static PviConnectionState _currentConnectionState = PviConnectionState.Disconnected;
|
||
|
||
#endregion
|
||
|
||
#region PVI 变量 - 电压/电流
|
||
|
||
private static Variable _varKVS; // 设置电压 PC_cmd.r32_TubeVoltage_kV
|
||
private static Variable _varKVR; // 电压反馈 PLC_stat.r32_TubeVoltage_kV_ist
|
||
private static Variable _varMAS; // 设置电流 PC_cmd.r32_TubeCurrent_uA
|
||
private static Variable _varMAR; // 电流反馈 PLC_stat.r32_TubeCurrent_uA_ist
|
||
|
||
#endregion
|
||
|
||
#region PVI 变量 - 射线开关
|
||
|
||
private static Variable _varXonS; // 开高压 PC_cmd.xrayON
|
||
private static Variable _varXoffS; // 关高压 PC_cmd.xrayOFF
|
||
private static Variable _varXonR; // 高压开关反馈 PLC_stat.bo_Xray_on
|
||
|
||
#endregion
|
||
|
||
#region PVI 变量 - 维护操作(暖机/真空/训机)
|
||
|
||
private static Variable _varWarmUpS; // 暖机设定 PC_cmd.warmUP
|
||
private static Variable _varWarmUpR; // 暖机状态反馈 PLC_stat.u32_warmup
|
||
private static Variable _varVaconS; // 真空设定 Vacon
|
||
private static Variable _varVaconR; // 真空状态反馈 PLC_stat.u32_vacuum
|
||
private static Variable _varVaconRV; // 真空值 Vac.ist_mbar
|
||
private static Variable _varStartUpS; // 训机设定 PC_cmd.startUP
|
||
private static Variable _varStartUpR; // 训机状态反馈 PLC_stat.u32_startup
|
||
|
||
#endregion
|
||
|
||
#region PVI 变量 - 校准(自动定心/灯丝调整)
|
||
|
||
private static Variable _varCurrentKVAutoCenter; // 当前电压自动定心 PC_cmd.autocentkV
|
||
private static Variable _varALLKVCenter; // 全部电压自动定心 PC_cmd.autocentALL
|
||
private static Variable _varAutoCenterR; // 自动定心反馈 PLC_stat.u32_autocenter
|
||
private static Variable _varFilamentAdjust; // 灯丝调整 PC_cmd.filamentadjust
|
||
private static Variable _varFilamentAdjustR; // 灯丝调整反馈 PLC_stat.u32_filamentadjust
|
||
|
||
#endregion
|
||
|
||
#region PVI 变量 - 状态监控
|
||
|
||
private static Variable _varInterLockR; // 连锁状态 Di_Interlock
|
||
private static Variable _varWatchingDog; // 看门狗 PLC_stat.bo_Watchdog
|
||
private static Variable _varPowerModeR; // 功率模式反馈 PLC_stat.u32_current_modenumber
|
||
private static Variable _varPowerModeS; // 功率模式设定 Mode.current_mode_number
|
||
private static Variable _varTxiR; // TXI 反馈 PLC_stat.bo_TXI
|
||
private static Variable _varTxiOpenS; // TXI 开启设定 PC_cmd.Ti_reg_on
|
||
private static Variable _varTxiCloseS; // TXI 关闭设定 PC_cmd.Ti_reg_off
|
||
|
||
#endregion
|
||
|
||
#region PVI 变量 - 错误监控
|
||
|
||
private static Variable _sysErrR; // 系统错误读取 Sys_error[0]
|
||
private static Variable _sysErrS; // 系统错误确认 Sys_errorquit
|
||
private static Variable _HSGErrR; // 高压错误读取 HSG_error[0]
|
||
private static Variable _HSGErrS; // 高压错误确认 HSG_errorquit
|
||
private static Variable _tubeErrR; // 管子错误读取 Tube_error[0]
|
||
private static Variable _tubeErrS; // 管子错误确认 Tube_errorquit
|
||
private static Variable _tubeACErrR; // 管子真空错误读取 TubeVac_error[0]
|
||
private static Variable _tubeACErrS; // 管子真空错误确认 Vac_errorquit
|
||
|
||
#endregion
|
||
|
||
#region 内部缓存状态
|
||
|
||
private static float _actualVoltage;
|
||
private static float _actualCurrent;
|
||
private static float _setVoltage;
|
||
private static float _setCurrent;
|
||
private static bool _isXRayOn;
|
||
// 原始 code 码(多语言映射由 .NET 8 侧处理)| Raw code (localization handled by .NET 8 side)
|
||
private static string _warmUpCode = "0";
|
||
private static string _vacuumCode = "0";
|
||
private static string _startUpCode = "0";
|
||
private static string _autoCenterCode = "0";
|
||
private static string _filamentAdjustCode = "0";
|
||
private static bool _isInterlockActive;
|
||
private static string _watchdogStatus = "";
|
||
private static string _powerModeCode = "";
|
||
private static string _txiCode = "False";
|
||
|
||
#endregion
|
||
|
||
#region 事件通知
|
||
|
||
/// <summary>
|
||
/// 状态更新事件(电压、电流、各子系统状态变化时触发)
|
||
/// </summary>
|
||
public static event EventHandler<CometStatusData> StatusChanged;
|
||
|
||
/// <summary>
|
||
/// 射线开关状态变更事件
|
||
/// </summary>
|
||
public static event EventHandler<bool> XRayStateChanged;
|
||
|
||
/// <summary>
|
||
/// PVI 连接错误事件
|
||
/// </summary>
|
||
public static event EventHandler<string> ErrorOccurred;
|
||
|
||
/// <summary>
|
||
/// PVI 连接状态变更事件(未连接、Service已连接、变量已连接)
|
||
/// </summary>
|
||
public static event EventHandler<PviConnectionState> ConnectionStateChanged;
|
||
|
||
#endregion
|
||
|
||
#region 属性
|
||
|
||
/// <summary>
|
||
/// PVI 连接是否已建立
|
||
/// </summary>
|
||
public static bool IsConnected => _isConnected;
|
||
|
||
/// <summary>
|
||
/// PVI 变量是否已连接
|
||
/// </summary>
|
||
public static bool IsVariablesConnected => _isVariablesConnected;
|
||
|
||
/// <summary>
|
||
/// 当前 PVI 连接状态
|
||
/// </summary>
|
||
public static PviConnectionState CurrentConnectionState => _currentConnectionState;
|
||
|
||
#endregion
|
||
|
||
#region 日志方法
|
||
|
||
/// <summary>
|
||
/// 设置日志回调委托
|
||
/// </summary>
|
||
public static void SetLogger(Action<CometLogLevel, string, object[]> logger)
|
||
{
|
||
_logger = logger;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 内部日志输出辅助方法
|
||
/// 如果未注入日志回调,则静默忽略
|
||
/// </summary>
|
||
private static void Log(CometLogLevel level, string message, params object[] args)
|
||
{
|
||
_logger?.Invoke(level, message, args);
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Initialize - PVI Service → CPU 回调链式连接
|
||
|
||
/// <summary>
|
||
/// 初始化 PVI Service 和 CPU 连接
|
||
/// </summary>
|
||
public static void Initialize(string ipAddress, int port, string cpuName, int sourcePort, int stationNumber)
|
||
{
|
||
// 保存连接参数
|
||
_ipAddress = ipAddress;
|
||
_port = port;
|
||
_cpuName = cpuName;
|
||
_sourcePort = sourcePort;
|
||
_stationNumber = stationNumber;
|
||
|
||
Log(CometLogLevel.Info, $"开始初始化 Comet PVI 连接,IP={ipAddress}, Port={port}, CPU={cpuName}");
|
||
|
||
try
|
||
{
|
||
if (_service == null)
|
||
{
|
||
// 创建 PVI Service 对象并注册回调
|
||
_service = new Service("service");
|
||
_service.Connected += new PviEventHandler(Service_Connected);
|
||
_service.Error += new PviEventHandler(Service_Error);
|
||
}
|
||
_service.Connect();
|
||
|
||
Log(CometLogLevel.Info, "PVI Service.Connect() 已调用,等待回调链完成");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log(CometLogLevel.Error, "PVI 连接初始化异常:{0}", ex.Message);
|
||
ErrorOccurred?.Invoke(null, $"PVI 连接初始化异常:{ex.Message}");
|
||
throw;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// PVI Service Connected 回调:创建 CPU 对象,设置 TCP/IP 参数,连接 CPU
|
||
/// </summary>
|
||
private static void Service_Connected(object sender, PviEventArgs e)
|
||
{
|
||
Log(CometLogLevel.Info, "PVI Service 连接成功,开始创建 CPU 对象");
|
||
|
||
try
|
||
{
|
||
if (_cpu == null)
|
||
{
|
||
_cpu = new Cpu(_service, _cpuName);
|
||
_cpu.Connected += new PviEventHandler(Cpu_Connected);
|
||
_cpu.Connection.DeviceType = DeviceType.TcpIp;
|
||
_cpu.Connection.TcpIp.DestinationIpAddress = _ipAddress;
|
||
_cpu.Connection.TcpIp.DestinationPort = (short)_port;
|
||
_cpu.Connection.TcpIp.SourcePort = (short)_sourcePort;
|
||
_cpu.Connection.TcpIp.SourceStation = (byte)_stationNumber;
|
||
}
|
||
_cpu.Connect();
|
||
|
||
Log(CometLogLevel.Info, $"CPU.Connect() 已调用,目标地址:{_ipAddress}:{_port}");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log(CometLogLevel.Error, "创建 CPU 对象异常:{0}", ex.Message);
|
||
ErrorOccurred?.Invoke(null, $"创建 CPU 对象异常:{ex.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// CPU Connected 回调:确认连接成功,触发连接状态变更事件
|
||
/// </summary>
|
||
private static void Cpu_Connected(object sender, PviEventArgs e)
|
||
{
|
||
try
|
||
{
|
||
_cpu.ReadDateTime();
|
||
_isConnected = true;
|
||
Log(CometLogLevel.Info, "CPU 连接成功,PVI 回调链完成");
|
||
ConnectionStateChanged?.Invoke(null, PviConnectionState.ServiceConnected);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log(CometLogLevel.Error, "CPU 连接确认异常:{0}", ex.Message);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// PVI Service Error 回调:记录错误并触发错误事件
|
||
/// </summary>
|
||
private static void Service_Error(object sender, PviEventArgs e)
|
||
{
|
||
int errorCode = _service.ErrorCode;
|
||
if (errorCode != 0)
|
||
{
|
||
string errorText = _service.GetErrorText(errorCode);
|
||
Log(CometLogLevel.Error, $"PVI Service 错误,错误码:{errorCode},错误信息:{errorText}");
|
||
ErrorOccurred?.Invoke(null, $"PVI Service 错误[{errorCode}]:{errorText}");
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region ConnectVariables - 创建和激活所有 PVI 变量
|
||
|
||
/// <summary>
|
||
/// 创建、激活并绑定所有 PVI 变量
|
||
/// </summary>
|
||
public static void ConnectVariables()
|
||
{
|
||
Log(CometLogLevel.Info, "开始创建和连接 PVI 变量");
|
||
|
||
try
|
||
{
|
||
// 创建变量
|
||
CreateVariables();
|
||
|
||
// 激活变量并连接
|
||
ActivateVariables();
|
||
|
||
// 绑定事件处理
|
||
BindEventHandlers();
|
||
|
||
_isVariablesConnected = true;
|
||
Log(CometLogLevel.Info, "所有 PVI 变量创建、激活和事件绑定完成");
|
||
|
||
// 主动读取一次当前功率模式和 TXI 状态(ValueChanged 仅在值变化时触发)
|
||
// Actively read current power mode and TXI status (ValueChanged only fires on change)
|
||
try
|
||
{
|
||
if (_varPowerModeR?.Value != null)
|
||
{
|
||
_powerModeCode = _varPowerModeR.Value.ToString()?.Trim() ?? "";
|
||
Log(CometLogLevel.Debug, "初始功率模式原始值: '{0}'", _powerModeCode);
|
||
}
|
||
if (_varTxiR?.Value != null)
|
||
{
|
||
_txiCode = _varTxiR.Value.ToString() ?? "False";
|
||
}
|
||
}
|
||
catch (Exception readEx)
|
||
{
|
||
Log(CometLogLevel.Warn, "初始读取功率模式/TXI状态异常: {0}", readEx.Message);
|
||
}
|
||
|
||
ConnectionStateChanged?.Invoke(null, PviConnectionState.VariablesConnected);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log(CometLogLevel.Error, "PVI 变量连接异常:{0}", ex.Message);
|
||
ErrorOccurred?.Invoke(null, $"PVI 变量连接异常:{ex.Message}");
|
||
throw;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建所有 PVI Variable 对象
|
||
/// </summary>
|
||
private static void CreateVariables()
|
||
{
|
||
// 电压/电流
|
||
_varKVS = new Variable(_cpu, "PC_cmd.r32_TubeVoltage_kV");
|
||
_varKVR = new Variable(_cpu, "PLC_stat.r32_TubeVoltage_kV_ist");
|
||
_varMAS = new Variable(_cpu, "PC_cmd.r32_TubeCurrent_uA");
|
||
_varMAR = new Variable(_cpu, "PLC_stat.r32_TubeCurrent_uA_ist");
|
||
|
||
// 射线开关
|
||
_varXonS = new Variable(_cpu, "PC_cmd.xrayON");
|
||
_varXoffS = new Variable(_cpu, "PC_cmd.xrayOFF");
|
||
_varXonR = new Variable(_cpu, "PLC_stat.bo_Xray_on");
|
||
|
||
// 暖机
|
||
_varWarmUpS = new Variable(_cpu, "PC_cmd.warmUP");
|
||
_varWarmUpR = new Variable(_cpu, "PLC_stat.u32_warmup");
|
||
|
||
// 真空
|
||
_varVaconS = new Variable(_cpu, "Vacon");
|
||
_varVaconR = new Variable(_cpu, "PLC_stat.u32_vacuum");
|
||
_varVaconRV = new Variable(_cpu, "Vac.ist_mbar");
|
||
|
||
// 训机
|
||
_varStartUpS = new Variable(_cpu, "PC_cmd.startUP");
|
||
_varStartUpR = new Variable(_cpu, "PLC_stat.u32_startup");
|
||
|
||
// 自动定心
|
||
_varCurrentKVAutoCenter = new Variable(_cpu, "PC_cmd.autocentkV");
|
||
_varALLKVCenter = new Variable(_cpu, "PC_cmd.autocentALL");
|
||
_varAutoCenterR = new Variable(_cpu, "PLC_stat.u32_autocenter");
|
||
|
||
// 灯丝调整
|
||
_varFilamentAdjust = new Variable(_cpu, "PC_cmd.filamentadjust");
|
||
_varFilamentAdjustR = new Variable(_cpu, "PLC_stat.u32_filamentadjust");
|
||
|
||
// 状态监控
|
||
_varInterLockR = new Variable(_cpu, "Di_Interlock");
|
||
_varWatchingDog = new Variable(_cpu, "PLC_stat.bo_Watchdog");
|
||
_varPowerModeR = new Variable(_cpu, "PLC_stat.u32_current_modenumber");
|
||
_varPowerModeS = new Variable(_cpu, "Mode.current_mode_number");
|
||
_varTxiR = new Variable(_cpu, "PLC_stat.bo_TXI");
|
||
_varTxiOpenS = new Variable(_cpu, "PC_cmd.Ti_reg_on");
|
||
_varTxiCloseS = new Variable(_cpu, "PC_cmd.Ti_reg_off");
|
||
|
||
// 错误监控
|
||
_sysErrR = new Variable(_cpu, "Sys_error[0]");
|
||
_sysErrS = new Variable(_cpu, "Sys_errorquit");
|
||
_HSGErrR = new Variable(_cpu, "HSG_error[0]");
|
||
_HSGErrS = new Variable(_cpu, "HSG_errorquit");
|
||
_tubeErrR = new Variable(_cpu, "Tube_error[0]");
|
||
_tubeErrS = new Variable(_cpu, "Tube_errorquit");
|
||
_tubeACErrR = new Variable(_cpu, "TubeVac_error[0]");
|
||
_tubeACErrS = new Variable(_cpu, "Vac_errorquit");
|
||
|
||
Log(CometLogLevel.Info, "所有 PVI 变量对象创建完成");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 激活所有变量并调用 Connect
|
||
/// </summary>
|
||
private static void ActivateVariables()
|
||
{
|
||
Variable[] allVariables = {
|
||
_varKVS, _varKVR, _varMAS, _varMAR,
|
||
_varXonS, _varXoffS, _varXonR,
|
||
_varWarmUpS, _varWarmUpR,
|
||
_varVaconS, _varVaconR, _varVaconRV,
|
||
_varStartUpS, _varStartUpR,
|
||
_varCurrentKVAutoCenter, _varALLKVCenter, _varAutoCenterR,
|
||
_varFilamentAdjust, _varFilamentAdjustR,
|
||
_varInterLockR, _varWatchingDog,
|
||
_varPowerModeR, _varPowerModeS, _varTxiR,
|
||
_varTxiOpenS, _varTxiCloseS,
|
||
_sysErrR, _sysErrS,
|
||
_HSGErrR, _HSGErrS,
|
||
_tubeErrR, _tubeErrS,
|
||
_tubeACErrR, _tubeACErrS
|
||
};
|
||
|
||
foreach (var variable in allVariables)
|
||
{
|
||
variable.Active = true;
|
||
variable.Connect();
|
||
}
|
||
|
||
Log(CometLogLevel.Info, "所有 PVI 变量已激活并连接");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 为所有反馈类变量绑定 ValueChanged 事件处理程序
|
||
/// </summary>
|
||
private static void BindEventHandlers()
|
||
{
|
||
// 电压/电流反馈
|
||
_varKVR.ValueChanged += new VariableEventHandler(VarKVR_ValueChanged);
|
||
_varMAR.ValueChanged += new VariableEventHandler(VarMAR_ValueChanged);
|
||
|
||
// 电压/电流设定值反馈(用于同步滑块显示)| Set value feedback (for slider sync)
|
||
_varKVS.ValueChanged += new VariableEventHandler(VarKVS_ValueChanged);
|
||
_varMAS.ValueChanged += new VariableEventHandler(VarMAS_ValueChanged);
|
||
|
||
// 射线开关反馈
|
||
_varXonR.ValueChanged += new VariableEventHandler(VarXonR_ValueChanged);
|
||
|
||
// 暖机反馈
|
||
_varWarmUpR.ValueChanged += new VariableEventHandler(VarWarmUpR_ValueChanged);
|
||
|
||
// 真空反馈
|
||
_varVaconR.ValueChanged += new VariableEventHandler(VarVaconR_ValueChanged);
|
||
|
||
// 训机反馈
|
||
_varStartUpR.ValueChanged += new VariableEventHandler(VarStartUpR_ValueChanged);
|
||
|
||
// 自动定心反馈
|
||
_varAutoCenterR.ValueChanged += new VariableEventHandler(VarAutoCenterR_ValueChanged);
|
||
|
||
// 灯丝调整反馈
|
||
_varFilamentAdjustR.ValueChanged += new VariableEventHandler(VarFilamentAdjustR_ValueChanged);
|
||
|
||
// 连锁状态
|
||
_varInterLockR.ValueChanged += new VariableEventHandler(VarInterLockR_ValueChanged);
|
||
|
||
// 看门狗
|
||
_varWatchingDog.ValueChanged += new VariableEventHandler(VarWatchingDog_ValueChanged);
|
||
|
||
// 功率模式
|
||
_varPowerModeR.ValueChanged += new VariableEventHandler(VarPowerModeR_ValueChanged);
|
||
|
||
// TXI
|
||
_varTxiR.ValueChanged += new VariableEventHandler(VarTxiR_ValueChanged);
|
||
|
||
Log(CometLogLevel.Info, "所有反馈类变量 ValueChanged 事件已绑定");
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region ValueChanged 回调处理方法
|
||
|
||
private static void VarKVR_ValueChanged(object sender, VariableEventArgs e)
|
||
{
|
||
Variable v = (Variable)sender;
|
||
_actualVoltage = (float)Math.Round(double.Parse(v.Value.ToString()), 2);
|
||
PublishStatusUpdate();
|
||
}
|
||
|
||
private static void VarMAR_ValueChanged(object sender, VariableEventArgs e)
|
||
{
|
||
Variable v = (Variable)sender;
|
||
_actualCurrent = (float)Math.Round(double.Parse(v.Value.ToString()), 2);
|
||
PublishStatusUpdate();
|
||
}
|
||
|
||
private static void VarKVS_ValueChanged(object sender, VariableEventArgs e)
|
||
{
|
||
Variable v = (Variable)sender;
|
||
_setVoltage = (float)Math.Round(double.Parse(v.Value.ToString()), 2);
|
||
PublishStatusUpdate();
|
||
}
|
||
|
||
private static void VarMAS_ValueChanged(object sender, VariableEventArgs e)
|
||
{
|
||
Variable v = (Variable)sender;
|
||
_setCurrent = (float)Math.Round(double.Parse(v.Value.ToString()), 2);
|
||
PublishStatusUpdate();
|
||
}
|
||
|
||
private static void VarXonR_ValueChanged(object sender, VariableEventArgs e)
|
||
{
|
||
Variable v = (Variable)sender;
|
||
_isXRayOn = bool.Parse(v.Value.ToString());
|
||
XRayStateChanged?.Invoke(null, _isXRayOn);
|
||
PublishStatusUpdate();
|
||
}
|
||
|
||
private static void VarWarmUpR_ValueChanged(object sender, VariableEventArgs e)
|
||
{
|
||
Variable v = (Variable)sender;
|
||
_warmUpCode = v.Value?.ToString() ?? "0";
|
||
PublishStatusUpdate();
|
||
}
|
||
|
||
private static void VarVaconR_ValueChanged(object sender, VariableEventArgs e)
|
||
{
|
||
Variable v = (Variable)sender;
|
||
_vacuumCode = v.Value?.ToString() ?? "0";
|
||
PublishStatusUpdate();
|
||
}
|
||
|
||
private static void VarStartUpR_ValueChanged(object sender, VariableEventArgs e)
|
||
{
|
||
Variable v = (Variable)sender;
|
||
_startUpCode = v.Value?.ToString() ?? "0";
|
||
PublishStatusUpdate();
|
||
}
|
||
|
||
private static void VarAutoCenterR_ValueChanged(object sender, VariableEventArgs e)
|
||
{
|
||
Variable v = (Variable)sender;
|
||
_autoCenterCode = v.Value?.ToString() ?? "0";
|
||
PublishStatusUpdate();
|
||
}
|
||
|
||
private static void VarFilamentAdjustR_ValueChanged(object sender, VariableEventArgs e)
|
||
{
|
||
Variable v = (Variable)sender;
|
||
_filamentAdjustCode = v.Value?.ToString() ?? "0";
|
||
PublishStatusUpdate();
|
||
}
|
||
|
||
private static void VarInterLockR_ValueChanged(object sender, VariableEventArgs e)
|
||
{
|
||
Variable v = (Variable)sender;
|
||
string val = v.Value.ToString();
|
||
_isInterlockActive = val == "True";
|
||
PublishStatusUpdate();
|
||
}
|
||
|
||
private static void VarWatchingDog_ValueChanged(object sender, VariableEventArgs e)
|
||
{
|
||
Variable v = (Variable)sender;
|
||
_watchdogStatus = v.Value.ToString();
|
||
// 注意:看门狗不触发 PublishStatusUpdate
|
||
}
|
||
|
||
private static void VarPowerModeR_ValueChanged(object sender, VariableEventArgs e)
|
||
{
|
||
Variable v = (Variable)sender;
|
||
_powerModeCode = v.Value?.ToString()?.Trim() ?? "";
|
||
Log(CometLogLevel.Debug, "功率模式原始值: '{0}'", _powerModeCode);
|
||
PublishStatusUpdate();
|
||
}
|
||
|
||
private static void VarTxiR_ValueChanged(object sender, VariableEventArgs e)
|
||
{
|
||
Variable v = (Variable)sender;
|
||
_txiCode = v.Value?.ToString() ?? "False";
|
||
PublishStatusUpdate();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 构建状态数据并触发 StatusChanged 事件
|
||
/// </summary>
|
||
private static void PublishStatusUpdate()
|
||
{
|
||
StatusChanged?.Invoke(null, BuildStatusData());
|
||
}
|
||
|
||
/// <summary>
|
||
/// 构建当前状态数据快照
|
||
/// </summary>
|
||
private static CometStatusData BuildStatusData()
|
||
{
|
||
return new CometStatusData
|
||
{
|
||
SetVoltage = _setVoltage,
|
||
ActualVoltage = _actualVoltage,
|
||
SetCurrent = _setCurrent,
|
||
ActualCurrent = _actualCurrent,
|
||
IsXRayOn = _isXRayOn,
|
||
WarmUpStatus = _warmUpCode,
|
||
VacuumStatus = _vacuumCode,
|
||
StartUpStatus = _startUpCode,
|
||
AutoCenterStatus = _autoCenterCode,
|
||
FilamentAdjustStatus = _filamentAdjustCode,
|
||
IsInterlockActive = _isInterlockActive,
|
||
WatchdogStatus = _watchdogStatus,
|
||
PowerMode = _powerModeCode,
|
||
TxiStatus = _txiCode
|
||
};
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 状态码映射方法
|
||
|
||
/// <summary>
|
||
/// 暖机状态码映射
|
||
/// </summary>
|
||
internal static string MapWarmUpStatus(string code)
|
||
{
|
||
switch (code)
|
||
{
|
||
case "0": return "初始状态";
|
||
case "1": return "暖机中";
|
||
case "2": return "暖机完成到最大电压";
|
||
case "3": return "暖机因故障失败";
|
||
case "33": return "需要暖机";
|
||
default: return "未知状态";
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 真空状态码映射
|
||
/// </summary>
|
||
internal static string MapVacuumStatus(string code)
|
||
{
|
||
switch (code)
|
||
{
|
||
case "0": return "初始状态";
|
||
case "1": return "抽真空中";
|
||
case "2": return "真空准备好";
|
||
case "22": return "真空值<1e-5mbar";
|
||
case "30": return "真空泵未使能";
|
||
case "40": return "真空泵通风能";
|
||
default: return "未知状态";
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 训机状态码映射
|
||
/// </summary>
|
||
internal static string MapStartUpStatus(string code)
|
||
{
|
||
switch (code)
|
||
{
|
||
case "0": return "初始状态";
|
||
case "1": return "训机中";
|
||
case "2": return "训机完成";
|
||
case "3": return "训机因故障失败";
|
||
default: return "未知状态";
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 自动定心状态码映射
|
||
/// </summary>
|
||
internal static string MapAutoCenterStatus(string code)
|
||
{
|
||
switch (code)
|
||
{
|
||
case "0": return "初始状态";
|
||
case "1": return "自动定心中";
|
||
case "2": return "自动定心完成";
|
||
case "3": return "定心因故障失败";
|
||
default: return "未知状态";
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 灯丝调整状态码映射
|
||
/// </summary>
|
||
internal static string MapFilamentAdjustStatus(string code)
|
||
{
|
||
switch (code)
|
||
{
|
||
case "0": return "初始状态";
|
||
case "1": return "灯丝校准中";
|
||
case "2": return "灯丝校准完成";
|
||
case "3": return "灯丝校准因故障失败";
|
||
case "33": return "需要灯丝校准";
|
||
default: return "未知状态";
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 功率模式映射
|
||
/// </summary>
|
||
internal static string MapPowerMode(string value)
|
||
{
|
||
// PVI 变量可能返回带空格或小数的值,统一处理 | PVI variable may return value with spaces or decimals
|
||
var trimmed = (value ?? "").Trim();
|
||
|
||
// 尝试解析为数字后再比较 | Try parsing as number before comparing
|
||
if (int.TryParse(trimmed, out var intVal))
|
||
{
|
||
switch (intVal)
|
||
{
|
||
case 1: return "Micro Focus";
|
||
case 2: return "High Power";
|
||
}
|
||
}
|
||
else if (double.TryParse(trimmed, out var dblVal))
|
||
{
|
||
switch ((int)dblVal)
|
||
{
|
||
case 1: return "Micro Focus";
|
||
case 2: return "High Power";
|
||
}
|
||
}
|
||
|
||
return $"Unknown({trimmed})";
|
||
}
|
||
|
||
/// <summary>
|
||
/// TXI 状态映射
|
||
/// </summary>
|
||
internal static string MapTxiStatus(string value)
|
||
{
|
||
switch (value)
|
||
{
|
||
case "True": return "TXI is on";
|
||
case "False": return "TXI is off";
|
||
default: return "未知状态";
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 射线控制和参数设置方法
|
||
|
||
/// <summary>
|
||
/// 开启高压
|
||
/// </summary>
|
||
public static void TurnOn()
|
||
{
|
||
Log(CometLogLevel.Info, "执行 TurnOn 操作");
|
||
try
|
||
{
|
||
_varXonS.Value = "True";
|
||
_varXonS.WriteValue();
|
||
Log(CometLogLevel.Info, "TurnOn 操作完成");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log(CometLogLevel.Error, "TurnOn 操作异常:{0}", ex.Message);
|
||
ErrorOccurred?.Invoke(null, $"TurnOn 操作异常:{ex.Message}");
|
||
throw;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 关闭高压
|
||
/// </summary>
|
||
public static void TurnOff()
|
||
{
|
||
Log(CometLogLevel.Info, "执行 TurnOff 操作");
|
||
try
|
||
{
|
||
_varXoffS.Value = "True";
|
||
_varXoffS.WriteValue();
|
||
Log(CometLogLevel.Info, "TurnOff 操作完成");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log(CometLogLevel.Error, "TurnOff 操作异常:{0}", ex.Message);
|
||
ErrorOccurred?.Invoke(null, $"TurnOff 操作异常:{ex.Message}");
|
||
throw;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置电压(kV)
|
||
/// </summary>
|
||
public static void SetVoltage(float voltage)
|
||
{
|
||
Log(CometLogLevel.Info, "执行 SetVoltage 操作,目标电压:{0}kV", voltage);
|
||
try
|
||
{
|
||
_varKVS.Value = voltage.ToString();
|
||
_varKVS.WriteValue();
|
||
_setVoltage = voltage;
|
||
Log(CometLogLevel.Info, "SetVoltage 操作完成,电压:{0}kV", voltage);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log(CometLogLevel.Error, "SetVoltage 操作异常:{0}", ex.Message);
|
||
ErrorOccurred?.Invoke(null, $"SetVoltage 操作异常:{ex.Message}");
|
||
throw;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置电流(μA)
|
||
/// </summary>
|
||
public static void SetCurrent(float current)
|
||
{
|
||
Log(CometLogLevel.Info, "执行 SetCurrent 操作,目标电流:{0}μA", current);
|
||
try
|
||
{
|
||
_varMAS.Value = current.ToString();
|
||
_varMAS.WriteValue();
|
||
_setCurrent = current;
|
||
Log(CometLogLevel.Info, "SetCurrent 操作完成,电流:{0}μA", current);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log(CometLogLevel.Error, "SetCurrent 操作异常:{0}", ex.Message);
|
||
ErrorOccurred?.Invoke(null, $"SetCurrent 操作异常:{ex.Message}");
|
||
throw;
|
||
}
|
||
}
|
||
|
||
public static void SetWatchDog()
|
||
{
|
||
if (_cpu != null)
|
||
{
|
||
if (_cpu.IsConnected)
|
||
{
|
||
if (_isVariablesConnected)
|
||
{
|
||
_varWatchingDog.Value = "0";
|
||
_varWatchingDog.WriteValue();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// TXI 开启
|
||
/// </summary>
|
||
public static void TxiOn()
|
||
{
|
||
Log(CometLogLevel.Info, "执行 TXI ON 操作");
|
||
try
|
||
{
|
||
_varTxiOpenS.Value = "True";
|
||
_varTxiOpenS.WriteValue();
|
||
Log(CometLogLevel.Info, "TXI ON 操作完成");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log(CometLogLevel.Error, "TXI ON 操作异常:{0}", ex.Message);
|
||
ErrorOccurred?.Invoke(null, $"TXI ON 操作异常:{ex.Message}");
|
||
throw;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// TXI 关闭
|
||
/// </summary>
|
||
public static void TxiOff()
|
||
{
|
||
Log(CometLogLevel.Info, "执行 TXI OFF 操作");
|
||
try
|
||
{
|
||
_varTxiCloseS.Value = "True";
|
||
_varTxiCloseS.WriteValue();
|
||
Log(CometLogLevel.Info, "TXI OFF 操作完成");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log(CometLogLevel.Error, "TXI OFF 操作异常:{0}", ex.Message);
|
||
ErrorOccurred?.Invoke(null, $"TXI OFF 操作异常:{ex.Message}");
|
||
throw;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 暖机设置
|
||
/// </summary>
|
||
public static void WarmUp()
|
||
{
|
||
Log(CometLogLevel.Info, "执行暖机设置操作");
|
||
try
|
||
{
|
||
_varWarmUpS.Value = "True";
|
||
_varWarmUpS.WriteValue();
|
||
Log(CometLogLevel.Info, "暖机设置操作完成");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log(CometLogLevel.Error, "暖机设置操作异常:{0}", ex.Message);
|
||
ErrorOccurred?.Invoke(null, $"暖机设置操作异常:{ex.Message}");
|
||
throw;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 训机设置
|
||
/// </summary>
|
||
public static void Training()
|
||
{
|
||
Log(CometLogLevel.Info, "执行训机设置操作");
|
||
try
|
||
{
|
||
_varStartUpS.Value = "True";
|
||
_varStartUpS.WriteValue();
|
||
Log(CometLogLevel.Info, "训机设置操作完成");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log(CometLogLevel.Error, "训机设置操作异常:{0}", ex.Message);
|
||
ErrorOccurred?.Invoke(null, $"训机设置操作异常:{ex.Message}");
|
||
throw;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 灯丝校准
|
||
/// </summary>
|
||
public static void FilamentCalibration()
|
||
{
|
||
Log(CometLogLevel.Info, "执行灯丝校准操作");
|
||
try
|
||
{
|
||
_varFilamentAdjust.Value = "True";
|
||
_varFilamentAdjust.WriteValue();
|
||
Log(CometLogLevel.Info, "灯丝校准操作完成");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log(CometLogLevel.Error, "灯丝校准操作异常:{0}", ex.Message);
|
||
ErrorOccurred?.Invoke(null, $"灯丝校准操作异常:{ex.Message}");
|
||
throw;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 全部电压自动定心
|
||
/// </summary>
|
||
public static void AutoCenter()
|
||
{
|
||
Log(CometLogLevel.Info, "执行全部电压自动定心操作");
|
||
try
|
||
{
|
||
_varALLKVCenter.Value = "True";
|
||
_varALLKVCenter.WriteValue();
|
||
Log(CometLogLevel.Info, "全部电压自动定心操作完成");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log(CometLogLevel.Error, "全部电压自动定心操作异常:{0}", ex.Message);
|
||
ErrorOccurred?.Invoke(null, $"全部电压自动定心操作异常:{ex.Message}");
|
||
throw;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置功率模式
|
||
/// </summary>
|
||
/// <param name="mode">功率模式值:1=Micro Focus,2=High Power</param>
|
||
public static void SetPowerMode(int mode)
|
||
{
|
||
Log(CometLogLevel.Info, "执行设置功率模式操作,Mode={0}", mode);
|
||
try
|
||
{
|
||
_varPowerModeS.Value = mode.ToString();
|
||
_varPowerModeS.WriteValue();
|
||
Log(CometLogLevel.Info, "设置功率模式操作完成,Mode={0}", mode);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log(CometLogLevel.Error, "设置功率模式操作异常:{0}", ex.Message);
|
||
ErrorOccurred?.Invoke(null, $"设置功率模式操作异常:{ex.Message}");
|
||
throw;
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 状态读取方法
|
||
|
||
/// <summary>
|
||
/// 读取实际电压反馈值
|
||
/// </summary>
|
||
public static float ReadVoltage()
|
||
{
|
||
return _actualVoltage;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 读取实际电流反馈值
|
||
/// </summary>
|
||
public static float ReadCurrent()
|
||
{
|
||
return _actualCurrent;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 读取完整系统状态
|
||
/// </summary>
|
||
public static CometStatusData ReadSystemStatus()
|
||
{
|
||
return BuildStatusData();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 读取连接状态
|
||
/// </summary>
|
||
/// <returns>true=已连接,false=未连接</returns>
|
||
public static bool ReadRaySourceConnectStatus()
|
||
{
|
||
PviConnectionState newState = PviConnectionState.Disconnected;
|
||
bool result = false;
|
||
|
||
if (_cpu != null)
|
||
{
|
||
if (_cpu.IsConnected && _isVariablesConnected)
|
||
{
|
||
newState = PviConnectionState.RaySourceConnected;
|
||
result = true;
|
||
}
|
||
else if (_isVariablesConnected)
|
||
{
|
||
newState = PviConnectionState.VariablesConnected;
|
||
}
|
||
else if (_isConnected)
|
||
{
|
||
newState = PviConnectionState.ServiceConnected;
|
||
}
|
||
}
|
||
|
||
// 仅在状态变化时触发事件
|
||
if (newState != _currentConnectionState)
|
||
{
|
||
_currentConnectionState = newState;
|
||
ConnectionStateChanged?.Invoke(null, _currentConnectionState);
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 读取错误状态
|
||
/// </summary>
|
||
public static CometErrorData ReadErrors()
|
||
{
|
||
return new CometErrorData
|
||
{
|
||
SystemError = _sysErrR?.Value?.ToString() ?? "",
|
||
HSGError = _HSGErrR?.Value?.ToString() ?? "",
|
||
TubeError = _tubeErrR?.Value?.ToString() ?? "",
|
||
TubeVacError = _tubeACErrR?.Value?.ToString() ?? ""
|
||
};
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Disconnect 和 Dispose 资源释放
|
||
|
||
/// <summary>
|
||
/// 断开所有 PVI 变量并释放资源
|
||
/// </summary>
|
||
public static void Disconnect()
|
||
{
|
||
Log(CometLogLevel.Info, "执行 Disconnect 操作,断开所有 PVI 变量");
|
||
|
||
try
|
||
{
|
||
// 如果射线仍处于开启状态,先关闭高压再断开连接
|
||
if (_isXRayOn)
|
||
{
|
||
Log(CometLogLevel.Warn, "检测到射线仍处于开启状态,先执行 TurnOff 关闭高压");
|
||
TurnOff();
|
||
}
|
||
|
||
Variable[] allVariables = {
|
||
_varKVS, _varKVR, _varMAS, _varMAR,
|
||
_varXonS, _varXoffS, _varXonR,
|
||
_varWarmUpS, _varWarmUpR,
|
||
_varVaconS, _varVaconR, _varVaconRV,
|
||
_varStartUpS, _varStartUpR,
|
||
_varCurrentKVAutoCenter, _varALLKVCenter, _varAutoCenterR,
|
||
_varFilamentAdjust, _varFilamentAdjustR,
|
||
_varInterLockR, _varWatchingDog,
|
||
_varPowerModeR, _varPowerModeS, _varTxiR,
|
||
_varTxiOpenS, _varTxiCloseS,
|
||
_sysErrR, _sysErrS,
|
||
_HSGErrR, _HSGErrS,
|
||
_tubeErrR, _tubeErrS,
|
||
_tubeACErrR, _tubeACErrS
|
||
};
|
||
|
||
foreach (var variable in allVariables)
|
||
{
|
||
if (variable != null)
|
||
{
|
||
variable.Active = false;
|
||
variable.Disconnected += new PviEventHandler(Variable_Disconnected);
|
||
variable.Disconnect();
|
||
}
|
||
}
|
||
|
||
_isConnected = false;
|
||
_isVariablesConnected = false;
|
||
ConnectionStateChanged?.Invoke(null, PviConnectionState.Disconnected);
|
||
|
||
Log(CometLogLevel.Info, "Disconnect 操作完成,所有变量已断开");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log(CometLogLevel.Warn, "Disconnect 过程中发生异常:{0}", ex.Message);
|
||
ErrorOccurred?.Invoke(null, $"Disconnect 异常:{ex.Message}");
|
||
_isConnected = false;
|
||
_isVariablesConnected = false;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 变量断开回调:释放变量资源
|
||
/// </summary>
|
||
private static void Variable_Disconnected(object sender, PviEventArgs e)
|
||
{
|
||
try
|
||
{
|
||
var variable = sender as Variable;
|
||
variable?.Dispose();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log(CometLogLevel.Warn, "变量 Dispose 异常:{0}", ex.Message);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 释放所有资源
|
||
/// </summary>
|
||
public static void Dispose()
|
||
{
|
||
Disconnect();
|
||
|
||
// 释放 CPU
|
||
try { _cpu?.Dispose(); } catch { }
|
||
|
||
// 释放 Service
|
||
try { _service?.Dispose(); } catch { }
|
||
}
|
||
|
||
#endregion
|
||
}
|
||
}
|