Files
monster/wiki/Reference-Contracts.md
znetsixe aff866bd9b docs(wiki): regenerate topic-contract AUTOGEN block via wiki-gen
Replaces the agent-written placeholder inside Reference-Contracts.md with
the authoritative table generated from src/commands/index.js. Both the
BEGIN and END markers are normalized to the canonical form used by
`@evolv/wiki-gen`.

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

12 KiB
Raw Blame History

Reference — Contracts

code-ref

Note

Full topic contract, configuration schema, and child-registration filters for monster. Source of truth: src/commands/index.js, src/specificClass.js configure(), and the schema at generalFunctions/src/configs/monster.json.

For an intuitive overview, return to the Home.

Note

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


Topic contract

The registry lives in src/commands/index.js. Each descriptor maps a canonical msg.topic to its handler; aliases emit a one-time deprecation warning the first time they fire.

Canonical topic Aliases Payload Unit Effect
cmd.start i_start any Trigger / release the sampler start gate.
set.schedule monsternametijden any Replace the sampling-times schedule.
set.rain rain_data any Push current rain-event data into the sampler logic.
data.flow input_q object Push the upstream flow measurement (payload: {value, unit}).
set.mode setMode any Switch the monster between auto / manual modes.
set.model-prediction model_prediction any Push the upstream rain-prediction snapshot used by the sampler.
child.register registerChild string Register a child node (typically a measurement) with this monster.

Mode / source / action allow-lists

monster has no allow-list enforcement. There is no flowController.handle equivalent and no mode.allowedActions / mode.allowedSources config slice. The set.mode handler is a placeholder. Compare rotatingMachine, which gates every topic through the mode matrix — on monster, every topic dispatches unconditionally.


Data model — getOutput() shape

Composed each tick by src/io/output.js buildOutput(). Delta-compressed: consumers see only the keys that changed.

Flat measurement keys

For every (type, variant, position) stored in MeasurementContainer, getFlattenedOutput() emits the three-segment key (note: monster does not add a <childId> segment, unlike rotatingMachine):

Key Type Unit Notes
flow.manual.atequipment number m³/h Last data.flow value (after conversion).
flow.measured.upstream number m³/h Last measured-child reading at this position.
flow.measured.atequipment number m³/h Same.
flow.measured.downstream number m³/h Same.

Scalar keys

Key Type Source Notes
running boolean m.running True between _beginRun and _endRun.
pulse boolean m.pulse True only on the tick a pulse is emitted; false otherwise.
bucketVol number (L) m.bucketVol Composite volume accumulated this run.
bucketWeight number (kg) m.bucketWeight bucketVol + emptyWeightBucket.
sumPuls number m.sumPuls Pulses emitted this run.
pulsesRemaining number targetPuls - sumPuls Clamped to ≥ 0.
m3PerPuls number (m³) m.m3PerPuls Volume per pulse; set in _beginRun from predFlow / targetPuls.
m3PerPulse number (m³) (alias of m3PerPuls) Both keys emitted; kept for legacy consumers.
m3Total number (m³) m.m3Total Integrated total flow this run.
q number (m³/h) m.q Effective flow (getEffectiveFlow).
predFlow number (m³) m.predFlow Predicted total volume over the run window.
predM3PerSec number (m³/s) m.predM3PerSec Predicted average rate during the run.
predictedRateM3h number (m³/h) params.getPredictedFlowRate Rain-scaled flow band between nominalFlowMin and flowMax.
timePassed number (s) m.timePassed Seconds since start_time.
timeLeft number (s) m.timeLeft Seconds remaining until stop_time.
pulseFraction number m.temp_pulse Sub-pulse integrator value (0..1+).
flowToNextPulseM3 number (m³) derived Volume left to integrate before the next pulse trigger.
timeToNextPulseSec number (s) derived ETA to next pulse at current q; 0 when q=0.
targetVolumeM3 number (m³) derived from targetVolume (L) Target composite volume converted to m³.
targetProgressPct number derived bucketVol / targetVolume × 100, 2-dp.
targetDeltaL number (L) derived Signed L difference vs targetVolume.
targetDeltaM3 number (m³) derived Same in m³, 4-dp.
nextDate number (epoch ms) m.nextDate Next scheduled START_DATE for aquonSampleName. null if never set.
daysPerYear number m.daysPerYear Count of remaining scheduled runs this calendar year.
sumRain number m.rainAggregator.sumRain Probability-weighted hourly precipitation sum.
avgRain number m.rainAggregator.avgRain sumRain / numberOfLocations.
nominalFlowMin number (m³/h) config Lower band for prediction.
flowMax number (m³/h) config Upper band for prediction.
minVolume number (L) config Lower bucket bound.
maxVolume number (L) derived maxWeight - emptyWeightBucket.
invalidFlowBounds boolean derived True when nominalFlowMin >= flowMax.
missedSamples number m.missedSamples Pulse attempts blocked by cooldown.
sampleCooldownMs number (ms) derived Ms remaining on the active cooldown; 0 when none.
minSampleIntervalSec number (s) config Cooldown window.

Status badge

buildStatusBadge in io/statusBadge.js:

Condition Badge Fill Shape
invalidFlowBounds=true Config error: nominalFlowMin (…) >= flowMax (…) red (error preset)
running=true + sampleCooldownMs > 0 SAMPLING (Ns) · <bucketVol>/<maxVolume> L yellow ring
running=true + cooldown clear AI: RUNNING · <bucketVol>/<maxVolume> L green dot
idle AI: IDLE grey (idle preset)

