更新20260526
This commit is contained in:
@@ -23,7 +23,8 @@ public sealed class CValueCalibrationViewModel : PageViewModel
|
||||
private const double PressureDifferenceMaximum = 5000;
|
||||
private const double CValueMinimum = 0;
|
||||
private const double CValueMaximum = 1000;
|
||||
private const double BaselineOxygenDisplayScale = 100;
|
||||
private const double FractionalOxygenMaximum = 0.3;
|
||||
private const double PlausibleOxygenMinimum = 1;
|
||||
private const ushort CirculatingWaterCoil = 49;
|
||||
private const ushort SamplingPumpCoil = 50;
|
||||
private const ushort IgniterCoil = 53;
|
||||
@@ -41,6 +42,13 @@ public sealed class CValueCalibrationViewModel : PageViewModel
|
||||
private const string MethaneValveAction = "甲烷阀";
|
||||
private const string BaselineCollectionAction = "基线采集";
|
||||
private const string CalibrationStartAction = "标定开始";
|
||||
private static readonly ModbusFloatByteOrder[] FloatByteOrders =
|
||||
[
|
||||
ModbusFloatByteOrder.Abcd,
|
||||
ModbusFloatByteOrder.Cdab,
|
||||
ModbusFloatByteOrder.Badc,
|
||||
ModbusFloatByteOrder.Dcba
|
||||
];
|
||||
|
||||
private readonly Action _closeAction;
|
||||
private readonly Action _helpAction;
|
||||
@@ -185,13 +193,10 @@ public sealed class CValueCalibrationViewModel : PageViewModel
|
||||
|
||||
private void RefreshDeviceValues()
|
||||
{
|
||||
BaselineOxygenText = ReadRangedFloatText(
|
||||
BaselineOxygenText = ReadOxygenPercentText(
|
||||
"BaselineOxygen",
|
||||
BaselineOxygenRegister,
|
||||
OxygenMinimum,
|
||||
OxygenMaximum / BaselineOxygenDisplayScale,
|
||||
"0.00",
|
||||
BaselineOxygenDisplayScale);
|
||||
"0.00");
|
||||
TemperatureText = ReadRangedFloatText(
|
||||
"Temperature",
|
||||
TemperatureRegister,
|
||||
@@ -224,8 +229,7 @@ public sealed class CValueCalibrationViewModel : PageViewModel
|
||||
ushort registerAddress,
|
||||
double minimum,
|
||||
double maximum,
|
||||
string format,
|
||||
double displayScale = 1)
|
||||
string format)
|
||||
{
|
||||
if (!_tcpDeviceConnectionService.TryReadFloatValues(registerAddress, out var result))
|
||||
{
|
||||
@@ -239,7 +243,107 @@ public sealed class CValueCalibrationViewModel : PageViewModel
|
||||
}
|
||||
|
||||
LogFloatDiagnostic(label, registerAddress, result, byteOrder, matchCount);
|
||||
return NormalizeDisplayValue(value * displayScale).ToString(format, CultureInfo.InvariantCulture);
|
||||
return NormalizeDisplayValue(value).ToString(format, CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
private string ReadOxygenPercentText(
|
||||
string label,
|
||||
ushort registerAddress,
|
||||
string format)
|
||||
{
|
||||
if (!_tcpDeviceConnectionService.TryReadFloatValues(registerAddress, out var result))
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
if (!TrySelectOxygenPercent(result, 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 static bool TrySelectOxygenPercent(
|
||||
ModbusFloatReadResult result,
|
||||
out ModbusFloatByteOrder byteOrder,
|
||||
out double value,
|
||||
out int matchCount)
|
||||
{
|
||||
var candidates = FloatByteOrders
|
||||
.Select(candidate => CreateOxygenCandidate(candidate, result.GetValue(candidate)))
|
||||
.Where(candidate => candidate.IsValid)
|
||||
.ToArray();
|
||||
|
||||
matchCount = candidates.Length;
|
||||
|
||||
var selected = candidates.FirstOrDefault(
|
||||
candidate => candidate.ByteOrder == ModbusFloatByteOrder.Abcd && candidate.IsPlausible);
|
||||
|
||||
if (!selected.IsValid)
|
||||
{
|
||||
var plausibleCandidates = candidates
|
||||
.Where(candidate => candidate.IsPlausible)
|
||||
.ToArray();
|
||||
|
||||
if (plausibleCandidates.Length == 1)
|
||||
{
|
||||
selected = plausibleCandidates[0];
|
||||
}
|
||||
}
|
||||
|
||||
if (!selected.IsValid)
|
||||
{
|
||||
selected = candidates.FirstOrDefault(candidate => candidate.ByteOrder == ModbusFloatByteOrder.Abcd);
|
||||
}
|
||||
|
||||
if (!selected.IsValid && candidates.Length == 1)
|
||||
{
|
||||
selected = candidates[0];
|
||||
}
|
||||
|
||||
if (!selected.IsValid)
|
||||
{
|
||||
byteOrder = default;
|
||||
value = double.NaN;
|
||||
return false;
|
||||
}
|
||||
|
||||
byteOrder = selected.ByteOrder;
|
||||
value = selected.PercentValue;
|
||||
return true;
|
||||
}
|
||||
|
||||
private static OxygenPercentCandidate CreateOxygenCandidate(
|
||||
ModbusFloatByteOrder byteOrder,
|
||||
double rawValue)
|
||||
{
|
||||
if (!double.IsFinite(rawValue) || rawValue < OxygenMinimum)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
double percentValue;
|
||||
if (rawValue > OxygenMinimum && rawValue <= FractionalOxygenMaximum)
|
||||
{
|
||||
percentValue = rawValue * 100;
|
||||
}
|
||||
else if (rawValue <= OxygenMaximum)
|
||||
{
|
||||
percentValue = rawValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
return new OxygenPercentCandidate(
|
||||
byteOrder,
|
||||
percentValue,
|
||||
percentValue >= PlausibleOxygenMinimum && percentValue <= OxygenMaximum,
|
||||
true);
|
||||
}
|
||||
|
||||
private void LogFloatDiagnostic(
|
||||
@@ -523,6 +627,12 @@ public sealed class CValueCalibrationViewModel : PageViewModel
|
||||
return action is BaselineCollectionAction or CalibrationStartAction;
|
||||
}
|
||||
|
||||
private readonly record struct OxygenPercentCandidate(
|
||||
ModbusFloatByteOrder ByteOrder,
|
||||
double PercentValue,
|
||||
bool IsPlausible,
|
||||
bool IsValid);
|
||||
|
||||
private sealed class PairedActionWaitState(
|
||||
ushort completionCoilAddress,
|
||||
string waitingText,
|
||||
|
||||
Reference in New Issue
Block a user