Files
monster/wiki/Home.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

9.3 KiB
Raw Blame History

monster

code-ref s88 status

A monster models the physical "monsternamekast" (composite-sampling cabinet) on a wastewater treatment plant. It runs an AQUON-scheduled, flow-proportional sampling program: aggregates measured + manual flow, blends in a rain-scaled prediction, integrates volume, and emits a pulse event whenever the integrated volume crosses m³ per pulse. Used downstream of reactor / settler for compliance + process diagnostics — but note that the node only integrates flow in the current implementation; multi-constituent reporting (NH4, NO3, COD, TSS, …) is a downstream consumer concern, not produced by this node.

Note

Pending full node review (2026-05). Content reflects CONTRACT.md and current source only.


At a glance

Thing Value
What it represents One composite-sampling cabinet running AQUON-scheduled, flow-proportional sampling
S88 level Unit
Use it when You need scheduled composite samples with flow-proportional pulses for a benchtop analyser / lab pickup
Don't use it for Generic flow totalising (use measurement), ad-hoc grab samples (fire cmd.start once instead), or analyser results — monster emits pulses, not analyte values
Children it accepts measurement with asset.type='flow' (or unset)
Parents it talks to Any node that issues cmd.start / set.schedule / set.rain / data.flow (typically a Process Cell coordinator)

How it fits

flowchart LR
    parent[plant parent<br/>Process Cell]:::pc
    monster[monster<br/>Unit]:::unit
    flow_up[measurement<br/>type=flow<br/>position=upstream]:::ctrl
    flow_at[measurement<br/>type=flow<br/>position=atequipment]:::ctrl
    flow_dn[measurement<br/>type=flow<br/>position=downstream]:::ctrl
    op[(operator / AQUON)]
    weather[(Open-Meteo)]

    flow_up -->|flow.measured.upstream| monster
    flow_at -->|flow.measured.atequipment| monster
    flow_dn -->|flow.measured.downstream| monster
    op -->|set.schedule / data.flow / cmd.start| monster
    weather -->|set.rain| monster
    monster -->|child.register| parent
    monster -.evt output (pulse / bucketVol).-> parent
    classDef pc fill:#0c99d9,color:#fff
    classDef unit fill:#50a8d9,color:#000
    classDef ctrl fill:#a9daee,color:#000

S88 colours are anchored in .claude/rules/node-red-flow-layout.md. The editor node tile in monster.html is currently #4f8582 (teal) and pending cleanup — Section 16 of the layout rules tracks it.


Try it — 3-minute demo

Import the basic example flow, deploy, and drive the sampler through a single run.

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

What to click after deploy (the inject buttons map to the topics in Reference — Contracts):

  1. set.rain — push an Open-Meteo precipitation snapshot so sumRain / avgRain populate (otherwise the rain-scaled prediction stays at nominalFlowMin).
  2. set.schedule — push an AQUON row array so nextDate arms.
  3. data.flow = {value: 240, unit: 'm3/h'} — supply a manual flow value (or wire a measurement child for the measured path).
  4. cmd.start = true — releases the start gate. On the next 1000 ms tick the sampling program checks validateFlowBounds; if nominalFlowMin < flowMax, _beginRun fires, running flips to true, and the bucket integrator starts.
  5. Watch Port 0: pulse blips to true for one tick whenever temp_pulse crosses 1; bucketVol rises in 50 mL steps (the hard-coded subSampleVolume); sumPuls increments.
  6. After constraints.samplingtime hours _endRun fires and running flips to false.

Important

GIF needed. Demo recording of steps 16 with the live status panel. Save as wiki/_partial-gifs/monster/basic-demo.gif, target ≤ 1 MB after gifsicle -O3 --lossy=80.


The seven things you'll send

