更新
This commit is contained in:
@@ -11,8 +11,10 @@ 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? _initialMass;
|
||||||
private double _accumulatedTotalHeatRelease;
|
private double _accumulatedTotalHeatRelease;
|
||||||
private double _accumulatedTotalSmoke;
|
private double _accumulatedTotalSmoke;
|
||||||
|
private bool _isTestRunning;
|
||||||
|
|
||||||
public ExperimentDataService(IRealtimeDataService realtimeDataService)
|
public ExperimentDataService(IRealtimeDataService realtimeDataService)
|
||||||
{
|
{
|
||||||
@@ -37,16 +39,34 @@ public sealed class ExperimentDataService : IExperimentDataService
|
|||||||
|
|
||||||
public event EventHandler<RealtimeSnapshot>? SnapshotUpdated;
|
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()
|
public void ClearRecords()
|
||||||
{
|
{
|
||||||
Records.Clear();
|
Records.Clear();
|
||||||
_accumulatedTotalHeatRelease = 0;
|
ResetComputedState();
|
||||||
_accumulatedTotalSmoke = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RecordSnapshot(RealtimeSnapshot snapshot)
|
private void RecordSnapshot(RealtimeSnapshot snapshot)
|
||||||
{
|
{
|
||||||
var accumulatedSnapshot = ApplyAccumulatedTotals(snapshot);
|
var massSnapshot = ApplyMassLoss(snapshot);
|
||||||
|
var accumulatedSnapshot = ApplyAccumulatedTotals(massSnapshot);
|
||||||
|
|
||||||
CurrentSnapshot = accumulatedSnapshot;
|
CurrentSnapshot = accumulatedSnapshot;
|
||||||
Records.Add(RealtimeDataRecord.FromSnapshot(accumulatedSnapshot));
|
Records.Add(RealtimeDataRecord.FromSnapshot(accumulatedSnapshot));
|
||||||
@@ -61,6 +81,15 @@ public sealed class ExperimentDataService : IExperimentDataService
|
|||||||
|
|
||||||
private RealtimeSnapshot ApplyAccumulatedTotals(RealtimeSnapshot snapshot)
|
private RealtimeSnapshot ApplyAccumulatedTotals(RealtimeSnapshot snapshot)
|
||||||
{
|
{
|
||||||
|
if (!_isTestRunning)
|
||||||
|
{
|
||||||
|
return snapshot with
|
||||||
|
{
|
||||||
|
TotalHeatRelease = double.NaN,
|
||||||
|
TotalSmoke = double.NaN
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
if (double.IsFinite(snapshot.HeatReleaseRate))
|
if (double.IsFinite(snapshot.HeatReleaseRate))
|
||||||
{
|
{
|
||||||
_accumulatedTotalHeatRelease += snapshot.HeatReleaseRate;
|
_accumulatedTotalHeatRelease += snapshot.HeatReleaseRate;
|
||||||
@@ -77,4 +106,36 @@ public sealed class ExperimentDataService : IExperimentDataService
|
|||||||
TotalSmoke = _accumulatedTotalSmoke
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,5 +11,9 @@ public interface IExperimentDataService
|
|||||||
|
|
||||||
event EventHandler<RealtimeSnapshot>? SnapshotUpdated;
|
event EventHandler<RealtimeSnapshot>? SnapshotUpdated;
|
||||||
|
|
||||||
|
void StartTest();
|
||||||
|
|
||||||
|
void StopTest();
|
||||||
|
|
||||||
void ClearRecords();
|
void ClearRecords();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ namespace ConeCalorimeter.Services;
|
|||||||
|
|
||||||
public sealed class ModbusRealtimeDataService : IRealtimeDataService
|
public sealed class ModbusRealtimeDataService : IRealtimeDataService
|
||||||
{
|
{
|
||||||
|
private const ushort CurrentMassRegister = 1;
|
||||||
private const ushort OxygenRegister = 10;
|
private const ushort OxygenRegister = 10;
|
||||||
private const ushort OrificeFlowRegister = 14;
|
private const ushort OrificeFlowRegister = 14;
|
||||||
private const ushort OrificePressureRegister = 16;
|
private const ushort OrificePressureRegister = 16;
|
||||||
@@ -45,7 +46,7 @@ public sealed class ModbusRealtimeDataService : IRealtimeDataService
|
|||||||
Qa300: ReadFloatOrEmpty(Qa300Register),
|
Qa300: ReadFloatOrEmpty(Qa300Register),
|
||||||
TotalHeatRelease: double.NaN,
|
TotalHeatRelease: double.NaN,
|
||||||
SmokeProduction: ReadFloatOrEmpty(SmokeProductionRegister),
|
SmokeProduction: ReadFloatOrEmpty(SmokeProductionRegister),
|
||||||
CurrentMass: double.NaN,
|
CurrentMass: ReadFloatOrEmpty(CurrentMassRegister),
|
||||||
MassLoss: double.NaN,
|
MassLoss: double.NaN,
|
||||||
IgnitionSeconds: ReadInt16OrEmpty(IgnitionSecondsRegister),
|
IgnitionSeconds: ReadInt16OrEmpty(IgnitionSecondsRegister),
|
||||||
TestSeconds: ReadInt16OrEmpty(TestSecondsRegister),
|
TestSeconds: ReadInt16OrEmpty(TestSecondsRegister),
|
||||||
|
|||||||
@@ -254,6 +254,16 @@ public sealed class TestPageViewModel : PageViewModel
|
|||||||
|
|
||||||
LastAction = action;
|
LastAction = action;
|
||||||
|
|
||||||
|
if (action == "测试开始")
|
||||||
|
{
|
||||||
|
_experimentDataService.StartTest();
|
||||||
|
ClearPlotSeries();
|
||||||
|
}
|
||||||
|
else if (action == "测试结束")
|
||||||
|
{
|
||||||
|
_experimentDataService.StopTest();
|
||||||
|
}
|
||||||
|
|
||||||
if (!TryGetDeviceActionCoil(action, out var coilAddress, out var value))
|
if (!TryGetDeviceActionCoil(action, out var coilAddress, out var value))
|
||||||
{
|
{
|
||||||
return;
|
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)
|
private static bool TryGetDeviceActionCoil(string action, out ushort coilAddress, out bool value)
|
||||||
{
|
{
|
||||||
value = true;
|
value = true;
|
||||||
|
|||||||
Reference in New Issue
Block a user