Files
XplorePlane/XP.Hardware.RaySource/ViewModels/RaySourceOperateViewModel.cs
T

772 lines
32 KiB
C#
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.
using Prism.Commands;
using Prism.Events;
using Prism.Mvvm;
using System;
using System.Threading.Tasks;
using System.Windows;
using XP.Common.Helpers;
using XP.Common.Localization.Interfaces;
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 XP.Hardware.RaySource.ViewModels
{
/// <summary>
/// 射线源操作视图模型 | X-Ray Source Operate ViewModel
/// 负责射线源开关控制、电压电流调节、状态监控 | Responsible for X-ray on/off control, voltage/current adjustment, status monitoring
/// </summary>
public class RaySourceOperateViewModel : BindableBase, IDisposable
{
#region | Fields
private readonly IRaySourceService _raySourceService;
private readonly IEventAggregator _eventAggregator;
private readonly RaySourceConfig _config;
private readonly ILoggerService _logger;
private readonly ILocalizationService _localizationService;
private bool _isDisposed = false;
private bool _isOperating = false;
private bool _isVariablesConnected = false;
private bool _autoInitialized = false;
private Views.RaySourceConfigWindow _configWindow;
/// <summary>
/// 标记当前是否正在从设备反馈更新值(防止 code-behind 误触发写入)
/// Flag indicating whether values are being updated from device feedback (prevents code-behind from triggering writes)
/// </summary>
public bool IsUpdatingFromDevice { get; private set; } = false;
#endregion
#region | Status Properties
private RaySourceStatus _raySourceStatus = RaySourceStatus.Unavailable;
/// <summary>
/// 射线源状态(不可用/关闭/开启)| X-ray source status (Unavailable/Closed/Opened)
/// </summary>
public RaySourceStatus RaySourceStatus
{
get => _raySourceStatus;
set
{
if (SetProperty(ref _raySourceStatus, value))
{
RaisePropertyChanged(nameof(StatusText));
RaisePropertyChanged(nameof(IsSlidersEnabled));
TurnOnCommand?.RaiseCanExecuteChanged();
TurnOffCommand?.RaiseCanExecuteChanged();
}
}
}
/// <summary>
/// 状态文本(绑定到腰圆内的文字)| Status text (bound to capsule text)
/// </summary>
public string StatusText
{
get
{
return RaySourceStatus switch
{
RaySourceStatus.Unavailable => $"{_localizationService.GetString("RaySource_StatusUnavailable")}",
RaySourceStatus.Closed => _localizationService.GetString("RaySource_StatusClosed"),
RaySourceStatus.Opened => _localizationService.GetString("RaySource_StatusOpened"),
_ => _localizationService.GetString("RaySource_StatusUnavailable")
};
}
}
/// <summary>
/// 滑块是否启用(仅服务已初始化时可调节)| Sliders enabled (only when service is initialized)
/// </summary>
public bool IsSlidersEnabled => _raySourceService.IsInitialized && _isVariablesConnected;
/// <summary>
/// PVI 变量是否已连接 | Whether PVI variables are connected
/// </summary>
public bool IsVariablesConnected
{
get => _isVariablesConnected;
private set
{
if (SetProperty(ref _isVariablesConnected, value))
{
RaisePropertyChanged(nameof(IsSlidersEnabled));
TurnOnCommand?.RaiseCanExecuteChanged();
TurnOffCommand?.RaiseCanExecuteChanged();
}
}
}
private bool _isInterlockActive;
/// <summary>
/// 连锁是否激活 | Whether interlock is active
/// </summary>
public bool IsInterlockActive
{
get => _isInterlockActive;
private set
{
if (SetProperty(ref _isInterlockActive, value))
{
TurnOnCommand?.RaiseCanExecuteChanged();
}
}
}
#endregion
#region | Voltage Properties
private double _voltageMin;
/// <summary>
/// 电压最小值(kV| Voltage minimum (kV)
/// </summary>
public double VoltageMin
{
get => _voltageMin;
set => SetProperty(ref _voltageMin, value);
}
private double _voltageMax;
/// <summary>
/// 电压最大值(kV| Voltage maximum (kV)
/// </summary>
public double VoltageMax
{
get => _voltageMax;
set => SetProperty(ref _voltageMax, value);
}
private double _voltageValue;
/// <summary>
/// 电压滑块值(kV),仅更新UI显示,不自动写入硬件 | Voltage slider value (kV), UI display only, no auto write to hardware
/// </summary>
public double VoltageValue
{
get => _voltageValue;
set => SetProperty(ref _voltageValue, Math.Round(value, 0));
}
private double _voltageActual;
/// <summary>
/// 电压实际值(kV| Voltage actual value (kV)
/// </summary>
public double VoltageActual
{
get => _voltageActual;
set => SetProperty(ref _voltageActual, value);
}
/// <summary>
/// 电压实际值显示文本 | Voltage actual value display text
/// </summary>
public string VoltageActualText => string.Format(_localizationService.GetString("RaySource_ActualValueLabel"), VoltageActual.ToString("F1"));
#endregion
#region | Current Properties
private double _currentMin;
/// <summary>
/// 电流最小值(μA| Current minimum (μA)
/// </summary>
public double CurrentMin
{
get => _currentMin;
set => SetProperty(ref _currentMin, value);
}
private double _currentMax;
/// <summary>
/// 电流最大值(μA| Current maximum (μA)
/// </summary>
public double CurrentMax
{
get => _currentMax;
set => SetProperty(ref _currentMax, value);
}
private double _currentValue;
/// <summary>
/// 电流滑块值(μA),仅更新UI显示,不自动写入硬件 | Current slider value (μA), UI display only, no auto write to hardware
/// </summary>
public double CurrentValue
{
get => _currentValue;
set => SetProperty(ref _currentValue, Math.Round(value, 0));
}
private double _currentActual;
/// <summary>
/// 电流实际值(μA| Current actual value (μA)
/// </summary>
public double CurrentActual
{
get => _currentActual;
set => SetProperty(ref _currentActual, value);
}
/// <summary>
/// 电流实际值显示文本 | Current actual value display text
/// </summary>
public string CurrentActualText => string.Format(_localizationService.GetString("RaySource_ActualValueLabel"), CurrentActual.ToString("F1"));
#endregion
#region | Commands
/// <summary>
/// 开启射线源命令 | Turn on X-ray command
/// </summary>
public DelegateCommand TurnOnCommand { get; }
/// <summary>
/// 关闭射线源命令 | Turn off X-ray command
/// </summary>
public DelegateCommand TurnOffCommand { get; }
/// <summary>
/// 提交电压值命令(滑块松手/输入框失焦时触发)| Apply voltage command (triggered on slider drag complete / input lost focus)
/// </summary>
public DelegateCommand ApplyVoltageCommand { get; }
/// <summary>
/// 提交电流值命令(滑块松手/输入框失焦时触发)| Apply current command (triggered on slider drag complete / input lost focus)
/// </summary>
public DelegateCommand ApplyCurrentCommand { get; }
/// <summary>
/// 设置命令(预留接口)| Settings command (reserved interface)
/// </summary>
public DelegateCommand SettingsCommand { get; }
/// <summary>
/// 配置命令(打开射线源配置窗口)| Config command (open ray source config window)
/// </summary>
public DelegateCommand ConfigCommand { get; }
#endregion
#region | Constructor
/// <summary>
/// 构造函数 | Constructor
/// </summary>
public RaySourceOperateViewModel(
IRaySourceService raySourceService,
IEventAggregator eventAggregator,
RaySourceConfig config,
ILoggerService logger,
ILocalizationService localizationService)
{
_raySourceService = raySourceService ?? throw new ArgumentNullException(nameof(raySourceService));
_eventAggregator = eventAggregator ?? throw new ArgumentNullException(nameof(eventAggregator));
_config = config ?? throw new ArgumentNullException(nameof(config));
_logger = (logger ?? throw new ArgumentNullException(nameof(logger))).ForModule("RaySource.ViewModel");
_localizationService = localizationService ?? throw new ArgumentNullException(nameof(localizationService));
_logger.Info("射线源操作视图模型已创建 | X-ray source operate view model created");
// 初始化极值 | Initialize min/max values
VoltageMin = _config.MinVoltage;
VoltageMax = _config.MaxVoltage;
CurrentMin = _config.MinCurrent;
CurrentMax = _config.MaxCurrent;
// 初始化滑块默认值 | Initialize slider default values
VoltageValue = _config.MinVoltage; //中间值:(_config.MinVoltage + _config.MaxVoltage) / 2;
CurrentValue = _config.MinCurrent; //中间值:(_config.MinCurrent + _config.MaxCurrent) / 2;
// 初始化命令 | Initialize commands
TurnOnCommand = new DelegateCommand(ExecuteTurnOn, CanExecuteTurnOn);
TurnOffCommand = new DelegateCommand(ExecuteTurnOff, CanExecuteTurnOff);
ApplyVoltageCommand = new DelegateCommand(ApplyVoltage);
ApplyCurrentCommand = new DelegateCommand(ApplyCurrent);
SettingsCommand = new DelegateCommand(ExecuteSettings, CanExecuteSettings);
ConfigCommand = new DelegateCommand(ExecuteConfig);
// 订阅事件 | Subscribe to events
SubscribeEvents();
// 初始化状态 | Initialize status
UpdateStatusFromService();
}
#endregion
#region | Event Subscription
/// <summary>
/// 订阅事件 | Subscribe to events
/// </summary>
private void SubscribeEvents()
{
// 订阅射线源状态变更事件(三态)| Subscribe to ray source status changed event (tri-state)
_eventAggregator.GetEvent<RaySourceStatusChangedEvent>().Subscribe(OnRaySourceStatusChanged, ThreadOption.UIThread);
// 订阅状态更新事件 | Subscribe to status updated event
_eventAggregator.GetEvent<StatusUpdatedEvent>().Subscribe(OnStatusUpdated, ThreadOption.UIThread);
// 订阅错误事件 | Subscribe to error event
_eventAggregator.GetEvent<ErrorOccurredEvent>().Subscribe(OnErrorOccurred, ThreadOption.UIThread);
// 订阅操作结果事件 | Subscribe to operation result event
_eventAggregator.GetEvent<OperationResultEvent>().Subscribe(OnOperationResult, ThreadOption.UIThread);
// 订阅变量连接状态变更事件 | Subscribe to variables connected event
_eventAggregator.GetEvent<VariablesConnectedEvent>().Subscribe(OnVariablesConnectedChanged, ThreadOption.UIThread);
}
/// <summary>
/// 射线源状态变更事件处理(三态)| Ray source status changed event handler (tri-state)
/// </summary>
private void OnRaySourceStatusChanged(RaySourceStatus newStatus)
{
var previousStatus = RaySourceStatus;
RaySourceStatus = newStatus;
RaisePropertyChanged(nameof(IsSlidersEnabled));
// 连接恢复处理:从不可用变为已连接,主动读取最新状态刷新UI | Connection restored: from unavailable to connected, actively read latest status to refresh UI
if (previousStatus == RaySourceStatus.Unavailable &&
(newStatus == RaySourceStatus.Opened || newStatus == RaySourceStatus.Closed))
{
_logger.Info("射线源连接已建立 | Ray Source Connected");
}
// 异常断联处理:从已连接状态变为不可用 | Handle unexpected disconnection: from connected to unavailable
if (newStatus == RaySourceStatus.Unavailable &&
(previousStatus == RaySourceStatus.Opened || previousStatus == RaySourceStatus.Closed))
{
// 断联时重置变量连接状态 | Reset variable connection state on disconnection
IsVariablesConnected = false;
_logger.Warn("ViewModel 检测到连接丢失(状态变为 Unavailable| ViewModel detected connection lost (status changed to Unavailable)");
//MessageBox.Show("射线源连接丢失,请检查设备连接后重新初始化。", "连接丢失", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
/// <summary>
/// 状态更新事件处理 | Status updated event handler
/// 仅在实际值真正变化时更新滑块/输入框,避免无意义赋值触发事件链
/// Only update slider/input when actual value truly changed, avoiding unnecessary assignment triggering event chain
/// </summary>
private void OnStatusUpdated(SystemStatusData statusData)
{
if (statusData == null) return;
IsUpdatingFromDevice = true;
try
{
// 电压实际值变化时,仅更新实际值标签显示 | When actual voltage changes, only update actual value label
if (Math.Abs(statusData.ActualVoltage - VoltageActual) > 0.01)
{
VoltageActual = statusData.ActualVoltage;
RaisePropertyChanged(nameof(VoltageActualText));
}
// 电流实际值变化时,仅更新实际值标签显示 | When actual current changes, only update actual value label
if (Math.Abs(statusData.ActualCurrent - CurrentActual) > 0.01)
{
CurrentActual = statusData.ActualCurrent;
RaisePropertyChanged(nameof(CurrentActualText));
}
// 设定电压反馈同步到滑块(仅设备反馈时更新,人工操作时 IsUpdatingFromDevice=false 不会进入此处)
// Sync set voltage feedback to slider (only during device feedback, not during manual operation)
if (statusData.SetVoltage >= _config.MinVoltage && Math.Abs(statusData.SetVoltage - VoltageValue) > 0.5)
{
VoltageValue = Math.Round(statusData.SetVoltage, 0);
}
// 设定电流反馈同步到滑块 | Sync set current feedback to slider
if (statusData.SetCurrent >= _config.MinCurrent && Math.Abs(statusData.SetCurrent - CurrentValue) > 0.5)
{
CurrentValue = Math.Round(statusData.SetCurrent, 0);
}
// 使用服务层的权威状态 | Use authoritative status from service layer
RaySourceStatus = _raySourceService.CurrentStatus;
// 同步连锁状态 | Sync interlock status
IsInterlockActive = statusData.IsInterlockActive;
}
finally
{
IsUpdatingFromDevice = false;
}
}
/// <summary>
/// 错误事件处理 | Error event handler
/// </summary>
private void OnErrorOccurred(string errorMessage)
{
// 显示错误消息 | Show error message
MessageBox.Show(errorMessage, "错误", MessageBoxButton.OK, MessageBoxImage.Error);
}
/// <summary>
/// 操作结果事件处理 | Operation result event handler
/// </summary>
private void OnOperationResult(OperationResultData resultData)
{
if (resultData == null) return;
if (!resultData.IsSuccess)
{
// 操作失败时显示消息 | Show message when operation fails
MessageBox.Show(resultData.Message, "操作失败", MessageBoxButton.OK, MessageBoxImage.Warning);
}
}
/// <summary>
/// 变量连接状态变更事件处理 | Variables connected state changed event handler
/// </summary>
private void OnVariablesConnectedChanged(bool isConnected)
{
IsVariablesConnected = isConnected;
_logger.Info("收到变量连接状态变更: {IsConnected} | Received variables connection state change: {IsConnected}", isConnected);
if (isConnected)
{
_logger.Info("变量已连接,主动读取最新状态 | Variables Connected, actively reading latest status");
RefreshStatusFromDevice();
}
}
#endregion
#region | Command Execution Logic
/// <summary>
/// 开启射线源执行逻辑 | Turn on X-ray execution logic
/// </summary>
private void ExecuteTurnOn()
{
_isOperating = true;
TurnOnCommand.RaiseCanExecuteChanged();
TurnOffCommand.RaiseCanExecuteChanged();
try
{
_logger.Info("用户请求开启射线 | User requested to turn on X-ray");
var result = _raySourceService.TurnOn();
if (result.Success)
{
_logger.Info("射线开启指令发送成功 | X-ray turned on successfully");
}
else
{
_logger.Warn("射线开启指令发送失败: {Error} | X-ray turn on failed: {Error}", result.ErrorMessage);
MessageBox.Show(result.ErrorMessage, "开启失败", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
catch (Exception ex)
{
_logger.Error(ex, "开启射线源异常: {Message} | Exception turning on X-ray: {Message}", ex.Message);
MessageBox.Show($"开启射线源异常: {ex.Message}", "异常", MessageBoxButton.OK, MessageBoxImage.Error);
}
finally
{
_isOperating = false;
TurnOnCommand.RaiseCanExecuteChanged();
TurnOffCommand.RaiseCanExecuteChanged();
}
}
/// <summary>
/// 开启命令是否可执行(仅关闭状态且连锁激活时可执行)| Can execute turn on command (only when closed and interlock active)
/// </summary>
private bool CanExecuteTurnOn()
{
return !_isOperating && _isVariablesConnected && IsInterlockActive && RaySourceStatus == RaySourceStatus.Closed && _raySourceService.IsInitialized;
}
/// <summary>
/// 关闭射线源执行逻辑 | Turn off X-ray execution logic
/// </summary>
private void ExecuteTurnOff()
{
_isOperating = true;
TurnOnCommand.RaiseCanExecuteChanged();
TurnOffCommand.RaiseCanExecuteChanged();
try
{
_logger.Info("用户请求关闭射线 | User requested to turn off X-ray");
var result = _raySourceService.TurnOff();
if (result.Success)
{
_logger.Info("射线关闭指令发送成功 | X-ray turned off successfully");
}
else
{
_logger.Warn("射线关闭指令发送失败: {Error} | X-ray turn off failed: {Error}", result.ErrorMessage);
MessageBox.Show(result.ErrorMessage, "关闭失败", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
catch (Exception ex)
{
_logger.Error(ex, "关闭射线源异常: {Message} | Exception turning off X-ray: {Message}", ex.Message);
MessageBox.Show($"关闭射线源异常: {ex.Message}", "异常", MessageBoxButton.OK, MessageBoxImage.Error);
}
finally
{
_isOperating = false;
TurnOnCommand.RaiseCanExecuteChanged();
TurnOffCommand.RaiseCanExecuteChanged();
}
}
/// <summary>
/// 关闭命令是否可执行(仅开启状态可执行)| Can execute turn off command (only when opened)
/// </summary>
private bool CanExecuteTurnOff()
{
return !_isOperating && _isVariablesConnected && RaySourceStatus == RaySourceStatus.Opened && _raySourceService.IsInitialized;
}
/// <summary>
/// 设置命令执行逻辑:打开外部高级设置程序 | Settings command: launch external advance settings program
/// 如果程序已运行则将窗口置前 | If program is already running, bring its window to front
/// </summary>
private void ExecuteSettings()
{
var exePath = _config.AdvanceExePath;
_logger.Info("用户点击高级按钮,目标程序: {ExePath} | User clicked advance button, target program: {ExePath}", exePath);
var result = ProcessHelper.StartOrActivate(exePath, true);
if (result.Success)
{
var action = result.IsNewlyStarted ? "已启动 | started" : "已激活 | activated";
_logger.Info("外部程序{Action} | External program {Action}", action, action);
}
else
{
_logger.Warn("外部程序操作失败: {Error} | External program operation failed: {Error}", result.ErrorMessage);
MessageBox.Show(result.ErrorMessage,
_localizationService.GetString("RaySource_Warning") ?? "警告",
MessageBoxButton.OK, MessageBoxImage.Warning);
}
}
/// <summary>
/// 设置命令是否可执行 | Can execute settings command
/// </summary>
private bool CanExecuteSettings()
{
return true; // 始终可用 | Always available
}
/// <summary>
/// 配置命令执行逻辑:打开射线源配置窗口 | Config command: open ray source config window
/// </summary>
private void ExecuteConfig()
{
_logger.Info("用户点击配置按钮 | User clicked config button");
// 如果窗口已存在且未关闭,激活它而不是重复创建
if (_configWindow != null && _configWindow.IsLoaded)
{
_configWindow.Activate();
return;
}
_configWindow = new Views.RaySourceConfigWindow
{
Owner = Application.Current.MainWindow,
ShowInTaskbar = false
};
_configWindow.Closed += (s, e) => _configWindow = null;
_configWindow.Show();
}
/// <summary>
/// 提交电压值到硬件(滑块松手/输入框失焦时调用)| Apply voltage to hardware (called on slider drag complete / input lost focus)
/// </summary>
private void ApplyVoltage()
{
var voltage = (float)VoltageValue;
if (!IsSlidersEnabled) return;
// 范围校验 | Range validation
if (voltage < _config.MinVoltage || voltage > _config.MaxVoltage)
{
_logger.Warn("电压值超出范围: {Voltage}kV,忽略提交 | Voltage out of range: {Voltage}kV, ignoring apply", voltage);
return;
}
try
{
_logger.Debug("用户确认电压值: {Voltage}kV | User confirmed voltage: {Voltage}kV", voltage);
var result = _raySourceService.SetVoltage(voltage);
if (!result.Success)
{
_logger.Warn("电压设置失败: {Error} | Voltage setting failed: {Error}", result.ErrorMessage);
// 设置失败时恢复滑块值(仅当实际值在有效范围内时)| Restore slider value when setting fails (only when actual value is in valid range)
if (VoltageActual >= _config.MinVoltage)
VoltageValue = VoltageActual;
}
}
catch (Exception ex)
{
_logger.Error(ex, "设置电压异常: {Message} | Exception setting voltage: {Message}", ex.Message);
MessageBox.Show($"设置电压异常: {ex.Message}", "异常", MessageBoxButton.OK, MessageBoxImage.Error);
if (VoltageActual >= _config.MinVoltage)
VoltageValue = VoltageActual;
}
}
/// <summary>
/// 提交电流值到硬件(滑块松手/输入框失焦时调用)| Apply current to hardware (called on slider drag complete / input lost focus)
/// </summary>
private void ApplyCurrent()
{
var current = (float)CurrentValue;
if (!IsSlidersEnabled) return;
// 范围校验 | Range validation
if (current < _config.MinCurrent || current > _config.MaxCurrent)
{
_logger.Warn("电流值超出范围: {Current}μA,忽略提交 | Current out of range: {Current}μA, ignoring apply", current);
return;
}
try
{
_logger.Debug("用户确认电流值: {Current}μA | User confirmed current: {Current}μA", current);
var result = _raySourceService.SetCurrent(current);
if (!result.Success)
{
_logger.Warn("电流设置失败: {Error} | Current setting failed: {Error}", result.ErrorMessage);
// 设置失败时恢复滑块值(仅当实际值在有效范围内时)| Restore slider value when setting fails (only when actual value is in valid range)
if (CurrentActual >= _config.MinCurrent)
CurrentValue = CurrentActual;
}
}
catch (Exception ex)
{
_logger.Error(ex, "设置电流异常: {Message} | Exception setting current: {Message}", ex.Message);
MessageBox.Show($"设置电流异常: {ex.Message}", "异常", MessageBoxButton.OK, MessageBoxImage.Error);
if (CurrentActual >= _config.MinCurrent)
CurrentValue = CurrentActual;
}
}
/// <summary>
/// 从服务更新状态 | Update status from service
/// </summary>
private void UpdateStatusFromService()
{
RaySourceStatus = _raySourceService.CurrentStatus;
}
/// <summary>
/// 从设备主动读取最新状态并刷新UI | Actively read latest status from device and refresh UI
/// </summary>
private void RefreshStatusFromDevice()
{
try
{
var result = _raySourceService.ReadSystemStatus();
if (result.Success && result.Data is SystemStatusData statusData)
{
OnStatusUpdated(statusData);
_logger.Info("已从设备刷新最新状态 | Refreshed latest status from device");
}
else
{
_logger.Warn("读取设备状态失败: {Error} | Failed to read device status: {Error}", result.ErrorMessage);
}
}
catch (Exception ex)
{
_logger.Error(ex, "刷新设备状态异常: {Message} | Exception refreshing device status: {Message}", ex.Message);
}
}
/// <summary>
/// 界面加载时自动执行初始化和连接变量流程(仅执行一次)
/// Auto-execute Initialize and ConnectVariables on view loaded (runs only once)
/// </summary>
/// <summary>
/// 自动初始化:异步执行初始化 + 连接变量 | Auto-initialize: async Initialize + ConnectVariables
/// 由 View 的 Loaded 事件触发,仅执行一次 | Triggered by View's Loaded event, runs only once
/// </summary>
public async Task AutoInitializeAsync()
{
// 防止重复执行 | Prevent duplicate execution
if (_autoInitialized) return;
_autoInitialized = true;
// 如果已经初始化并连接,跳过 | Skip if already initialized and connected
if (_raySourceService.IsInitialized && _isVariablesConnected)
{
_logger.Info("射线源已初始化且变量已连接,跳过自动初始化 | Ray source already initialized and variables connected, skipping auto-init");
return;
}
_logger.Info("开始自动初始化流程 | Starting auto-initialization sequence");
var result = await _raySourceService.InitializeAndConnectAsync();
if (result.Success)
{
_logger.Info("自动初始化命令已发送,等待设备确认 | Auto-initialization command sent, waiting for device confirmation");
}
else
{
_logger.Warn("自动初始化流程失败: {Error} | Auto-initialization sequence failed: {Error}", result.ErrorMessage);
}
}
#endregion
#region IDisposable Implementation
/// <summary>
/// 释放资源 | Dispose resources
/// </summary>
public void Dispose()
{
if (!_isDisposed)
{
// 断开射线源连接 | Disconnect X-ray source
if (_raySourceService.IsInitialized)
{
_logger.Info("界面关闭,执行断开操作 | View closing, executing disconnect");
try
{
Task.Run(() => _raySourceService.Disconnect()).Wait(5000);
}
catch (Exception ex)
{
_logger.Warn("断开射线源异常: {Message} | Disconnect exception: {Message}", ex.Message);
}
}
// 关闭配置窗口 | Close config window
if (_configWindow != null && _configWindow.IsLoaded)
{
_configWindow.Close();
_configWindow = null;
}
// 取消订阅事件 | Unsubscribe events
_eventAggregator.GetEvent<RaySourceStatusChangedEvent>().Unsubscribe(OnRaySourceStatusChanged);
_eventAggregator.GetEvent<StatusUpdatedEvent>().Unsubscribe(OnStatusUpdated);
_eventAggregator.GetEvent<ErrorOccurredEvent>().Unsubscribe(OnErrorOccurred);
_eventAggregator.GetEvent<OperationResultEvent>().Unsubscribe(OnOperationResult);
_eventAggregator.GetEvent<VariablesConnectedEvent>().Unsubscribe(OnVariablesConnectedChanged);
_isDisposed = true;
}
}
#endregion
}
}