Files
EVOLV/examples/WORKFLOW.md

112 lines
5.6 KiB
Markdown
Raw Normal View History

# 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.