Files
valve/wiki/Reference-Examples.md
znetsixe 87214788d2 docs(wiki): full 5-page wiki matching the rotatingMachine reference format
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>
2026-05-19 09:42:11 +02:00

8.9 KiB
Raw Blame History

Reference — Examples

code-ref

Note

Every example flow shipped under nodes/valve/examples/, plus how to load them, what they show, and the debug recipes that go with them. Live source: nodes/valve/examples/.

Pending full node review (2026-05). The shipped flows are currently minimal stubs; tiered demos (matching the rotatingMachine template) are on the backlog.


Shipped examples

File Tier Dependencies What it shows
basic.flow.json 1 (stub) EVOLV only Minimal: one inject → one valve → one debug. Sanity check that the node loads.
integration.flow.json 2 (stub) EVOLV only Same shape as basic; placeholder for VGC + measurement integration.
edge.flow.json 3 (stub) EVOLV only Placeholder for edge cases (gas-choke, e-stop, invalid setpoints).

Important

Tiered example flows TODO. Replace the three stubs with 01 - Basic Manual Control.json / 02 - Integration with Valve Group.json / 03 - Dashboard Visualization.json following the rotatingMachine template. Track in .agents/improvements/IMPROVEMENTS_BACKLOG.md and validate live against Docker-stack Node-RED. Screenshots / GIFs land under wiki/_partial-screenshots/valve/ and wiki/_partial-gifs/valve/.


Loading a flow

Via the editor

  1. Open the Node-RED editor at http://localhost:1880.
  2. Menu → Import → drag the JSON file.
  3. Click Deploy.

Via the Admin API

curl -X POST -H 'Content-Type: application/json' \
  --data @"nodes/valve/examples/basic.flow.json" \
  http://localhost:1880/flow

Use POST /flow (single tab, full replace) or POST /flows (full deploy) depending on whether other tabs are already loaded.


Driving the basic flow manually

The shipped basic.flow.json has a single inject wired to the valve. To exercise the FSM + hydraulic model, send the following sequence by hand (e.g. via additional inject nodes you wire in, or the Admin API):

  1. set.mode — payload "virtualControl" — lets the GUI source drive the valve.
  2. cmd.startup — payload {}. FSM walks idle &rarr; starting &rarr; warmingup &rarr; operational. Watch state on Port 0.
  3. set.position — payload {"setpoint": 60}. FSM goes operational &rarr; accelerating &rarr; operational; percentageOpen ramps 0 → 60 at movement.speed %/s.
  4. data.flow — payload {"variant": "measured", "value": 25, "position": "downstream", "unit": "m3/h"}. Flow lands in MeasurementContainer; MeasurementRouter.updateFlow recomputes deltaP. delta_predicted_pressure appears on Port 0; evt.deltaPChange fires upward.
  5. data.flow — payload {"variant": "measured", "value": 0, "position": "downstream", "unit": "mbar"} to push downstream pressure as well (needed for the gas-flow path).
  6. cmd.shutdown — payload {}. Because the valve is operational, the controller first ramps percentageOpen to 0, then state transitions stopping &rarr; coolingdown &rarr; idle.

Important

GIF needed. Demo recording of steps 16 + status badge progression. Save as wiki/_partial-gifs/valve/01-basic-demo.gif, target ≤ 1 MB after gifsicle -O3 --lossy=80.

Try the position-residue handler

After the valve reaches operational at 60 %:

  1. Send set.position = {setpoint: 20}. State goes operational &rarr; decelerating &rarr; ....
  2. While decelerating, send set.position = {setpoint: 80}.
  3. state.moveTo recognises the residue state, transitions back to operational synchronously, then ramps up to 80. No setpoint is lost.

This is the same residue mechanism rotatingMachine uses for fast retargets.

Try the e-stop sequence

From operational, send cmd.estop. The valve runs the emergencystop sequence ([emergencystop, off]). Allowed transitions out of emergencystop are idle / off / maintenance. To restart, drop to idle first (cmd.shutdown from off may not work depending on the state graph — TODO: confirm).


Integration with valveGroupControl

Important

