> If this banner is stale, the page may be out of date. Treat as informative, not authoritative.
## 1. What this node is
**measurement** is an S88 Control Module that turns a raw sensor signal into a validated, scaled, smoothed reading and re-emits it for any parent. Two modes: **analog** (one channel built from the flat config) and **digital** (one Channel per `config.channels[]` entry). It is a leaf in the hierarchy — no children of its own.
## 2. Position in the platform
```mermaid
flowchart LR
raw[Raw sensor / MQTT / inject<br/>analog scalar or digital object]
m[measurement<br/>Control Module]:::ctrl
p1[rotatingMachine<br/>Equipment]:::equip
p2[machineGroupControl<br/>Unit]:::unit
p3[pumpingStation<br/>Process Cell]:::pc
raw -->|data.measurement| m
m -->|child.register| p1
m -->|child.register| p2
m -->|child.register| p3
m -.<type>.measured.<position>.-> p1
m -.<type>.measured.<position>.-> p2
m -.<type>.measured.<position>.-> p3
classDef pc fill:#0c99d9,color:#fff
classDef unit fill:#50a8d9,color:#000
classDef equip fill:#86bbdd,color:#000
classDef ctrl fill:#a9daee,color:#000
```
S88 colours: Control Module `#a9daee`, Equipment `#86bbdd`, Unit `#50a8d9`, Process Cell `#0c99d9`. Source of truth: `.claude/rules/node-red-flow-layout.md`.
## 3. Capability matrix
| Capability | Status | Notes |
|---|---|---|
| Analog mode — single channel from flat config | ✅ | Default. `data.measurement` payload is numeric. |
| Digital mode — many channels from `config.channels[]` | ✅ | Payload is an object keyed by `channel.key`. |
| Outlier detection | ✅ | Median ± window check. Toggleable via `set.outlier-detection`. |
| Scaling (input range → process range + offset) | ✅ | `config.scaling.{inputMin,inputMax,absMin,absMax,offset}`. |
| `commands/` | Input-topic registry and handlers | New input topics, payload validation. |
The analog/digital branch is decided once in `configure()` based on `config.mode.current`. There is no FSM — `tick()` only pumps the simulator when enabled.
```mermaid
flowchart LR
cfg[config.mode.current]
cfg -->|"=== 'digital'"| dig[Build N Channels<br/>from config.channels[]]
Tier 1/2/3 visual-first example flows are still TODO (see `MEMORY.md` "TODO: Example Flows"). Screenshots will land under `wiki/_partial-screenshots/measurement/` when the new flows ship.
| Symptom | First thing to check | Where to look |
|---|---|---|
| Parent never receives `<type>.measured.<position>` | `assetType` must match parent's filter exactly (e.g. `flow` — not `flow-electromagnetic`). | `config.asset.type` + `MEMORY.md` integration gotcha. |
| Position labels look uppercase to parent | Event name lowercases — but `functionality.positionVsParent` is sent as-is on `child.register`. | `_buildAnalogChannel` event-name composition. |
| Outliers seem to pass through | `outlierDetection.enabled` may be off (default varies by config). Toggle with `set.outlier-detection`. | `Channel._isOutlier`. |
| Digital payload silently dropped | Unknown channel keys land in the `unknown` log line only at debug level. | enable `logging.logLevel=debug` momentarily. |
| Simulator still running after toggle off | `tick()` reads `config.simulation.enabled` each tick — confirm the toggle actually mutated the config. | `toggleSimulation`. |
> Never ship `enableLog: 'debug'` in a demo — fills the container log within seconds and obscures real errors.
- Don't use measurement to **fuse** signals from multiple sensors — it's per-channel only. Aggregate at the parent.
- Don't use measurement for **control output** — it's read-only signal conditioning. Use `rotatingMachine` / `valve` for actuation.
- Don't use measurement for **alarm logic** — there is no threshold-trip output. Build that on top of the emitted reading at the parent or in a dashboard rule.
| 1 | Legacy `source.emitter` 'mAbs' event still fired alongside `measurements.emitter` — slated for removal in Phase 7. | `OPEN_QUESTIONS.md` (2026-05-10) |
| 2 | Digital mode's per-channel scaling/smoothing falls back to the analog block's defaults when not specified per channel. | `_buildDigitalChannels`. |
| 3 | Tier 1/2/3 visual-first example flows not yet written; current `examples/` only contains pre-refactor flows. | P9 / P2.14 follow-up. |
| 4 | No automatic recalibration — `cmd.calibrate` is operator-triggered. | `calibration/calibrator.js`. |