更新
This commit is contained in:
@@ -11,10 +11,14 @@ namespace ConeCalorimeter.ViewModels;
|
|||||||
public sealed class SmokeDensitySettingsViewModel : PageViewModel
|
public sealed class SmokeDensitySettingsViewModel : PageViewModel
|
||||||
{
|
{
|
||||||
private const ushort AbsorbanceRegister = 120;
|
private const ushort AbsorbanceRegister = 120;
|
||||||
|
private const double AbsorbanceMinimum = 0;
|
||||||
|
private const double AbsorbanceMaximum = 100;
|
||||||
|
|
||||||
private readonly Action _closeAction;
|
private readonly Action _closeAction;
|
||||||
private readonly ITcpDeviceConnectionService _tcpDeviceConnectionService;
|
private readonly ITcpDeviceConnectionService _tcpDeviceConnectionService;
|
||||||
private readonly DispatcherTimer _refreshTimer;
|
private readonly DispatcherTimer _refreshTimer;
|
||||||
|
private readonly HashSet<ushort> _loggedFloatDiagnostics = [];
|
||||||
|
private readonly HashSet<ushort> _loggedInvalidFloatDiagnostics = [];
|
||||||
private string _absorbanceText = "";
|
private string _absorbanceText = "";
|
||||||
private string _lastCalibration = "待校准";
|
private string _lastCalibration = "待校准";
|
||||||
|
|
||||||
@@ -86,9 +90,67 @@ public sealed class SmokeDensitySettingsViewModel : PageViewModel
|
|||||||
|
|
||||||
private void RefreshDeviceValues()
|
private void RefreshDeviceValues()
|
||||||
{
|
{
|
||||||
AbsorbanceText = _tcpDeviceConnectionService.TryReadFloat(AbsorbanceRegister, out var value)
|
AbsorbanceText = ReadRangedFloatText(
|
||||||
? value.ToString("0.00", CultureInfo.InvariantCulture)
|
"Absorbance",
|
||||||
: string.Empty;
|
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)
|
private static bool TryGetCalibrationCoil(string label, out ushort coilAddress)
|
||||||
|
|||||||
Reference in New Issue
Block a user