更新
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
using System.ComponentModel;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
@@ -13,6 +14,8 @@ public partial class MainWindow : Window
|
|||||||
private readonly DispatcherTimer _hiddenSettingsPressTimer;
|
private readonly DispatcherTimer _hiddenSettingsPressTimer;
|
||||||
private bool _isHiddenSettingsPressActive;
|
private bool _isHiddenSettingsPressActive;
|
||||||
private bool _hasOpenedHiddenSettingsForCurrentPress;
|
private bool _hasOpenedHiddenSettingsForCurrentPress;
|
||||||
|
private bool _isCloseStopInProgress;
|
||||||
|
private bool _allowConfirmedClose;
|
||||||
|
|
||||||
public MainWindow()
|
public MainWindow()
|
||||||
{
|
{
|
||||||
@@ -25,9 +28,59 @@ public partial class MainWindow : Window
|
|||||||
};
|
};
|
||||||
_hiddenSettingsPressTimer.Tick += HiddenSettingsPressTimer_Tick;
|
_hiddenSettingsPressTimer.Tick += HiddenSettingsPressTimer_Tick;
|
||||||
Deactivated += (_, _) => ReleaseAllManualMotionTargetsAsync();
|
Deactivated += (_, _) => ReleaseAllManualMotionTargetsAsync();
|
||||||
|
Closing += MainWindow_Closing;
|
||||||
Log.Information("主窗口创建完成");
|
Log.Information("主窗口创建完成");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async void MainWindow_Closing(object? sender, CancelEventArgs e)
|
||||||
|
{
|
||||||
|
if (_allowConfirmedClose
|
||||||
|
|| DataContext is not MainWindowViewModel viewModel
|
||||||
|
|| !viewModel.HasActiveControlRun())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
e.Cancel = true;
|
||||||
|
if (_isCloseStopInProgress)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_isCloseStopInProgress = true;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Log.Warning("检测到活动测试,关闭窗口前开始发送并确认停止指令");
|
||||||
|
if (!await viewModel.TryStopActiveTestsForCloseAsync())
|
||||||
|
{
|
||||||
|
viewModel.CancelCloseStopRequest();
|
||||||
|
MessageBox.Show(
|
||||||
|
"测试停止状态未确认,软件将保持开启。请检查设备状态并再次点击停止。",
|
||||||
|
"无法安全关闭",
|
||||||
|
MessageBoxButton.OK,
|
||||||
|
MessageBoxImage.Warning);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_allowConfirmedClose = true;
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
viewModel.CancelCloseStopRequest();
|
||||||
|
Log.Error(ex, "关闭软件前停止活动测试失败,窗口保持开启");
|
||||||
|
MessageBox.Show(
|
||||||
|
$"关闭软件前停止测试失败,软件将保持开启:{OperatorMessageFormatter.FromException(ex)}",
|
||||||
|
"无法安全关闭",
|
||||||
|
MessageBoxButton.OK,
|
||||||
|
MessageBoxImage.Error);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_isCloseStopInProgress = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void HiddenSettingsHotspot_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
private void HiddenSettingsHotspot_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||||
{
|
{
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ public sealed class MainWindowViewModel : ObservableObject
|
|||||||
private const ushort VentValveCoil = 6;
|
private const ushort VentValveCoil = 6;
|
||||||
private const ushort AxialForceModeCoil = 30;
|
private const ushort AxialForceModeCoil = 30;
|
||||||
private const ushort AxialStartCoil = 70;
|
private const ushort AxialStartCoil = 70;
|
||||||
|
private const ushort AxialEnabledCoil = 71;
|
||||||
private const ushort AxialDoneCoil = 72;
|
private const ushort AxialDoneCoil = 72;
|
||||||
private const ushort AxialStopCoil = 73;
|
private const ushort AxialStopCoil = 73;
|
||||||
private const ushort SpeedTorqueStartCoil = 80;
|
private const ushort SpeedTorqueStartCoil = 80;
|
||||||
@@ -107,7 +108,7 @@ public sealed class MainWindowViewModel : ObservableObject
|
|||||||
private static readonly TimeSpan RealtimeDataFreshnessTimeout = TimeSpan.FromSeconds(3);
|
private static readonly TimeSpan RealtimeDataFreshnessTimeout = TimeSpan.FromSeconds(3);
|
||||||
private static readonly TimeSpan SnapshotInterval = TimeSpan.FromSeconds(5);
|
private static readonly TimeSpan SnapshotInterval = TimeSpan.FromSeconds(5);
|
||||||
private static readonly TimeSpan NoLoadCaptureDuration = TimeSpan.FromSeconds(3);
|
private static readonly TimeSpan NoLoadCaptureDuration = TimeSpan.FromSeconds(3);
|
||||||
private static readonly TimeSpan SpeedTorqueStartConfirmationTimeout = TimeSpan.FromSeconds(5);
|
private static readonly TimeSpan RunStateConfirmationTimeout = TimeSpan.FromSeconds(5);
|
||||||
|
|
||||||
private static readonly ushort[] RealtimeRegisterAddresses =
|
private static readonly ushort[] RealtimeRegisterAddresses =
|
||||||
[
|
[
|
||||||
@@ -154,7 +155,9 @@ public sealed class MainWindowViewModel : ObservableObject
|
|||||||
[
|
[
|
||||||
VentValveCoil,
|
VentValveCoil,
|
||||||
AxialForceModeCoil,
|
AxialForceModeCoil,
|
||||||
|
AxialEnabledCoil,
|
||||||
AxialDoneCoil,
|
AxialDoneCoil,
|
||||||
|
SpeedTorqueEnabledCoil,
|
||||||
SpeedTorqueDoneCoil,
|
SpeedTorqueDoneCoil,
|
||||||
SpeedTorqueStableCoil,
|
SpeedTorqueStableCoil,
|
||||||
SpeedTorqueResetEnabledCoil,
|
SpeedTorqueResetEnabledCoil,
|
||||||
@@ -200,7 +203,10 @@ public sealed class MainWindowViewModel : ObservableObject
|
|||||||
private double? _finalDisplacement;
|
private double? _finalDisplacement;
|
||||||
private double _axialForce;
|
private double _axialForce;
|
||||||
private double? _finalAxialForce;
|
private double? _finalAxialForce;
|
||||||
|
private bool _isDisplacementStarting;
|
||||||
private bool _isDisplacementRunning;
|
private bool _isDisplacementRunning;
|
||||||
|
private bool _isDisplacementStartupUncertain;
|
||||||
|
private int _axialDisabledPollCount;
|
||||||
private double _realtimeSpeed;
|
private double _realtimeSpeed;
|
||||||
private double _realtimeTorque;
|
private double _realtimeTorque;
|
||||||
private double _realtimePressure;
|
private double _realtimePressure;
|
||||||
@@ -215,23 +221,28 @@ public sealed class MainWindowViewModel : ObservableObject
|
|||||||
private double? _finalSpeed;
|
private double? _finalSpeed;
|
||||||
private double? _finalTorque;
|
private double? _finalTorque;
|
||||||
private DateTime? _speedTorqueStartedAt;
|
private DateTime? _speedTorqueStartedAt;
|
||||||
|
private bool _isSpeedTorqueStarting;
|
||||||
private bool _isSpeedTorqueRunning;
|
private bool _isSpeedTorqueRunning;
|
||||||
private bool _isSpeedTorqueCompletionArmed;
|
private bool _isSpeedTorqueStartupUncertain;
|
||||||
private bool _hasLoggedStaleSpeedTorqueDone;
|
private int _speedTorqueDisabledPollCount;
|
||||||
private bool _wasSpeedTorqueStable;
|
private bool _wasSpeedTorqueStable;
|
||||||
private bool _isReadingRealtime;
|
private bool _isReadingRealtime;
|
||||||
private bool _isWritingAxialForceMode;
|
private bool _isWritingAxialForceMode;
|
||||||
private bool _isReadingParameterConfig;
|
private bool _isReadingParameterConfig;
|
||||||
private bool _hasLoadedParameterConfigFromPlc;
|
private bool _hasLoadedParameterConfigFromPlc;
|
||||||
private bool _lastRealtimeReadFailed;
|
private bool _lastRealtimeReadFailed;
|
||||||
|
private bool _hasReportedRunStateCommunicationLoss;
|
||||||
private DateTime _lastSuccessfulRealtimeReadAt = DateTime.MinValue;
|
private DateTime _lastSuccessfulRealtimeReadAt = DateTime.MinValue;
|
||||||
private bool _isAutoStoppingDisplacement;
|
private bool _isAutoStoppingDisplacement;
|
||||||
private bool _isAutoStoppingSpeedTorque;
|
private bool _isAutoStoppingSpeedTorque;
|
||||||
|
private bool _isConfirmingDisplacementStop;
|
||||||
|
private bool _isConfirmingSpeedTorqueStop;
|
||||||
private bool _isApplyingParameterConfigToInputs;
|
private bool _isApplyingParameterConfigToInputs;
|
||||||
private bool _isDisplacementResetting;
|
private bool _isDisplacementResetting;
|
||||||
private bool _isSpeedTorqueResetting;
|
private bool _isSpeedTorqueResetting;
|
||||||
private bool _isSpeedTorqueZeroing;
|
private bool _isSpeedTorqueZeroing;
|
||||||
private bool _hasShownSpeedTorqueEndWarnings;
|
private bool _hasShownSpeedTorqueEndWarnings;
|
||||||
|
private bool _isCloseStopRequested;
|
||||||
private DateTime _lastParameterReadFailureLogAt = DateTime.MinValue;
|
private DateTime _lastParameterReadFailureLogAt = DateTime.MinValue;
|
||||||
private string _dialIndicatorText = "0.000 mm";
|
private string _dialIndicatorText = "0.000 mm";
|
||||||
private string _axialAxisPositionText = "0.000 mm";
|
private string _axialAxisPositionText = "0.000 mm";
|
||||||
@@ -382,6 +393,39 @@ public sealed class MainWindowViewModel : ObservableObject
|
|||||||
return _parameterConfig.ToPlcConnectionConfig();
|
return _parameterConfig.ToPlcConnectionConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal bool HasActiveControlRun()
|
||||||
|
{
|
||||||
|
return _isDisplacementStarting
|
||||||
|
|| _isDisplacementRunning
|
||||||
|
|| _isSpeedTorqueStarting
|
||||||
|
|| _isSpeedTorqueRunning;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal async Task<bool> TryStopActiveTestsForCloseAsync()
|
||||||
|
{
|
||||||
|
_isCloseStopRequested = true;
|
||||||
|
if (_isDisplacementStarting)
|
||||||
|
{
|
||||||
|
await AbortDisplacementStartupAsync("关闭软件前已中止轴向启动。", "关闭软件");
|
||||||
|
_isDisplacementStarting = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_isSpeedTorqueStarting)
|
||||||
|
{
|
||||||
|
await AbortSpeedTorqueStartupAsync("关闭软件前已中止转速/扭矩启动。", "关闭软件");
|
||||||
|
_isSpeedTorqueStarting = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool axialStopped = await StopDisplacementControlAsync("状态:关闭软件前已停止", "关闭软件前轴向停止");
|
||||||
|
bool speedTorqueStopped = await StopSpeedTorqueControlAsync("状态:关闭软件前已停止", "关闭软件前转速/扭矩停止");
|
||||||
|
return axialStopped && speedTorqueStopped;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void CancelCloseStopRequest()
|
||||||
|
{
|
||||||
|
_isCloseStopRequested = false;
|
||||||
|
}
|
||||||
|
|
||||||
internal async Task<bool> BeginManualMotionAsync(ManualMotionTarget target)
|
internal async Task<bool> BeginManualMotionAsync(ManualMotionTarget target)
|
||||||
{
|
{
|
||||||
return target switch
|
return target switch
|
||||||
@@ -814,38 +858,30 @@ public sealed class MainWindowViewModel : ObservableObject
|
|||||||
FinalizeNoLoadSpeedRunIfDue();
|
FinalizeNoLoadSpeedRunIfDue();
|
||||||
QueueSnapshotIfDue();
|
QueueSnapshotIfDue();
|
||||||
|
|
||||||
if (_isDisplacementRunning && ReadCoilValue(coilValues, AxialDoneCoil))
|
bool hadActiveControlRun = HasActiveControlRun();
|
||||||
{
|
SynchronizeAxialRunState(
|
||||||
StopDisplacementTest("状态:已完成");
|
ReadCoilValue(coilValues, AxialEnabledCoil),
|
||||||
}
|
ReadCoilValue(coilValues, AxialDoneCoil));
|
||||||
|
await SynchronizeSpeedTorqueRunStateAsync(
|
||||||
bool isSpeedTorqueDone = ReadCoilValue(coilValues, SpeedTorqueDoneCoil);
|
ReadCoilValue(coilValues, SpeedTorqueEnabledCoil),
|
||||||
if (_isSpeedTorqueRunning && !_isSpeedTorqueCompletionArmed)
|
ReadCoilValue(coilValues, SpeedTorqueDoneCoil));
|
||||||
{
|
|
||||||
if (!isSpeedTorqueDone)
|
|
||||||
{
|
|
||||||
_isSpeedTorqueCompletionArmed = true;
|
|
||||||
_hasLoggedStaleSpeedTorqueDone = false;
|
|
||||||
Log.Information("转速/扭矩完成判定已就绪:新测试启动后已确认 M{DoneCoil}=0", SpeedTorqueDoneCoil);
|
|
||||||
}
|
|
||||||
else if (!_hasLoggedStaleSpeedTorqueDone)
|
|
||||||
{
|
|
||||||
_hasLoggedStaleSpeedTorqueDone = true;
|
|
||||||
Log.Warning("忽略转速/扭矩测试启动后的残留完成状态:M{DoneCoil}=1;等待先恢复为0后再接受完成信号", SpeedTorqueDoneCoil);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (_isSpeedTorqueRunning && isSpeedTorqueDone)
|
|
||||||
{
|
|
||||||
await StopSpeedTorqueTestAsync("状态:已完成");
|
|
||||||
}
|
|
||||||
|
|
||||||
await AutoStopIfSetpointReachedAsync();
|
await AutoStopIfSetpointReachedAsync();
|
||||||
await AutoStopIfSpeedTorqueProtectionReachedAsync();
|
await AutoStopIfSpeedTorqueProtectionReachedAsync();
|
||||||
|
|
||||||
if (_lastRealtimeReadFailed)
|
if (_lastRealtimeReadFailed)
|
||||||
{
|
{
|
||||||
StatusText = "实时数据已恢复";
|
if (HasActiveControlRun())
|
||||||
|
{
|
||||||
|
StatusText = "PLC 实时通信已恢复,测试运行状态已按实际点位同步。";
|
||||||
|
}
|
||||||
|
else if (!hadActiveControlRun)
|
||||||
|
{
|
||||||
|
StatusText = "实时数据已恢复";
|
||||||
|
}
|
||||||
|
|
||||||
_lastRealtimeReadFailed = false;
|
_lastRealtimeReadFailed = false;
|
||||||
|
_hasReportedRunStateCommunicationLoss = false;
|
||||||
Log.Information("PLC实时数据读取已恢复");
|
Log.Information("PLC实时数据读取已恢复");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -857,6 +893,15 @@ public sealed class MainWindowViewModel : ObservableObject
|
|||||||
_lastRealtimeReadFailed = true;
|
_lastRealtimeReadFailed = true;
|
||||||
Log.Warning(ex, "PLC实时数据读取失败,后续相同故障将等待恢复后再记录");
|
Log.Warning(ex, "PLC实时数据读取失败,后续相同故障将等待恢复后再记录");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (HasActiveControlRun()
|
||||||
|
&& !_hasReportedRunStateCommunicationLoss
|
||||||
|
&& DateTime.Now - _lastSuccessfulRealtimeReadAt > RealtimeDataFreshnessTimeout)
|
||||||
|
{
|
||||||
|
_hasReportedRunStateCommunicationLoss = true;
|
||||||
|
StatusText = "PLC 通讯异常超过 3 秒,测试运行状态无法确认;保持测试中并持续重连。";
|
||||||
|
Log.Error("PLC通讯异常超过 {TimeoutSeconds} 秒,活动测试运行状态无法确认,软件保持运行状态", RealtimeDataFreshnessTimeout.TotalSeconds);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -864,6 +909,48 @@ public sealed class MainWindowViewModel : ObservableObject
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void SynchronizeAxialRunState(bool enabled, bool done)
|
||||||
|
{
|
||||||
|
if (!_isDisplacementRunning || _isConfirmingDisplacementStop)
|
||||||
|
{
|
||||||
|
_axialDisabledPollCount = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (done)
|
||||||
|
{
|
||||||
|
StopDisplacementTest("状态:已完成");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_axialDisabledPollCount = enabled ? 0 : _axialDisabledPollCount + 1;
|
||||||
|
if (_axialDisabledPollCount >= 3)
|
||||||
|
{
|
||||||
|
StopDisplacementTest("状态:PLC 轴向运行使能已断开");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task SynchronizeSpeedTorqueRunStateAsync(bool enabled, bool done)
|
||||||
|
{
|
||||||
|
if (!_isSpeedTorqueRunning || _isConfirmingSpeedTorqueStop)
|
||||||
|
{
|
||||||
|
_speedTorqueDisabledPollCount = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (done)
|
||||||
|
{
|
||||||
|
await StopSpeedTorqueTestAsync("状态:已完成");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_speedTorqueDisabledPollCount = enabled ? 0 : _speedTorqueDisabledPollCount + 1;
|
||||||
|
if (_speedTorqueDisabledPollCount >= 3)
|
||||||
|
{
|
||||||
|
await StopSpeedTorqueTestAsync("状态:PLC 转速/扭矩运行使能已断开");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async void ParameterRetryTimer_Tick(object? sender, EventArgs e)
|
private async void ParameterRetryTimer_Tick(object? sender, EventArgs e)
|
||||||
{
|
{
|
||||||
if (_hasLoadedParameterConfigFromPlc)
|
if (_hasLoadedParameterConfigFromPlc)
|
||||||
@@ -2597,18 +2684,20 @@ public sealed class MainWindowViewModel : ObservableObject
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_isSpeedTorqueRunning)
|
if (_isSpeedTorqueStarting || _isSpeedTorqueRunning)
|
||||||
{
|
{
|
||||||
UpdateSpeedTorqueDisplay();
|
UpdateSpeedTorqueDisplay();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_isSpeedTorqueStarting = true;
|
||||||
SpeedTorqueTestButtonText = "启动中";
|
SpeedTorqueTestButtonText = "启动中";
|
||||||
StatusText = "转速/扭矩测试启动中...";
|
StatusText = "转速/扭矩测试启动中...";
|
||||||
|
|
||||||
if (!await PulsePlcAsync(SpeedTorqueStartCoil, "转速/扭矩测试"))
|
if (!await PulsePlcAsync(SpeedTorqueStartCoil, "转速/扭矩测试"))
|
||||||
{
|
{
|
||||||
await AbortSpeedTorqueStartupAsync("M80 启动指令失败,已停止测试。", "M80启动指令失败");
|
await AbortSpeedTorqueStartupAsync("M80 启动指令失败,已停止测试。", "M80启动指令失败");
|
||||||
|
_isSpeedTorqueStarting = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2617,20 +2706,30 @@ public sealed class MainWindowViewModel : ObservableObject
|
|||||||
if (!await WaitForSpeedTorqueStartAsync())
|
if (!await WaitForSpeedTorqueStartAsync())
|
||||||
{
|
{
|
||||||
await AbortSpeedTorqueStartupAsync("PLC 未进入扭矩测试运行状态,已停止测试。", "启动状态确认失败");
|
await AbortSpeedTorqueStartupAsync("PLC 未进入扭矩测试运行状态,已停止测试。", "启动状态确认失败");
|
||||||
|
_isSpeedTorqueStarting = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_isCloseStopRequested)
|
||||||
|
{
|
||||||
|
await AbortSpeedTorqueStartupAsync("关闭软件请求已中止转速/扭矩启动。", "关闭软件");
|
||||||
|
_isSpeedTorqueStarting = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!TryGetRealtimeSpeed(out _) || !TryGetRealtimeTorque(out _))
|
if (!TryGetRealtimeSpeed(out _) || !TryGetRealtimeTorque(out _))
|
||||||
{
|
{
|
||||||
await AbortSpeedTorqueStartupAsync("实时数据无效,已停止测试。", "启动数据无效");
|
await AbortSpeedTorqueStartupAsync("实时数据无效,已停止测试。", "启动数据无效");
|
||||||
|
_isSpeedTorqueStarting = false;
|
||||||
UpdateSpeedTorqueDisplay();
|
UpdateSpeedTorqueDisplay();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_isSpeedTorqueStarting = false;
|
||||||
PrepareSessionForNewRun();
|
PrepareSessionForNewRun();
|
||||||
_isSpeedTorqueRunning = true;
|
_isSpeedTorqueRunning = true;
|
||||||
_isSpeedTorqueCompletionArmed = true;
|
_isSpeedTorqueStartupUncertain = false;
|
||||||
_hasLoggedStaleSpeedTorqueDone = false;
|
_speedTorqueDisabledPollCount = 0;
|
||||||
_wasSpeedTorqueStable = false;
|
_wasSpeedTorqueStable = false;
|
||||||
SpeedTorqueTestButtonText = "测试中";
|
SpeedTorqueTestButtonText = "测试中";
|
||||||
_hasShownSpeedTorqueEndWarnings = false;
|
_hasShownSpeedTorqueEndWarnings = false;
|
||||||
@@ -2655,7 +2754,15 @@ public sealed class MainWindowViewModel : ObservableObject
|
|||||||
|
|
||||||
private async Task<bool> WaitForSpeedTorqueStartAsync()
|
private async Task<bool> WaitForSpeedTorqueStartAsync()
|
||||||
{
|
{
|
||||||
DateTime deadline = DateTime.Now.Add(SpeedTorqueStartConfirmationTimeout);
|
return await WaitForRunStartAsync(
|
||||||
|
SpeedTorqueEnabledCoil,
|
||||||
|
SpeedTorqueDoneCoil,
|
||||||
|
"转速/扭矩");
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<bool> WaitForRunStartAsync(ushort enabledCoil, ushort doneCoil, string testName)
|
||||||
|
{
|
||||||
|
DateTime deadline = DateTime.Now.Add(RunStateConfirmationTimeout);
|
||||||
bool lastEnabled = false;
|
bool lastEnabled = false;
|
||||||
bool lastDone = false;
|
bool lastDone = false;
|
||||||
bool hasReadState = false;
|
bool hasReadState = false;
|
||||||
@@ -2667,17 +2774,18 @@ public sealed class MainWindowViewModel : ObservableObject
|
|||||||
{
|
{
|
||||||
IReadOnlyDictionary<ushort, bool> values = await _plcCoilService.ReadCoilValuesAsync(
|
IReadOnlyDictionary<ushort, bool> values = await _plcCoilService.ReadCoilValuesAsync(
|
||||||
_parameterConfig.ToPlcConnectionConfig(),
|
_parameterConfig.ToPlcConnectionConfig(),
|
||||||
[SpeedTorqueEnabledCoil, SpeedTorqueDoneCoil]);
|
[enabledCoil, doneCoil]);
|
||||||
lastEnabled = ReadCoilValue(values, SpeedTorqueEnabledCoil);
|
lastEnabled = ReadCoilValue(values, enabledCoil);
|
||||||
lastDone = ReadCoilValue(values, SpeedTorqueDoneCoil);
|
lastDone = ReadCoilValue(values, doneCoil);
|
||||||
hasReadState = true;
|
hasReadState = true;
|
||||||
|
|
||||||
if (lastEnabled && !lastDone)
|
if (lastEnabled && !lastDone)
|
||||||
{
|
{
|
||||||
Log.Information(
|
Log.Information(
|
||||||
"转速/扭矩启动状态确认成功:M{EnabledCoil}=1,M{DoneCoil}=0,通气阀保持手动控制",
|
"{TestName}启动状态确认成功:M{EnabledCoil}=1,M{DoneCoil}=0",
|
||||||
SpeedTorqueEnabledCoil,
|
testName,
|
||||||
SpeedTorqueDoneCoil);
|
enabledCoil,
|
||||||
|
doneCoil);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2688,50 +2796,47 @@ public sealed class MainWindowViewModel : ObservableObject
|
|||||||
hasLoggedReadFailure = true;
|
hasLoggedReadFailure = true;
|
||||||
Log.Warning(
|
Log.Warning(
|
||||||
ex,
|
ex,
|
||||||
"转速/扭矩启动状态读取失败,继续等待 M{EnabledCoil}/M{DoneCoil}",
|
"{TestName}启动状态读取失败,继续等待 M{EnabledCoil}/M{DoneCoil}",
|
||||||
SpeedTorqueEnabledCoil,
|
testName,
|
||||||
SpeedTorqueDoneCoil);
|
enabledCoil,
|
||||||
|
doneCoil);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await Task.Delay(200);
|
await Task.Delay(200);
|
||||||
}
|
}
|
||||||
|
|
||||||
StatusText = "M80 启动后 PLC 未确认扭矩使能,已阻止测试运行。";
|
StatusText = $"{testName}启动后 PLC 未确认运行使能,已阻止测试运行。";
|
||||||
Log.Error(
|
Log.Error(
|
||||||
"转速/扭矩启动状态确认超时:等待 {TimeoutSeconds} 秒,已读取状态 {HasReadState},最后 M{EnabledCoil}={Enabled},M{DoneCoil}={Done}",
|
"{TestName}启动状态确认超时:等待 {TimeoutSeconds} 秒,已读取状态 {HasReadState},最后 M{EnabledCoil}={Enabled},M{DoneCoil}={Done}",
|
||||||
SpeedTorqueStartConfirmationTimeout.TotalSeconds,
|
testName,
|
||||||
|
RunStateConfirmationTimeout.TotalSeconds,
|
||||||
hasReadState,
|
hasReadState,
|
||||||
SpeedTorqueEnabledCoil,
|
enabledCoil,
|
||||||
lastEnabled ? 1 : 0,
|
lastEnabled ? 1 : 0,
|
||||||
SpeedTorqueDoneCoil,
|
doneCoil,
|
||||||
lastDone ? 1 : 0);
|
lastDone ? 1 : 0);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task AbortSpeedTorqueStartupAsync(string status, string reason)
|
private async Task AbortSpeedTorqueStartupAsync(string status, string reason)
|
||||||
{
|
{
|
||||||
bool stopSent = await PulsePlcAsync(SpeedTorqueStopCoil, $"转速/扭矩{reason}停止");
|
bool stopped = await SendStopAndConfirmAsync(SpeedTorqueStopCoil, SpeedTorqueEnabledCoil, $"转速/扭矩{reason}停止");
|
||||||
_isSpeedTorqueRunning = false;
|
_isSpeedTorqueRunning = !stopped;
|
||||||
_isSpeedTorqueCompletionArmed = false;
|
_isSpeedTorqueStartupUncertain = !stopped;
|
||||||
_hasLoggedStaleSpeedTorqueDone = false;
|
_speedTorqueDisabledPollCount = 0;
|
||||||
SpeedTorqueTestButtonText = "测试";
|
SpeedTorqueTestButtonText = stopped ? "测试" : "停止未确认";
|
||||||
StatusText = status;
|
StatusText = stopped ? status : $"{status} M83 停止未确认,请再次点击停止。";
|
||||||
Log.Error(
|
Log.Error(
|
||||||
"转速/扭矩启动已中止:原因 {Reason},M{StopCoil}停止指令成功 {StopSent},通气阀保持手动控制",
|
"转速/扭矩启动已中止:原因 {Reason},M{StopCoil}停止状态确认 {Stopped},通气阀保持手动控制",
|
||||||
reason,
|
reason,
|
||||||
SpeedTorqueStopCoil,
|
SpeedTorqueStopCoil,
|
||||||
stopSent);
|
stopped);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task StopSpeedTorqueAsync()
|
private async Task StopSpeedTorqueAsync()
|
||||||
{
|
{
|
||||||
if (!await PulsePlcAsync(SpeedTorqueStopCoil, "转速/扭矩停止"))
|
await StopSpeedTorqueControlAsync("状态:已停止", "转速/扭矩停止");
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await StopSpeedTorqueTestAsync("状态:已停止");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ResetSpeedTorqueAsync()
|
private async Task ResetSpeedTorqueAsync()
|
||||||
@@ -2767,8 +2872,8 @@ public sealed class MainWindowViewModel : ObservableObject
|
|||||||
FinalizeSpeedTorqueRun("复位前中止");
|
FinalizeSpeedTorqueRun("复位前中止");
|
||||||
PersistCurrentPayloadSnapshot("转速/扭矩复位前");
|
PersistCurrentPayloadSnapshot("转速/扭矩复位前");
|
||||||
_isSpeedTorqueRunning = false;
|
_isSpeedTorqueRunning = false;
|
||||||
_isSpeedTorqueCompletionArmed = false;
|
_isSpeedTorqueStartupUncertain = false;
|
||||||
_hasLoggedStaleSpeedTorqueDone = false;
|
_speedTorqueDisabledPollCount = 0;
|
||||||
SpeedTorqueTestButtonText = "测试";
|
SpeedTorqueTestButtonText = "测试";
|
||||||
_realtimeSpeed = 0;
|
_realtimeSpeed = 0;
|
||||||
_realtimeTorque = 0;
|
_realtimeTorque = 0;
|
||||||
@@ -2857,31 +2962,52 @@ public sealed class MainWindowViewModel : ObservableObject
|
|||||||
|
|
||||||
private async Task StartDisplacementAsync()
|
private async Task StartDisplacementAsync()
|
||||||
{
|
{
|
||||||
if (_isDisplacementRunning)
|
if (_isDisplacementStarting || _isDisplacementRunning)
|
||||||
{
|
{
|
||||||
UpdateDisplacementDisplay();
|
UpdateDisplacementDisplay();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_isDisplacementStarting = true;
|
||||||
DisplacementTestButtonText = "启动中";
|
DisplacementTestButtonText = "启动中";
|
||||||
StatusText = "轴向测试启动中...";
|
StatusText = "轴向测试启动中...";
|
||||||
|
|
||||||
if (!await PulsePlcAsync(AxialStartCoil, "轴向测试"))
|
if (!await PulsePlcAsync(AxialStartCoil, "轴向测试"))
|
||||||
{
|
{
|
||||||
|
_isDisplacementStarting = false;
|
||||||
DisplacementTestButtonText = "测试";
|
DisplacementTestButtonText = "测试";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DisplacementTestButtonText = "启动确认中";
|
||||||
|
StatusText = "轴向测试启动指令已发送,正在确认 PLC 轴向使能。";
|
||||||
|
if (!await WaitForRunStartAsync(AxialEnabledCoil, AxialDoneCoil, "轴向测试"))
|
||||||
|
{
|
||||||
|
await AbortDisplacementStartupAsync("PLC 未进入轴向测试运行状态,已停止测试。", "启动状态确认失败");
|
||||||
|
_isDisplacementStarting = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_isCloseStopRequested)
|
||||||
|
{
|
||||||
|
await AbortDisplacementStartupAsync("关闭软件请求已中止轴向启动。", "关闭软件");
|
||||||
|
_isDisplacementStarting = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!TryGetDialValue(out _) || !TryGetAxialForceValue(out _))
|
if (!TryGetDialValue(out _) || !TryGetAxialForceValue(out _))
|
||||||
{
|
{
|
||||||
await PulsePlcAsync(AxialStopCoil, "实时数据无效,停止轴向测试");
|
await AbortDisplacementStartupAsync("实时数据无效,已停止轴向测试。", "启动数据无效");
|
||||||
DisplacementTestButtonText = "测试";
|
_isDisplacementStarting = false;
|
||||||
UpdateDisplacementDisplay();
|
UpdateDisplacementDisplay();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_isDisplacementStarting = false;
|
||||||
PrepareSessionForNewRun();
|
PrepareSessionForNewRun();
|
||||||
_isDisplacementRunning = true;
|
_isDisplacementRunning = true;
|
||||||
|
_isDisplacementStartupUncertain = false;
|
||||||
|
_axialDisabledPollCount = 0;
|
||||||
DisplacementTestButtonText = "测试中";
|
DisplacementTestButtonText = "测试中";
|
||||||
_activeDisplacementRun = CreateTestRun("轴向位移动量测试");
|
_activeDisplacementRun = CreateTestRun("轴向位移动量测试");
|
||||||
_finalDisplacement = null;
|
_finalDisplacement = null;
|
||||||
@@ -2894,12 +3020,22 @@ public sealed class MainWindowViewModel : ObservableObject
|
|||||||
|
|
||||||
private async Task StopDisplacementAsync()
|
private async Task StopDisplacementAsync()
|
||||||
{
|
{
|
||||||
if (!await PulsePlcAsync(AxialStopCoil, "轴向停止"))
|
await StopDisplacementControlAsync("状态:已停止", "轴向停止");
|
||||||
{
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
StopDisplacementTest("状态:已停止");
|
private async Task AbortDisplacementStartupAsync(string status, string reason)
|
||||||
|
{
|
||||||
|
bool stopped = await SendStopAndConfirmAsync(AxialStopCoil, AxialEnabledCoil, $"轴向{reason}停止");
|
||||||
|
_isDisplacementRunning = !stopped;
|
||||||
|
_isDisplacementStartupUncertain = !stopped;
|
||||||
|
_axialDisabledPollCount = 0;
|
||||||
|
DisplacementTestButtonText = stopped ? "测试" : "停止未确认";
|
||||||
|
StatusText = stopped ? status : $"{status} M73 停止未确认,请再次点击停止。";
|
||||||
|
Log.Error(
|
||||||
|
"轴向测试启动已中止:原因 {Reason},M{StopCoil}停止状态确认 {Stopped}",
|
||||||
|
reason,
|
||||||
|
AxialStopCoil,
|
||||||
|
stopped);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ResetDisplacementAsync()
|
private async Task ResetDisplacementAsync()
|
||||||
@@ -2940,6 +3076,8 @@ public sealed class MainWindowViewModel : ObservableObject
|
|||||||
_finalAxialForce = null;
|
_finalAxialForce = null;
|
||||||
await UpdateAxialForceFromInputAsync();
|
await UpdateAxialForceFromInputAsync();
|
||||||
_isDisplacementRunning = false;
|
_isDisplacementRunning = false;
|
||||||
|
_isDisplacementStartupUncertain = false;
|
||||||
|
_axialDisabledPollCount = 0;
|
||||||
DisplacementTestButtonText = "测试";
|
DisplacementTestButtonText = "测试";
|
||||||
UpdateDisplacementDisplay();
|
UpdateDisplacementDisplay();
|
||||||
Log.Information("轴向复位完成,千分表零点 {DialZero}", _dialZero);
|
Log.Information("轴向复位完成,千分表零点 {DialZero}", _dialZero);
|
||||||
@@ -3006,6 +3144,53 @@ public sealed class MainWindowViewModel : ObservableObject
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task<bool> SendStopAndConfirmAsync(ushort stopCoil, ushort enabledCoil, string actionName)
|
||||||
|
{
|
||||||
|
if (!await PulsePlcAsync(stopCoil, actionName))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DateTime deadline = DateTime.Now.Add(RunStateConfirmationTimeout);
|
||||||
|
bool hasLoggedReadFailure = false;
|
||||||
|
while (DateTime.Now < deadline)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IReadOnlyDictionary<ushort, bool> values = await _plcCoilService.ReadCoilValuesAsync(
|
||||||
|
_parameterConfig.ToPlcConnectionConfig(),
|
||||||
|
[enabledCoil]);
|
||||||
|
if (!ReadCoilValue(values, enabledCoil))
|
||||||
|
{
|
||||||
|
Log.Information(
|
||||||
|
"PLC停止状态确认成功:{ActionName},M{StopCoil}已触发,M{EnabledCoil}=0",
|
||||||
|
actionName,
|
||||||
|
stopCoil,
|
||||||
|
enabledCoil);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
if (!hasLoggedReadFailure)
|
||||||
|
{
|
||||||
|
hasLoggedReadFailure = true;
|
||||||
|
Log.Warning(ex, "PLC停止状态读取失败:{ActionName},继续等待 M{EnabledCoil}=0", actionName, enabledCoil);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await Task.Delay(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusText = $"{actionName}未确认:PLC M{enabledCoil}仍未确认断开。";
|
||||||
|
Log.Error(
|
||||||
|
"PLC停止状态确认超时:{ActionName},等待 {TimeoutSeconds} 秒后 M{EnabledCoil}仍未确认断开",
|
||||||
|
actionName,
|
||||||
|
RunStateConfirmationTimeout.TotalSeconds,
|
||||||
|
enabledCoil);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private async Task<bool> ExecuteZeroingSequenceAsync(
|
private async Task<bool> ExecuteZeroingSequenceAsync(
|
||||||
string testName,
|
string testName,
|
||||||
params (ushort CoilAddress, string ActionName)[] zeroingActions)
|
params (ushort CoilAddress, string ActionName)[] zeroingActions)
|
||||||
@@ -3249,10 +3434,7 @@ public sealed class MainWindowViewModel : ObservableObject
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
Log.Warning("轴向测试触发自动停止:{Status},位移 {Displacement},轴向力 {AxialForce}", status, _relativeDisplacement, GetScaledAxialForce());
|
Log.Warning("轴向测试触发自动停止:{Status},位移 {Displacement},轴向力 {AxialForce}", status, _relativeDisplacement, GetScaledAxialForce());
|
||||||
if (await PulsePlcAsync(AxialStopCoil, "轴向保护停止"))
|
await StopDisplacementControlAsync(status, "轴向保护停止");
|
||||||
{
|
|
||||||
StopDisplacementTest(status);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -3260,21 +3442,59 @@ public sealed class MainWindowViewModel : ObservableObject
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task<bool> StopDisplacementControlAsync(string status, string actionName)
|
||||||
|
{
|
||||||
|
if (!_isDisplacementRunning)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
_isConfirmingDisplacementStop = true;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
StatusText = $"{actionName}指令已发送,正在确认 PLC 轴向使能断开。";
|
||||||
|
if (!await SendStopAndConfirmAsync(AxialStopCoil, AxialEnabledCoil, actionName))
|
||||||
|
{
|
||||||
|
DisplacementTestButtonText = "停止未确认";
|
||||||
|
StatusText = $"{actionName}未确认,现场运行状态未知;请检查设备并再次点击停止。";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
StopDisplacementTest(status);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_isConfirmingDisplacementStop = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void StopDisplacementTest(string status)
|
private void StopDisplacementTest(string status)
|
||||||
{
|
{
|
||||||
if (!_isDisplacementRunning && _finalDisplacement.HasValue)
|
if (!_isDisplacementRunning)
|
||||||
{
|
{
|
||||||
UpdateDisplacementDisplay();
|
UpdateDisplacementDisplay();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_isDisplacementRunning = false;
|
_isDisplacementRunning = false;
|
||||||
|
_axialDisabledPollCount = 0;
|
||||||
DisplacementTestButtonText = "测试";
|
DisplacementTestButtonText = "测试";
|
||||||
|
if (_isDisplacementStartupUncertain)
|
||||||
|
{
|
||||||
|
_isDisplacementStartupUncertain = false;
|
||||||
|
StatusText = status;
|
||||||
|
UpdateDisplacementDisplay();
|
||||||
|
Log.Warning("轴向启动未确认状态已解除:{Status}", status);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_finalDisplacement = Math.Abs(_axialSampleDifference) > 0.000001 ? _axialSampleDifference : _relativeDisplacement;
|
_finalDisplacement = Math.Abs(_axialSampleDifference) > 0.000001 ? _axialSampleDifference : _relativeDisplacement;
|
||||||
_finalAxialForce = GetScaledAxialForce();
|
_finalAxialForce = GetScaledAxialForce();
|
||||||
FinalizeDisplacementRun(status);
|
FinalizeDisplacementRun(status);
|
||||||
PersistCurrentPayloadSnapshot("轴向测试停止");
|
PersistCurrentPayloadSnapshot("轴向测试停止");
|
||||||
UpdateDisplacementDisplay();
|
UpdateDisplacementDisplay();
|
||||||
|
StatusText = status;
|
||||||
Log.Information("轴向测试停止:{Status},最终位移 {FinalDisplacement},最终轴向力 {FinalAxialForce}", status, _finalDisplacement, _finalAxialForce);
|
Log.Information("轴向测试停止:{Status},最终位移 {FinalDisplacement},最终轴向力 {FinalAxialForce}", status, _finalDisplacement, _finalAxialForce);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3345,10 +3565,7 @@ public sealed class MainWindowViewModel : ObservableObject
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
Log.Warning("转速/扭矩测试触发自动停止:{Status},位移 {Displacement},转速 {Speed},扭矩 {Torque}", status, _speedTorqueDisplacement, _realtimeSpeed, GetScaledTorque());
|
Log.Warning("转速/扭矩测试触发自动停止:{Status},位移 {Displacement},转速 {Speed},扭矩 {Torque}", status, _speedTorqueDisplacement, _realtimeSpeed, GetScaledTorque());
|
||||||
if (await PulsePlcAsync(SpeedTorqueStopCoil, "转速/扭矩保护停止"))
|
await StopSpeedTorqueControlAsync(status, "转速/扭矩保护停止");
|
||||||
{
|
|
||||||
await StopSpeedTorqueTestAsync(status);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -3356,30 +3573,60 @@ public sealed class MainWindowViewModel : ObservableObject
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task<bool> StopSpeedTorqueControlAsync(string status, string actionName)
|
||||||
|
{
|
||||||
|
if (!_isSpeedTorqueRunning)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
_isConfirmingSpeedTorqueStop = true;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
StatusText = $"{actionName}指令已发送,正在确认 PLC 扭矩使能断开。";
|
||||||
|
if (!await SendStopAndConfirmAsync(SpeedTorqueStopCoil, SpeedTorqueEnabledCoil, actionName))
|
||||||
|
{
|
||||||
|
SpeedTorqueTestButtonText = "停止未确认";
|
||||||
|
StatusText = $"{actionName}未确认,现场运行状态未知;请检查设备并再次点击停止。";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
await StopSpeedTorqueTestAsync(status);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_isConfirmingSpeedTorqueStop = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async Task StopSpeedTorqueTestAsync(string status)
|
private async Task StopSpeedTorqueTestAsync(string status)
|
||||||
{
|
{
|
||||||
if (!TryGetRealtimeSpeed(out double speed) || !TryGetRealtimeTorque(out double torque))
|
if (!_isSpeedTorqueRunning)
|
||||||
{
|
{
|
||||||
_isSpeedTorqueRunning = false;
|
|
||||||
_isSpeedTorqueCompletionArmed = false;
|
|
||||||
_hasLoggedStaleSpeedTorqueDone = false;
|
|
||||||
SpeedTorqueTestButtonText = "测试";
|
|
||||||
UpdateSpeedTorqueDisplay();
|
UpdateSpeedTorqueDisplay();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_isSpeedTorqueRunning = false;
|
_isSpeedTorqueRunning = false;
|
||||||
_isSpeedTorqueCompletionArmed = false;
|
_speedTorqueDisabledPollCount = 0;
|
||||||
_hasLoggedStaleSpeedTorqueDone = false;
|
|
||||||
SpeedTorqueTestButtonText = "测试";
|
SpeedTorqueTestButtonText = "测试";
|
||||||
_realtimeSpeed = speed;
|
if (_isSpeedTorqueStartupUncertain)
|
||||||
_realtimeTorque = torque;
|
{
|
||||||
_finalSpeed = speed;
|
_isSpeedTorqueStartupUncertain = false;
|
||||||
|
StatusText = status;
|
||||||
|
UpdateSpeedTorqueDisplay();
|
||||||
|
Log.Warning("转速/扭矩启动未确认状态已解除:{Status}", status);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_finalSpeed = _realtimeSpeed;
|
||||||
_finalTorque = GetScaledTorque();
|
_finalTorque = GetScaledTorque();
|
||||||
_finalSpeedTorqueDisplacement = _speedTorqueDisplacement;
|
_finalSpeedTorqueDisplacement = _speedTorqueDisplacement;
|
||||||
FinalizeSpeedTorqueRun(status);
|
FinalizeSpeedTorqueRun(status);
|
||||||
PersistCurrentPayloadSnapshot("转速/扭矩测试停止");
|
PersistCurrentPayloadSnapshot("转速/扭矩测试停止");
|
||||||
UpdateSpeedTorqueDisplay();
|
UpdateSpeedTorqueDisplay();
|
||||||
|
StatusText = status;
|
||||||
Log.Information("转速/扭矩测试停止:{Status},最终位移 {FinalDisplacement},最终转速 {FinalSpeed},最终扭矩 {FinalTorque},通气阀保持手动控制", status, _finalSpeedTorqueDisplacement, _finalSpeed, _finalTorque);
|
Log.Information("转速/扭矩测试停止:{Status},最终位移 {FinalDisplacement},最终转速 {FinalSpeed},最终扭矩 {FinalTorque},通气阀保持手动控制", status, _finalSpeedTorqueDisplacement, _finalSpeed, _finalTorque);
|
||||||
|
|
||||||
await ShowSpeedTorqueEndWarningsAsync();
|
await ShowSpeedTorqueEndWarningsAsync();
|
||||||
@@ -3983,7 +4230,8 @@ public sealed class MainWindowViewModel : ObservableObject
|
|||||||
|
|
||||||
private bool HasActiveRuns()
|
private bool HasActiveRuns()
|
||||||
{
|
{
|
||||||
return _activeDisplacementRun is not null
|
return HasActiveControlRun()
|
||||||
|
|| _activeDisplacementRun is not null
|
||||||
|| _activeSpeedTorqueRun is not null
|
|| _activeSpeedTorqueRun is not null
|
||||||
|| _activeNoLoadSpeedRun is not null;
|
|| _activeNoLoadSpeedRun is not null;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user