# pumpingStation ![code-ref](https://img.shields.io/badge/code--ref-b825ac1-blue) ![s88](https://img.shields.io/badge/S88-Process_Cell-0c99d9) ![status](https://img.shields.io/badge/status-trial--ready-brightgreen) A `pumpingStation` models a wet-well lift station: one basin with sensors, and one or more pumps that move water against an elevation difference. It integrates basin volume each tick, picks a control mode (level-based by default), and sends a demand setpoint to its pumps so the basin level stays inside its safe operating band. --- ## At a glance | Thing | Value | |:---|:---| | What it represents | A wet-well lift station: a basin + N pumps | | S88 level | Process Cell | | Use it when | You need to lift water from a low point to a higher one, with sensors driving demand | | Don't use it for | Pressurised distribution networks (use a pumpingStation cascade or VGC instead), or a single pump with no basin (parent a `rotatingMachine` directly) | | Children it accepts | `measurement`, `machine`, `machinegroup`, `pumpingstation` | --- ## How it looks in Node-RED ![pumpingStation node and edit dialog](_partial-screenshots/pumpingStation/01-node-and-editor.png) --- ## What it models A rectangular basin with measured inflow, measured (or pump-summed) outflow, and a level sensor. The diagram below is the live source; open it in [draw.io](https://app.diagrams.net/) to edit. ![Basin model — physical reference diagram](diagrams/basin-model.drawio.svg) The basin has five horizontal reference lines that matter to the controller: | Line | Role | |:---|:---| | `overflowLevel` | Physical weir crest. Above this level the basin is spilling. | | `maxLevel` | Demand saturates at 100 % at or above this level. | | `startLevel` | Falling-ramp returns to 0 % demand here; deadband upper bound. | | `minLevel` | Below this level the controller commands all pumps off. | | `dryRunLevel` | Pump-protection cutoff (safety layer, mode-independent). | --- ## Try it — 3-minute demo Import the basic example flow, deploy, and watch the basin react to inject buttons. ```bash curl -X POST -H 'Content-Type: application/json' \ --data @nodes/pumpingStation/examples/01-Basic.json \ http://localhost:1880/flow ``` ![Basic example flow in Node-RED editor](_partial-screenshots/pumpingStation/02-basic-flow.png) What to click in the dashboard after deploy: 1. `set.mode = levelbased` → the controller switches to level-based mode. 2. `set.inflow = 60 m³/h` → inflow is now feeding the basin. 3. `cmd.calibrate.level = 1.5 m` → the volume integrator syncs to a known level. 4. Watch Port 0 in the debug pane: level rises, predicted volume integrates, demand follows the curve. > [!IMPORTANT] > **GIF needed.** Demo recording of the basic flow reacting to mode + inflow clicks. Save as `wiki/_partial-gifs/pumpingStation/01-basic-demo.gif`, target ≤ 1 MB after `gifsicle -O3 --lossy=80`. --- ## Typical wiring The two patterns you'll see most. ### Standalone (`01-Basic.json`) ![Standalone wiring — inject buttons → pumpingStation → debug](_partial-screenshots/pumpingStation/03-wiring-standalone.png) ### With a measurement child and an MGC parent ![Integrated wiring — measurement → pumpingStation → MGC → 2 pumps](_partial-screenshots/pumpingStation/04-wiring-integrated.png) --- ## The five things you'll send | Topic | Payload | What it does | |:---|:---|:---| | `set.mode` | `"levelbased"` or `"manual"` | Switches control strategy. Manual exposes `set.demand` as the direct setpoint. | | `set.demand` | number, m³/h | Operator outflow setpoint. Honoured in `manual` mode. | | `set.inflow` | number, m³/h | Push a measured inflow into the basin balance (if you don't have a `measurement` child for inflow). | | `cmd.calibrate.level` | number, m | Sync the volume integrator to a known level reading. Useful at startup. | | `cmd.calibrate.volume` | number, m³ | Sync the volume integrator to a known volume reading. | ## What you'll see come out Sample Port 0 message (delta-compressed — only changed fields each tick): ```json { "topic": "pumpingStation#PS1", "payload": { "level": 1.62, "volume": 32.4, "direction": "filling", "demand": 38, "safety": { "blocked": false }, "etaSeconds": 412 } } ``` | Field | Meaning | |:---|:---| | `level` | Current basin level (m). Measured if a level `measurement` is registered; predicted otherwise. | | `volume` | Integrated predicted volume (m³). | | `direction` | `filling` / `draining` / `steady` based on the flow dead-band. | | `demand` | What the station is asking its pumps to do (0–100 %). | | `safety.blocked` | True when the safety layer is overriding the control loop. | | `etaSeconds` | Predicted time to full (if filling) or empty (if draining). | --- ## Need more? | Page | What you'll find | |:---|:---| | [Reference — Contracts](Reference-Contracts) | Full topic contract, config schema, child registration filters | | [Reference — Architecture](Reference-Architecture) | Code map, state chart, lifecycle sequence, output ports | | [Reference — Examples](Reference-Examples) | All shipped example flows + Docker compose snippet + debug recipes | | [Reference — Limitations](Reference-Limitations) | When not to use this node, 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)