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

3.7 KiB
Raw Blame History

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.