Files
settler/wiki/Reference-Contracts.md
znetsixe 93ea000734 docs(wiki): regenerate topic-contract AUTOGEN block via wiki-gen
Replaces the agent-written placeholder inside Reference-Contracts.md with
the authoritative table generated from src/commands/index.js. Both the
BEGIN and END markers are normalized to the canonical form used by
`@evolv/wiki-gen`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 10:11:49 +02:00

9.4 KiB

Reference — Contracts

code-ref

Note

Pending full node review (2026-05). Content reflects CONTRACT.md, src/commands/index.js, and generalFunctions/src/configs/settler.json only.

Full topic contract, configuration schema, and child-registration filters for settler. Source of truth: src/commands/index.js, src/specificClass.js configure(), and the schema at generalFunctions/src/configs/settler.json. For an intuitive overview, return to the Home.


Topic contract

The registry lives in src/commands/index.js. Each descriptor maps a canonical msg.topic to its handler; aliases emit a one-time deprecation warning the first time they fire.

Canonical topic Aliases Payload Unit Effect
data.influent influent, setInfluent any Push the influent stream (payload: {F: flow m3/h, C: [concentrations mg/L]}).
child.register registerChild string Register a child node (typically a measurement) with this settler.

Note

Pending full node review (2026-05). The autogen markers above will be populated by a future npm run wiki:contract tool. Until then the table is hand-maintained against src/commands/index.js.

Mode / source / action allow-lists

Not applicable. Settler has no operational mode, no source allow-list, no action allow-list. Both topics are accepted unconditionally; payload-shape validation lives in the handler itself.

The data.influent handler validates:

if (!p || typeof p !== 'object' || Array.isArray(p)) {
  log?.warn?.(`data.influent expects an object {F, C}; got ${typeof p}`);
  return;
}
if (typeof p.F === 'number' && Number.isFinite(p.F)) source.F_in = p.F;
if (Array.isArray(p.C)) source.Cs_in = [...p.C];

Non-finite or non-numeric F is silently ignored. Non-array C is silently ignored. Either field may be omitted to update only the other. Negative F is not rejected — the downstream getEffluent math will produce nonsense but the node will not throw.


Data model — getOutput() shape

Composed each tick by src/specificClass.js getOutput(). Port 0 carries the 3-message Fluent stream directly (not via getOutput); Port 1 (this snapshot) is the scalar dashboard view.

Scalar keys

Key Type Unit Source Notes
F_in number m³/h host.F_in Influent flow. Default 0.
C_TS number mg/L host.C_TS Target return-sludge concentration. Default 2500. Updated by quantity (tss) measurement child.
F_eff number m³/h streams[0].payload.F Clarified effluent flow.
F_surplus number m³/h streams[1].payload.F Surplus sludge flow (F_s - F_sr).
F_return number m³/h streams[2].payload.F Return sludge flow (min(pumpFlow, F_s)).

Per-measurement keys

For every (type, variant, position) stored in this.measurements MeasurementContainer, the flattened output emits:

<type>.<variant>.<position>.<childId>

Position labels are normalised to lowercase. The trailing <childId> is the registering measurement child's id. Settler does not write its own measurements directly — every key in this group came from a registered child (the _connectMeasurement re-emit).

Status badge

getStatusBadge() in src/specificClass.js:

Condition Badge
F_in <= 0 statusBadge.idle('no influent') (grey ring)
else green dot, label F_in=<n.nn> eff=<n.nn> surplus=<n.nn> (m³/h, 2 dp)

No state-symbol enumeration — settler has no FSM.


Configuration schema — editor form to config keys

Source of truth: generalFunctions/src/configs/settler.json plus settler.html.

General (config.general)

Form field Config key Default Notes
Name general.name "Settler" Human-readable name.
(auto-assigned) general.id null Node-RED node id.
Default unit general.unit null Default measurement unit. Currently unused by settler — child measurements carry their own units.
Enable logging general.logging.enabled true Master switch.
Log level general.logging.logLevel info debug / info / warn / error.