Configuration schema — editor form to config keys

Source of truth: generalFunctions/src/configs/monster.json plus nodeClass.buildDomainConfig.

General (config.general)

Form field Config key Default Notes
Name general.name "Monster Configuration" Free-text.
(auto-assigned) general.id null Node-RED node id.
Default unit general.unit unitless Not used by the sampling program.
Enable logging general.logging.enabled true Master switch.
Log level general.logging.logLevel info debug / info / warn / error.

Functionality (config.functionality)

Form field Config key Default Notes
(hidden) functionality.softwareType monster Constant.
(hidden) functionality.role samplingCabinet Constant.
AQUON sample name functionality.aquonSampleName unset Forwarded to source.aquonSampleName in extraSetup. Falls back to '112100' in _initState.

Asset (config.asset)

Form field Config key Default Notes
Asset UUID asset.uuid null Globally-unique identifier.
Geolocation asset.geoLocation {x:0, y:0, z:0}
Supplier asset.supplier "Unknown" Schema only — not used by the sampling program.
Type asset.type "sensor" (enum) Schema only.
SubType asset.subType "pressure" Schema only; misleading default for a sampling cabinet (flag).
Model asset.model "Unknown" Schema only.
Empty bucket weight (kg) asset.emptyWeightBucket 3 Used in bucketWeight = bucketVol + emptyWeightBucket and in maxVolume = maxWeight - emptyWeightBucket.

Constraints (config.constraints)

Form field Config key Default Range Notes
Sampling time (hr) constraints.samplingtime 0 ≥ 0 Run length. Used as samplingtime · 3600 · 1000 ms for stop_time.
Sampling period (hr) constraints.samplingperiod 24 ≥ 1 Documented as the fixed composite-collection period; not enforced by samplingProgram — the AQUON schedule arms the run.
Min volume (L) constraints.minVolume 5 ≥ 5 Used in targetVolume = minVolume · √(maxVolume / minVolume).
Max weight (kg) constraints.maxWeight 23 ≤ 23 Bucket-overload bound; maxVolume = maxWeight - emptyWeightBucket.
Sub-sample volume (mL) constraints.subSampleVolume 50 fixed Schema enforces min=max=50. Hard-coded as volume_pulse = 0.05 in domain.
Storage temperature (°C) constraints.storageTemperature.min/max {1, 5} per-leg Schema only — informational.
Flowmeter present constraints.flowmeter true bool ⚠️ In schema but not wired in buildDomainConfig. Effectively always true.
Closed system constraints.closedSystem false bool Schema only.
Intake speed (m/s) constraints.intakeSpeed 0.3 ≥ 0 Schema only — informational.
Intake diameter (mm) constraints.intakeDiameter 12 ≥ 0 Schema only — informational.
Nominal flow min (m³/h) constraints.nominalFlowMin 0 ≥ 0 Lower bound of rain-driven flow prediction.
Flow max (m³/h) constraints.flowMax 0 ≥ 0 Upper bound of rain-driven flow prediction.
Max rain reference constraints.maxRainRef 10 > 0 Rain index that maps to flowMax.
Min sample interval (s) constraints.minSampleIntervalSec 60 ≥ 0 Cooldown guard.

Warning

Default flowMax = 0 blocks every run. validateFlowBounds requires 0 ≤ nominalFlowMin < flowMax. Out of the box the bounds are invalid and _beginRun never fires. Set flowMax to a realistic upper bound before deploying.

Unit policy

monster has no requireUnitForTypes policy declared in specificClass. Conversions happen at the boundary:

Quantity Canonical (internal) Carried as Notes
Flow (data.flow) m³/h m³/h handlers.dataFlow converts inbound via convert(value).from(unit).to('m3/h').
Flow (measured-child) as supplied as supplied flowTracker.handleMeasuredFlow defaults to 'm3/h' when unit is missing; does not convert. Wire children that emit in m³/h.
Volume (bucketVol) L L Output also exposes m³ derivations (targetVolumeM3, targetDeltaM3).
Weight kg kg
Time s (timers) / ms (timestamps) mixed timePassed / timeLeft in s, nextDate in epoch ms.

Child registration

Source: src/specificClass.js _wireMeasurementChild. The registrar subscribes to all three flow.measured.<position> events on the child's measurement emitter as long as the child's config.asset.type is 'flow' or unset.

Software type Filter Wired to Side-effect
measurement asset.type='flow' (or missing) flowTracker.handleMeasuredFlow (handles all three positions) Latches latest measured flow per position; getEffectiveFlow blends across positions and with manualFlow.
measurement asset.type anything else ignored The branch returns early; no listener is attached.

monster has no position-based filtering. Unlike rotatingMachine (which routes upstream pressure separately from downstream), all three flow positions are wired to the same handler and the latest value per position wins.

There are no auto-registered virtual children (no dashboard-sim-* equivalent). Inject simulated flow via data.flow instead.


Page Why
Home Intuitive overview
Reference — Architecture Code map, sampling-program loop, prediction + cooldown pipeline
Reference — Examples Shipped flows + debug recipes
Reference — Limitations Known issues and open questions
EVOLV — Topic Conventions Platform-wide topic rules
EVOLV — Telemetry Port 0 / 1 / 2 InfluxDB layout