src/curves/ loader + normalizer (with cross-pressure anomaly
detection) + reverseCurve helper
src/prediction/ predictors (predictFlow/Power/Ctrl) +
groupPredictors (lazy group-scope views) +
OperatingPoint (pressure-driven prediction setpoints)
src/drift/ DriftAssessor (per-metric drift) + PredictionHealth
(composes flow/power/pressure into HealthStatus +
confidence sibling — see OPEN_QUESTIONS 2026-05-10)
src/pressure/ VirtualPressureChildren (dashboard-sim) +
PressureInitialization (real-vs-virtual tracking) +
PressureRouter (dispatches by position)
src/state/ stateBindings (state.emitter listener helper) +
isOperationalState
src/measurement/ measurementHandlers (dispatcher for flow/power/temp/pressure)
src/flow/ flowController (handleInput body — execSequence,
execMovement, flowMovement, emergencystop)
src/display/ workingCurves (showWorkingCurves + showCoG admin)
src/commands/ canonical names: set.mode, cmd.startup/shutdown/estop,
set.setpoint, set.flow-setpoint,
data.simulate-measurement, query.curves, query.cog,
child.register. execSequence demuxes by payload.action
to canonical cmd.* handlers.
CONTRACT.md inputs/outputs/events/children surface
110 basic tests pass (100 new + 10 pre-existing).
specificClass.js / nodeClass.js untouched — integration in P5 wave 2.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
71 lines
2.8 KiB
JavaScript
71 lines
2.8 KiB
JavaScript
'use strict';
|
|
|
|
const test = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
|
|
const VirtualPressureChildren = require('../../src/pressure/virtualChildren');
|
|
|
|
const SILENT = { warn() {}, debug() {}, info() {}, error() {} };
|
|
|
|
const UNIT_POLICY = {
|
|
canonical: { pressure: 'Pa', flow: 'm3/s', power: 'W', temperature: 'K', atmPressure: 'Pa' },
|
|
output: { pressure: 'mbar', flow: 'm3/h', power: 'kW', temperature: 'C' },
|
|
};
|
|
|
|
test('build() returns two children with the expected config shape', () => {
|
|
const factory = new VirtualPressureChildren({ logger: SILENT, unitPolicy: UNIT_POLICY });
|
|
const { upstream, downstream } = factory.build();
|
|
|
|
for (const child of [upstream, downstream]) {
|
|
assert.ok(child.config.general.id);
|
|
assert.ok(child.config.general.name);
|
|
assert.equal(child.config.functionality.softwareType, 'measurement');
|
|
assert.ok(['upstream', 'downstream'].includes(child.config.functionality.positionVsParent));
|
|
assert.equal(child.config.asset.type, 'pressure');
|
|
assert.equal(child.config.asset.unit, 'mbar');
|
|
}
|
|
|
|
assert.equal(upstream.config.functionality.positionVsParent, 'upstream');
|
|
assert.equal(downstream.config.functionality.positionVsParent, 'downstream');
|
|
});
|
|
|
|
test('each child has its own MeasurementContainer instance', () => {
|
|
const factory = new VirtualPressureChildren({ logger: SILENT, unitPolicy: UNIT_POLICY });
|
|
const { upstream, downstream } = factory.build();
|
|
assert.ok(upstream.measurements);
|
|
assert.ok(downstream.measurements);
|
|
assert.notStrictEqual(upstream.measurements, downstream.measurements);
|
|
});
|
|
|
|
test('the MeasurementContainer accepts pressure writes (unit policy applied)', () => {
|
|
const factory = new VirtualPressureChildren({ logger: SILENT, unitPolicy: UNIT_POLICY });
|
|
const { upstream } = factory.build();
|
|
upstream.measurements
|
|
.type('pressure').variant('measured').position('upstream')
|
|
.value(1000, Date.now(), 'mbar');
|
|
const v = upstream.measurements
|
|
.type('pressure').variant('measured').position('upstream').getCurrentValue();
|
|
assert.ok(v != null);
|
|
});
|
|
|
|
test('setParentRef wires children to the supplied parent ref', () => {
|
|
const parent = { id: 'parent-machine' };
|
|
const factory = new VirtualPressureChildren({
|
|
logger: SILENT, unitPolicy: UNIT_POLICY, parentRef: parent,
|
|
});
|
|
const { upstream, downstream } = factory.build();
|
|
assert.equal(typeof upstream.measurements.setParentRef, 'function');
|
|
assert.equal(typeof downstream.measurements.setParentRef, 'function');
|
|
});
|
|
|
|
test('custom ids are honoured', () => {
|
|
const factory = new VirtualPressureChildren({
|
|
logger: SILENT,
|
|
unitPolicy: UNIT_POLICY,
|
|
ids: { upstream: 'sim-u', downstream: 'sim-d' },
|
|
});
|
|
const { upstream, downstream } = factory.build();
|
|
assert.equal(upstream.config.general.id, 'sim-u');
|
|
assert.equal(downstream.config.general.id, 'sim-d');
|
|
});
|