P6: convert settler to platform infrastructure

Refactor of settler to use BaseNodeAdapter + commandRegistry + statusBadge.
settler follows the platform refactor plan in .claude/refactor/MODULE_SPLIT.md.
Tests stay green; CONTRACT.md generated; legacy aliases preserved.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
znetsixe
2026-05-10 22:23:44 +02:00
parent b199663c77
commit b8247fc755
6 changed files with 328 additions and 190 deletions

53
CONTRACT.md Normal file
View File

@@ -0,0 +1,53 @@
# settler — 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 |
|---|---|---|---|
| `data.influent` | `influent`, `setInfluent` | `{ F: number, C: number[13] }` — either field optional | Replaces influent flow and/or the 13-species concentration vector. Triggers `output-changed`, re-emits the 3-stream Fluent envelope. |
Aliases log a one-time deprecation warning the first time they fire.
Plumbing topics (`child.register`) are handled by the BaseNodeAdapter and
not listed here.
## Outputs
- **Port 0 (process):** array of three Node-RED messages, each with
`topic = 'Fluent'` and `payload = { inlet, F, C }`:
- `inlet=0` — clarified effluent (particulate species 712 zeroed when `F_s > 0`).
- `inlet=1` — surplus sludge (particulates concentrated by `F_in / F_s`).
- `inlet=2` — return sludge (drawn by the downstream return pump up to `F_s`).
Re-emitted whenever the upstream reactor fires `stateChange`, an
operator pushes `data.influent`, or a child measurement updates `C_TS`.
- **Port 1 (InfluxDB telemetry):** `msg.topic = config.general.name`,
payload built by `outputUtils.formatMsg(..., 'influxdb')` from
`getOutput()`. Carries `F_in`, `C_TS`, `F_eff`, `F_surplus`, `F_return`
plus the flat measurements snapshot. Delta-compressed.
- **Port 2 (registration):** at startup the node sends one
`{ topic: 'child.register', payload: <node.id>, positionVsParent, distance }`
to its parent.
## Events emitted by `source.measurements.emitter`
The `MeasurementContainer` fires `<type>.measured.<position>` whenever a
matching series receives a new value. Settler re-emits incoming child
measurements (e.g. `quantity (tss).measured.atequipment`) so its own
parent can subscribe.
## Children accepted
| Software type | Position | Effect |
|---|---|---|
| `measurement` | any | Re-emit on `source.measurements`. `quantity (tss)` updates `C_TS` and triggers `output-changed`. |
| `reactor` | `upstream` (warns otherwise) | Stored as `upstreamReactor`. Listener attached to the reactor's own `emitter` (NOT measurements) for `'stateChange'`; on fire, settler pulls `reactor.getEffluent` and copies `F_in` + `Cs_in`. Handles both array and single-envelope `getEffluent` shapes. |
| `machine` | `downstream` | Stored as `returnPump`. Settler reads `returnPump.measurements.type('flow').variant('measured').position('atEquipment').getCurrentValue()` to determine `F_sr`. Sets `machineChild.upstreamSource = this`. |
## Parent relationship
Settler typically registers as `softwareType: 'settler'` with
`positionVsParent: 'downstream'` against a reactor (the reactor's
downstream stage). The downstream reactor consumes the three Fluent
streams via `payload.inlet`.