Functionality (config.functionality)

Form field Config key Default Notes
(hidden) functionality.softwareType settler Constant. Used by the parent's router as a registration filter.
(hidden) functionality.role Secondary settler for sludge separation Documentation string.
Position vs parent functionality.positionVsParent downstream One of upstream / atEquipment / downstream. Settler typically registers as downstream against an upstream reactor.

Node-RED-side (editor form, not domain config)

Form field Stored on Default Notes
Process Output Format nodeClass.processOutputFormat process process / json / csv. Port-0 serialisation.
Database Output Format nodeClass.dbaseOutputFormat influxdb influxdb / json / csv. Port-1 serialisation.

buildDomainConfig() returns {} — settler does not push any editor-derived values into the domain at start-up. All operational state is runtime (F_in, Cs_in, C_TS).

Note

Pending full node review (2026-05). The editor form (settler.html) is currently colour-drifted to #e4a363 (orange); should be #50a8d9 (Unit blue) per .claude/rules/node-red-flow-layout.md §16.

Unit policy

Quantity Canonical (internal) Output (Port 1) Notes
Flow (F_in, F_eff, F_surplus, F_return) m³/h m³/h No conversion — settler is unit-agnostic above the storage layer.
Concentration (C_TS, Cs_in[*]) mg/L mg/L Same.

Note

Pending full node review (2026-05). Settler does not declare a requireUnitForTypes policy via MeasurementContainer; verify against the general unit policy before relying on internal canonicalisation.


Child registration

Source: src/specificClass.js configure() (the this.router.onRegister(...) chain) and the three _connect* methods.

Software type Filter Wired to Side-effect
measurement any (no asset-type / position filter at register time) _connectMeasurement(child) Subscribes to <type>.measured.<position> on the child's measurements.emitter. Re-emits on settler's own MeasurementContainer (lets settler's parent see the value). quantity (tss) updates C_TS; anything else logs an error from _updateMeasurement but the re-emit still happened.
reactor positionVsParent === 'upstream' (warns otherwise but still registers) _connectReactor(child) Stored as this.upstreamReactor. Listener attached manually to reactor.emitter (NOT measurements.emitter) for 'stateChange'; on fire, settler pulls reactor.getEffluent and copies F_in + Cs_in. Handles both array and single-envelope getEffluent shapes.
machine positionVsParent === 'downstream' (warns + skips otherwise) _connectMachine(child) Stored as this.returnPump. Settler reads returnPump.measurements.type('flow').variant('measured').position('atEquipment').getCurrentValue() to determine F_sr. Sets machineChild.upstreamSource = this so the pump can use settler's inlet=2 Fluent as its suction-side context.

Note

Pending full node review (2026-05). The measurement filter accepts any asset-type at register time; only the runtime _updateMeasurement switch acts on quantity (tss). Other measurement types are silently re-emitted but not consumed. TODO: decide whether this is desired (pass-through telemetry) or a contract gap.

No virtual children

Unlike rotatingMachine, settler does not auto-register any virtual measurement children. Every measurement must come from an explicitly wired child node.


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:

inlet Consumer expectation
0 (clarified effluent) Routed onward to the next process unit.
1 (surplus sludge) Typically routed to a sludge-handling process (digestion, thickening, dewatering).
2 (return sludge) Drawn back to a reactor inlet or the head of the biological train.

Multi-reactor settlers are not supportedthis.upstreamReactor is a single slot; the last child.register call wins.


Page Why
Home Intuitive overview
Reference — Architecture Code map, reactor ↔ settler wiring, mass-balance math
Reference — Examples Shipped flows + debug recipes
Reference — Limitations Known issues and open questions
EVOLV — Topic Conventions Platform-wide topic rules
EVOLV — Telemetry Port 0 / 1 / 2 InfluxDB layout