Files
valveGroupControl/CONTRACT.md
znetsixe e02cd1a7a7 P6: convert valveGroupControl to BaseDomain + BaseNodeAdapter + concern split
Refactor of valveGroupControl to use the platform infrastructure (BaseDomain, BaseNodeAdapter,
ChildRouter, commandRegistry, statusBadge). Extracts concerns into
focused modules per .claude/refactor/MODULE_SPLIT.md generic template.
Tests stay green; CONTRACT.md generated; legacy aliases preserved.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:09:24 +02:00

3.9 KiB

valveGroupControl — Contract

Hand-maintained for Phase 6; the ## Inputs table is generated from src/commands/index.js (see Phase 9 generator). Keep ≤ 80 lines.

Inputs (msg.topic on Port 0)

Canonical Aliases (deprecated) Payload Effect
set.mode setMode string — one of auto, virtualControl, fysicalControl, maintenance Switches the control strategy via source.setMode(payload).
set.position setpoint any Reserved for future per-valve positional override; currently a debug-logged no-op pending Phase 7.
child.register registerChild string — the child node's Node-RED id Resolves the child via RED.nodes.getNode and registers it through childRegistrationUtils.registerChild(childObj.source, msg.positionVsParent).
cmd.execSequence execSequence { source, action, parameter } Forwards to source.handleInput(source, action, parameter).
data.totalFlow totalFlowChange numeric, { value, position?, variant?, unit? }, or { source, action, ... } Updates total measured/predicted flow at the configured position; drives calcValveFlows to re-distribute across valves.
cmd.emergencyStop emergencyStop, emergencystop optional { source } Runs the emergencystop sequence via handleInput.
set.reconcileInterval setReconcileInterval numeric — seconds (> 0) Re-tunes the periodic flow-reconciliation interval. Min clamp 100 ms.

Aliases log a one-time deprecation warning the first time they fire.

Outputs (msg.topic on Port 0/1/2)

  • Port 0 (process): msg.topic = config.general.name. Payload built by outputUtils.formatMsg(..., 'process') from getOutput() — delta-compressed (only changed fields are emitted). Output keys follow <position>_<variant>_<type> plus mode and maxDeltaP.
  • Port 1 (InfluxDB telemetry): same shape as Port 0, formatted with the 'influxdb' formatter.
  • Port 2 (registration): at startup the node sends one { topic: 'child.register', payload: <node.id>, positionVsParent } to the upstream parent.

Events emitted by source.emitter / source.measurements.emitter

  • output-changed (source.emitter) — public output state shifted; the adapter listens and pushes Ports 0/1.
  • fluidContractChange (source.emitter) — group-level fluid contract (status / serviceType / sourceCount) changed. Parents (e.g. an upstream valve registering this VGC as its parent) subscribe to react.
  • reconcileIntervalChange (source.emitter) — emitted by setReconcileIntervalSeconds; the adapter restarts the tick loop.
  • flow.predicted.atequipment (source.measurements.emitter) — total predicted group flow (sum of per-valve assigned flows).
  • pressure.predicted.deltaMax (source.measurements.emitter) — max delta-P across registered valves.

The exact set is data-driven by which sources/valves register and what they publish; downstream consumers subscribe by event name.

Children registered by this node

valveGroupControl accepts two child classes through the childRegistrationUtils handshake:

  • valve — an individual valve. Stored in source.valves[id]. VGC binds to the child's positionChange (via child.state.emitter) and deltaPChange (via child.emitter) events to re-distribute flow and re-compute group max delta-P.
  • machine / rotatingmachine / machinegroup / machinegroupcontrol / pumpingstation / valvegroupcontrol — an upstream source. Stored in source.sources[id]. VGC subscribes to the source's flow.predicted.* / flow.measured.* events to drive updateFlow, and reads the child's getFluidContract() (if present) plus fluidContractChange events to aggregate the group's upstream service type (getFluidContract() exposes the resolved view).

Position labels accepted from children are upstream, downstream, atEquipment (and case variants — normalised internally).