From c3a8a4088d0db9e1539d016df67c5e3cce4860f8 Mon Sep 17 00:00:00 2001 From: Dave Conway-Jones Date: Mon, 21 Mar 2016 00:01:50 +0000 Subject: [PATCH] Let rbe node compare to previous input OR output closes #192 and #193 Also update info and test. --- function/rbe/README.md | 7 ++++++- function/rbe/locales/en-US/rbe.json | 4 +++- function/rbe/package.json | 2 +- function/rbe/rbe.html | 17 ++++++++++++++--- function/rbe/rbe.js | 6 ++++-- test/function/rbe/rbe_spec.js | 24 ++++++++++++++++++++++++ 6 files changed, 52 insertions(+), 8 deletions(-) diff --git a/function/rbe/README.md b/function/rbe/README.md index 1f38b036..39ba78be 100644 --- a/function/rbe/README.md +++ b/function/rbe/README.md @@ -36,7 +36,12 @@ same value. Saves bandwidth, etc... In deadband mode the incoming payload should contain a parseable *number* and is output only if greater than + or - the *band gap* away from the previous output. It can also be set to block values more than a certain distance away from the present value. -This can be used to remove outliers or unexpected readings. +This can be used to remove outliers or unexpected readings. + +You can specify compare with *previous valid output value* or *previous input value*. +The former ignores any values outside the valid range, whereas the latter allows +two "bad" readings in a row to reset the range based on those values. +For example a valid step change. The deadband value can be specified as a fixed number, or a percentage. E.g. 10 or 5% . If % mode is used then the output will only get sent if the input payload diff --git a/function/rbe/locales/en-US/rbe.json b/function/rbe/locales/en-US/rbe.json index e7b24b59..2dc6535b 100644 --- a/function/rbe/locales/en-US/rbe.json +++ b/function/rbe/locales/en-US/rbe.json @@ -12,7 +12,9 @@ "opts": { "rbe": "block unless value changes", "deadband": "block unless value changes by more than", - "narrowband": "block if value changes by more than" + "narrowband": "block if value changes by more than", + "in": "compared to last input value", + "out": "compared to last valid output value" }, "warn": { "nonumber": "no number found in payload" diff --git a/function/rbe/package.json b/function/rbe/package.json index 5dc0c999..c86efb11 100644 --- a/function/rbe/package.json +++ b/function/rbe/package.json @@ -1,6 +1,6 @@ { "name" : "node-red-node-rbe", - "version" : "0.1.4", + "version" : "0.1.5", "description" : "A Node-RED node that provides report-by-exception (RBE) and deadband capability.", "dependencies" : { }, diff --git a/function/rbe/rbe.html b/function/rbe/rbe.html index 95918756..49aa8c53 100644 --- a/function/rbe/rbe.html +++ b/function/rbe/rbe.html @@ -25,7 +25,11 @@
- + +
@@ -43,11 +47,14 @@ different to the previous one - rbe mode. This works on numbers, strings, and simple objects.

Or it can block until the value changes by a specified amount - deadband mode.

In deadband mode the incoming payload must contain a parseable number and is - output only if greater than + or - the band gap away from the previous output.

+ output only if greater than + or - the band gap away from a previous value.

Deadband also supports % - only sends if the input differs by more than x% of the original value.

It can also ignore outlier values - narrowband mode.

In narrowband mode the incoming payload is blocked if it is more than + or - the band gap away from the previous value. Useful for ignoring outliers from a faulty sensor for example.

+

Both Deadband and Narrowband allow comparison against either the previous valid output value, thus + ignoring any values out of range; or the previous input value, which resets the set point, thus allowing + gradual drift (deadband), or a step change (narrowband).

Note: This works on a per msg.topic basis. This means that a single rbe node can handle multiple topics at the same time.

@@ -60,7 +67,8 @@ name: {value:""}, func: {value:"rbe"}, gap: {value:"",validate:RED.validators.regex(/^(\d*[.]*\d*|)(%|)$/)}, - start: {value:""} + start: {value:""}, + inout: {value:"out"} }, inputs:1, outputs:1, @@ -73,6 +81,9 @@ }, oneditprepare: function() { //$( "#node-input-gap" ).spinner({min:0}); + if ($("#node-input-inout").val() === null) { + $("#node-input-inout").val("out"); + } $("#node-input-func").on("change",function() { if ($("#node-input-func").val() === "rbe") { $("#node-bandgap").hide(); diff --git a/function/rbe/rbe.js b/function/rbe/rbe.js index 53cda99e..79ab9f19 100644 --- a/function/rbe/rbe.js +++ b/function/rbe/rbe.js @@ -21,6 +21,7 @@ module.exports = function(RED) { this.func = n.func || "rbe"; this.gap = n.gap || "0"; this.start = n.start || ''; + this.inout = n.inout || "out"; this.pc = false; if (this.gap.substr(-1) === "%") { this.pc = true; @@ -59,16 +60,17 @@ module.exports = function(RED) { if (!node.previous.hasOwnProperty(t)) { node.previous[t] = n - node.gap; } if (Math.abs(n - node.previous[t]) >= node.gap) { if (this.func === "deadband") { - node.previous[t] = n; + if (node.inout === "out") { node.previous[t] = n; } node.send(msg); } } else { if (this.func === "narrowband") { - node.previous[t] = n; + if (node.inout === "out") { node.previous[t] = n; } node.send(msg); } } + if (node.inout === "in") { node.previous[t] = n; } } else { node.warn(RED._("rbe.warn.nonumber")); diff --git a/test/function/rbe/rbe_spec.js b/test/function/rbe/rbe_spec.js index b934411e..5294f336 100644 --- a/test/function/rbe/rbe_spec.js +++ b/test/function/rbe/rbe_spec.js @@ -197,4 +197,28 @@ describe('rbe node', function() { }); }); + it('should not send output if more than x away from original value (narrowband in step mode)', function(done) { + var flow = [{"id":"n1", "type":"rbe", func:"narrowband", gap:"10", inout:"in", start:"500", wires:[["n2"]] }, + {id:"n2", type:"helper"} ]; + helper.load(testNode, flow, function() { + var n1 = helper.getNode("n1"); + var n2 = helper.getNode("n2"); + var c = 0; + n2.on("input", function(msg) { + if (c === 0) { + msg.should.have.a.property("payload", 55); + } + else if (c === 1) { + msg.should.have.a.property("payload", 205); + done(); + } + c += 1; + }); + n1.emit("input", {payload:50}); + n1.emit("input", {payload:55}); + n1.emit("input", {payload:200}); + n1.emit("input", {payload:205}); + }); + }); + });