Files
monster/wiki/Reference-Examples.md
znetsixe 76951f104d 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:13 +02:00

157 lines
9.3 KiB
Markdown

# Reference &mdash; Examples
![code-ref](https://img.shields.io/badge/code--ref-cd185dc-blue)
> [!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 &mdash; 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 &mdash; 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/` &mdash; 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 &rarr; Import &rarr; 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 &mdash; 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 &mdash; 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 &mdash; 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 &mdash; 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 &mdash; `getEffectiveFlow` averages both when present.
- Schedule-armed sampling run &mdash; `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` &mdash; 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&times; 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` &mdash; 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 &mdash; fills the container log within seconds and obscures real errors.
---
## Related pages
| Page | Why |
|:---|:---|
| [Home](Home) | Intuitive overview |
| [Reference &mdash; Contracts](Reference-Contracts) | Topic + config + child filters |
| [Reference &mdash; Architecture](Reference-Architecture) | Code map, sampling-program loop, prediction + cooldown pipeline |
| [Reference &mdash; Limitations](Reference-Limitations) | Known issues and open questions |
| [EVOLV &mdash; Topology Patterns](https://gitea.wbd-rd.nl/RnD/EVOLV/wiki/Topology-Patterns) | Where monster fits in a larger plant |