72 lines
3.8 KiB
Markdown
72 lines
3.8 KiB
Markdown
|
|
# 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: <name>, 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: <node.id>, positionVsParent }`
|
||
|
|
to the upstream parent.
|
||
|
|
|
||
|
|
## Events emitted by `source.measurements.emitter`
|
||
|
|
|
||
|
|
The `MeasurementContainer` fires `<type>.<variant>.<position>` 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 `<asset.type>.measured.<positionVsParent>` 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).
|