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>
118 lines
7.9 KiB
Markdown
118 lines
7.9 KiB
Markdown
# Reference — Limitations
|
|
|
|

|
|
|
|
> [!NOTE]
|
|
> What `measurement` does not do, current rough edges, and open questions. Open items live in `.agents/improvements/IMPROVEMENTS_BACKLOG.md` in the EVOLV superproject; node-local follow-ups are tracked in the superproject's `MEMORY.md` and `.claude/refactor/OPEN_QUESTIONS.md`.
|
|
>
|
|
> Pending full node review (2026-05).
|
|
|
|
---
|
|
|
|
## When you would not use this node
|
|
|
|
| Scenario | Use instead |
|
|
|:---|:---|
|
|
| Fusing signals from multiple sensors into one virtual measurement | This node is per-channel only. Aggregate at the parent (e.g. `rotatingMachine` already combines upstream + downstream into a differential). |
|
|
| Producing a control output / actuating something | This is read-only signal conditioning. Use `rotatingMachine`, `valve`, or another equipment-level node. |
|
|
| Threshold-trip alarms / latched state | There is no comparator / latch output. Build alarm logic on top of the emitted reading at the parent or in a dashboard rule. |
|
|
| A "passive" measurement that should not register with a parent | Registration is automatic at startup — not currently opt-out. TODO: confirm whether a "no-parent" mode exists; if not, leave the parent input unwired. |
|
|
|
|
---
|
|
|
|
## Known limitations
|
|
|
|
### Asset type must match the parent's filter exactly
|
|
|
|
Parents subscribe to events by exact string match on `<asset.type>.measured.<position>`. A measurement configured as `flow-electromagnetic` will not be picked up by a parent that filters on `flow`. The fix is mechanical — set `asset.type` to the bare type the parent expects.
|
|
|
|
This is documented in the superproject `MEMORY.md` under "Key Integration Gotchas":
|
|
|
|
> Measurement `assetType: "flow"` required (not "flow-electromagnetic") for pumpingStation/monster.
|
|
|
|
### Position labels lowercase only in the event name
|
|
|
|
The event name emits `<type>.measured.<position>` with `position` lowercased (`upstream`, `downstream`, `atequipment`). The `positionVsParent` field in the `child.register` payload, however, is sent **as configured** (preserves case). If a parent indexes children by the register-payload position string, mixed-case there will not match the lowercase position in subsequent events. Document the convention in any new parent that joins measurement.
|
|
|
|
### Legacy `source.emitter`
|
|
|
|
`source.emitter` fires `'mAbs'` on the analog `inputValue` setter alongside the canonical `measurements.emitter` path. It is kept for the editor status badge during the refactor window and is **slated for removal in Phase 7**. New consumers must use `measurements.emitter`.
|
|
|
|
### Digital mode — `notifyOutputChanged()` not explicitly called
|
|
|
|
`Measurement.handleDigitalPayload` collects a per-key summary but does not directly call `notifyOutputChanged()`. The analog `inputValue` setter does. TODO: confirm whether digital-mode Port 0 emissions rely on the next `tick()` or a follow-up notify path inside `BaseNodeAdapter`. Until verified, treat digital-mode Port 0 latency as "up to one tick" (1000 ms).
|
|
|
|
### Digital mode — per-channel scaling / smoothing fall back to the analog block
|
|
|
|
When a `config.channels[i]` entry omits a per-channel `scaling`, `smoothing`, `outlierDetection`, or `interpolation`, the missing fields fall back to the node-level config — **not** to a sensible per-type default. Setting `smoothing.smoothMethod = 'kalman'` at the node level applies that to every digital channel that does not override it. Operators should set every block per channel in production digital flows.
|
|
|
|
### `data.measurement` accepts numeric strings — not arrays / NaN
|
|
|
|
The analog handler parses with `Number(p)` and rejects `NaN`. Empty / whitespace strings are skipped silently. Arrays are not accepted in either mode and log a warn in digital mode.
|
|
|
|
### Simulator does not respect outlier detection
|
|
|
|
`Simulator.step()` writes directly into `m.inputValue`. The downstream `Channel.update` does run outlier detection if enabled — but the simulator's random walk is well-behaved enough that this is effectively a no-op. Don't expect the outlier path to be exercised by the simulator alone.
|
|
|
|
### `cmd.calibrate` requires ≥ 2 stored values
|
|
|
|
`Calibrator.isStable()` returns `{isStable:false}` when `storedValues.length < 2`. The legacy `Measurement.isStable()` wrapper returns a bare `false` in that case. A fresh calibration call before any data has arrived is silently rejected.
|
|
|
|
### Calibration baseline depends on `scaling.enabled`
|
|
|
|
When `scaling.enabled` is true, the calibration baseline is `scaling.inputMin`. When disabled, it is `scaling.absMin`. Toggling `scaling.enabled` after calibrating shifts the meaning of the captured offset; recalibrate after any scaling-toggle.
|
|
|
|
### Smoothing buffer not cleared on config change
|
|
|
|
Changing `smoothing.smoothMethod` or `smoothing.smoothWindow` at runtime does not clear `storedValues`. A previously-mean-smoothed buffer can produce a stale first sample after switching to `lowPass` until the window churns. The conservative workaround is to redeploy.
|
|
|
|
### `outlierDetection.enabled` mirrored only into `analogChannel`
|
|
|
|
`toggleOutlierDetection()` propagates the new boolean to `this.analogChannel.outlierDetection.enabled` only. In digital mode the per-channel `Channel.outlierDetection.enabled` is **not** updated by the toggle. TODO: digital-mode parity for `set.outlier-detection`.
|
|
|
|
### Min/max counters never reset
|
|
|
|
`totalMinValue` / `totalMaxValue` / `totalMinSmooth` / `totalMaxSmooth` are monotonic over the node's lifetime. There is no explicit reset command. The smooth-min/max additionally have a "first-write" rule that snaps both to the first value — before that, both read `0`, which can mislead downstream chart axes.
|
|
|
|
---
|
|
|
|
## Open questions (tracked)
|
|
|
|
| Question | Where it lives |
|
|
|:---|:---|
|
|
| Should digital-mode `notifyOutputChanged()` fire on every accepted update? | Internal — pending P9 review |
|
|
| Drop the legacy `source.emitter 'mAbs'` event | Phase 7 removal |
|
|
| Replace legacy `examples/{basic,integration,edge}.flow.json` with Tier-1/2/3 visual-first flows | Superproject `MEMORY.md` "TODO: Example Flows" |
|
|
| Add `data.clear-min-max` / `data.reset` topic for the rolling counters | Internal |
|
|
| Add per-channel `set.outlier-detection` for digital mode | Internal |
|
|
| Auto-recalibration heuristics (currently operator-triggered only) | Internal |
|
|
| Per-channel `smoothing` window-clear on config change | Internal |
|
|
|
|
---
|
|
|
|
## Migration notes
|
|
|
|
### From pre-refactor flat config
|
|
|
|
Older flows used `assetType` / `supplier` / `category` at the top level of the editor config. `nodeClass.buildDomainConfig` reshapes the editor's flat `uiConfig` into the nested domain config slice (`scaling`, `smoothing`, `simulation`, `calibration`, `mode`, `channels`), so legacy flows continue to deploy. The migration is best-effort — re-saving each measurement node in the editor regenerates the canonical shape.
|
|
|
|
### From analog-only
|
|
|
|
Adding `config.mode.current` was additive. Flows that omit it default to `analog` and behave exactly as before. To switch to digital: set the editor's "Input Mode" to `digital` and define `config.channels`.
|
|
|
|
### From legacy alias topics
|
|
|
|
`simulator`, `outlierDetection`, `calibrate`, `measurement` continue to work; each emits a one-time deprecation warning on first fire. Prefer the canonical `set.simulator` / `set.outlier-detection` / `cmd.calibrate` / `data.measurement` for new flows.
|
|
|
|
---
|
|
|
|
## Related pages
|
|
|
|
| Page | Why |
|
|
|:---|:---|
|
|
| [Home](Home) | Intuitive overview |
|
|
| [Reference — Contracts](Reference-Contracts) | Topic + config + child registration (alias map at the end) |
|
|
| [Reference — Architecture](Reference-Architecture) | Code map + per-`Channel` pipeline + lifecycle |
|
|
| [Reference — Examples](Reference-Examples) | Shipped flows + debug recipes |
|
|
| [rotatingMachine — Limitations](https://gitea.wbd-rd.nl/RnD/rotatingMachine/wiki/Reference-Limitations) | Where the most common consumer's caveats overlap |
|