# EVOLV — Wastewater Treatment Plant Automation ![code-ref](https://img.shields.io/badge/code--ref-9ab9f6b-blue) ![platform-tests](https://img.shields.io/badge/platform_tests-823%2F823-brightgreen) ![branch](https://img.shields.io/badge/branch-development-orange) ![nodes](https://img.shields.io/badge/active_nodes-11_%2B_library-blue) > [!NOTE] > EVOLV is a Node-RED node library for wastewater plant automation, built by Waterschap Brabantse Delta R&D. It exposes 11 active nodes across four ISA-88 (S88) levels plus one Grafana-provisioning utility, all on a shared `generalFunctions` library. Every node follows the same three-tier code shape: entry registers the node type; `nodeClass` (extends `BaseNodeAdapter`) bridges to the Node-RED runtime; `specificClass` (extends `BaseDomain`) holds pure-JS domain logic. Source of truth for everything claimed on this page: each node's `src/specificClass.js` `configure()` plus `.claude/refactor/CONTRACTS.md`. --- ## Platform overview Every solid arrow is a real `router.onRegister(, …)` call in the parent's `configure()`. Dashed arrows are emitter subscriptions (no child-register handshake). Thick `==>` arrows are Unit-to-Unit `stateChange` subscriptions. Verified node by node against current source. ```mermaid flowchart TB subgraph PC["Process Cell"] ps[pumpingStation]:::pc end subgraph UN["Unit"] mgc[machineGroupControl] vgc[valveGroupControl] reactor[reactor] settler[settler] monster[monster] end subgraph EM["Equipment Module"] rm[rotatingMachine] v[valve] diff[diffuser] end subgraph CM["Control Module"] meas["measurement — registers with any process node"] end subgraph UT["Utility"] dash["dashboardAPI — any node → Grafana"] end ps -->|owns| mgc ps -.->|direct child, no group| rm mgc -->|load-shares| rm vgc -->|positions| v settler -->|return pump| rm reactor ==stateChange==> settler diff -. OTR data .-> reactor class ps pc class mgc,vgc,reactor,settler,monster unit class rm,v,diff equip class meas ctrl class dash util classDef pc fill:#0c99d9,color:#fff,stroke:#075a82,stroke-width:2px classDef unit fill:#50a8d9,color:#000,stroke:#2c7ba8,stroke-width:2px classDef equip fill:#86bbdd,color:#000,stroke:#5a90b2,stroke-width:2px classDef ctrl fill:#a9daee,color:#000,stroke:#76b7d4,stroke-width:2px classDef util fill:#dddddd,color:#000,stroke:#a8a8a8,stroke-width:2px ``` ### Edge legend | Arrow | Meaning | Implementation | |---|---|---| | `A --> B` (solid) | A owns B as an S88 child via `child.register` | `router.onRegister('', ...)` | | `A -.-> B` (dashed) | A subscribes to B's emitter events; no handshake | `B.emitter.on('', ...)` | | `A ==> B` (thick) | Unit-to-Unit `stateChange` subscription | `settler._connectReactor` pattern | ### S88 colours | Hex | Level | Used by | |:---|:---|:---| | `#0f52a5` | Area | Reserved — no node yet | | `#0c99d9` | Process Cell | pumpingStation | | `#50a8d9` | Unit | MGC, VGC, reactor, settler, monster | | `#86bbdd` | Equipment Module | rotatingMachine, valve, diffuser | | `#a9daee` | Control Module | measurement | | `#dddddd` | Utility / neutral | dashboardAPI, helper functions | Source: `.claude/rules/node-red-flow-layout.md` §14. For the full data-flow map — every `measurement -> parent` edge, VGC's flow-source registrations, dashboardAPI's provisioning calls, and the worked plant example — see [Topology Patterns](Topology-Patterns). --- ## Live nodes | S88 level | Node | Role | Per-node wiki | |:---|:---|:---|:---| | Process Cell | pumpingStation | Wet-well basin model; dispatches demand to pump groups. | [Open](https://gitea.wbd-rd.nl/RnD/pumpingStation/wiki/Home) | | Unit | machineGroupControl | Load-sharing across a group of `rotatingMachine` children. | [Open](https://gitea.wbd-rd.nl/RnD/machineGroupControl/wiki/Home) | | Unit | valveGroupControl | Coordinated position control over `valve` children. Registers upstream pumps / PS / MGC as flow sources. | [Open](https://gitea.wbd-rd.nl/RnD/valveGroupControl/wiki/Home) | | Unit | reactor | Bioreactor — ASM kinetics (CSTR / PFR). Pairs with diffuser and downstream settler. | [Open](https://gitea.wbd-rd.nl/RnD/reactor/wiki/Home) | | Unit | settler | Secondary clarifier; subscribes to upstream reactor `stateChange`, drives a return pump. | [Open](https://gitea.wbd-rd.nl/RnD/settler/wiki/Home) | | Unit | monster | Composite-sample sensor surrogate; proportional sampling program. | [Open](https://gitea.wbd-rd.nl/RnD/monster/wiki/Home) | | Equipment | rotatingMachine | Single pump or compressor — characteristic curves, prediction, full FSM. | [Open](https://gitea.wbd-rd.nl/RnD/rotatingMachine/wiki/Home) | | Equipment | valve | Single valve actuator — shared FSM with rotatingMachine. | [Open](https://gitea.wbd-rd.nl/RnD/valve/wiki/Home) | | Equipment | diffuser | Aeration diffuser; gas-side modelling, OTR emission. | [Open](https://gitea.wbd-rd.nl/RnD/diffuser/wiki/Home) | | Control Module | measurement | Sensor signal conditioning — scaling, smoothing, outlier detection; analog / digital / MQTT modes. | [Open](https://gitea.wbd-rd.nl/RnD/measurement/wiki/Home) | | Utility | dashboardAPI | Receives `child.register` from any node; provisions a Grafana dashboard via HTTP. | [Open](https://gitea.wbd-rd.nl/RnD/dashboardAPI/wiki/Home) | | Library | generalFunctions | `BaseDomain`, `BaseNodeAdapter`, `ChildRouter`, commandRegistry, `UnitPolicy`, `MeasurementContainer`, `statusBadge`, `HealthStatus`, `LatestWinsGate`, logger, configManager. Not a Node-RED node. | [Open](https://gitea.wbd-rd.nl/RnD/generalFunctions/wiki/Home) | --- ## Start here | If you want to… | Read | |:---|:---| | Stand up a local dev environment and run an example flow | [Getting Started](Getting-Started) | | Understand the codebase layout, BaseDomain / adapter pattern, output ports | [Architecture](Architecture) | | See typical plant configurations and how nodes wire together | [Topology Patterns](Topology-Patterns) | | Know what topic names to use, units, S88 colours, measurement keys | [Topic Conventions](Topic-Conventions) | | Understand what Port 0 / Port 1 / Port 2 carry, InfluxDB layout, Grafana | [Telemetry](Telemetry) | | Decode S88 / EVOLV / WWTP jargon | [Glossary](Glossary) | --- ## Domain concepts (evergreen) Domain knowledge that doesn't change when code is refactored. | Page | Topic | |:---|:---| | [ASM Models](Concept-ASM-Models) | Activated Sludge Models — biological process kinetics | | [PID Control Theory](Concept-PID-Control-Theory) | Loop tuning, anti-windup, controller forms | | [Pump Affinity Laws](Concept-Pump-Affinity-Laws) | Speed / flow / head / power scaling | | [Settling Models](Concept-Settling-Models) | Takács / Vesilind / discrete settling | | [Signal Processing — Sensors](Concept-Signal-Processing-Sensors) | Smoothing, outlier rejection | | [InfluxDB Schema Design](Concept-InfluxDB-Schema-Design) | Cardinality, tags vs fields | | [Wastewater Compliance NL](Concept-Wastewater-Compliance-NL) | Dutch regulatory context | | [OT Security — IEC 62443](Concept-OT-Security-IEC62443) | OT cybersecurity baseline | ## Operations findings (algorithm proofs) | Page | Topic | |:---|:---| | [BEP Gravitation Proof](Finding-BEP-Gravitation-Proof) | Best-Efficiency-Point convergence | | [Curve Non-Convexity](Finding-Curve-Non-Convexity) | When pump curves break local optima | | [NCog Behaviour](Finding-NCog-Behavior) | NCog control metric notes | | [Pump Switching Stability](Finding-Pump-Switching-Stability) | Hysteresis design for multi-pump groups | ## Node-RED / FlowFuse manuals | Page | Topic | |:---|:---| | [Manual Index](Manual-NodeRED-INDEX) | Top of the Node-RED reference set | | [Runtime — Node.js](Manual-NodeRED-Runtime-Node-Js) | `send`, `done`, multi-output arrays | | [Function Node Patterns](Manual-NodeRED-Function-Node-Patterns) | Return / send patterns | | [Messages and Editor Structure](Manual-NodeRED-Messages-And-Editor-Structure) | Msg shape + HTML / editor / runtime split | | [FlowFuse ui-chart](Manual-NodeRED-Flowfuse-Ui-Chart-Manual) | Data contract, runtime controls | | [FlowFuse ui-button](Manual-NodeRED-Flowfuse-Ui-Button-Manual) | Button reference | | [FlowFuse ui-gauge](Manual-NodeRED-Flowfuse-Ui-Gauge-Manual) | Gauge reference | | [FlowFuse ui-text](Manual-NodeRED-Flowfuse-Ui-Text-Manual) | Text reference | | [FlowFuse ui-template](Manual-NodeRED-Flowfuse-Ui-Template-Manual) | Template reference | | [FlowFuse ui-config](Manual-NodeRED-Flowfuse-Ui-Config-Manual) | Config reference | | [Dashboard Layout](Manual-NodeRED-Flowfuse-Dashboard-Layout-Manual) | Compact layout guidance | | [Widgets Catalog](Manual-NodeRED-Flowfuse-Widgets-Catalog) | All widgets at a glance | --- ## Refactor status | Tier | Scope | Status | |:---:|:---|:---| | 1 | Add infra in `generalFunctions` (additive only) | Done | | 2 | Pilot: pumpingStation on new infra | Done | | 3 | Convert measurement, MGC, rotatingMachine | Done | | 4 | Convert valve, VGC, reactor, settler, monster, diffuser, dashboardAPI | Done | | 5 | Canonical topic names + alias deprecation map | Done | | 6 | Promote `development` → `main` | Pending Docker E2E + human review | | 8.5 | Remove deprecated paths in `generalFunctions` | Done | | 9 | Visual-first wiki refactor — per-node + master | Done 2026-05-11 | | 10 | Test-suite refactor across all nodes | In progress | > [!IMPORTANT] > Active branch is `development` everywhere — 12 submodules plus parent EVOLV. `main` will receive the merged refactor only after Docker E2E sign-off (pumpingStation P2.14 pending). --- ## Archive Pre-refactor wiki content has been removed from the live wiki. The git history of `EVOLV.wiki.git` preserves every prior page if you need to consult it. See [Archive](Archive) for the changelog of what was removed and when. --- ## Need help? | Channel | Use it for | |:---|:---| | Per-node wiki on Gitea | Operator-level questions for one node | | `.claude/refactor/OPEN_QUESTIONS.md` | Live decisions log — issues being worked on | | Submodule issues on Gitea | File a bug against a specific node | | R&D team Slack / Teams | Anything urgent or strategic |