更新
This commit is contained in:
@@ -18,8 +18,12 @@ public sealed class ConeRadiationSettingsViewModel : PageViewModel
|
||||
private const double CurrentTemperatureMaximumDropPerRefresh = 80;
|
||||
private const double CurrentHeatFluxMinimum = 0;
|
||||
private const double CurrentHeatFluxMaximum = 1000;
|
||||
private const double CurrentHeatFluxStableTolerance = 5;
|
||||
private const double CurrentHeatFluxZeroTolerance = 0.005;
|
||||
private const double CurrentHeatFluxStableAbsoluteTolerance = 0.25;
|
||||
private const double CurrentHeatFluxStableRelativeTolerance = 0.1;
|
||||
private const double CurrentHeatFluxStableMaximumTolerance = 5;
|
||||
private const int CurrentHeatFluxStableReadCount = 3;
|
||||
private const int CurrentHeatFluxZeroStableReadCount = 10;
|
||||
private const double HeatTransferInputMinimum = 0;
|
||||
private const double HeatTransferReadMinimum = 0.01;
|
||||
private const double HeatTransferMaximum = 20000;
|
||||
@@ -36,6 +40,14 @@ public sealed class ConeRadiationSettingsViewModel : PageViewModel
|
||||
private readonly DispatcherTimer _refreshTimer;
|
||||
private readonly HashSet<ushort> _loggedFloatDiagnostics = [];
|
||||
private readonly HashSet<ushort> _loggedInvalidFloatDiagnostics = [];
|
||||
private static readonly ModbusFloatByteOrder[] CurrentHeatFluxByteOrders =
|
||||
[
|
||||
ModbusFloatByteOrder.Abcd,
|
||||
ModbusFloatByteOrder.Cdab,
|
||||
ModbusFloatByteOrder.Badc,
|
||||
ModbusFloatByteOrder.Dcba
|
||||
];
|
||||
|
||||
private string _currentTemperatureText = "";
|
||||
private string _currentHeatFluxText = "";
|
||||
private string _targetTemperatureText = "";
|
||||
@@ -49,6 +61,8 @@ public sealed class ConeRadiationSettingsViewModel : PageViewModel
|
||||
private double? _lastStableCurrentHeatFlux;
|
||||
private double? _pendingCurrentHeatFlux;
|
||||
private int _pendingCurrentHeatFluxReadCount;
|
||||
private int _pendingCurrentHeatFluxZeroReadCount;
|
||||
private ModbusFloatByteOrder? _currentHeatFluxByteOrder;
|
||||
private DateTime _parameterRefreshBlockedUntil = DateTime.MinValue;
|
||||
|
||||
public ConeRadiationSettingsViewModel(
|
||||
@@ -190,14 +204,7 @@ public sealed class ConeRadiationSettingsViewModel : PageViewModel
|
||||
|
||||
private void RefreshDeviceValues()
|
||||
{
|
||||
if (TryReadRangedFloatText(
|
||||
"ConeCurrentHeatFlux",
|
||||
CurrentHeatFluxRegister,
|
||||
CurrentHeatFluxMinimum,
|
||||
CurrentHeatFluxMaximum,
|
||||
"0.00",
|
||||
out _,
|
||||
out var currentHeatFlux))
|
||||
if (TryReadCurrentHeatFlux(out var currentHeatFlux))
|
||||
{
|
||||
if (TryUpdateStableCurrentHeatFlux(currentHeatFlux, out var stableCurrentHeatFlux))
|
||||
{
|
||||
@@ -243,6 +250,46 @@ public sealed class ConeRadiationSettingsViewModel : PageViewModel
|
||||
}
|
||||
}
|
||||
|
||||
private bool TryReadCurrentHeatFlux(out double value)
|
||||
{
|
||||
value = double.NaN;
|
||||
|
||||
if (!_tcpDeviceConnectionService.TryReadFloatValues(CurrentHeatFluxRegister, out var result))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var preferredByteOrder = _currentHeatFluxByteOrder;
|
||||
if (!ModbusFloatSelector.TrySelectRangedFloat(
|
||||
result,
|
||||
CurrentHeatFluxMinimum,
|
||||
CurrentHeatFluxMaximum,
|
||||
out var byteOrder,
|
||||
out var selectedValue,
|
||||
out var matchCount,
|
||||
preferredByteOrder))
|
||||
{
|
||||
if (!TrySelectSingleNonZeroCurrentHeatFluxCandidate(result, out byteOrder, out selectedValue))
|
||||
{
|
||||
LogFloatDiagnostic("ConeCurrentHeatFlux", CurrentHeatFluxRegister, result, null, matchCount);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!preferredByteOrder.HasValue
|
||||
&& IsZeroLikeCurrentHeatFlux(selectedValue)
|
||||
&& TrySelectSingleNonZeroCurrentHeatFluxCandidate(result, out var nonZeroByteOrder, out var nonZeroValue))
|
||||
{
|
||||
byteOrder = nonZeroByteOrder;
|
||||
selectedValue = nonZeroValue;
|
||||
}
|
||||
|
||||
LogFloatDiagnostic("ConeCurrentHeatFlux", CurrentHeatFluxRegister, result, byteOrder, matchCount);
|
||||
RememberCurrentHeatFluxByteOrder(byteOrder, selectedValue);
|
||||
value = NormalizeDisplayValue(selectedValue);
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool TryReadRangedFloatText(
|
||||
string label,
|
||||
ushort registerAddress,
|
||||
@@ -288,8 +335,26 @@ public sealed class ConeRadiationSettingsViewModel : PageViewModel
|
||||
value = NormalizeDisplayValue(value);
|
||||
stableValue = _lastStableCurrentHeatFlux ?? value;
|
||||
|
||||
if (IsZeroLikeCurrentHeatFlux(value))
|
||||
{
|
||||
_pendingCurrentHeatFlux = null;
|
||||
_pendingCurrentHeatFluxReadCount = 0;
|
||||
_pendingCurrentHeatFluxZeroReadCount++;
|
||||
|
||||
if (_pendingCurrentHeatFluxZeroReadCount < CurrentHeatFluxZeroStableReadCount)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
AcceptStableCurrentHeatFlux(0);
|
||||
stableValue = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
_pendingCurrentHeatFluxZeroReadCount = 0;
|
||||
|
||||
if (_lastStableCurrentHeatFlux.HasValue
|
||||
&& Math.Abs(value - _lastStableCurrentHeatFlux.Value) <= CurrentHeatFluxStableTolerance)
|
||||
&& IsWithinCurrentHeatFluxStableTolerance(value, _lastStableCurrentHeatFlux.Value))
|
||||
{
|
||||
AcceptStableCurrentHeatFlux(value);
|
||||
stableValue = value;
|
||||
@@ -297,7 +362,7 @@ public sealed class ConeRadiationSettingsViewModel : PageViewModel
|
||||
}
|
||||
|
||||
if (!_pendingCurrentHeatFlux.HasValue
|
||||
|| Math.Abs(value - _pendingCurrentHeatFlux.Value) > CurrentHeatFluxStableTolerance)
|
||||
|| !IsWithinCurrentHeatFluxStableTolerance(value, _pendingCurrentHeatFlux.Value))
|
||||
{
|
||||
_pendingCurrentHeatFlux = value;
|
||||
_pendingCurrentHeatFluxReadCount = 1;
|
||||
@@ -321,6 +386,62 @@ public sealed class ConeRadiationSettingsViewModel : PageViewModel
|
||||
_lastStableCurrentHeatFlux = value;
|
||||
_pendingCurrentHeatFlux = null;
|
||||
_pendingCurrentHeatFluxReadCount = 0;
|
||||
_pendingCurrentHeatFluxZeroReadCount = 0;
|
||||
}
|
||||
|
||||
private static bool TrySelectSingleNonZeroCurrentHeatFluxCandidate(
|
||||
ModbusFloatReadResult result,
|
||||
out ModbusFloatByteOrder byteOrder,
|
||||
out double value)
|
||||
{
|
||||
var matches = CurrentHeatFluxByteOrders
|
||||
.Select(candidate => new
|
||||
{
|
||||
ByteOrder = candidate,
|
||||
Value = result.GetValue(candidate)
|
||||
})
|
||||
.Where(candidate => ModbusFloatSelector.IsInRange(
|
||||
candidate.Value,
|
||||
CurrentHeatFluxMinimum,
|
||||
CurrentHeatFluxMaximum)
|
||||
&& !IsZeroLikeCurrentHeatFlux(candidate.Value))
|
||||
.ToArray();
|
||||
|
||||
if (matches.Length != 1)
|
||||
{
|
||||
byteOrder = default;
|
||||
value = double.NaN;
|
||||
return false;
|
||||
}
|
||||
|
||||
byteOrder = matches[0].ByteOrder;
|
||||
value = matches[0].Value;
|
||||
return true;
|
||||
}
|
||||
|
||||
private void RememberCurrentHeatFluxByteOrder(ModbusFloatByteOrder byteOrder, double value)
|
||||
{
|
||||
if (!IsZeroLikeCurrentHeatFlux(value))
|
||||
{
|
||||
_currentHeatFluxByteOrder = byteOrder;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsWithinCurrentHeatFluxStableTolerance(double value, double referenceValue)
|
||||
{
|
||||
return Math.Abs(value - referenceValue) <= GetCurrentHeatFluxStableTolerance(referenceValue);
|
||||
}
|
||||
|
||||
private static double GetCurrentHeatFluxStableTolerance(double referenceValue)
|
||||
{
|
||||
return Math.Min(
|
||||
CurrentHeatFluxStableMaximumTolerance,
|
||||
Math.Max(CurrentHeatFluxStableAbsoluteTolerance, Math.Abs(referenceValue) * CurrentHeatFluxStableRelativeTolerance));
|
||||
}
|
||||
|
||||
private static bool IsZeroLikeCurrentHeatFlux(double value)
|
||||
{
|
||||
return double.IsFinite(value) && Math.Abs(value) < CurrentHeatFluxZeroTolerance;
|
||||
}
|
||||
|
||||
private string ReadScaledInt16Text(ushort registerAddress, double scale, string format)
|
||||
|
||||
Reference in New Issue
Block a user