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>
9.4 KiB
Reference — Contracts
Note
Pending full node review (2026-05). Content reflects
CONTRACT.md,src/commands/index.js, andgeneralFunctions/src/configs/settler.jsononly.
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:contracttool. Until then the table is hand-maintained againstsrc/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
requireUnitForTypespolicy 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
measurementfilter accepts any asset-type at register time; only the runtime_updateMeasurementswitch acts onquantity (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 supported — this.upstreamReactor is a single slot; the last child.register call wins.
Related pages
| 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 |