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>
157 lines
9.3 KiB
Markdown
157 lines
9.3 KiB
Markdown
# Reference — Examples
|
|
|
|

|
|
|
|
> [!NOTE]
|
|
> Every example flow shipped under `nodes/monster/examples/`, plus how to load them, what they show, and the debug recipes that go with them. Live source: `nodes/monster/examples/`.
|
|
|
|
> [!NOTE]
|
|
> Pending full node review (2026-05). Content reflects `CONTRACT.md`, `examples/README.md`, and current source only. Example flows have not been validated end-to-end on a live Docker instance.
|
|
|
|
---
|
|
|
|
## Shipped examples
|
|
|
|
| File | Tier | Dependencies | What it shows |
|
|
|:---|:---:|:---|:---|
|
|
| `basic.flow.json` | 1 | EVOLV only | Quick-start flow — manual flow inject, manual start, seeded `rain_data` and `monsternametijden`, debug taps on the three ports. **Status: pending validation.** |
|
|
| `02-integrated-e2e.json` | 2 | EVOLV only | End-to-end integration — measurement child wired in, schedule arming, sampling-run completion. **Status: pending validation.** |
|
|
|
|
Per `examples/README.md`, the following files are also referenced but **not currently in this directory** at `cd185dc`:
|
|
|
|
| Referenced filename | Status |
|
|
|:---|:---|
|
|
| `integration.flow.json` | Referenced in README; not present in `examples/` — possibly renamed to `02-integrated-e2e.json`. Flag for review. |
|
|
| `edge.flow.json` | Referenced in README; not present. Flag for review. |
|
|
| `monster-dashboard.flow.json` | Referenced in README + top-level `README.md`; not present. Flag for review. |
|
|
| `monster-api-dashboard.flow.json` | Referenced in README + top-level `README.md`; not present. Flag for review. The README warns that production use requires hardening of placeholder credentials (`__SET_*__`). |
|
|
|
|
> [!IMPORTANT]
|
|
> Reconcile the example flow inventory: either restore the four referenced flows from history, or update `examples/README.md` + the top-level `README.md` to remove dangling references. Tracked.
|
|
|
|
---
|
|
|
|
## 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
|
|
|
|
```bash
|
|
curl -X POST -H 'Content-Type: application/json' \
|
|
--data @"nodes/monster/examples/basic.flow.json" \
|
|
http://localhost:1880/flows
|
|
```
|
|
|
|
---
|
|
|
|
## Example 01 — Basic (`basic.flow.json`)
|
|
|
|
Single-cabinet flow with the minimum inputs to drive one sampling run. Pending live validation.
|
|
|
|
### Suggested click order after deploy
|
|
|
|
1. **Seed the rain forecast.** Click the `set.rain` inject. `sumRain` / `avgRain` populate; `predictedRateM3h` jumps from `nominalFlowMin` to a band-scaled value. (Skip this step and the prediction collapses to `nominalFlowMin`, which is `0` out of the box — the run will still start, but `predFlow` will be 0 and `m3PerPuls` will round to 0; see [Limitations](Reference-Limitations#mperpuls-can-round-to-zero).)
|
|
2. **Seed the schedule.** Click the `set.schedule` inject with an AQUON row array containing at least one `START_DATE` in the future for `aquonSampleName=112100` (the default).
|
|
3. **Push a manual flow.** Click `data.flow = {value: 240, unit: 'm3/h'}`.
|
|
4. **Start.** Click `cmd.start = true`. On the next tick `validateFlowBounds` runs — if `nominalFlowMin < flowMax`, `_beginRun` fires and `running` flips to `true`.
|
|
5. **Watch Port 0.** `pulse` blips to `true` for one tick on each integrated-volume threshold cross. `bucketVol` rises in 50 mL steps. `sumPuls` increments.
|
|
6. **Stop.** Either wait `samplingtime` hours for `_endRun`, or redeploy.
|
|
|
|
> [!IMPORTANT]
|
|
> **Screenshot needed.** Editor capture of `basic.flow.json` after step 4. Save as `wiki/_partial-screenshots/monster/basic-running.png`.
|
|
|
|
### Try the cooldown guard
|
|
|
|
After the first pulse:
|
|
|
|
1. Push a higher manual flow (`data.flow = {value: 1200, unit: 'm3/h'}`) so the integrator races past `m3PerPuls` again within `minSampleIntervalSec` (default 60 s).
|
|
2. Watch the log: `Sampling too fast. Cooldown active for Ns.`
|
|
3. `missedSamples` increments, `pulse` stays `false`, `sampleCooldownMs` ticks down to 0, then the next pulse fires.
|
|
|
|
---
|
|
|
|
## Example 02 — Integrated end-to-end (`02-integrated-e2e.json`)
|
|
|
|
> [!IMPORTANT]
|
|
> **Screenshot needed.** Editor capture of `02-integrated-e2e.json`. Save as `wiki/_partial-screenshots/monster/02-integrated.png`. Replace this callout with the image link.
|
|
|
|
One monster + one or more `measurement` flow children. Demonstrates:
|
|
|
|
- Auto-registration via Port 2 at deploy (each child's `child.register` reaches the monster).
|
|
- Measured + manual flow blend — `getEffectiveFlow` averages both when present.
|
|
- Schedule-armed sampling run — `nextDate` triggers `_beginRun` without an `i_start` click.
|
|
|
|
Detailed click order: pending review.
|
|
|
|
---
|
|
|
|
## Dashboard / API example flows
|
|
|
|
The `examples/README.md` references `monster-dashboard.flow.json` (FlowFuse charts for `pulse`, `bucket`, `predFlow`) and `monster-api-dashboard.flow.json` (Open-Meteo + AQUON SFTP + Grafana publish template with placeholder credentials). Neither file is present at `cd185dc`. See the inventory note at the top of this page.
|
|
|
|
When restored, the API flow MUST be hardened before production:
|
|
|
|
- Replace every `__SET_*__` placeholder with an env-backed secret.
|
|
- Pin the Open-Meteo endpoint and Aquon SFTP host to environment variables.
|
|
- Route the dashboard publish through `dashboardAPI`, not a hardcoded Grafana URL.
|
|
|
|
---
|
|
|
|
## Docker compose snippet
|
|
|
|
To bring up Node-RED + InfluxDB with EVOLV nodes pre-loaded:
|
|
|
|
```yaml
|
|
# 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](https://gitea.wbd-rd.nl/RnD/EVOLV/src/branch/development/docker-compose.yml).
|
|
|
|
---
|
|
|
|
## Debug recipes
|
|
|
|
| Symptom | First thing to check | Where to look |
|
|
|:---|:---|:---|
|
|
| `pulse` never fires | Is `running=true`? If not, check `validateFlowBounds` — the `Invalid flow bounds. nominalFlowMin=…, flowMax=…` warn means the default `flowMax=0` is in play. Set `nominalFlowMin < flowMax` in the editor. | `parameters/parameters.js → validateFlowBounds` |
|
|
| `pulse` never fires (bounds OK) | Is `m3PerPuls` zero? `_beginRun` rounds `predFlow / targetPuls` to nearest integer m³. Low `predFlow` rounds to 0; integrator divides by 0 → `temp_pulse = Infinity`, the `sumPuls < absMaxPuls` guard then runs out. | `sampling/samplingProgram.js → _beginRun` |
|
|
| Pulses arrive too fast / skipped | Cooldown guard active. Inspect `missedSamples` + `sampleCooldownMs`. Look for `Sampling too fast. Cooldown active for Ns.` in the log. | `sampling/samplingProgram.js → _maybeEmitPulse` |
|
|
| `q` always zero | Measured-flow child not registered, manual flow not pushed. Watch Port 2 + `data.flow` history. | `flow/flowTracker.js` |
|
|
| Measurement child ignored at register | Child's `config.asset.type` is set to something other than `"flow"` (e.g. `"flow-electromagnetic"`). monster only accepts `asset.type = "flow"` or unset. Set `asset.type: "flow"` on the measurement node. | `specificClass.js → _wireMeasurementChild` |
|
|
| Measured-flow values look 60× high or wrong unit | `flowTracker.handleMeasuredFlow` does **not** convert: it stores the value as-supplied (defaulting unit to `'m3/h'`). Wire children that already emit m³/h or fix at the source. | `flow/flowTracker.js → handleMeasuredFlow` |
|
|
| `nextDate` not arming | `set.schedule` payload didn't include any rows matching `aquonSampleName` with a future `START_DATE`. | `schedule/schedule.js → regNextDate` |
|
|
| `sumRain` stays zero with rain input | `set.rain` is ignored while `running=true` — only consumed between runs. Wait for `_endRun` or push the rain payload before `cmd.start`. | `specificClass.js → updateRainData` |
|
|
| `data.flow` payloads dropped silently | The handler requires `{value: <number>, unit: <string>}`. Bare numbers or missing `unit` log `data.flow payload must include numeric value and unit.` | `commands/handlers.js → dataFlow` |
|
|
| `predictedRateM3h` stays at `nominalFlowMin` | `set.rain` not sent, `lastRainUpdate` is 0, or > 2 hours have passed (`RAIN_STALE_MS`). Re-push the rain payload. | `parameters/parameters.js → getRainIndex` |
|
|
| `flowmeter=false` has no effect | `constraints.flowmeter` is in the schema but **not** wired in `buildDomainConfig`. The sampling program always runs in proportional mode. | `src/nodeClass.js → buildDomainConfig` |
|
|
| `set.mode` / `set.model-prediction` no-op | Handlers delegate to `source.setMode()` / `source.setModelPrediction()` which don't exist. These topics are reserved for future use. | `commands/handlers.js` |
|
|
| Status badge stuck at `Config error: …` | `nominalFlowMin >= flowMax`. Fix the bounds and redeploy. | `io/statusBadge.js` |
|
|
|
|
> Never ship `enableLog: 'debug'` in a demo — fills the container log within seconds and obscures real errors.
|
|
|
|
---
|
|
|
|
## Related pages
|
|
|
|
| Page | Why |
|
|
|:---|:---|
|
|
| [Home](Home) | Intuitive overview |
|
|
| [Reference — Contracts](Reference-Contracts) | Topic + config + child filters |
|
|
| [Reference — Architecture](Reference-Architecture) | Code map, sampling-program loop, prediction + cooldown pipeline |
|
|
| [Reference — Limitations](Reference-Limitations) | Known issues and open questions |
|
|
| [EVOLV — Topology Patterns](https://gitea.wbd-rd.nl/RnD/EVOLV/wiki/Topology-Patterns) | Where monster fits in a larger plant |
|