New standard, pilot pass for pumpingStation. Sets the pattern the other 10 nodes will follow once we sign off on this one. Zone A (wiki/Home.md, ~180 lines): - one-sentence opener - "at a glance" 5-row fact table - "How it looks in Node-RED" — screenshot placeholder - "What it models" — embeds the existing basin-model.drawio.svg - "Try it" — 3-minute demo with curl-load command, click list, GIF placeholder - "Typical wiring" — two placeholder screenshots (standalone + integrated), no mermaid (per user direction) - "The five things you'll send" + sample Port-0 payload table - "Need more?" footer linking to Reference-* siblings Zone B (4 sibling pages): - Reference-Contracts.md — full topic contract + data model (AUTOGEN markers); config schema; child registration filters; unit policy - Reference-Architecture.md — 3-tier code layout; safety FSM (stateDiagram-v2); tick lifecycle (sequenceDiagram); output ports - Reference-Examples.md — 01-Basic / 02-Integration / 03-Dashboard walk-through with per-example screenshot + GIF placeholders; debug-recipes table - Reference-Limitations.md — implemented vs schema-only modes; basin-shape constraint; net-flow source caveat; alias-removal map Asset directory placeholders created: - wiki/_partial-screenshots/pumpingStation/.gitkeep - wiki/_partial-gifs/pumpingStation/.gitkeep - wiki/_partial-flows/pumpingStation/.gitkeep Abandoned per user direction (no longer linked, removed from source): - wiki/README.md - wiki/functional-description.md (377 lines retired) - wiki/modes/*.md (5 files retired) Diagrams kept in place (wiki/diagrams/*.drawio.svg) — referenced from Home and Reference-Architecture. package.json: wiki:contract + wiki:datamodel now target Reference-Contracts.md instead of Home.md. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
179 lines
7.5 KiB
Markdown
179 lines
7.5 KiB
Markdown
# pumpingStation
|
|
|
|
  
|
|
|
|
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
|
|
|
|
> [!IMPORTANT]
|
|
> **Screenshot needed.** Drop a `pumpingStation` node onto a fresh Node-RED canvas and capture:
|
|
> - The node tile itself (its colour, badge text, label).
|
|
> - The full edit dialog when you double-click it (basin geometry section visible).
|
|
>
|
|
> Save as `wiki/_partial-screenshots/pumpingStation/01-node-and-editor.png` (PNG, target 1200×800, optimise to ≤ 200 KB).
|
|
> Then replace this callout with:
|
|
>
|
|
> ```markdown
|
|
> 
|
|
> ```
|
|
|
|
---
|
|
|
|
## 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.
|
|
|
|

|
|
|
|
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
|
|
```
|
|
|
|
> [!IMPORTANT]
|
|
> **Flow screenshot needed.** Open the imported `01-Basic.json` flow in the Node-RED editor and capture the whole tab. The inject row should be visible on the left, the pumpingStation in the middle, the debug taps on the right.
|
|
>
|
|
> Save as `wiki/_partial-screenshots/pumpingStation/02-basic-flow.png` (PNG, target 1600×900, optimise to ≤ 250 KB).
|
|
> Replace this callout with:
|
|
>
|
|
> ```markdown
|
|
> 
|
|
> ```
|
|
|
|
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.** Record the dashboard reacting to the four clicks above. 15–25 seconds is enough. Use `peek` (Linux), LICEcap (Win/Mac), or any screen recorder; convert to GIF and optimise:
|
|
>
|
|
> ```bash
|
|
> # if you started from an mp4:
|
|
> ffmpeg -i raw.mp4 -vf "fps=15,scale=720:-1" -loop 0 stage.gif
|
|
> gifsicle -O3 --lossy=80 stage.gif -o final.gif
|
|
> ```
|
|
>
|
|
> Save as `wiki/_partial-gifs/pumpingStation/01-basic-demo.gif` (target ≤ 1 MB).
|
|
> Replace this callout with:
|
|
>
|
|
> ```markdown
|
|
> 
|
|
> ```
|
|
|
|
---
|
|
|
|
## Typical wiring
|
|
|
|
The two patterns you'll see most.
|
|
|
|
### Standalone (`01-Basic.json`)
|
|
|
|
> [!IMPORTANT]
|
|
> **Screenshot needed.** From the imported `01-Basic.json`, crop a tight view of just the inject column → pumpingStation → debug nodes. Skip the comment header.
|
|
>
|
|
> Save as `wiki/_partial-screenshots/pumpingStation/03-wiring-standalone.png` (PNG, target 1400×700).
|
|
> Replace this callout with:
|
|
>
|
|
> ```markdown
|
|
> 
|
|
> ```
|
|
|
|
### With a measurement child and an MGC parent (`02-Integration.json`)
|
|
|
|
> [!IMPORTANT]
|
|
> **Screenshot needed.** From the imported `02-Integration.json`, capture the whole tab. The measurement node feeding the pumpingStation should be visible on the left; the MGC with its two `rotatingMachine` pumps on the right.
|
|
>
|
|
> Save as `wiki/_partial-screenshots/pumpingStation/04-wiring-integrated.png` (PNG, target 1600×900).
|
|
> Replace this callout with:
|
|
>
|
|
> ```markdown
|
|
> 
|
|
> ```
|
|
|
|
---
|
|
|
|
## 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)
|