更新
This commit is contained in:
@@ -49,6 +49,14 @@ public sealed record RealtimeDataRecord(
|
|||||||
snapshot.TotalSmoke);
|
snapshot.TotalSmoke);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public double MassLossRate =>
|
||||||
|
double.IsFinite(MassLoss) && TestSeconds > 0 ? MassLoss / TestSeconds : double.NaN;
|
||||||
|
|
||||||
|
public double HeatReleaseRateKw =>
|
||||||
|
double.IsFinite(HeatReleaseRate) ? HeatReleaseRate * 1000 : double.NaN;
|
||||||
|
|
||||||
public double EffectiveHeatOfCombustion =>
|
public double EffectiveHeatOfCombustion =>
|
||||||
TotalHeatRelease <= 0 ? 0 : HeatReleaseRate / Math.Max(TotalHeatRelease, 1);
|
double.IsFinite(HeatReleaseRate) && double.IsFinite(MassLossRate) && MassLossRate > 0
|
||||||
|
? HeatReleaseRate / MassLossRate * 10
|
||||||
|
: double.NaN;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ public sealed class ExperimentDataService : IExperimentDataService
|
|||||||
private readonly IRealtimeDataService _realtimeDataService;
|
private readonly IRealtimeDataService _realtimeDataService;
|
||||||
private readonly DispatcherTimer _timer;
|
private readonly DispatcherTimer _timer;
|
||||||
private readonly DateTime _startedAt = DateTime.Now;
|
private readonly DateTime _startedAt = DateTime.Now;
|
||||||
|
private double _accumulatedTotalHeatRelease;
|
||||||
|
private double _accumulatedTotalSmoke;
|
||||||
|
|
||||||
public ExperimentDataService(IRealtimeDataService realtimeDataService)
|
public ExperimentDataService(IRealtimeDataService realtimeDataService)
|
||||||
{
|
{
|
||||||
@@ -38,18 +40,41 @@ public sealed class ExperimentDataService : IExperimentDataService
|
|||||||
public void ClearRecords()
|
public void ClearRecords()
|
||||||
{
|
{
|
||||||
Records.Clear();
|
Records.Clear();
|
||||||
|
_accumulatedTotalHeatRelease = 0;
|
||||||
|
_accumulatedTotalSmoke = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RecordSnapshot(RealtimeSnapshot snapshot)
|
private void RecordSnapshot(RealtimeSnapshot snapshot)
|
||||||
{
|
{
|
||||||
CurrentSnapshot = snapshot;
|
var accumulatedSnapshot = ApplyAccumulatedTotals(snapshot);
|
||||||
Records.Add(RealtimeDataRecord.FromSnapshot(snapshot));
|
|
||||||
|
CurrentSnapshot = accumulatedSnapshot;
|
||||||
|
Records.Add(RealtimeDataRecord.FromSnapshot(accumulatedSnapshot));
|
||||||
|
|
||||||
while (Records.Count > MaximumRows)
|
while (Records.Count > MaximumRows)
|
||||||
{
|
{
|
||||||
Records.RemoveAt(0);
|
Records.RemoveAt(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
SnapshotUpdated?.Invoke(this, snapshot);
|
SnapshotUpdated?.Invoke(this, accumulatedSnapshot);
|
||||||
|
}
|
||||||
|
|
||||||
|
private RealtimeSnapshot ApplyAccumulatedTotals(RealtimeSnapshot snapshot)
|
||||||
|
{
|
||||||
|
if (double.IsFinite(snapshot.HeatReleaseRate))
|
||||||
|
{
|
||||||
|
_accumulatedTotalHeatRelease += snapshot.HeatReleaseRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (double.IsFinite(snapshot.SmokeProduction))
|
||||||
|
{
|
||||||
|
_accumulatedTotalSmoke += snapshot.SmokeProduction;
|
||||||
|
}
|
||||||
|
|
||||||
|
return snapshot with
|
||||||
|
{
|
||||||
|
TotalHeatRelease = _accumulatedTotalHeatRelease,
|
||||||
|
TotalSmoke = _accumulatedTotalSmoke
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ public sealed class ModbusRealtimeDataService : IRealtimeDataService
|
|||||||
private const ushort HeatReleaseRateRegister = 354;
|
private const ushort HeatReleaseRateRegister = 354;
|
||||||
private const ushort Qa180Register = 366;
|
private const ushort Qa180Register = 366;
|
||||||
private const ushort Qa300Register = 370;
|
private const ushort Qa300Register = 370;
|
||||||
private const ushort TotalHeatReleaseRegister = 372;
|
|
||||||
private const ushort SmokeProductionRegister = 390;
|
private const ushort SmokeProductionRegister = 390;
|
||||||
private const ushort IgnitionSecondsRegister = 1014;
|
private const ushort IgnitionSecondsRegister = 1014;
|
||||||
private const ushort TestSecondsRegister = 1015;
|
private const ushort TestSecondsRegister = 1015;
|
||||||
@@ -44,13 +43,13 @@ public sealed class ModbusRealtimeDataService : IRealtimeDataService
|
|||||||
HeatReleaseRate: ReadFloatOrEmpty(HeatReleaseRateRegister),
|
HeatReleaseRate: ReadFloatOrEmpty(HeatReleaseRateRegister),
|
||||||
Qa180: ReadFloatOrEmpty(Qa180Register),
|
Qa180: ReadFloatOrEmpty(Qa180Register),
|
||||||
Qa300: ReadFloatOrEmpty(Qa300Register),
|
Qa300: ReadFloatOrEmpty(Qa300Register),
|
||||||
TotalHeatRelease: ReadFloatOrEmpty(TotalHeatReleaseRegister),
|
TotalHeatRelease: double.NaN,
|
||||||
SmokeProduction: ReadFloatOrEmpty(SmokeProductionRegister),
|
SmokeProduction: ReadFloatOrEmpty(SmokeProductionRegister),
|
||||||
CurrentMass: double.NaN,
|
CurrentMass: double.NaN,
|
||||||
MassLoss: double.NaN,
|
MassLoss: double.NaN,
|
||||||
IgnitionSeconds: ReadInt16OrEmpty(IgnitionSecondsRegister),
|
IgnitionSeconds: ReadInt16OrEmpty(IgnitionSecondsRegister),
|
||||||
TestSeconds: ReadInt16OrEmpty(TestSecondsRegister),
|
TestSeconds: ReadInt16OrEmpty(TestSecondsRegister),
|
||||||
TotalSmoke: ReadFloatOrEmpty(SmokeProductionRegister));
|
TotalSmoke: double.NaN);
|
||||||
}
|
}
|
||||||
|
|
||||||
private double ReadFloatOrEmpty(ushort registerAddress)
|
private double ReadFloatOrEmpty(ushort registerAddress)
|
||||||
|
|||||||
@@ -18,9 +18,9 @@ public sealed class NpoiReportExportService : IReportExportService
|
|||||||
"CO (%)",
|
"CO (%)",
|
||||||
"孔板压差 (Pa)",
|
"孔板压差 (Pa)",
|
||||||
"孔板温度 (℃)",
|
"孔板温度 (℃)",
|
||||||
"HRR50",
|
"HRR",
|
||||||
"THR (MJ/m2)",
|
"THR (MJ/m2)",
|
||||||
"SPR50",
|
"SPR",
|
||||||
"TSR (m2)",
|
"TSR (m2)",
|
||||||
"MLR (g/s)",
|
"MLR (g/s)",
|
||||||
"热释放KW/m2",
|
"热释放KW/m2",
|
||||||
@@ -119,7 +119,7 @@ public sealed class NpoiReportExportService : IReportExportService
|
|||||||
{
|
{
|
||||||
var row = sheet.CreateRow(i + 1);
|
var row = sheet.CreateRow(i + 1);
|
||||||
var record = records[i];
|
var record = records[i];
|
||||||
SetNumeric(row, 0, record.TestSeconds);
|
SetNumeric(row, 0, record.TestSeconds >= 0 ? record.TestSeconds : double.NaN);
|
||||||
SetNumeric(row, 1, record.Oxygen);
|
SetNumeric(row, 1, record.Oxygen);
|
||||||
SetNumeric(row, 2, record.CarbonDioxide);
|
SetNumeric(row, 2, record.CarbonDioxide);
|
||||||
SetNumeric(row, 3, record.CarbonMonoxide);
|
SetNumeric(row, 3, record.CarbonMonoxide);
|
||||||
@@ -129,11 +129,11 @@ public sealed class NpoiReportExportService : IReportExportService
|
|||||||
SetNumeric(row, 7, record.TotalHeatRelease);
|
SetNumeric(row, 7, record.TotalHeatRelease);
|
||||||
SetNumeric(row, 8, record.SmokeProduction);
|
SetNumeric(row, 8, record.SmokeProduction);
|
||||||
SetNumeric(row, 9, record.TotalSmoke);
|
SetNumeric(row, 9, record.TotalSmoke);
|
||||||
SetNumeric(row, 10, record.MassLoss);
|
SetNumeric(row, 10, record.MassLossRate);
|
||||||
SetNumeric(row, 11, record.HeatReleaseRate);
|
SetNumeric(row, 11, record.HeatReleaseRateKw);
|
||||||
SetNumeric(row, 12, record.EffectiveHeatOfCombustion);
|
SetNumeric(row, 12, record.EffectiveHeatOfCombustion);
|
||||||
SetNumeric(row, 13, record.MassLoss);
|
SetNumeric(row, 13, record.MassLoss);
|
||||||
SetNumeric(row, 14, record.ConeTemperature);
|
SetNumeric(row, 14, record.SampleTemperature);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var i = 0; i < DataHeaders.Length; i++)
|
for (var i = 0; i < DataHeaders.Length; i++)
|
||||||
@@ -223,7 +223,10 @@ public sealed class NpoiReportExportService : IReportExportService
|
|||||||
|
|
||||||
private static void SetNumeric(IRow row, int columnIndex, double value)
|
private static void SetNumeric(IRow row, int columnIndex, double value)
|
||||||
{
|
{
|
||||||
row.CreateCell(columnIndex).SetCellValue(double.IsFinite(value) ? value : 0);
|
if (double.IsFinite(value))
|
||||||
|
{
|
||||||
|
row.CreateCell(columnIndex).SetCellValue(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string FindTemplatePath()
|
private static string FindTemplatePath()
|
||||||
@@ -270,7 +273,7 @@ public sealed class NpoiReportExportService : IReportExportService
|
|||||||
|
|
||||||
private static string FormatWithUnit(double? value, string unit)
|
private static string FormatWithUnit(double? value, string unit)
|
||||||
{
|
{
|
||||||
return value is null ? "" : $"{value.Value:0.00} {unit}";
|
return value is null || !double.IsFinite(value.Value) ? "" : $"{value.Value:0.00} {unit}";
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string FirstNonEmpty(params string[] values)
|
private static string FirstNonEmpty(params string[] values)
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ public sealed class RealtimeDataRowViewModel
|
|||||||
ThrText = Format(record.TotalHeatRelease);
|
ThrText = Format(record.TotalHeatRelease);
|
||||||
Spr50Text = Format(record.SmokeProduction);
|
Spr50Text = Format(record.SmokeProduction);
|
||||||
TsrText = Format(record.TotalSmoke);
|
TsrText = Format(record.TotalSmoke);
|
||||||
MlrText = Format(record.MassLoss);
|
MlrText = Format(record.MassLossRate);
|
||||||
HeatReleaseText = Format(record.HeatReleaseRate);
|
HeatReleaseText = Format(record.HeatReleaseRateKw);
|
||||||
EhcText = Format(record.EffectiveHeatOfCombustion);
|
EhcText = Format(record.EffectiveHeatOfCombustion);
|
||||||
MassLossText = Format(record.MassLoss);
|
MassLossText = Format(record.MassLoss);
|
||||||
SampleTemperatureText = Format(record.SampleTemperature, "0.0");
|
SampleTemperatureText = Format(record.SampleTemperature, "0.0");
|
||||||
|
|||||||
@@ -139,9 +139,9 @@
|
|||||||
<DataGridTextColumn Header="CO (%)" Binding="{Binding CarbonMonoxideText}" Width="82" ElementStyle="{StaticResource RealtimeTextElementStyle}" />
|
<DataGridTextColumn Header="CO (%)" Binding="{Binding CarbonMonoxideText}" Width="82" ElementStyle="{StaticResource RealtimeTextElementStyle}" />
|
||||||
<DataGridTextColumn Header="孔板压差 (Pa)" Binding="{Binding OrificePressureText}" Width="116" ElementStyle="{StaticResource RealtimeTextElementStyle}" />
|
<DataGridTextColumn Header="孔板压差 (Pa)" Binding="{Binding OrificePressureText}" Width="116" ElementStyle="{StaticResource RealtimeTextElementStyle}" />
|
||||||
<DataGridTextColumn Header="孔板温度 (℃)" Binding="{Binding OrificeTemperatureText}" Width="116" ElementStyle="{StaticResource RealtimeTextElementStyle}" />
|
<DataGridTextColumn Header="孔板温度 (℃)" Binding="{Binding OrificeTemperatureText}" Width="116" ElementStyle="{StaticResource RealtimeTextElementStyle}" />
|
||||||
<DataGridTextColumn Header="HRR50" Binding="{Binding Hrr50Text}" Width="78" ElementStyle="{StaticResource RealtimeTextElementStyle}" />
|
<DataGridTextColumn Header="HRR" Binding="{Binding Hrr50Text}" Width="78" ElementStyle="{StaticResource RealtimeTextElementStyle}" />
|
||||||
<DataGridTextColumn Header="THR (MJ/m2)" Binding="{Binding ThrText}" Width="108" ElementStyle="{StaticResource RealtimeTextElementStyle}" />
|
<DataGridTextColumn Header="THR (MJ/m2)" Binding="{Binding ThrText}" Width="108" ElementStyle="{StaticResource RealtimeTextElementStyle}" />
|
||||||
<DataGridTextColumn Header="SPR50" Binding="{Binding Spr50Text}" Width="78" 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}" />
|
<DataGridTextColumn Header="TSR (m2)" Binding="{Binding TsrText}" Width="88" ElementStyle="{StaticResource RealtimeTextElementStyle}" />
|
||||||
<DataGridTextColumn Header="MLR (g/s)" Binding="{Binding MlrText}" Width="92" ElementStyle="{StaticResource RealtimeTextElementStyle}" />
|
<DataGridTextColumn Header="MLR (g/s)" Binding="{Binding MlrText}" Width="92" ElementStyle="{StaticResource RealtimeTextElementStyle}" />
|
||||||
<DataGridTextColumn Header="热释放KW/m2" Binding="{Binding HeatReleaseText}" Width="122" ElementStyle="{StaticResource RealtimeTextElementStyle}" />
|
<DataGridTextColumn Header="热释放KW/m2" Binding="{Binding HeatReleaseText}" Width="122" ElementStyle="{StaticResource RealtimeTextElementStyle}" />
|
||||||
|
|||||||
Reference in New Issue
Block a user