# machineGroupControl — Contract Hand-maintained for Phase 4; 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 `prioritycontrol`, `optimalcontrol`, `dynamiccontrol`, … | Switches the control strategy via `source.setMode(payload)`. | | `set.scaling` | `setScaling` | `string` — one of `absolute`, `normalized` | Sets the demand-scaling convention via `source.setScaling(payload)`. | | `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)`. | | `set.demand` | `Qd` | numeric (number or numeric string) | Calls `source.handleInput('parent', parseFloat(payload))`. On success, replies on Port 0 with `topic = source.config.general.name`, `payload = 'done'`. Non-numeric payloads log `error` and are skipped. | 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). On a successful `set.demand` dispatch the node additionally emits `{ topic: , payload: 'done' }` as an acknowledgement. - **Port 1 (InfluxDB telemetry):** same shape as Port 0, formatted with the `'influxdb'` formatter. - **Port 2 (registration):** at startup the node sends one `{ topic: 'registerChild', payload: , positionVsParent }` to the upstream parent. ## Events emitted by `source.measurements.emitter` The `MeasurementContainer` fires `..` whenever the corresponding series receives a new value. Parents subscribe via the generic `child.measurements.emitter.on(eventName, ...)` handshake. machineGroupControl publishes: - `flow.predicted.atequipment` — aggregated predicted group flow (sum of member-machine predicted flows at the group operating point). - `flow.predicted.downstream` — mirror of the live group flow seen at the discharge header (written by `handlePressureChange` for downstream consumers such as pumpingStation). - `power.predicted.atequipment` — aggregated predicted group power. - `efficiency.predicted.atequipment` — group efficiency = flow/power at the selected operating point. - `Ncog.predicted.atequipment` — group normalised cost-of-goods score. - `pressure.measured.upstream`, `pressure.measured.downstream`, `pressure.measured.differential` — mirrored from header-side measurement children (`asset.type='pressure'`), when registered. The exact set is data-driven by which children register and what they publish; downstream consumers should subscribe by event name, not assume a fixed catalogue. ## Children registered by this node machineGroupControl accepts two `softwareType`s through the `childRegistrationUtils` handshake: - `machine` — a rotatingMachine. Stored in `source.machines[id]`. The group subscribes to its child's `pressure.measured.differential`, `pressure.measured.downstream`, and `flow.predicted.downstream` events to trigger `handlePressureChange`. - `measurement` — a header-side sensor (typically a pressure transmitter at the discharge or suction manifold). The group subscribes to the matching `.measured.` event and mirrors the value into its own MeasurementContainer; pressure events also trigger `handlePressureChange` so optimalControl can use ONE header operating point for all pumps. Position labels accepted from children are `upstream`, `downstream`, `atequipment` (and case variants — normalised internally).