Compare commits

..

1 Commits

Author SHA1 Message Date
znetsixe
e041877ae4 fix(ps): keep canonical flow in m³/s, emit output in m³/h
Reverts the canonical half of 8216480 (which set BOTH canonical and output
to m³/h) back to the platform-wide m³/s convention. Canonical m³/s is what
every cross-node consumer assumes — MGC percent→flow demand interpolation,
the volume integrator (flow × dt), and physics-sanity balances. Changing the
canonical basis to m³/h silently scaled those by 3600×.

Output flow / netFlowRate stay m³/h so telemetry and dashboard series remain
on the same axis as the rest of the pump group (verified slice #47). The
m³/s→m³/h conversion now happens at the output boundary only, never on the
internal integrator basis.

No smoothing/hysteresis added for the PS→MGC demand hunting: per design
review that belongs in a dedicated intermediate node (e.g. a PID), not in
the pumpingStation or machineGroupControl control path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 18:31:39 +02:00

View File

@@ -18,13 +18,19 @@ class PumpingStation extends BaseDomain {
static name = 'pumpingStation'; static name = 'pumpingStation';
// Internal math runs in m3/s for flow and m for level so the volume // Internal math runs in m3/s for flow and m for level so the volume
// integrator (flow × dt) is unit-consistent. Strict canonicals make // integrator (flow × dt) is unit-consistent canonical stays m3/s, the
// unit drift in child-fed measurements an explicit error. // platform-wide convention every cross-node consumer (MGC demand math,
// physics-sanity) assumes. Strict canonicals make unit drift in child-fed
// measurements an explicit error.
// Output flow / netFlowRate are emitted in m3/h so telemetry/dashboard
// series land on the same axis as the rest of the pump group (verified
// slice #47); the m3/s→m3/h presentation conversion happens at the output
// boundary only — it never touches the canonical integrator basis.
// overflowVolume / underflowVolume are listed in output so the // overflowVolume / underflowVolume are listed in output so the
// MeasurementContainer keeps the integrator's m³ unit on those streams // MeasurementContainer keeps the integrator's m³ unit on those streams
// (FlowAggregator writes spill / underflow per tick). // (FlowAggregator writes spill / underflow per tick).
static unitPolicy = UnitPolicy.declare({ static unitPolicy = UnitPolicy.declare({
canonical: { flow: 'm3/h', pressure: 'Pa', power: 'W', temperature: 'K' }, canonical: { flow: 'm3/s', pressure: 'Pa', power: 'W', temperature: 'K' },
output: { output: {
flow: 'm3/h', netFlowRate: 'm3/h', level: 'm', volume: 'm3', flow: 'm3/h', netFlowRate: 'm3/h', level: 'm', volume: 'm3',
overflowVolume: 'm3', underflowVolume: 'm3', overflowVolume: 'm3', underflowVolume: 'm3',