Files
diffuser/CONTRACT.md
znetsixe 0ec9dd15a7 P6: convert diffuser to BaseDomain + BaseNodeAdapter + concern split
Refactor of diffuser 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:26 +02:00

72 lines
3.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# diffuser — Contract
Hand-maintained for Phase 6; the `## Inputs` table is generated from
`src/commands/index.js` (see Phase 9 generator). Keep ≤ 100 lines.
## Inputs (msg.topic on Port 0)
| Canonical | Aliases (deprecated) | Payload | Effect |
|---|---|---|---|
| `data.flow` | `air_flow` | `number` — airflow in Nm³/h | Calls `source.setFlow(payload)`; clamps to ≥ 0 and recomputes OTR. |
| `set.density` | `density` | `number` — diffuser density (per m²) | Calls `source.setDensity(payload)` and recomputes. |
| `set.water-height` | `height_water` | `number` — water column height in m | Calls `source.setWaterHeight(payload)`; clamps to ≥ 0 and recomputes head + total pressure. |
| `set.header-pressure` | `header_pressure` | `number` — header gauge pressure in mbar | Calls `source.setHeaderPressure(payload)` and recomputes. |
| `set.elements` | `elements` | `number` — element count (rounded; must be > 0) | Calls `source.setElementCount(payload)` and recomputes per-element flow. |
| `set.alfa-factor` | `alfaFactor` | `number` — alpha correction (≥ 0) | Calls `source.setAlfaFactor(payload)` and recomputes oxygen output. |
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). Fields:
- `iPressure`, `iMWater`, `iFlow` — echoed inputs.
- `nFlow` — normalised airflow (Nm³/h).
- `oOtr` — interpolated oxygen transfer rate (g O₂ / Nm³).
- `oPLoss` — total head loss (mbar) = static head + diffuser ΔP.
- `oKgo2H` — kg O₂ per hour at current operating point.
- `oFlowElement` — flow per element (Nm³/h/element).
- `efficiency` — combined OTR/ΔP efficiency (0100).
- `slope` — local OTR-vs-flow slope.
- `oZoneOtr` — reactor zone OTR (kg O₂ / m³ / day) computed against
`diffuser.zoneVolume`; `0` when zone volume is unset.
- `idle` — true when `data.flow ≤ 0`.
- `warning`, `alarm` — string arrays describing flow-per-element band
excursions.
- **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,
distance }` to the upstream parent (typically a reactor).
`positionVsParent` defaults to `'atEquipment'`.
## Port-count change (Phase 6)
Pre-refactor the diffuser exposed 4 outputs (process, dbase, reactor
control with `topic: 'OTR'`, parent registration). The reactor control
message merged into Port 0 as `oZoneOtr`; consumers that previously
listened to the dedicated control port should switch to reading
`payload.oZoneOtr` from the process output. The legacy `OTR` topic is
removed in this refactor — there is no alias, since the data shape
differs (single value vs full process payload).
## Events emitted by `source.measurements.emitter`
None today. The diffuser does not currently publish typed measurements
through `MeasurementContainer`; all output flows via `getOutput()`.
A future phase may promote `oOtr` and `oZoneOtr` to typed series so
parent reactors can subscribe through the standard `ChildRouter`
handshake.
## Events emitted by `source.emitter`
- `output-changed` — fires whenever an input setter recomputes the
oxygen-transfer state. `BaseNodeAdapter` listens and pushes the
delta-compressed Port 0 / Port 1 messages.
## Children registered by this node
None. The diffuser is a leaf Equipment Module; it registers itself with
its parent (reactor / process cell) via the Port 2 handshake.