Files
EVOLV/wiki/Archive/manuals-nodes-measurement.md
znetsixe b8cb889d87 wiki: audit + archive stale pages; refresh Home for 2026-05-11 wave
- Archived 20 pre-refactor pages to wiki/Archive/ with standard banners:
  - All 6 architecture/ pages (old _loadConfig/_setupSpecificClass internals,
    pre-refactor S88 hierarchy, deployment blueprint)
  - All 3 sessions/ logs (Apr-07 + Apr-13 session summaries)
  - findings/open-issues-2026-03.md (issues 1-5 all resolved by refactor)
  - concepts/generalfunctions-api.md (missing BaseDomain/BaseNodeAdapter)
  - concepts/sources-readme.md (empty PDF placeholder, never populated)
  - manuals/nodes/rotatingMachine.md + measurement.md (superseded by per-repo wikis)
  - Top-level SCHEMA.md, index.md, log.md, metrics.md, overview.md,
    knowledge-graph.yaml (all Apr-07 snapshot, pre-refactor)
- Kept wiki/concepts/ domain pages (ASM, PID, pump-affinity, settling, etc.)
- Kept wiki/findings/ proven results (BEP, NCog, curve-non-convexity, stability)
- Kept wiki/manuals/node-red/* (FlowFuse + Node-RED runtime docs, still current)
- Kept wiki/tools/* (utility scripts)
- Updated wiki/Archive.md index with 20 rows
- Fixed wiki/Home.md: Tier 6 was wrongly marked done; corrected to pending;
  Tier 9 updated to reflect 2026-05-11 in-progress wave

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

9.1 KiB
Raw Permalink Blame History

title, node, updated, status
title node updated status
measurement — User Manual measurement 2026-04-13 trial-ready

⚠️ ARCHIVED — pre-refactor (Tier 14, 2026-05)

This page describes the architecture before the platform refactor. The current page is the per-node wiki on gitea.wbd-rd.nl/RnD or Home.

Kept for historical reference only. Do not update.

measurement — User Manual

The measurement node is the sensor-side of every EVOLV flow. It takes raw signal data, applies offset / scaling / smoothing / outlier rejection, and publishes a conditioned value into the shared MeasurementContainer. A parent equipment node (rotatingMachine, pumpingStation, reactor, ...) subscribes automatically via the child-registration handshake on port 2.

At a glance

Item Value
Node category EVOLV
Inputs 1 (message-driven)
Outputs 3 — process / dbase / parent
Tick period 1 s
Input modes analog (default) — one scalar per msg. digital — object payload with many keys.
Smoothing methods 12 (none, mean, min, max, sd, lowPass, highPass, weightedMovingAverage, bandPass, median, kalman, savitzkyGolay)
Outlier methods 3 (zScore, iqr, modifiedZScore)

Choosing a mode

Analog — one scalar per message (PLC / 4-20 mA)

The classic pattern — what the node did before v1.1. msg.payload is a single number. The node runs one offset → scaling → smoothing → outlier pipeline and emits exactly one MeasurementContainer slot keyed by the asset's type + position.

{ "topic": "measurement", "payload": 12.34 }

Use when one Node-RED measurement node represents one physical sensor.

Digital — object payload, many channels (MQTT / IoT / JSON)

Use when one Node-RED measurement node represents one physical device that publishes multiple readings. Common shapes:

{ "topic": "measurement",
  "payload": { "temperature": 22.5, "humidity": 45, "pressure": 1013 } }
{ "topic": "measurement",
  "payload": { "co2": 618, "voc": 122, "pm25": 8 } }

Each top-level key maps to a channel with its own type, position, unit, and pipeline parameters. Unknown keys are ignored (logged at debug).

Configuration

Common (both modes)

  • Asset (menu): supplier, category, asset type (assetType), model, unit.
  • Logger (menu): log level + enable flag.
  • Position (menu): upstream / atEquipment / downstream, optional distance offset.

Analog fields

Field Meaning
Scaling enables linear interpolation from source range to process range
Source Min / Max raw input bounds (e.g. 4 / 20 for mA)
Input Offset additive bias applied before scaling
Process Min / Max mapped output bounds (e.g. 0 / 3000 for mbar)
Simulator internal random-walk source for testing
Smoothing method (dropdown)
Window smoothing window size

Digital fields

  • Input Mode: set to digital in the dropdown.
  • Channels (JSON): array of channel definitions.

Each channel:

{
  "key":      "temperature",
  "type":     "temperature",
  "position": "atEquipment",
  "unit":     "C",
  "scaling":  { "enabled": false, "inputMin": 0, "inputMax": 1, "absMin": -50, "absMax": 150, "offset": 0 },
  "smoothing": { "smoothWindow": 5, "smoothMethod": "mean" },
  "outlierDetection": { "enabled": true, "method": "zScore", "threshold": 3 }
}

scaling / smoothing / outlierDetection are optional — missing sections inherit the top-level analog-mode fields. key is the JSON field name inside msg.payload; type is the MeasurementContainer axis — any string works, not just the physical-unit-backed defaults.

Input topics

Topic Payload Effect
measurement number (analog) / object (digital) drives the pipeline
simulator toggle the internal random-walk simulator
outlierDetection toggle outlier rejection
calibrate set the offset so the current output matches Source Min (scaling on) or Process Min (scaling off). Requires a stable window — aborts if the signal is fluctuating.

Output ports

Port 0 — process

Delta-compressed payload.

Analog shape:

{ "mAbs": 4.2, "mPercent": 42, "totalMinValue": 0, "totalMaxValue": 100,
  "totalMinSmooth": 0, "totalMaxSmooth": 4.2 }

Digital shape:

{ "channels": {
    "temperature": { "key": "temperature", "type": "temperature", "position": "atEquipment",
                     "unit": "C", "mAbs": 24, "mPercent": 37,
                     "totalMinValue": 22.5, "totalMaxValue": 25.5,
                     "totalMinSmooth": 22.5, "totalMaxSmooth": 24 },
    "humidity":    { ... },
    "pressure":    { ... }
} }

Port 1 — dbase

InfluxDB line-protocol telemetry. Tags = asset metadata; fields = measurements. See InfluxDB Schema Design.

Port 2 — parent

{ topic: "registerChild", payload: <nodeId>, positionVsParent, distance } — emitted once ~200 ms after deploy so the parent equipment node registers this sensor.

Pipeline per value

  1. Outlier check (if enabled) — rejects via zScore / IQR / modifiedZScore. Rejected values never advance, don't update min/max, don't emit.
  2. Offsetvalue + scaling.offset.
  3. Scaling (if enabled) — linear interpolation from [inputMin, inputMax] to [absMin, absMax] with boundary clamping.
  4. Smoothing — current value pushed into the rolling window; the configured method produces the smoothed output.
  5. Min/Max tracking — both raw (pre-smoothing) and smoothed min/max tracked for display.
  6. Constrain — smoothed value clamped to [absMin, absMax].
  7. EmitMeasurementContainer.type(...).variant('measured').position(...).distance(...).value(out, ts, unit) triggers the event <type>.measured.<position> (lowercase) that the parent equipment subscribes to.

In digital mode, each channel runs this pipeline independently.

Smoothing methods — quick reference

Method Use case
none pass raw value through — useful for testing
mean simple arithmetic average over window
min / max worst-case / peak reporting
sd outputs standard deviation (noise indicator)
median outlier-resistant central tendency
weightedMovingAverage later samples weighted higher
lowPass EMA-style attenuation of high-frequency noise
highPass emphasises rapid changes (step detection)
bandPass lowPass + highPass - raw — band-of-interest filtering
kalman recursive noise filter, converges to steady value
savitzkyGolay polynomial smoothing over 5-point window

Outlier methods — quick reference

Method Best when
zScore signal is approximately normal; threshold = # of SDs
iqr signal is non-normal; robust to skewed distributions
modifiedZScore small samples; uses median / MAD instead of mean / SD

Historical bug fixed 2026-04-13: The dispatcher compared against camelCase keys (lowPass, zScore, ...) but the validator lowercases enum values. Result: 4 smoothing methods and 2 outlier methods were silently no-ops when chosen from the editor — they fell through to the "unknown" branch and emitted the raw last value. Review any flow deployed before 2026-04-13 that relied on these methods.

Unit policy

Unknown measurement types (anything not in the container's built-in measureMap: pressure, flow, power, temperature, volume, length, mass, energy) are accepted without unit compatibility checks. This lets digital channels use humidity (%), co2 (ppm), arbitrary IoT units. Known types still validate strictly.

Example flow (digital)

[
  { "id": "dig", "type": "measurement",
    "mode": "digital",
    "channels": "[{\"key\":\"temperature\",\"type\":\"temperature\",\"position\":\"atEquipment\",\"unit\":\"C\",\"scaling\":{\"enabled\":false,\"absMin\":-50,\"absMax\":150},\"smoothing\":{\"smoothWindow\":5,\"smoothMethod\":\"mean\"}},{\"key\":\"humidity\",\"type\":\"humidity\",\"position\":\"atEquipment\",\"unit\":\"%\",\"scaling\":{\"enabled\":false,\"absMin\":0,\"absMax\":100},\"smoothing\":{\"smoothWindow\":5,\"smoothMethod\":\"mean\"}}]",
    ...
  }
]

Testing

cd nodes/measurement
npm test

71 tests — coverage includes every smoothing method, every outlier strategy, scaling, interpolation, constrain, calibration, stability, simulation, per-channel pipelines, digital-mode dispatch, malformed-channel handling, event emits.

End-to-end benchmark scripts live in the superproject at /tmp/m_e2e_baseline.py (analog) and /tmp/m_digital_e2e.py (digital). Run against a Dockerized Node-RED stack (docker compose up -d nodered).

Production status

Trial-ready as of 2026-04-13 after the session that fixed the silent dispatcher bug and added digital mode. See session 2026-04-13 and the memory file node_measurement.md.