Files
EVOLV/examples/WORKFLOW.md
Rene De Ren 0cab98c196
Some checks failed
CI / lint-and-test (push) Has been cancelled
Pumping-station demo overhaul + cross-node test harness + bumps
Submodule bumps land the deadlock fix (state.js residue unpark + MGC
optimalControl dispatch reorder) and pumpingStation stopLevel hysteresis.

- Renames examples/pumpingstation-3pumps-dashboard →
  pumpingstation-complete-example with regenerated flow.json. New
  dashboard groups, demand-broadcast wiring, S88 placement rule
  applied, ui-chart trend-split and link-channel naming follow
  .claude/rules/node-red-flow-layout.md.
- New cross-node test harness under test/: end-to-end-pumpingstation
  drives PS + MGC + 3 pumps + physics simulator end-to-end and
  verifies the ~5/15 min cycle.
- Adds Grafana provisioning dashboards (pumping-station.json) and a
  helper sync-example.sh script for export/import to live Node-RED.
- Docker entrypoint + settings + compose tweaks for the persistent
  user dir layout used by the demo.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 11:21:21 +02:00

112 lines
5.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# EVOLV Examples — Team Workflow
This file is the canonical guide for working with the example flows that live under `examples/`. Each subfolder is a Node-RED **project**; the Docker stack is set up so switching between them is two clicks in the editor.
## Stack at a glance
| Container | What | URL |
|---|---|---|
| `evolv-nodered` | Node-RED runtime + dashboard | <http://localhost:1880> · dashboard at <http://localhost:1880/dashboard> |
| `evolv-influxdb` | Time-series store (port-1 telemetry) | <http://localhost:8086> · `evolv` / `evolv-dev-pw` |
| `evolv-grafana` | Provisioned dashboards (anonymous viewer enabled) | <http://localhost:3000> |
The `evolv_nodered_data` named volume keeps `/data` (flows, projects, sessions) across `docker compose down && up`. The `examples/` directory in this repo is the **source of truth**; the Node-RED Projects feature operates on a copy in the volume.
## Quick start
```bash
cd /path/to/EVOLV
docker compose up -d
# Node-RED: http://localhost:1880
# Dashboard: http://localhost:1880/dashboard
# Grafana: http://localhost:3000 (anonymous viewer)
```
The first time you start it, the entrypoint copies every `examples/<name>/` into `/data/projects/<name>/` and `git init`s each. Subsequent starts skip folders that already exist in the volume.
## Switching examples
Open the editor → **menu → Projects → Open Project** → pick another project. The editor reloads the chosen flow.
The default active project on first boot is `pumpingstation-complete-example`. To change the default for fresh volumes, set `DEFAULT_PROJECT=<name>` on the `nodered` service in `docker-compose.yml`.
## Editing a flow
You have two paths. They serve different purposes — pick based on what you're doing.
### Path A — edit `build_flow.py` (canonical, recommended)
```bash
# 1. Edit the Python generator
vim examples/<name>/build_flow.py
# 2. Regenerate flow.json
python3 examples/<name>/build_flow.py > examples/<name>/flow.json
# 3. Push to the runtime
./scripts/sync-example.sh <name>
```
The Python is the **source of truth**. It's diff-friendly and the right place for any change you intend to commit.
### Path B — edit in the Node-RED editor (experimentation)
```
Open editor → Make changes → Deploy
```
Edits go into the volume (`/data/projects/<name>/flow.json`). They survive `docker compose down && up` but are **not in the EVOLV git repo**. To incorporate them back:
```bash
docker cp evolv-nodered:/data/projects/<name>/flow.json examples/<name>/flow.json
```
Then commit `examples/<name>/flow.json` (and reverse-engineer the change into `build_flow.py` if you want it diff-friendly going forward).
## Adding a new example
```bash
mkdir examples/<scenario>-<focus>
# Build a flow.json (recommended: a build_flow.py that generates it)
vim examples/<scenario>-<focus>/{build_flow.py,README.md,flow.json}
# Restart Node-RED so the entrypoint bootstraps the new project
docker compose restart nodered
```
The entrypoint synthesizes `package.json`, runs `git init`, and makes an initial commit so Node-RED recognises it as a project. Bootstrap is idempotent — if a `/data/projects/<name>/` already exists, it's left alone.
After restart, **Projects → Open Project** in the editor will list the new entry.
## Resetting state
| Goal | Command |
|---|---|
| Push the repo's `flow.json` into the runtime, reload | `./scripts/sync-example.sh <name>` |
| Wipe one project's volume copy and re-bootstrap | `docker exec evolv-nodered rm -rf /data/projects/<name>` then `docker compose restart nodered` |
| Wipe **everything** in the volume (flows, sessions, all projects, but NOT InfluxDB/Grafana) | `docker compose down && docker volume rm evolv_nodered_data && docker compose up -d` |
| Wipe everything including telemetry | `docker compose down -v && docker compose up -d` |
## Debugging
| Symptom | Where to look |
|---|---|
| Flow not loading after deploy | `docker logs evolv-nodered` for crash backtraces |
| InfluxDB empty / not receiving | Telemetry tab in editor → status of the `Count writes` node. Should show `N POSTs · M lines (0 err)`. |
| Dashboard widget shows `n/a` | Check the Process Plant tab → output formatter function for that node — `c.<key>` keys the dispatcher reads from |
| Grafana dashboard panels empty | Open InfluxDB UI (<http://localhost:8086>) → Data Explorer → confirm the field name the panel queries actually exists. Field names are flat dotted keys like `level.predicted.atequipment.default`. |
| `interpolation configuration: New f =... is constrained` warnings | The pump curve f-axis is out-of-range. f = downstream upstream pressure differential, in Pa, must be inside the curve's range (e.g. 70 000 390 000 Pa for `hidrostal-H05K-S03R`). Check the per-pump physics feeder formula. |
| High CPU in Node-RED | Per-tick HTTP fan-out to InfluxDB; the pumpingstation example uses a 500 ms batch in the Telemetry tab. If CPU is still high, lower `tickIntervalMs` in the EVOLV node configs (currently 1000). |
## File map per example
```
examples/<name>/
├── build_flow.py ← canonical source of flow.json (Python generator)
├── flow.json ← regenerated artefact, also tracked in Git
├── README.md ← topology, control modes, dashboard map, things to try
└── package.json ← (synthesized in volume by entrypoint, not in repo)
```
The repo tracks `build_flow.py`, `flow.json`, and `README.md`. The `package.json` and `.git/` directory of the project live only in the named volume — they're created by the entrypoint on first bootstrap and don't leak back into the EVOLV Git history.