This commit is contained in:
GukSang.Jin
2026-05-05 17:41:46 +08:00
parent 9559e61bf9
commit 6a57776f96
4 changed files with 91 additions and 4 deletions

View File

@@ -11,8 +11,10 @@ public sealed class ExperimentDataService : IExperimentDataService
private readonly IRealtimeDataService _realtimeDataService;
private readonly DispatcherTimer _timer;
private readonly DateTime _startedAt = DateTime.Now;
private double? _initialMass;
private double _accumulatedTotalHeatRelease;
private double _accumulatedTotalSmoke;
private bool _isTestRunning;
public ExperimentDataService(IRealtimeDataService realtimeDataService)
{
@@ -37,16 +39,34 @@ public sealed class ExperimentDataService : IExperimentDataService
public event EventHandler<RealtimeSnapshot>? SnapshotUpdated;
public void StartTest()
{
Records.Clear();
ResetComputedState();
_isTestRunning = true;
if (double.IsFinite(CurrentSnapshot.CurrentMass))
{
_initialMass = CurrentSnapshot.CurrentMass;
}
}
public void StopTest()
{
_isTestRunning = false;
_initialMass = null;
}
public void ClearRecords()
{
Records.Clear();
_accumulatedTotalHeatRelease = 0;
_accumulatedTotalSmoke = 0;
ResetComputedState();
}
private void RecordSnapshot(RealtimeSnapshot snapshot)
{
var accumulatedSnapshot = ApplyAccumulatedTotals(snapshot);
var massSnapshot = ApplyMassLoss(snapshot);
var accumulatedSnapshot = ApplyAccumulatedTotals(massSnapshot);
CurrentSnapshot = accumulatedSnapshot;
Records.Add(RealtimeDataRecord.FromSnapshot(accumulatedSnapshot));
@@ -61,6 +81,15 @@ public sealed class ExperimentDataService : IExperimentDataService
private RealtimeSnapshot ApplyAccumulatedTotals(RealtimeSnapshot snapshot)
{
if (!_isTestRunning)
{
return snapshot with
{
TotalHeatRelease = double.NaN,
TotalSmoke = double.NaN
};
}
if (double.IsFinite(snapshot.HeatReleaseRate))
{
_accumulatedTotalHeatRelease += snapshot.HeatReleaseRate;
@@ -77,4 +106,36 @@ public sealed class ExperimentDataService : IExperimentDataService
TotalSmoke = _accumulatedTotalSmoke
};
}
private RealtimeSnapshot ApplyMassLoss(RealtimeSnapshot snapshot)
{
if (!_isTestRunning)
{
return snapshot with
{
MassLoss = double.NaN
};
}
if (!_initialMass.HasValue && double.IsFinite(snapshot.CurrentMass))
{
_initialMass = snapshot.CurrentMass;
}
var massLoss = _initialMass.HasValue && double.IsFinite(snapshot.CurrentMass)
? _initialMass.Value - snapshot.CurrentMass
: double.NaN;
return snapshot with
{
MassLoss = massLoss
};
}
private void ResetComputedState()
{
_initialMass = null;
_accumulatedTotalHeatRelease = 0;
_accumulatedTotalSmoke = 0;
}
}

View File

@@ -11,5 +11,9 @@ public interface IExperimentDataService
event EventHandler<RealtimeSnapshot>? SnapshotUpdated;
void StartTest();
void StopTest();
void ClearRecords();
}

View File

@@ -4,6 +4,7 @@ namespace ConeCalorimeter.Services;
public sealed class ModbusRealtimeDataService : IRealtimeDataService
{
private const ushort CurrentMassRegister = 1;
private const ushort OxygenRegister = 10;
private const ushort OrificeFlowRegister = 14;
private const ushort OrificePressureRegister = 16;
@@ -45,7 +46,7 @@ public sealed class ModbusRealtimeDataService : IRealtimeDataService
Qa300: ReadFloatOrEmpty(Qa300Register),
TotalHeatRelease: double.NaN,
SmokeProduction: ReadFloatOrEmpty(SmokeProductionRegister),
CurrentMass: double.NaN,
CurrentMass: ReadFloatOrEmpty(CurrentMassRegister),
MassLoss: double.NaN,
IgnitionSeconds: ReadInt16OrEmpty(IgnitionSecondsRegister),
TestSeconds: ReadInt16OrEmpty(TestSecondsRegister),

View File

@@ -254,6 +254,16 @@ public sealed class TestPageViewModel : PageViewModel
LastAction = action;
if (action == "测试开始")
{
_experimentDataService.StartTest();
ClearPlotSeries();
}
else if (action == "测试结束")
{
_experimentDataService.StopTest();
}
if (!TryGetDeviceActionCoil(action, out var coilAddress, out var value))
{
return;
@@ -265,6 +275,17 @@ public sealed class TestPageViewModel : PageViewModel
}
}
private void ClearPlotSeries()
{
_heatReleaseSeries.Points.Clear();
_totalHeatSeries.Points.Clear();
_totalSmokeSeries.Points.Clear();
var bottomAxis = HeatReleasePlot.Axes.First(axis => axis.Position == AxisPosition.Bottom);
bottomAxis.Maximum = 300;
HeatReleasePlot.InvalidatePlot(true);
}
private static bool TryGetDeviceActionCoil(string action, out ushort coilAddress, out bool value)
{
value = true;