更新
This commit is contained in:
@@ -12,6 +12,7 @@ public sealed record RealtimeDataRecord(
|
||||
double Oxygen,
|
||||
double CarbonDioxide,
|
||||
double CarbonMonoxide,
|
||||
double Absorbance,
|
||||
double HeatReleaseRate,
|
||||
double PeakHeatReleaseRate,
|
||||
double CFactor,
|
||||
@@ -43,6 +44,7 @@ public sealed record RealtimeDataRecord(
|
||||
snapshot.Oxygen,
|
||||
snapshot.CarbonDioxide,
|
||||
snapshot.CarbonMonoxide,
|
||||
snapshot.Absorbance,
|
||||
snapshot.HeatReleaseRate,
|
||||
snapshot.PeakHeatReleaseRate,
|
||||
snapshot.CFactor,
|
||||
|
||||
@@ -11,6 +11,7 @@ public sealed record RealtimeSnapshot(
|
||||
double Oxygen,
|
||||
double CarbonDioxide,
|
||||
double CarbonMonoxide,
|
||||
double Absorbance,
|
||||
double HeatReleaseRate,
|
||||
double PeakHeatReleaseRate,
|
||||
double CFactor,
|
||||
|
||||
@@ -16,6 +16,9 @@ public sealed class ModbusRealtimeDataService : IRealtimeDataService
|
||||
private const ushort ConeTemperatureRegister = 26;
|
||||
private const ushort OrificeTemperatureRegister = 30;
|
||||
private const ushort SampleTemperatureRegister = 36;
|
||||
private const ushort AbsorbanceRegister = 120;
|
||||
private const double AbsorbanceStableTolerance = 0.25;
|
||||
private const int AbsorbanceStableReadCount = 2;
|
||||
private const ushort CFactorRegister = 312;
|
||||
private const ushort HeatReleaseRateRegister = 354;
|
||||
private const ushort PeakHeatReleaseRateRegister = 376;
|
||||
@@ -40,6 +43,9 @@ public sealed class ModbusRealtimeDataService : IRealtimeDataService
|
||||
private readonly HashSet<ushort> _loggedInvalidFloatDiagnostics = [];
|
||||
private readonly Dictionary<int, double> _stableRealtimeValues = [];
|
||||
private readonly Dictionary<int, int> _pendingZeroReadCounts = [];
|
||||
private double? _stableAbsorbance;
|
||||
private double? _pendingAbsorbance;
|
||||
private int _pendingAbsorbanceReadCount;
|
||||
private ModbusFloatByteOrder? _preferredFloatByteOrder;
|
||||
|
||||
public ModbusRealtimeDataService(
|
||||
@@ -69,6 +75,7 @@ public sealed class ModbusRealtimeDataService : IRealtimeDataService
|
||||
Oxygen: ReadRangedFloatOrEmpty("O2", OxygenRegister, 0, 30),
|
||||
CarbonDioxide: ReadRangedFloatOrEmpty("CO2", CarbonDioxideRegister, 0, 20),
|
||||
CarbonMonoxide: ReadRangedFloatOrEmpty("CO", CarbonMonoxideRegister, 0, 10),
|
||||
Absorbance: ReadAbsorbanceOrEmpty(),
|
||||
HeatReleaseRate: ReadRangedFloatOrEmpty("HeatReleaseRate", HeatReleaseRateRegister, 0, 5000),
|
||||
PeakHeatReleaseRate: ReadRangedFloatOrEmpty("PeakHeatReleaseRate", PeakHeatReleaseRateRegister, 0, 5000),
|
||||
CFactor: ReadRangedFloatOrEmpty("CFactor", CFactorRegister, 0, 1000),
|
||||
@@ -102,6 +109,49 @@ public sealed class ModbusRealtimeDataService : IRealtimeDataService
|
||||
return StabilizeRealtimeValue(registerAddress, value);
|
||||
}
|
||||
|
||||
private double ReadAbsorbanceOrEmpty()
|
||||
{
|
||||
var value = ReadRangedFloatOrEmpty("Absorbance", AbsorbanceRegister, 0, 100);
|
||||
return double.IsFinite(value) && TryUpdateStableAbsorbance(value, out var stableValue)
|
||||
? stableValue
|
||||
: double.NaN;
|
||||
}
|
||||
|
||||
private bool TryUpdateStableAbsorbance(double value, out double stableValue)
|
||||
{
|
||||
stableValue = _stableAbsorbance ?? value;
|
||||
|
||||
if (_stableAbsorbance.HasValue
|
||||
&& Math.Abs(value - _stableAbsorbance.Value) <= AbsorbanceStableTolerance)
|
||||
{
|
||||
_pendingAbsorbance = null;
|
||||
_pendingAbsorbanceReadCount = 0;
|
||||
stableValue = _stableAbsorbance.Value;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!_pendingAbsorbance.HasValue
|
||||
|| Math.Abs(value - _pendingAbsorbance.Value) > AbsorbanceStableTolerance)
|
||||
{
|
||||
_pendingAbsorbance = value;
|
||||
_pendingAbsorbanceReadCount = 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
_pendingAbsorbanceReadCount++;
|
||||
|
||||
if (_pendingAbsorbanceReadCount < AbsorbanceStableReadCount)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
_stableAbsorbance = value;
|
||||
_pendingAbsorbance = null;
|
||||
_pendingAbsorbanceReadCount = 0;
|
||||
stableValue = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool TrySelectRealtimeFloat(
|
||||
ModbusFloatReadResult result,
|
||||
double minimum,
|
||||
|
||||
@@ -13,19 +13,17 @@ public sealed class NpoiRealtimeDataExportService : IRealtimeDataExportService
|
||||
"O2 (%)",
|
||||
"CO2 (%)",
|
||||
"CO (%)",
|
||||
"吸光率%",
|
||||
"孔板压差 (Pa)",
|
||||
"孔板温度 (K)",
|
||||
"HRR",
|
||||
"热释放速率180",
|
||||
"热释放速率300",
|
||||
"THR (MJ/m2)",
|
||||
"SPR",
|
||||
"TSR (m2)",
|
||||
"MLR (g/s)",
|
||||
"热释放KW/m2",
|
||||
"EHC",
|
||||
"损失质量",
|
||||
"试样温度(℃)"
|
||||
"损失质量"
|
||||
];
|
||||
|
||||
public void Export(string outputPath, IReadOnlyList<RealtimeDataRecord> records)
|
||||
@@ -60,19 +58,17 @@ public sealed class NpoiRealtimeDataExportService : IRealtimeDataExportService
|
||||
SetNumeric(row, 1, record.Oxygen);
|
||||
SetNumeric(row, 2, record.CarbonDioxide);
|
||||
SetNumeric(row, 3, record.CarbonMonoxide);
|
||||
SetNumeric(row, 4, record.OrificePressure);
|
||||
SetNumeric(row, 5, record.OrificeTemperature);
|
||||
SetNumeric(row, 6, record.HeatReleaseRate);
|
||||
SetNumeric(row, 7, record.Qa180);
|
||||
SetNumeric(row, 8, record.Qa300);
|
||||
SetNumeric(row, 9, record.TotalHeatRelease);
|
||||
SetNumeric(row, 10, record.SmokeProduction);
|
||||
SetNumeric(row, 11, record.TotalSmoke);
|
||||
SetNumeric(row, 12, record.MassLossRate);
|
||||
SetNumeric(row, 13, record.HeatReleaseRateKw);
|
||||
SetNumeric(row, 14, record.EffectiveHeatOfCombustion);
|
||||
SetNumeric(row, 15, record.MassLoss);
|
||||
SetNumeric(row, 16, record.SampleTemperature);
|
||||
SetNumeric(row, 4, record.Absorbance);
|
||||
SetNumeric(row, 5, record.OrificePressure);
|
||||
SetNumeric(row, 6, record.OrificeTemperature);
|
||||
SetNumeric(row, 7, record.HeatReleaseRate);
|
||||
SetNumeric(row, 8, record.TotalHeatRelease);
|
||||
SetNumeric(row, 9, record.SmokeProduction);
|
||||
SetNumeric(row, 10, record.TotalSmoke);
|
||||
SetNumeric(row, 11, record.MassLossRate);
|
||||
SetNumeric(row, 12, record.HeatReleaseRateKw);
|
||||
SetNumeric(row, 13, record.EffectiveHeatOfCombustion);
|
||||
SetNumeric(row, 14, record.MassLoss);
|
||||
}
|
||||
|
||||
for (var i = 0; i < Headers.Length; i++)
|
||||
|
||||
@@ -22,13 +22,13 @@ public sealed class NpoiReportExportService : IReportExportService
|
||||
"O2 (%)",
|
||||
"CO2 (%)",
|
||||
"CO (%)",
|
||||
"吸光率%",
|
||||
"孔板压差 (Pa)",
|
||||
"孔板温度 (K)",
|
||||
"MLR (g/s)",
|
||||
"热释放KW/m2",
|
||||
"EHC",
|
||||
"损失质量",
|
||||
"试样温度(℃)",
|
||||
"Timestamp",
|
||||
"点火计时(s)",
|
||||
"火焰监测",
|
||||
@@ -37,8 +37,6 @@ public sealed class NpoiReportExportService : IReportExportService
|
||||
"当前质量",
|
||||
"初始质量",
|
||||
"最大热释放",
|
||||
"热释放速率180",
|
||||
"热释放速率300",
|
||||
"C-系数"
|
||||
];
|
||||
|
||||
@@ -176,13 +174,13 @@ public sealed class NpoiReportExportService : IReportExportService
|
||||
SetNumeric(row, 7, record.Oxygen);
|
||||
SetNumeric(row, 8, record.CarbonDioxide);
|
||||
SetNumeric(row, 9, record.CarbonMonoxide);
|
||||
SetNumeric(row, 10, record.OrificePressure);
|
||||
SetNumeric(row, 11, record.OrificeTemperature);
|
||||
SetNumeric(row, 12, record.MassLossRate);
|
||||
SetNumeric(row, 13, record.HeatReleaseRateKw);
|
||||
SetNumeric(row, 14, record.EffectiveHeatOfCombustion);
|
||||
SetNumeric(row, 15, record.MassLoss);
|
||||
SetNumeric(row, 16, record.SampleTemperature);
|
||||
SetNumeric(row, 10, record.Absorbance);
|
||||
SetNumeric(row, 11, record.OrificePressure);
|
||||
SetNumeric(row, 12, record.OrificeTemperature);
|
||||
SetNumeric(row, 13, record.MassLossRate);
|
||||
SetNumeric(row, 14, record.HeatReleaseRateKw);
|
||||
SetNumeric(row, 15, record.EffectiveHeatOfCombustion);
|
||||
SetNumeric(row, 16, record.MassLoss);
|
||||
row.CreateCell(17).SetCellValue(record.Timestamp.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.CurrentCulture));
|
||||
SetNumeric(row, 18, record.IgnitionSeconds >= 0 ? record.IgnitionSeconds : double.NaN);
|
||||
SetNumeric(row, 19, record.FlameDetected ? 1 : 0);
|
||||
@@ -191,9 +189,7 @@ public sealed class NpoiReportExportService : IReportExportService
|
||||
SetNumeric(row, 22, record.CurrentMass);
|
||||
SetNumeric(row, 23, record.InitialMass);
|
||||
SetNumeric(row, 24, record.PeakHeatReleaseRate);
|
||||
SetNumeric(row, 25, record.Qa180);
|
||||
SetNumeric(row, 26, record.Qa300);
|
||||
SetNumeric(row, 27, record.CFactor);
|
||||
SetNumeric(row, 25, record.CFactor);
|
||||
}
|
||||
|
||||
for (var i = 0; i < DataHeaders.Length; i++)
|
||||
|
||||
@@ -20,7 +20,7 @@ public sealed record SerialScaleOptions(
|
||||
public const string RegisterEnvironmentVariable = "CONE_SCALE_REGISTER";
|
||||
|
||||
public static SerialScaleOptions Default { get; } = new(
|
||||
"COM1",
|
||||
"COM3",
|
||||
9600,
|
||||
Parity.None,
|
||||
8,
|
||||
|
||||
@@ -17,9 +17,8 @@ public sealed class RealtimeDataRowViewModel
|
||||
CarbonMonoxideText = Format(record.CarbonMonoxide);
|
||||
OrificePressureText = Format(record.OrificePressure);
|
||||
OrificeTemperatureText = Format(record.OrificeTemperature);
|
||||
AbsorbanceText = Format(record.Absorbance);
|
||||
Hrr50Text = Format(record.HeatReleaseRate);
|
||||
Qa180Text = Format(record.Qa180);
|
||||
Qa300Text = Format(record.Qa300);
|
||||
ThrText = Format(record.TotalHeatRelease);
|
||||
Spr50Text = Format(record.SmokeProduction);
|
||||
TsrText = Format(record.TotalSmoke);
|
||||
@@ -27,7 +26,6 @@ public sealed class RealtimeDataRowViewModel
|
||||
HeatReleaseText = Format(record.HeatReleaseRateKw);
|
||||
EhcText = Format(record.EffectiveHeatOfCombustion);
|
||||
MassLossText = Format(record.MassLoss);
|
||||
SampleTemperatureText = Format(record.SampleTemperature, "0.0");
|
||||
}
|
||||
|
||||
public string TimeText { get; init; } = string.Empty;
|
||||
@@ -42,12 +40,10 @@ public sealed class RealtimeDataRowViewModel
|
||||
|
||||
public string OrificeTemperatureText { get; init; } = string.Empty;
|
||||
|
||||
public string AbsorbanceText { get; init; } = string.Empty;
|
||||
|
||||
public string Hrr50Text { get; init; } = string.Empty;
|
||||
|
||||
public string Qa180Text { get; init; } = string.Empty;
|
||||
|
||||
public string Qa300Text { get; init; } = string.Empty;
|
||||
|
||||
public string ThrText { get; init; } = string.Empty;
|
||||
|
||||
public string Spr50Text { get; init; } = string.Empty;
|
||||
@@ -62,8 +58,6 @@ public sealed class RealtimeDataRowViewModel
|
||||
|
||||
public string MassLossText { get; init; } = string.Empty;
|
||||
|
||||
public string SampleTemperatureText { get; init; } = string.Empty;
|
||||
|
||||
private static string Format(double value, string format = "0.00")
|
||||
{
|
||||
return double.IsFinite(value) ? value.ToString(format, CultureInfo.InvariantCulture) : string.Empty;
|
||||
|
||||
@@ -138,11 +138,10 @@
|
||||
<DataGridTextColumn Header="O2 (%)" Binding="{Binding OxygenText}" Width="82" ElementStyle="{StaticResource RealtimeTextElementStyle}" />
|
||||
<DataGridTextColumn Header="CO2 (%)" Binding="{Binding CarbonDioxideText}" Width="88" ElementStyle="{StaticResource RealtimeTextElementStyle}" />
|
||||
<DataGridTextColumn Header="CO (%)" Binding="{Binding CarbonMonoxideText}" Width="82" ElementStyle="{StaticResource RealtimeTextElementStyle}" />
|
||||
<DataGridTextColumn Header="吸光率%" Binding="{Binding AbsorbanceText}" Width="88" ElementStyle="{StaticResource RealtimeTextElementStyle}" />
|
||||
<DataGridTextColumn Header="孔板压差 (Pa)" Binding="{Binding OrificePressureText}" Width="116" ElementStyle="{StaticResource RealtimeTextElementStyle}" />
|
||||
<DataGridTextColumn Header="孔板温度 (K)" Binding="{Binding OrificeTemperatureText}" Width="116" ElementStyle="{StaticResource RealtimeTextElementStyle}" />
|
||||
<DataGridTextColumn Header="HRR" Binding="{Binding Hrr50Text}" Width="78" ElementStyle="{StaticResource RealtimeTextElementStyle}" />
|
||||
<DataGridTextColumn Header="热释放速率180" Binding="{Binding Qa180Text}" Width="118" ElementStyle="{StaticResource RealtimeTextElementStyle}" />
|
||||
<DataGridTextColumn Header="热释放速率300" Binding="{Binding Qa300Text}" Width="118" ElementStyle="{StaticResource RealtimeTextElementStyle}" />
|
||||
<DataGridTextColumn Header="THR (MJ/m2)" Binding="{Binding ThrText}" Width="108" ElementStyle="{StaticResource RealtimeTextElementStyle}" />
|
||||
<DataGridTextColumn Header="SPR" Binding="{Binding Spr50Text}" Width="78" ElementStyle="{StaticResource RealtimeTextElementStyle}" />
|
||||
<DataGridTextColumn Header="TSR (m2)" Binding="{Binding TsrText}" Width="88" ElementStyle="{StaticResource RealtimeTextElementStyle}" />
|
||||
@@ -150,7 +149,6 @@
|
||||
<DataGridTextColumn Header="热释放KW/m2" Binding="{Binding HeatReleaseText}" Width="122" ElementStyle="{StaticResource RealtimeTextElementStyle}" />
|
||||
<DataGridTextColumn Header="EHC" Binding="{Binding EhcText}" Width="70" ElementStyle="{StaticResource RealtimeTextElementStyle}" />
|
||||
<DataGridTextColumn Header="损失质量" Binding="{Binding MassLossText}" Width="84" ElementStyle="{StaticResource RealtimeTextElementStyle}" />
|
||||
<DataGridTextColumn Header="试样温度(℃)" Binding="{Binding SampleTemperatureText}" Width="124" ElementStyle="{StaticResource RealtimeTextElementStyle}" />
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
</Grid>
|
||||
|
||||
Reference in New Issue
Block a user