更新
This commit is contained in:
@@ -18,8 +18,12 @@ public sealed class ConeRadiationSettingsViewModel : PageViewModel
|
|||||||
private const double CurrentTemperatureMaximumDropPerRefresh = 80;
|
private const double CurrentTemperatureMaximumDropPerRefresh = 80;
|
||||||
private const double CurrentHeatFluxMinimum = 0;
|
private const double CurrentHeatFluxMinimum = 0;
|
||||||
private const double CurrentHeatFluxMaximum = 1000;
|
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 CurrentHeatFluxStableReadCount = 3;
|
||||||
|
private const int CurrentHeatFluxZeroStableReadCount = 10;
|
||||||
private const double HeatTransferInputMinimum = 0;
|
private const double HeatTransferInputMinimum = 0;
|
||||||
private const double HeatTransferReadMinimum = 0.01;
|
private const double HeatTransferReadMinimum = 0.01;
|
||||||
private const double HeatTransferMaximum = 20000;
|
private const double HeatTransferMaximum = 20000;
|
||||||
@@ -36,6 +40,14 @@ public sealed class ConeRadiationSettingsViewModel : PageViewModel
|
|||||||
private readonly DispatcherTimer _refreshTimer;
|
private readonly DispatcherTimer _refreshTimer;
|
||||||
private readonly HashSet<ushort> _loggedFloatDiagnostics = [];
|
private readonly HashSet<ushort> _loggedFloatDiagnostics = [];
|
||||||
private readonly HashSet<ushort> _loggedInvalidFloatDiagnostics = [];
|
private readonly HashSet<ushort> _loggedInvalidFloatDiagnostics = [];
|
||||||
|
private static readonly ModbusFloatByteOrder[] CurrentHeatFluxByteOrders =
|
||||||
|
[
|
||||||
|
ModbusFloatByteOrder.Abcd,
|
||||||
|
ModbusFloatByteOrder.Cdab,
|
||||||
|
ModbusFloatByteOrder.Badc,
|
||||||
|
ModbusFloatByteOrder.Dcba
|
||||||
|
];
|
||||||
|
|
||||||
private string _currentTemperatureText = "";
|
private string _currentTemperatureText = "";
|
||||||
private string _currentHeatFluxText = "";
|
private string _currentHeatFluxText = "";
|
||||||
private string _targetTemperatureText = "";
|
private string _targetTemperatureText = "";
|
||||||
@@ -49,6 +61,8 @@ public sealed class ConeRadiationSettingsViewModel : PageViewModel
|
|||||||
private double? _lastStableCurrentHeatFlux;
|
private double? _lastStableCurrentHeatFlux;
|
||||||
private double? _pendingCurrentHeatFlux;
|
private double? _pendingCurrentHeatFlux;
|
||||||
private int _pendingCurrentHeatFluxReadCount;
|
private int _pendingCurrentHeatFluxReadCount;
|
||||||
|
private int _pendingCurrentHeatFluxZeroReadCount;
|
||||||
|
private ModbusFloatByteOrder? _currentHeatFluxByteOrder;
|
||||||
private DateTime _parameterRefreshBlockedUntil = DateTime.MinValue;
|
private DateTime _parameterRefreshBlockedUntil = DateTime.MinValue;
|
||||||
|
|
||||||
public ConeRadiationSettingsViewModel(
|
public ConeRadiationSettingsViewModel(
|
||||||
@@ -190,14 +204,7 @@ public sealed class ConeRadiationSettingsViewModel : PageViewModel
|
|||||||
|
|
||||||
private void RefreshDeviceValues()
|
private void RefreshDeviceValues()
|
||||||
{
|
{
|
||||||
if (TryReadRangedFloatText(
|
if (TryReadCurrentHeatFlux(out var currentHeatFlux))
|
||||||
"ConeCurrentHeatFlux",
|
|
||||||
CurrentHeatFluxRegister,
|
|
||||||
CurrentHeatFluxMinimum,
|
|
||||||
CurrentHeatFluxMaximum,
|
|
||||||
"0.00",
|
|
||||||
out _,
|
|
||||||
out var currentHeatFlux))
|
|
||||||
{
|
{
|
||||||
if (TryUpdateStableCurrentHeatFlux(currentHeatFlux, out var stableCurrentHeatFlux))
|
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(
|
private bool TryReadRangedFloatText(
|
||||||
string label,
|
string label,
|
||||||
ushort registerAddress,
|
ushort registerAddress,
|
||||||
@@ -288,8 +335,26 @@ public sealed class ConeRadiationSettingsViewModel : PageViewModel
|
|||||||
value = NormalizeDisplayValue(value);
|
value = NormalizeDisplayValue(value);
|
||||||
stableValue = _lastStableCurrentHeatFlux ?? 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
|
if (_lastStableCurrentHeatFlux.HasValue
|
||||||
&& Math.Abs(value - _lastStableCurrentHeatFlux.Value) <= CurrentHeatFluxStableTolerance)
|
&& IsWithinCurrentHeatFluxStableTolerance(value, _lastStableCurrentHeatFlux.Value))
|
||||||
{
|
{
|
||||||
AcceptStableCurrentHeatFlux(value);
|
AcceptStableCurrentHeatFlux(value);
|
||||||
stableValue = value;
|
stableValue = value;
|
||||||
@@ -297,7 +362,7 @@ public sealed class ConeRadiationSettingsViewModel : PageViewModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!_pendingCurrentHeatFlux.HasValue
|
if (!_pendingCurrentHeatFlux.HasValue
|
||||||
|| Math.Abs(value - _pendingCurrentHeatFlux.Value) > CurrentHeatFluxStableTolerance)
|
|| !IsWithinCurrentHeatFluxStableTolerance(value, _pendingCurrentHeatFlux.Value))
|
||||||
{
|
{
|
||||||
_pendingCurrentHeatFlux = value;
|
_pendingCurrentHeatFlux = value;
|
||||||
_pendingCurrentHeatFluxReadCount = 1;
|
_pendingCurrentHeatFluxReadCount = 1;
|
||||||
@@ -321,6 +386,62 @@ public sealed class ConeRadiationSettingsViewModel : PageViewModel
|
|||||||
_lastStableCurrentHeatFlux = value;
|
_lastStableCurrentHeatFlux = value;
|
||||||
_pendingCurrentHeatFlux = null;
|
_pendingCurrentHeatFlux = null;
|
||||||
_pendingCurrentHeatFluxReadCount = 0;
|
_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)
|
private string ReadScaledInt16Text(ushort registerAddress, double scale, string format)
|
||||||
|
|||||||
Reference in New Issue
Block a user