# settler
  
A `settler` models a secondary clarifier — the sludge-separation stage that sits downstream of a biological reactor. It receives the upstream reactor's effluent stream, performs a 13-species TSS mass balance, and splits the result into three Fluent envelopes: clarified effluent, surplus sludge, and return sludge. A downstream return pump (a `rotatingMachine` registered as `machine` / `downstream`) draws the return-sludge flow.
> [!NOTE]
> Pending full node review (2026-05). Content reflects `CONTRACT.md` and current source only. The shipped `examples/` folder ships stubs only — production-grade flows are still TODO. Treat this page as informative, not authoritative.
---
## At a glance
| Thing | Value |
|:---|:---|
| What it represents | Secondary clarifier / sludge settler — the gravity-separation stage between a biological reactor and its downstream sludge handling |
| S88 level | Unit |
| Use it when | You have a reactor whose effluent must be split into clarified water + return / surplus sludge by a TSS mass balance |
| Don't use it for | Primary sedimentation (species 7–12 zeroing is wrong), generic mass-balance transforms (the 13-species ASM3 vector is hard-coded), single-tank SBRs that don't need a 3-stream split |
| Children it accepts | `measurement` (any, but `quantity (tss)` is the only one that mutates state), `reactor` (upstream), `machine` (downstream — the return pump) |
| Parents it talks to | Typically a downstream `reactor` — the three Fluent streams are routed by `payload.inlet` |
---
## How it fits
```mermaid
flowchart LR
upstream[reactor
upstream
Unit]:::unit
settler[settler
Unit]:::unit
downstream[reactor
downstream
Unit]:::unit
return_pump[rotatingMachine
return pump
Equipment]:::equip
tss[measurement
quantity tss
atequipment]:::ctrl
upstream -.stateChange.-> settler
settler -->|Fluent inlet=0 effluent| downstream
settler -->|Fluent inlet=1 surplus| downstream
settler -->|Fluent inlet=2 return| return_pump
return_pump -->|child.register downstream| settler
tss -->|quantity tss.measured.atequipment| settler
classDef unit fill:#50a8d9,color:#000
classDef equip fill:#86bbdd,color:#000
classDef ctrl fill:#a9daee,color:#000
```
S88 colours are anchored in `.claude/rules/node-red-flow-layout.md`. The settler editor colour is currently `#e4a363` (orange) — tracked as drift in §16 of that rule; diagrams in this wiki use the correct Unit blue (`#50a8d9`).
---
## Try it — 1-minute demo
> [!IMPORTANT]
> The shipped examples (`examples/basic.flow.json`, `integration.flow.json`, `edge.flow.json`) are skeleton stubs — they create a settler node and a debug tap, but do not exercise the reactor → settler → pump chain. A proper Tier-1 / Tier-2 / Tier-3 example set is on the TODO list; until then this section walks the minimum stimulus.
Import the basic stub, deploy, then drive influent manually:
```bash
curl -X POST -H 'Content-Type: application/json' \
--data @nodes/settler/examples/basic.flow.json \
http://localhost:1880/flow
```
After deploy, send one inject:
| Topic | Payload | What it does |
|:---|:---|:---|
| `data.influent` | `{ "F": 1000, "C": [0,0,0,0,0,0,0,0,0,0,0,0,3000] }` | Pushes 1000 m³/h influent with 3000 mg/L total solids (index 12 = `X_TS`). Three Fluent envelopes appear on Port 0 immediately. |
> [!NOTE]
> Pending full node review (2026-05). Real flows (Tier-1 inject only, Tier-2 reactor + settler + pump, Tier-3 dashboard) are not yet shipped. See [Reference — Examples](Reference-Examples).
---
## The two things you'll send
| Topic | Aliases | Payload | What it does |
|:---|:---|:---|:---|
| `data.influent` | `influent`, `setInfluent` | `{F: number, C: number[13]}` — either field optional | Override the influent stream directly. Triggers a recompute of all three Fluent envelopes. |
| `child.register` | `registerChild` | `string` (child node id) | Register a `measurement`, `reactor`, or `machine` child. Port 2 wiring does this automatically in normal flows. |
That is the entire input contract. Settler has no FSM, no setpoint, no startup sequence — it is a stateless transform on top of whatever the upstream reactor + measurement children push into it.
---
## What you'll see come out
Sample Port 0 messages (one push, three envelopes):
```json
[
{ "topic": "Fluent", "payload": { "inlet": 0, "F": 850.0, "C": [/*7-12 zeroed*/] }, "timestamp": 1715000000000 },
{ "topic": "Fluent", "payload": { "inlet": 1, "F": 50.0, "C": [/*7-12 concentrated*/] }, "timestamp": 1715000000000 },
{ "topic": "Fluent", "payload": { "inlet": 2, "F": 100.0, "C": [/*7-12 concentrated*/] }, "timestamp": 1715000000000 }
]
```
| `payload.inlet` | Meaning | Particulate species (indices 7–12) |
|:---:|:---|:---|
| `0` | Clarified effluent | zeroed when `F_s > 0` |
| `1` | Surplus sludge (the fraction the return pump does not draw) | concentrated by `F_in / F_s` |
| `2` | Return sludge (drawn by the downstream return pump, capped at `F_s`) | concentrated by `F_in / F_s` |
Mass balance invariant: `F_eff + F_surplus + F_return = F_in` (modulo float).
Port 1 (InfluxDB) is the scalar dashboard view — see [Reference — Contracts](Reference-Contracts#data-model--getoutput-shape). Port 2 carries the one-shot `child.register` upward at startup.
---
## Capability matrix
| Capability | Status | Notes |
|:---|:---:|:---|
| TSS mass-balance split (3 streams) | yes | `F_s = min(F_in * Cs[12] / C_TS, F_in)` — clamped to prevent negative effluent. |
| Particulate zeroing in effluent | yes | Species 7–12 set to 0 in `inlet=0` when `F_s > 0`. |
| Particulate concentration in sludge | yes | Species 7–12 scaled by `F_in / F_s` in `inlet=1` + `inlet=2`. |
| Return-pump flow draw | yes | `F_sr = min(pump flow at equipment, F_s)`. Surplus = `F_s - F_sr`. |
| `F_s` clamp to `F_in` | yes | Prevents negative effluent when `X_TS_in > C_TS`. |
| Manual influent override | yes | `data.influent` lets ops supply `{F, C}` directly. |
| Multiple reactor upstreams | no | Only one `upstreamReactor` slot; last registration wins. |
| Stateful FSM | no | Stateless transform — recomputes on every trigger. |
| Curve loading / drift / sequence-abort | n/a | Not applicable to a passive split. |
---
## Need more?
| Page | What you'll find |
|:---|:---|
| [Reference — Contracts](Reference-Contracts) | Topic registry, config schema, child registration filters |
| [Reference — Architecture](Reference-Architecture) | Three-tier code map, reactor ↔ settler wiring (the load-bearing bit), lifecycle, output ports |
| [Reference — Examples](Reference-Examples) | Shipped example flows (currently stubs) + the TODO list for production-grade demos |
| [Reference — Limitations](Reference-Limitations) | When not to use, known limitations, open questions |
[EVOLV master wiki](https://gitea.wbd-rd.nl/RnD/EVOLV/wiki/Home) · [Topology Patterns](https://gitea.wbd-rd.nl/RnD/EVOLV/wiki/Topology-Patterns) · [Topic Conventions](https://gitea.wbd-rd.nl/RnD/EVOLV/wiki/Topic-Conventions)