Compare commits

...

1 Commits

Author SHA1 Message Date
znetsixe
e50be2ee66 feat: permissive unit check for user-defined measurement types + measurement digital-mode schema
MeasurementContainer.isUnitCompatible now short-circuits to accept any unit
when the measurement type is not in the built-in measureMap. Known types
(pressure, flow, power, temperature, volume, length, mass, energy) still
validate strictly. This unblocks user-defined types in the measurement
node's new digital/MQTT mode — e.g. 'humidity' with unit '%', 'co2' with
'ppm' — without forcing those units into the convert-module unit system.

measurement.json schema: add 'mode.current' (analog | digital) and
'channels' (array) so the validator stops stripping them from the runtime
config. Ignored in analog mode.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 13:42:31 +02:00
2 changed files with 36 additions and 2 deletions

View File

@@ -411,6 +411,34 @@
}
}
},
"mode": {
"current": {
"default": "analog",
"rules": {
"type": "enum",
"values": [
{
"value": "analog",
"description": "Single-scalar input mode (classic 4-20mA / PLC style). msg.payload is a number; the node runs one offset/scaling/smoothing/outlier pipeline and emits one MeasurementContainer slot."
},
{
"value": "digital",
"description": "Multi-channel input mode (MQTT / IoT JSON style). msg.payload is an object keyed by channel names declared under config.channels; the node routes each key through its own pipeline and emits N slots from one input message."
}
],
"description": "Selects how incoming msg.payload is interpreted."
}
}
},
"channels": {
"default": [],
"rules": {
"type": "array",
"itemType": "object",
"minLength": 0,
"description": "Channel map used in digital mode. Each entry is a self-contained pipeline definition: {key, type, position, unit, scaling?, smoothing?, outlierDetection?, distance?}. Ignored in analog mode."
}
},
"outlierDetection": {
"enabled": {
"default": false,

View File

@@ -141,11 +141,17 @@ class MeasurementContainer {
}
isUnitCompatible(measurementType, unit) {
const desc = this._describeUnit(unit);
if (!desc) return false;
// Unknown type (not in measureMap): accept any unit. This lets user-
// defined measurement types (e.g. 'humidity', 'co2', arbitrary IoT
// channels in digital mode) pass through without being rejected just
// because their unit string ('%', 'ppm', …) is not a known physical
// unit to the convert module. Known types are still validated strictly.
const normalizedType = this._normalizeType(measurementType);
const expectedMeasure = this.measureMap[normalizedType];
if (!expectedMeasure) return true;
const desc = this._describeUnit(unit);
if (!desc) return false;
return desc.measure === expectedMeasure;
}