fix(level): pass timestamp on level samples for level-rate fallback
MeasurementRouter.onLevelMeasurement was writing level samples via .value(value).unit(context.unit), which dropped the timestamp. The level-rate fallback in FlowAggregator derives netFlow from dlevel/dt, so without a timestamp on each sample it had nothing to differentiate. Switch to the positional .value(value, timestamp, unit) form so the fallback works. Add a basic test that drives two level samples 2 s apart and asserts the aggregator produces direction=filling with a finite dlevel/dt-derived netFlow. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -34,7 +34,7 @@ class MeasurementRouter {
|
|||||||
|
|
||||||
onLevelMeasurement(position, value, context = {}) {
|
onLevelMeasurement(position, value, context = {}) {
|
||||||
this.measurements.type('level').variant('measured').position(position)
|
this.measurements.type('level').variant('measured').position(position)
|
||||||
.value(value).unit(context.unit);
|
.value(value, context.timestamp, context.unit);
|
||||||
|
|
||||||
const series = this.measurements.type('level').variant('measured').position(position);
|
const series = this.measurements.type('level').variant('measured').position(position);
|
||||||
const levelMeters = series.getCurrentValue('m');
|
const levelMeters = series.getCurrentValue('m');
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
const test = require('node:test');
|
const test = require('node:test');
|
||||||
const assert = require('node:assert/strict');
|
const assert = require('node:assert/strict');
|
||||||
|
|
||||||
|
const { MeasurementContainer } = require('generalFunctions');
|
||||||
const PumpingStation = require('../../src/specificClass');
|
const PumpingStation = require('../../src/specificClass');
|
||||||
|
|
||||||
// machineGroups is a registry-backed getter (declareChildGetter) — direct
|
// machineGroups is a registry-backed getter (declareChildGetter) — direct
|
||||||
@@ -84,6 +85,39 @@ function makeConfig(overrides = {}) {
|
|||||||
return base;
|
return base;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function makeMeasurementChild({ type = 'level', position = 'atequipment', name = 'child-level' } = {}) {
|
||||||
|
return {
|
||||||
|
config: {
|
||||||
|
general: { id: name, name },
|
||||||
|
functionality: { positionVsParent: position },
|
||||||
|
asset: { type },
|
||||||
|
},
|
||||||
|
measurements: new MeasurementContainer({
|
||||||
|
autoConvert: true,
|
||||||
|
preferredUnits: { level: 'm', flow: 'm3/s', pressure: 'Pa' },
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
test('level child subscription records one sample per event for level-rate fallback', async () => {
|
||||||
|
const ps = new PumpingStation(makeConfig());
|
||||||
|
const child = makeMeasurementChild();
|
||||||
|
|
||||||
|
ps._subscribeMeasurement(child);
|
||||||
|
child.measurements.type('level').variant('measured').position('atequipment')
|
||||||
|
.value(1.0, 1000, 'm');
|
||||||
|
child.measurements.type('level').variant('measured').position('atequipment')
|
||||||
|
.value(1.1, 3000, 'm');
|
||||||
|
|
||||||
|
const series = ps.measurements.type('level').variant('measured').position('atequipment').get();
|
||||||
|
assert.deepEqual(series.values, [1.0, 1.1]);
|
||||||
|
|
||||||
|
const net = ps.flowAggregator.selectBestNetFlow();
|
||||||
|
assert.equal(net.source, 'level:measured');
|
||||||
|
assert.equal(net.direction, 'filling');
|
||||||
|
assert.ok(Math.abs(net.value - 0.5) < 1e-9, `net flow was ${net.value}`);
|
||||||
|
});
|
||||||
|
|
||||||
test('Basin geometry — derived values', async (t) => {
|
test('Basin geometry — derived values', async (t) => {
|
||||||
const ps = new PumpingStation(makeConfig());
|
const ps = new PumpingStation(makeConfig());
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user