Replaces the prior stub/partial wiki with a Home + Reference-{Architecture,
Contracts,Examples,Limitations} + _Sidebar structure. Topic-contract and
data-model sections wrapped in AUTOGEN markers for the future wiki-gen tool.
Source-vs-spec contradictions surfaced and flagged inline (not silently
fixed). Pending-review notes mark sections that need a full node review.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
135 lines
7.8 KiB
Markdown
135 lines
7.8 KiB
Markdown
# valve
|
|
|
|
  
|
|
|
|
A `valve` models a single actuated throttling valve. It loads a supplier Kv-vs-position characteristic curve, drives a position FSM (`accelerating` / `decelerating` through `operational`), and recomputes pressure drop from flow + Kv via a hydraulic model that picks a liquid or gas formula by `serviceType`. Used standalone, or as a child of `valveGroupControl`, downstream of a `rotatingMachine` / `machineGroupControl` / `pumpingStation`.
|
|
|
|
> [!NOTE]
|
|
> Pending full node review (2026-05). Content reflects `CONTRACT.md` and current source only.
|
|
|
|
---
|
|
|
|
## At a glance
|
|
|
|
| Thing | Value |
|
|
|:---|:---|
|
|
| What it represents | One actuated throttling valve — supplier Kv curve, position FSM, deltaP estimate |
|
|
| S88 level | Equipment Module |
|
|
| Use it when | You need a position-controlled valve whose deltaP depends on flow, Kv(position), and service-type (gas / liquid) |
|
|
| Don't use it for | Fixed-restriction orifices, non-return / check valves, or curveless throttling devices (no fallback model) |
|
|
| Children it accepts | Upstream sources (`rotatingmachine`, `machinegroup` / `machinegroupcontrol`, `pumpingstation`, `valvegroupcontrol`) for fluid-contract tracking; `measurement` for pressure / flow |
|
|
| Parents it talks to | `valveGroupControl` (typical) or any node that issues `set.position` / `cmd.startup` / `cmd.shutdown` |
|
|
|
|
---
|
|
|
|
## How it fits
|
|
|
|
```mermaid
|
|
flowchart LR
|
|
parent[valveGroupControl]:::unit -->|set.position<br/>cmd.startup / shutdown| v[valve<br/>Equipment]:::equip
|
|
src["rotatingMachine /<br/>MGC / pumpingStation"]:::unit -->|child.register<br/>(fluid contract)| v
|
|
m_p[measurement<br/>pressure]:::ctrl -.measured.-> v
|
|
m_f[measurement<br/>flow]:::ctrl -.measured.-> v
|
|
v -->|child.register| parent
|
|
v -.->|evt.deltaPChange<br/>evt.fluidCompatibilityChange<br/>evt.fluidContractChange| parent
|
|
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`.
|
|
|
|
---
|
|
|
|
## Try it — 3-minute demo
|
|
|
|
Import the basic example flow, deploy, and drive a single valve through a position move.
|
|
|
|
```bash
|
|
curl -X POST -H 'Content-Type: application/json' \
|
|
--data @nodes/valve/examples/basic.flow.json \
|
|
http://localhost:1880/flow
|
|
```
|
|
|
|
> [!NOTE]
|
|
> The shipped `examples/{basic,integration,edge}.flow.json` files are minimal stubs (one inject → valve → debug). A tiered `01 - Basic Manual Control.json` / `02 - Integration with Valve Group.json` / `03 - Dashboard Visualization.json` set, matching the `rotatingMachine` template, is on the backlog. Until then, drive the node directly with injects.
|
|
|
|
What to send after deploy (the topics map one-to-one to entries in [Reference — Contracts](Reference-Contracts#topic-contract)):
|
|
|
|
1. `set.mode = virtualControl` — lets the GUI source drive the valve (parent path is for grouped use).
|
|
2. `cmd.startup` — FSM runs `idle → starting → warmingup → operational`.
|
|
3. `set.position = {setpoint: 60}` (position %) — valve ramps from 0 to 60; state goes `operational → accelerating → operational`. Each position tick fires a Kv lookup + deltaP recompute.
|
|
4. `data.flow = {variant: 'measured', value: 25, position: 'downstream', unit: 'm3/h'}` — push flow so the hydraulic model has something to chew on. `delta_predicted_pressure` updates and `evt.deltaPChange` fires upward.
|
|
5. `cmd.shutdown` — if currently `operational`, the controller first ramps to position 0, then transitions `stopping → coolingdown → idle`.
|
|
|
|
> [!IMPORTANT]
|
|
> **GIF needed.** Demo recording of steps 1–5 with the live status badge. Save as `wiki/_partial-gifs/valve/01-basic-demo.gif`, target ≤ 1 MB after `gifsicle -O3 --lossy=80`.
|
|
|
|
---
|
|
|
|
## The seven things you'll send
|
|
|
|
| Topic | Aliases | Payload | What it does |
|
|
|:---|:---|:---|:---|
|
|
| `set.mode` | `setMode` | `"auto"` \| `"virtualControl"` \| `"fysicalControl"` \| `"maintenance"` | Switch operational mode. Source allow-list per mode (defaults from `valve.json`). |
|
|
| `cmd.startup` | — | `{ source?: string }` | Run the configured `startup` sequence (default `[starting, warmingup, operational]`). |
|
|
| `cmd.shutdown` | — | `{ source?: string }` | Run `shutdown`. If currently `operational`, first ramps the valve to position 0, then transitions `stopping → coolingdown → idle`. |
|
|
| `cmd.estop` | `emergencystop`, `emergencyStop` | `{ source?: string, action?: string }` | Trigger an emergency stop — runs the `emergencystop` sequence (default `[emergencystop, off]`). |
|
|
| `set.position` | `execMovement` | `{ source?: string, action?: string, setpoint: number }` | Move the valve to a position (control-%, `0..100`). Setpoint is coerced to `Number`. |
|
|
| `data.flow` | `updateFlow` | `{ variant, value, position, unit? }` — `variant ∈ {'measured','predicted'}` | Push a flow measurement; triggers a Kv lookup + deltaP recompute via the hydraulic model. |
|
|
| `query.curve` | `showcurve` | any | Reply on Port 0 with `{ topic: 'Showing curve', payload: <curve snapshot> }`. |
|
|
|
|
Plus the registration topic emitted upward at startup and accepted from real `measurement` children:
|
|
|
|
| Topic | Aliases | Payload |
|
|
|:---|:---|:---|
|
|
| `child.register` | `registerChild` | child Node-RED id (string); `msg.positionVsParent` carries the position label |
|
|
|
|
The legacy umbrella `execSequence` (`{action: 'startup' \| 'shutdown' \| 'emergencystop'}`) is still accepted — it forwards to the canonical `cmd.*` handler and logs a one-time deprecation warning. Scheduled for removal in Phase 7.
|
|
|
|
---
|
|
|
|
## What you'll see come out
|
|
|
|
Sample Port 0 message (delta-compressed, while operational at ~60 % open with a 25 m³/h flow):
|
|
|
|
```json
|
|
{
|
|
"topic": "valve#valve_a",
|
|
"payload": {
|
|
"state": "operational",
|
|
"percentageOpen": 60,
|
|
"moveTimeleft": 0,
|
|
"mode": "auto",
|
|
"downstream_measured_flow": 25,
|
|
"downstream_predicted_flow": 0,
|
|
"delta_predicted_pressure": 84
|
|
}
|
|
}
|
|
```
|
|
|
|
Key shape: **`<position>_<variant>_<type>`** — the legacy three-segment shape. Position labels are lowercase (`downstream`, `delta`, `upstream`). `valve` does **not** use the four-segment `<type>.<variant>.<position>.<childId>` shape that `rotatingMachine` emits.
|
|
|
|
| Field | Meaning |
|
|
|:---|:---|
|
|
| `state` | Current FSM state. See [Architecture — FSM](Reference-Architecture#fsm). |
|
|
| `percentageOpen` | Current position (`0..100`). 0 = closed, 100 = fully open. |
|
|
| `moveTimeleft` | Seconds remaining on the current position move (0 when stationary). |
|
|
| `mode` | One of `auto` / `virtualControl` / `fysicalControl` / `maintenance`. |
|
|
| `delta_predicted_pressure` | Predicted deltaP across the valve (output unit `mbar`). |
|
|
| `downstream_predicted_flow` / `_measured_flow` | Last flow pushed via `data.flow` (output unit `m3/h`). |
|
|
| `downstream_measured_pressure` / `_predicted_pressure` | Pressure measurements pushed via the `MeasurementRouter`. |
|
|
|
|
---
|
|
|
|
## 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, FSM, hydraulic model, lifecycle |
|
|
| [Reference — Examples](Reference-Examples) | Shipped example flows + debug recipes |
|
|
| [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)
|