From e2ee1b2a2d74034baab3e8aeacd0afd70c7cfb94 Mon Sep 17 00:00:00 2001 From: "GukSang.Jin" Date: Fri, 22 May 2026 15:15:48 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SmokeDensitySettingsViewModel.cs | 68 ++++++++++++++++++- 1 file changed, 65 insertions(+), 3 deletions(-) diff --git a/ConeCalorimeter/ViewModels/SmokeDensitySettingsViewModel.cs b/ConeCalorimeter/ViewModels/SmokeDensitySettingsViewModel.cs index 2b5de72..9be537a 100644 --- a/ConeCalorimeter/ViewModels/SmokeDensitySettingsViewModel.cs +++ b/ConeCalorimeter/ViewModels/SmokeDensitySettingsViewModel.cs @@ -11,10 +11,14 @@ namespace ConeCalorimeter.ViewModels; public sealed class SmokeDensitySettingsViewModel : PageViewModel { private const ushort AbsorbanceRegister = 120; + private const double AbsorbanceMinimum = 0; + private const double AbsorbanceMaximum = 100; private readonly Action _closeAction; private readonly ITcpDeviceConnectionService _tcpDeviceConnectionService; private readonly DispatcherTimer _refreshTimer; + private readonly HashSet _loggedFloatDiagnostics = []; + private readonly HashSet _loggedInvalidFloatDiagnostics = []; private string _absorbanceText = ""; private string _lastCalibration = "待校准"; @@ -86,9 +90,67 @@ public sealed class SmokeDensitySettingsViewModel : PageViewModel private void RefreshDeviceValues() { - AbsorbanceText = _tcpDeviceConnectionService.TryReadFloat(AbsorbanceRegister, out var value) - ? value.ToString("0.00", CultureInfo.InvariantCulture) - : string.Empty; + AbsorbanceText = ReadRangedFloatText( + "Absorbance", + AbsorbanceRegister, + AbsorbanceMinimum, + AbsorbanceMaximum, + "0.00"); + } + + private string ReadRangedFloatText( + string label, + ushort registerAddress, + double minimum, + double maximum, + string format) + { + if (!_tcpDeviceConnectionService.TryReadFloatValues(registerAddress, out var result)) + { + return string.Empty; + } + + if (!ModbusFloatSelector.TrySelectRangedFloat(result, minimum, maximum, out var byteOrder, out var value, out var matchCount)) + { + LogFloatDiagnostic(label, registerAddress, result, null, matchCount); + return string.Empty; + } + + LogFloatDiagnostic(label, registerAddress, result, byteOrder, matchCount); + return NormalizeDisplayValue(value).ToString(format, CultureInfo.InvariantCulture); + } + + private void LogFloatDiagnostic( + string label, + ushort registerAddress, + ModbusFloatReadResult result, + ModbusFloatByteOrder? selectedByteOrder, + int matchCount) + { + if (selectedByteOrder is null) + { + if (!_loggedInvalidFloatDiagnostics.Add(registerAddress)) + { + return; + } + } + else if (!_loggedFloatDiagnostics.Add(registerAddress)) + { + return; + } + + var selectedText = selectedByteOrder?.ToString() ?? "none"; + + Debug.WriteLine( + $"Smoke density float {label} register {registerAddress} raw [{result.RawHex}], " + + $"ABCD={result.Abcd:G9}, CDAB={result.Cdab:G9}, " + + $"BADC={result.Badc:G9}, DCBA={result.Dcba:G9}, " + + $"selected={selectedText}, matches={matchCount}."); + } + + private static double NormalizeDisplayValue(double value) + { + return Math.Abs(value) < 0.005 ? 0 : value; } private static bool TryGetCalibrationCoil(string label, out ushort coilAddress)