From 57b423fef19b63bd6ef0b2b558800b4758db5f93 Mon Sep 17 00:00:00 2001 From: "GukSang.Jin" Date: Mon, 15 Jun 2026 14:32:45 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B020260615?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DentistryHandpieces/MainWindowViewModel.cs | 86 ++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/DentistryHandpieces/MainWindowViewModel.cs b/DentistryHandpieces/MainWindowViewModel.cs index 04a542b..1de119e 100644 --- a/DentistryHandpieces/MainWindowViewModel.cs +++ b/DentistryHandpieces/MainWindowViewModel.cs @@ -218,6 +218,7 @@ public sealed class MainWindowViewModel : ObservableObject private bool _isSpeedTorqueRunning; private bool _isSpeedTorqueCompletionArmed; private bool _hasLoggedStaleSpeedTorqueDone; + private bool _wasSpeedTorqueStable; private bool _isReadingRealtime; private bool _isWritingAxialForceMode; private bool _isReadingParameterConfig; @@ -2630,6 +2631,7 @@ public sealed class MainWindowViewModel : ObservableObject _isSpeedTorqueRunning = true; _isSpeedTorqueCompletionArmed = true; _hasLoggedStaleSpeedTorqueDone = false; + _wasSpeedTorqueStable = false; SpeedTorqueTestButtonText = "测试中"; _hasShownSpeedTorqueEndWarnings = false; _finalSpeed = null; @@ -3749,9 +3751,91 @@ public sealed class MainWindowViewModel : ObservableObject AppendSample(_activeDisplacementRun, sample); AppendSample(_activeSpeedTorqueRun, sample); AppendSample(_activeNoLoadSpeedRun, sample); + TrackStableTorqueSample(sample); UpdateDataCaptureStatus(); } + private void TrackStableTorqueSample(RealtimeSamplePayload sample) + { + if (_activeSpeedTorqueRun is null) + { + _wasSpeedTorqueStable = false; + return; + } + + double elapsedSeconds = Math.Max(0, (sample.SampledAt - _activeSpeedTorqueRun.StartedAt).TotalSeconds); + if (sample.SpeedTorqueStable) + { + if (!_wasSpeedTorqueStable) + { + Log.Information( + "转速/扭矩稳定保持段开始:运行 {RunId},M{StableCoil}=1,时间 {SampledAt:yyyy-MM-dd HH:mm:ss.fff},已运行 {ElapsedSeconds:F3} s,保持扭矩设置 {HoldTorque:F6} {TorqueUnit},保持时间设置 {HoldTime:F3} s", + _activeSpeedTorqueRun.RunId, + SpeedTorqueStableCoil, + sample.SampledAt, + elapsedSeconds, + _activeSpeedTorqueRun.ParameterSnapshot.HoldTorque, + TorqueUnit, + _activeSpeedTorqueRun.ParameterSnapshot.TorqueHoldTime); + } + + Log.Information( + "转速/扭矩稳定保持采样:运行 {RunId},序号 {Sequence},M{StableCoil}=1,时间 {SampledAt:yyyy-MM-dd HH:mm:ss.fff},已运行 {ElapsedSeconds:F3} s,D{TorqueRegister}扭矩 {Torque:F6} {TorqueUnit},转速 {Speed:F3} r/min,压力 {Pressure:F3} kPa", + _activeSpeedTorqueRun.RunId, + sample.Sequence, + SpeedTorqueStableCoil, + sample.SampledAt, + elapsedSeconds, + TorqueDisplayRegister, + sample.RealtimeTorqueMilliNewtonMeters, + TorqueUnit, + sample.RealtimeSpeedRpm, + sample.RealtimePressureKpa); + } + else if (_wasSpeedTorqueStable) + { + LogStableTorqueSummary(_activeSpeedTorqueRun, "M87稳定标志退出"); + } + + _wasSpeedTorqueStable = sample.SpeedTorqueStable; + } + + private static void LogStableTorqueSummary(TestRunPayload run, string reason) + { + TorqueCurvePayload curve = CreateTorqueCurvePayload(run); + if (curve.EvaluationSampleCount < 2) + { + Log.Warning( + "转速/扭矩稳定保持段汇总不足:运行 {RunId},原因 {Reason},保持段采样数 {SampleCount},判定 {Result}", + run.RunId, + reason, + curve.EvaluationSampleCount, + curve.Result); + return; + } + + Log.Information( + "转速/扭矩稳定保持段汇总:运行 {RunId},原因 {Reason},数据源 M{StableCoil}/D{TorqueRegister},保持段 {StartSeconds:F3}-{EndSeconds:F3} s,采样数 {SampleCount},扭矩最小 {MinTorque:F6} {TorqueUnit},最大 {MaxTorque:F6} {TorqueUnit},平均 {AverageTorque:F6} {TorqueUnit},波动 {Fluctuation:F6} {TorqueUnit},转速最小 {MinSpeed:F3} r/min,最大 {MaxSpeed:F3} r/min,平均 {AverageSpeed:F3} r/min", + run.RunId, + reason, + SpeedTorqueStableCoil, + TorqueDisplayRegister, + curve.EvaluationStartSeconds, + curve.EvaluationEndSeconds, + curve.EvaluationSampleCount, + curve.MinTorqueMilliNewtonMeters, + TorqueUnit, + curve.MaxTorqueMilliNewtonMeters, + TorqueUnit, + curve.AverageTorqueMilliNewtonMeters, + TorqueUnit, + curve.FluctuationMilliNewtonMeters, + TorqueUnit, + curve.MinSpeedRpm, + curve.MaxSpeedRpm, + curve.AverageSpeedRpm); + } + private static void AppendSample(TestRunPayload? run, RealtimeSamplePayload sample) { if (run is null || run.Samples.LastOrDefault()?.Sequence == sample.Sequence) @@ -3807,6 +3891,8 @@ public sealed class MainWindowViewModel : ObservableObject AppendLatestSample(_activeSpeedTorqueRun); _cachedTorqueCurve = CreateTorqueCurvePayload(_activeSpeedTorqueRun); + LogStableTorqueSummary(_activeSpeedTorqueRun, $"测试结束:{status}"); + _wasSpeedTorqueStable = false; _activeSpeedTorqueRun.CompletedAt = DateTime.Now; _activeSpeedTorqueRun.CompletionStatus = status; _activeSpeedTorqueRun.FinalDisplacementMm = _finalSpeedTorqueDisplacement ?? _speedTorqueDisplacement;