Digital mode only. One entry per payload key. See README for schema.
+
+
+
+
+
+
One entry per payload key. Each channel has its own type / position / unit / scaling / smoothing / outlier detection. See README for the full schema.
+
+
-
+
+
+
+
+
+
+
+ Enable input scaling?
+
-
-
-
-
- Enable input scaling?
-
+
+
+
+
+
-
-
-
-
-
+
+
+
+
-
-
-
-
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+ Activate internal simulation?
+
-
-
-
-
- Activate internal simulation?
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
Number of samples for smoothing
+
+
+
+
+
Number of samples for smoothing
+
diff --git a/src/nodeClass.js b/src/nodeClass.js
index df7b60f..2893b47 100644
--- a/src/nodeClass.js
+++ b/src/nodeClass.js
@@ -97,10 +97,18 @@ class nodeClass {
*/
_bindEvents() {
+ // Analog mode: the classic 'mAbs' event pushes a green dot with the
+ // current value + unit to the editor.
this.source.emitter.on('mAbs', (val) => {
this.node.status({ fill: 'green', shape: 'dot', text: `${val} ${this.config.general.unit}` });
});
-
+
+ // Digital mode: summarise how many channels have ticked a value.
+ // This runs on every accepted channel update so the editor shows live
+ // activity instead of staying blank when no single scalar exists.
+ if (this.source.mode === 'digital') {
+ this.node.status({ fill: 'blue', shape: 'ring', text: `digital · ${this.source.channels.size} channel(s)` });
+ }
}
/**
@@ -168,7 +176,16 @@ class nodeClass {
// digital -> object payload keyed by channel name
if (this.source.mode === 'digital') {
if (msg.payload && typeof msg.payload === 'object' && !Array.isArray(msg.payload)) {
- this.source.handleDigitalPayload(msg.payload);
+ const summary = this.source.handleDigitalPayload(msg.payload);
+ // Summarise what actually got accepted on the node status so
+ // the editor shows a heartbeat per message.
+ const accepted = Object.values(summary).filter((s) => s.ok).length;
+ const total = Object.keys(summary).length;
+ this.node.status({ fill: 'green', shape: 'dot',
+ text: `digital · ${accepted}/${total} ch updated` });
+ } else if (typeof msg.payload === 'number') {
+ // Helpful hint: the user probably configured the wrong mode.
+ this.source.logger?.warn(`digital mode received a number (${msg.payload}); expected an object like {key: value, ...}. Switch Input Mode to 'analog' in the editor or send an object payload.`);
} else {
this.source.logger?.warn(`digital mode expects an object payload; got ${typeof msg.payload}`);
}
@@ -180,6 +197,11 @@ class nodeClass {
} else {
this.source.logger?.warn(`Invalid numeric measurement payload: ${msg.payload}`);
}
+ } else if (msg.payload && typeof msg.payload === 'object' && !Array.isArray(msg.payload)) {
+ // Helpful hint: the payload is object-shaped but the node is
+ // configured analog. Most likely the user wanted digital mode.
+ const keys = Object.keys(msg.payload).slice(0, 3).join(', ');
+ this.source.logger?.warn(`analog mode received an object payload (keys: ${keys}). Switch Input Mode to 'digital' in the editor and define channels, or feed a numeric payload.`);
}
}
break;