# measurement — Contract Hand-maintained for Phase 3; the `## Inputs` table is generated from `src/commands/index.js` (see Phase 9 generator). Keep ≤ 80 lines. ## Inputs (msg.topic on Port 0) | Canonical | Aliases (deprecated) | Payload | Effect | |---|---|---|---| | `set.simulator` | `simulator` | none (payload ignored) | Toggles `source.toggleSimulation()` — flips `config.simulation.enabled`. | | `set.outlier-detection` | `outlierDetection` | none (payload ignored) | Toggles `source.toggleOutlierDetection()` — flips `config.outlierDetection.enabled`. | | `cmd.calibrate` | `calibrate` | none | Calls `source.calibrate()` — captures the current input as the zero/reference offset. | | `data.measurement` | `measurement` | mode-dependent — see below | Pushes a sensor reading into the pipeline. Analog: numeric scalar (number or numeric string) → `source.inputValue`. Digital: object payload keyed by channel name → `source.handleDigitalPayload(payload)`. Wrong shape for the configured mode logs a helpful warning suggesting the other mode. | Aliases log a one-time deprecation warning the first time they fire. ## Outputs (msg.topic on Port 0/1/2) - **Port 0 (process):** `msg.topic = config.general.name`. Payload built by `outputUtils.formatMsg(..., 'process')` from `getOutput()` (analog) or `getDigitalOutput()` (digital). Delta-compressed — only changed fields are emitted. - **Port 1 (InfluxDB telemetry):** same shape as Port 0, formatted with the `'influxdb'` formatter. - **Port 2 (registration):** at startup the node sends one `{ topic: 'registerChild', payload: , positionVsParent, distance }` to its parent. ## Events emitted by `source.measurements.emitter` The `MeasurementContainer` fires `.measured.` whenever a matching series receives a new value. The type / position labels are set from `config.asset.type` and `config.functionality.positionVsParent` (analog), or per-channel from `config.channels[*]` (digital). Examples: - `pressure.measured.upstream` - `flow.measured.atequipment` - `level.measured.downstream` - `temperature.measured.atequipment` Position labels are always lowercase in the event name. Parents subscribe through the generic `child.measurements.emitter.on(eventName, ...)` handshake established by `childRegistrationUtils`. In digital mode one input message can fan out into several events — one per channel that accepted a value on that tick. The legacy internal `source.emitter` also fires `'mAbs'` with the current scaled absolute value (analog mode only). This is deprecated in favour of `measurements.emitter` and kept only for the editor status badge during the refactor window. ## Children registered by this node None — `measurement` is a leaf in the S88 hierarchy (Control Module). It registers itself as a child of an upstream parent (rotatingMachine, pumpingStation, reactor, monster, …) but does not accept its own children. Registration goes via Port 2 at startup and is keyed off `positionVsParent` / `distance` in the node's UI config.