TODO: Tier-2 example. A proper integration flow with valveGroupControl + 2×valve children + an upstream rotatingMachine / pumpingStation for fluid-contract tracking is on the backlog. Screenshot under wiki/_partial-screenshots/valve/02-integration.png.

When built, the integration flow will demonstrate:

  • Auto-registration via Port 2 at deploy — each valve's child.register reaches the VGC; no manual wiring needed.
  • Upstream-source registration — a rotatingMachine registered as a child of the valve feeds getFluidContract() into FluidCompatibility. Status flips from pending / compatible / mismatch based on serviceType agreement.
  • evt.deltaPChange propagation from each valve to the VGC for group-level deltaP aggregation.

Dashboard visualization

Important

TODO: Tier-3 example. A FlowFuse Dashboard 2.0 page (@flowfuse/node-red-dashboard) with control buttons (mode, startup, shutdown, e-stop, position slider), live status (state badge, position %, deltaP, flow), and trend charts (deltaP, position) is on the backlog. Save as 03 - Dashboard Visualization.json.


Docker compose snippet

To bring up Node-RED + InfluxDB with EVOLV nodes pre-loaded:

# docker-compose.yml (extract)
services:
  nodered:
    build: ./docker/nodered
    ports: ['1880:1880']
    volumes:
      - ./docker/nodered/data:/data/evolv
  influxdb:
    image: influxdb:2.7
    ports: ['8086:8086']

Full file: EVOLV/docker-compose.yml.


Debug recipes

Symptom First thing to check Where to look
Editor throws legacy asset field(s) [supplier, ...] on deploy Flow predates the AssetResolver refactor. Re-open the node, pick the model from the asset menu, save. The registry derives supplier / category / type. src/nodeClass.js _rejectLegacyAssetFields.
Status badge shows ⚠ <message> (yellow ring) getFluidCompatibility().status is mismatch or conflict. An upstream source advertised a service type that doesn't match this valve's expected type. src/fluid/fluidCompatibility.js, getFluidCompatibility().
delta_predicted_pressure stuck at 0 or missing kv is 0 (valve closed), the FSM isn't in operational / accelerating / decelerating, or no flow has landed. For gas flow, also needs a finite downstream_measured_pressure. state.getCurrentState(), percentageOpen, MeasurementRouter.updateDeltaP.
set.position has no effect Source not in mode.allowedSources[currentMode]. Watch for Source '...' is not valid for mode '...' in the warn log. src/flow/flowController.js isValidSourceForMode.
data.flow payloads aren't reflected on Port 0 Payload shape: {variant: 'measured'|'predicted', value: <number>, position: <string>, unit?: 'm3/h'}. Missing variant warns Unrecognized variant '...' for flow update. Missing value warns Received null or undefined value for flow update. src/measurement/measurementRouter.js updateFlow.
Gas-flow deltaP saturates at a ceiling The choked-flow cap fired (isChoked: true in hydraulicDiagnostics). Increase gasChokedRatioLimit or revise downstream pressure. src/hydraulicModel.js _calculateGasDeltaP.
query.curve returns empty valveCurve asset.model not found by assetResolver; the predictor falls back to inline asset.valveCurve — check that exists. src/curve/supplierCurve.js SupplierCurvePredictor.snapshot().
FSM stuck in accelerating / decelerating A move was aborted with returnToOperationalOnAbort = false. Send a new set.position — the residue handler in state.moveTo transitions back to operational first. generalFunctions/src/state/state.js moveTo residue branch.
Per-valve Port 0 key names differ from what your dashboard expects valve uses <position>_<variant>_<type> (e.g. delta_predicted_pressure, downstream_measured_flow). rotatingMachine uses <type>.<variant>.<position>.<childId>. Don't mix them. src/io/output.js buildOutput.

Never ship enableLog: 'debug' in a demo — fills the container log within seconds and obscures real errors.


Page Why
Home Intuitive overview
Reference — Contracts Topic + config + child filters
Reference — Architecture Code map, FSM, hydraulic-model pipeline
Reference — Limitations Known issues and open questions
valveGroupControl — Examples Group-control demo flows
EVOLV — Topology Patterns Where valve fits in a larger plant