Topic Aliases Payload What it does
cmd.start i_start truthy / falsy Sets source.i_start. On the next tick a sampling run begins if validateFlowBounds passes.
set.schedule monsternametijden array of AQUON rows (SAMPLE_NAME, DESCRIPTION, SAMPLED_DATE, START_DATE, END_DATE) Stores the schedule and recomputes nextDate + daysPerYear for the configured aquonSampleName.
set.rain rain_data per-location rain forecast (Open-Meteo shape) Aggregates hourly precipitation into sumRain / avgRain; feeds the rain-scaled flow prediction. Ignored while running=true.
data.flow input_q { value: number, unit: string } Converts to m³/h and pushes into flow.manual.atequipment. Blends with measured-child flow in getEffectiveFlow().
set.mode setMode string Reserved — handler delegates to source.setMode() which is currently undefined. No-op today.
set.model-prediction model_prediction numeric Reserved — handler delegates to source.setModelPrediction() which is currently undefined. No-op today.
child.register registerChild string (child node id) Register a measurement child. Port 2 wiring does this automatically.

There is no query.* topic on monster (unlike rotatingMachine's query.curves / query.cog). All state is on Port 0.


What you'll see come out

Sample Port 0 message (mid-run snapshot, delta-compressed):

{
  "topic": "monster#cabinet_1",
  "payload": {
    "running": true,
    "pulse": false,
    "bucketVol": 1.25,
    "bucketWeight": 4.25,
    "sumPuls": 25,
    "m3PerPuls": 4,
    "m3Total": 100.0,
    "q": 215.4,
    "predFlow": 240.0,
    "predM3PerSec": 0.067,
    "timeLeft": 12340,
    "timePassed": 600,
    "targetVolumeM3": 0.005,
    "targetProgressPct": 41.6,
    "targetDeltaL": -2.93,
    "predictedRateM3h": 240.0,
    "sumRain": 3.2,
    "avgRain": 0.13,
    "nextDate": 1746940800000,
    "daysPerYear": 12,
    "missedSamples": 0,
    "sampleCooldownMs": 0,
    "invalidFlowBounds": false
  }
}
Field Meaning
running Run/idle flag — monster has no formal FSM, just this boolean and the timer fields below.
pulse true for the tick on which a pulse is emitted; falls back to false on the next tick.
bucketVol / bucketWeight Accumulated composite volume (L) and total bucket mass (kg = vol + emptyWeightBucket).
sumPuls / pulsesRemaining Pulses fired this run vs target ceiling.
m3PerPuls Volume per pulse, set at _beginRun from predFlow / targetPuls.
m3Total Total integrated flow this run (m³).
q Effective flow (m³/h) — flowTracker.getEffectiveFlow() blends measured + manual.
predFlow / predM3PerSec Predicted total volume over the run window (m³) and its average rate.
timeLeft / timePassed Run-window seconds remaining / elapsed.
targetVolumeM3 / targetProgressPct / targetDeltaL Target composite volume (m³), % of target accumulated, signed L delta against target.
predictedRateM3h Rain-scaled flow prediction (m³/h) — between nominalFlowMin and flowMax.
sumRain / avgRain Probability-weighted hourly precipitation, summed / averaged across locations.
nextDate / daysPerYear Next scheduled run epoch ms; count of remaining runs this calendar year.
missedSamples / sampleCooldownMs Cooldown-blocked pulse count; ms remaining on the active cooldown.
invalidFlowBounds True when nominalFlowMin >= flowMax — gates _beginRun.

Full Port-0 key list: see Reference — Contracts — Data model.

Key shape is flat scalars on the snapshot plus a MeasurementContainer.getFlattenedOutput() flush of flow.<variant>.<position> entries. monster does not use the four-segment <type>.<variant>.<position>.<childId> shape that rotatingMachine emits — no childId is appended because monster fans incoming children into the same three positions and the latest value wins.


Status badge

State Badge Fill
invalidFlowBounds=true Config error: nominalFlowMin (…) >= flowMax (…) red
running=true + cooldown active SAMPLING (Ns) · <bucketVol>/<maxVolume> L yellow ring
running=true + normal AI: RUNNING · <bucketVol>/<maxVolume> L green dot
idle AI: IDLE grey ring

Need more?

Page What you'll find
Reference — Contracts Full topic contract, config schema, child registration filters
Reference — Architecture Code map, sampling-program loop, prediction + cooldown pipeline
Reference — Examples Shipped example flows + debug recipes
Reference — Limitations When not to use, known limitations, open questions

EVOLV master wiki · Topology Patterns · Topic Conventions