Files
measurement/wiki/Reference-Examples.md
znetsixe 1a16f9c4f1 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:10 +02:00

8.9 KiB
Raw Blame History

Reference — Examples

code-ref

Note

Every example flow shipped under nodes/measurement/examples/, plus how to load them, what they show, and the debug recipes that go with them. Live source: nodes/measurement/examples/.

Pending full node review (2026-05). Tier-1/2/3 visual-first example flows are still TODO (tracked in the superproject MEMORY.md "TODO: Example Flows"). The current shipped flows pre-date the refactor; treat them as smoke tests, not as production templates.


Shipped examples

File Tier Dependencies What it shows Status
basic.flow.json 1 EVOLV only Single measurement node driven by inject buttons — analog scalar input, scaling enabled, three debug taps on Port 0/1/2. Legacy pre-refactor shape, still imports.
integration.flow.json 2 EVOLV only Parent-child wiring — measurement registers as a child of another node and emits its <type>.measured.<position> events. Legacy pre-refactor shape.
edge.flow.json 3 EVOLV only Invalid / edge payload driving for robustness checks (non-numeric strings, object in analog mode, …). Legacy pre-refactor shape.

The three legacy files predate the AssetResolver refactor and the analog-vs-digital mode flag. They still deploy (the editor will accept the older shape and nodeClass.buildDomainConfig reshapes whatever it finds), but the recommended Tier-1/2/3 visual-first replacements are still to be written.

Important

TODO — Tier-1/2/3 visual-first flows. Replace the three legacy files with:

  • 01 - Basic Analog.json — one measurement, inject + scaling + smoothing + outlier-detection toggle + simulator.
  • 02 - Integration with rotatingMachine.json — measurement registered as a pressure sensor on a rotatingMachine, Port 2 auto-register on deploy, parent's prediction updates as the measurement value moves.
  • 03 - Digital Multi-Channel.json — one measurement in digital mode with 23 channels (e.g. level-a, temp-a, flow-a) fed by a single object-payload inject.

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

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

Example — basic.flow.json

Single-measurement flow with the minimum kit to exercise scaling.

Nodes on the tab

Type Purpose
inject One-shot topic: 'measurement', payload: 42 (legacy alias of data.measurement)
measurement The unit under test — analog mode, scaling enabled (0..100 → 0..10), mean smoothing, window 5
debug × 3 Port 0 (process), Port 1 (InfluxDB), Port 2 (registration)

What to do after deploy

  1. Click the inject. Port 0 fires with mAbs ≈ 4.2 (42 scaled into 0..10), mPercent ≈ 42.
  2. Send another value via the same inject (edit the inject payload to 60). totalMinValue / totalMaxValue start tracking, mAbs jumps to ~6.0.
  3. Send topic: 'set.simulator' (use a second inject). tick() starts driving inputValue through Simulator.step() every 1000 ms; Port 0 updates appear automatically.
  4. Send topic: 'cmd.calibrate'. If stdDev <= 0.01 (the default stabilityThreshold), config.scaling.offset jumps to inputMin - currentOutput; if not, a warn appears in the log.
  5. Send topic: 'set.outlier-detection', then inject a wildly out-of-band value (e.g. 9999). With outlier detection on the value is dropped with Outlier detected. Ignoring value=9999.

Important

Screenshot needed. Editor capture of basic.flow.json plus the Port 0 debug output. Save as wiki/_partial-screenshots/measurement/basic-flow.png. Replace this callout with the image link.


Example — integration.flow.json

Demonstrates the parent-child handshake: the measurement node's Port 2 auto-fires child.register to its parent on deploy, and the parent then receives the <type>.measured.<position> event whenever a new reading lands.

Important

Screenshot needed. Editor capture of integration.flow.json showing the wiring. Save as wiki/_partial-screenshots/measurement/integration-flow.png.

Note

TODO: confirm the integration flow targets a real EVOLV parent (e.g. rotatingMachine) versus a mock function node; if it's a mock, the Tier-2 replacement should use a real parent.


Example — edge.flow.json

Drives the node with malformed inputs to verify the warn paths land cleanly:

  • Non-numeric string in analog mode → Invalid numeric measurement payload: <value>.
  • Object payload in analog mode → analog mode received an object payload (keys: &hellip;). Switch Input Mode to 'digital' &hellip;.
  • Numeric scalar in digital mode → digital mode received a number (&hellip;); expected an object &hellip;.
  • Outlier toggle on/off mid-stream → verifies analogChannel.outlierDetection.enabled mirrors config.outlierDetection.enabled.

Important

Screenshot needed. Editor capture of edge.flow.json plus the log lines each inject triggers. Save as wiki/_partial-screenshots/measurement/edge-flow.png.


Debug recipes

Symptom First thing to check Where to look
Parent never receives <type>.measured.<position> asset.type must match the parent's filter exactly (e.g. flow — not flow-electromagnetic). Position labels lowercase in the event name. config.asset.type + parent's childRegistrationUtils filter.
Outliers seem to pass through outlierDetection.enabled may be off (default false). Toggle with set.outlier-detection. With <2 samples in the buffer, _isOutlier returns false regardless. Channel._isOutlier.
cmd.calibrate does nothing Calibrator requires stdDev <= calibration.stabilityThreshold over storedValues. If storedValues.length < 2, isStable() returns false (legacy shape). src/calibration/calibrator.js isStable, calibrate.
Digital payload silently dropped Unknown channel keys are reported only at debug log level (digital payload contained unmapped keys). Numeric values that fail Number.isFinite warn at warn. Measurement.handleDigitalPayload.
Simulator still running after toggle off tick() reads config.simulation.enabled each tick. Confirm the toggle actually mutated the config (the set.simulator handler is idempotent — it just flips). Measurement.tick, toggleSimulation.
Port 0 emits nothing after data.measurement Analog: _writeOutput only emits when rounded !== outputAbs. A repeated identical value is silent by design. Channel._writeOutput.
mPercent is stuck at 0 or unbounded processRange <= 0 (i.e. absMax <= absMin); percent falls back to totalMinValue / totalMaxValue which start at 0 / 0. Configure absMin < absMax. Channel._computePercent.
Scaling output looks clamped _applyScaling clamps the input to [inputMin, inputMax] before mapping. Wide-band sensors need inputMin / inputMax set to the full physical range. Channel._applyScaling.
mAbs jumps after cmd.calibrate Expected. Calibration sets config.scaling.offset = baseline - currentOutputAbs, which makes the next reading land on the baseline (inputMin when scaling enabled, absMin otherwise). Calibrator.calibrate.
Legacy setpoint / simulator topics work without warning First fire emits a one-time deprecation warning via BaseNodeAdapter's alias handling. Subsequent fires are silent — the topic still works. commands/index.js aliases.

Never ship enableLog: 'debug' in a demo — fills the container log within seconds and obscures real errors.


Docker compose snippet

To bring up Node-RED + InfluxDB with EVOLV nodes pre-loaded:

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


Page Why
Home Intuitive overview
Reference — Contracts Topic + config + child registration
Reference — Architecture Code map + per-Channel pipeline + lifecycle
Reference — Limitations Known issues and open questions
rotatingMachine — Examples Most common consumer of measurement
EVOLV — Topology Patterns Where measurement fits in a larger plant