From 2d5f90ff9d0516cdc53ad4ade72623d02a3ce666 Mon Sep 17 00:00:00 2001 From: Denys Berkovskyy Date: Sun, 26 Apr 2020 13:05:21 +0100 Subject: [PATCH] Implement per topic counting. --- counter.html | 1 + counter.js | 52 +++++++++++++++++++++++++++++++++++++++------------- readme.md | 4 +++- 3 files changed, 43 insertions(+), 14 deletions(-) diff --git a/counter.html b/counter.html index ce4e0ff..037b76c 100644 --- a/counter.html +++ b/counter.html @@ -60,6 +60,7 @@

diff --git a/counter.js b/counter.js index 0ca4b31..aa798b2 100644 --- a/counter.js +++ b/counter.js @@ -11,12 +11,28 @@ module.exports = function(RED) { this.lower = config.lower || null; this.upper = config.upper || null; this.mode = config.mode || "increment"; - this.count = this.init; + this.count_per_topic = {}; this.on("input", function(msg) { var lowerLimitReached = false, upperLimitReached = false; + // Extract topic + var topic = ""; + if ( msg.hasOwnProperty("topic") ) { + if ( typeof msg.topic === "string" ) { + topic = msg.topic; + } + else { + this.error("topic is not a string", msg); + } + } + + // Initialize counter if required + if ( !node.count_per_topic.hasOwnProperty(topic) ) { + node.count_per_topic[topic] = this.init + } + // use message parameters if( msg.hasOwnProperty("increment") || msg.hasOwnProperty("decrement") ) { var decremented = false; @@ -26,7 +42,7 @@ module.exports = function(RED) { var decrement = Number(msg.decrement); if( !isNaN(decrement) && isFinite(decrement) ) { - node.count -= decrement; + node.count_per_topic[topic] -= decrement; decremented = true; } else { @@ -39,7 +55,7 @@ module.exports = function(RED) { var increment = Number(msg.increment || 1); if( !isNaN(increment) && isFinite(increment) ) { - node.count += increment; + node.count_per_topic[topic] += increment; } else { this.error("increment is not a numeric value", msg); @@ -54,10 +70,10 @@ module.exports = function(RED) { } if( node.mode === "increment" ) { - node.count += node.step; + node.count_per_topic[topic] += node.step; } else if( node.mode === "decrement" ) { - node.count -= node.step; + node.count_per_topic[topic] -= node.step; } else { this.error("unknown mode '" + node.mode + "'", msg); @@ -65,16 +81,26 @@ module.exports = function(RED) { } // handle reset - if( msg.hasOwnProperty("reset") && msg.reset ) { - node.count = typeof msg.reset === "number" ? msg.reset : node.init; + if( msg.hasOwnProperty("reset") && msg.reset !== false ) { + if ( topic !== "" ) { + node.count_per_topic[topic] = typeof msg.reset === "number" ? msg.reset : node.init; + } + else { + if (typeof msg.reset !== "number") { + node.count_per_topic = {} + } + else { + Object.keys(node.count_per_topic).forEach(v => node.count_per_topic[v] = msg.reset) + } + } } // handle lower limit if( node.lower !== null ) { var lower = Number(node.lower); - if( !isNaN(lower) && isFinite(lower) && node.count < lower ) { - node.count = lower; + if( !isNaN(lower) && isFinite(lower) && node.count_per_topic[topic] < lower ) { + node.count_per_topic[topic] = lower; lowerLimitReached = true; } } @@ -83,15 +109,15 @@ module.exports = function(RED) { if( node.upper !== null ) { var upper = Number(node.upper); - if( !isNaN(upper) && isFinite(upper) && node.count > upper ) { - node.count = upper; + if( !isNaN(upper) && isFinite(upper) && node.count_per_topic[topic] > upper ) { + node.count_per_topic[topic] = upper; upperLimitReached = true; } } // single output if( node.outputs === "single" ) { - msg.count = node.count; + msg.count = node.count_per_topic[topic]; if( lowerLimitReached ) { msg.countLowerLimitReached = true; @@ -106,7 +132,7 @@ module.exports = function(RED) { // split output else { - var obj = {payload: node.count}; + var obj = {payload: node.count_per_topic[topic]}; if( lowerLimitReached ) { obj.countLowerLimitReached = true; diff --git a/readme.md b/readme.md index 76f6107..6d12c61 100644 --- a/readme.md +++ b/readme.md @@ -35,6 +35,7 @@ npm install node-red-contrib-counter By default the counter will be incremented for every inbound message and append the current count to `msg.count`. +This works on a per msg.topic basis. This means that a single counter node can handle multiple topics at the same time. ### Configuration @@ -60,7 +61,8 @@ It's possible to control the counter with incoming `msg` properties: - `msg.increment`: counter will be incremented by the given value. - `msg.decrement`: counter will be decremented by the given value. -- `msg.reset`: resets the counter to it's initial count, or to the given value, when it's a number. +- `msg.topic`: if specified the counter will work on a per topic basis. +- `msg.reset`: resets the counter to it's initial count, or to the given value, when it's a number (if msg.topic is not specified the counter will reset all known topics). ## Example Flows