1
0
mirror of https://github.com/node-red/node-red-nodes.git synced 2023-10-10 13:36:58 +02:00

Let rbe node compare to previous input OR output

closes #192 and #193
Also update info and test.
This commit is contained in:
Dave Conway-Jones 2016-03-21 00:01:50 +00:00
parent 2ed8e5a306
commit c3a8a4088d
6 changed files with 52 additions and 8 deletions

View File

@ -38,6 +38,11 @@ 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. 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 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 or 5% . If % mode is used then the output will only get sent if the input payload
value is equal or more than the specified % away from the previously sent value. value is equal or more than the specified % away from the previously sent value.

View File

@ -12,7 +12,9 @@
"opts": { "opts": {
"rbe": "block unless value changes", "rbe": "block unless value changes",
"deadband": "block unless value changes by more than", "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": { "warn": {
"nonumber": "no number found in payload" "nonumber": "no number found in payload"

View File

@ -1,6 +1,6 @@
{ {
"name" : "node-red-node-rbe", "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.", "description" : "A Node-RED node that provides report-by-exception (RBE) and deadband capability.",
"dependencies" : { "dependencies" : {
}, },

View File

@ -25,7 +25,11 @@
</div> </div>
<div class="form-row" id="node-bandgap"> <div class="form-row" id="node-bandgap">
<label for="node-input-gap">&nbsp;</label> <label for="node-input-gap">&nbsp;</label>
<input type="text" id="node-input-gap" data-i18n="[placeholder]rbe.placeholder.bandgap" style="width:71%;"> <input type="text" id="node-input-gap" data-i18n="[placeholder]rbe.placeholder.bandgap" style="width:70px;">
<select type="text" id="node-input-inout" style="width:55%;">
<option value="out" data-i18n="rbe.opts.out"></option>
<option value="in" data-i18n="rbe.opts.in"></option>
</select>
</div> </div>
<div class="form-row" id="node-startvalue"> <div class="form-row" id="node-startvalue">
<label for="node-input-start"><i class="fa fa-thumb-tack"/> <span data-i18n="rbe.label.start"></span></label> <label for="node-input-start"><i class="fa fa-thumb-tack"/> <span data-i18n="rbe.label.start"></span></label>
@ -43,11 +47,14 @@
different to the previous one - <b>rbe</b> mode. This works on numbers, strings, and simple objects.</p> different to the previous one - <b>rbe</b> mode. This works on numbers, strings, and simple objects.</p>
<p>Or it can block until the value changes by a specified amount - <b>deadband</b> mode.</p> <p>Or it can block until the value changes by a specified amount - <b>deadband</b> mode.</p>
<p>In deadband mode the incoming payload must contain a parseable <i>number</i> and is <p>In deadband mode the incoming payload must contain a parseable <i>number</i> and is
output only if greater than + or - the <i>band gap</i> away from the previous output.</p> output only if greater than + or - the <i>band gap</i> away from a previous value.</p>
<p>Deadband also supports % - only sends if the input differs by more than x% of the original value.</p> <p>Deadband also supports % - only sends if the input differs by more than x% of the original value.</p>
<p>It can also ignore outlier values - <b>narrowband</b> mode.</p> <p>It can also ignore outlier values - <b>narrowband</b> mode.</p>
<p>In narrowband mode the incoming payload is blocked if it is more than + or - the band gap <p>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.</p> away from the previous value. Useful for ignoring outliers from a faulty sensor for example.</p>
<p>Both Deadband and Narrowband allow comparison against either the <i>previous valid output value</i>, thus
ignoring any values out of range; or the <i>previous input value</i>, which resets the set point, thus allowing
gradual drift (deadband), or a step change (narrowband).</p>
<p><b>Note:</b> This works on a per <code>msg.topic</code> basis. This means that a single rbe node can <p><b>Note:</b> This works on a per <code>msg.topic</code> basis. This means that a single rbe node can
handle multiple topics at the same time.</p> handle multiple topics at the same time.</p>
</script> </script>
@ -60,7 +67,8 @@
name: {value:""}, name: {value:""},
func: {value:"rbe"}, func: {value:"rbe"},
gap: {value:"",validate:RED.validators.regex(/^(\d*[.]*\d*|)(%|)$/)}, gap: {value:"",validate:RED.validators.regex(/^(\d*[.]*\d*|)(%|)$/)},
start: {value:""} start: {value:""},
inout: {value:"out"}
}, },
inputs:1, inputs:1,
outputs:1, outputs:1,
@ -73,6 +81,9 @@
}, },
oneditprepare: function() { oneditprepare: function() {
//$( "#node-input-gap" ).spinner({min:0}); //$( "#node-input-gap" ).spinner({min:0});
if ($("#node-input-inout").val() === null) {
$("#node-input-inout").val("out");
}
$("#node-input-func").on("change",function() { $("#node-input-func").on("change",function() {
if ($("#node-input-func").val() === "rbe") { if ($("#node-input-func").val() === "rbe") {
$("#node-bandgap").hide(); $("#node-bandgap").hide();

View File

@ -21,6 +21,7 @@ module.exports = function(RED) {
this.func = n.func || "rbe"; this.func = n.func || "rbe";
this.gap = n.gap || "0"; this.gap = n.gap || "0";
this.start = n.start || ''; this.start = n.start || '';
this.inout = n.inout || "out";
this.pc = false; this.pc = false;
if (this.gap.substr(-1) === "%") { if (this.gap.substr(-1) === "%") {
this.pc = true; this.pc = true;
@ -59,16 +60,17 @@ module.exports = function(RED) {
if (!node.previous.hasOwnProperty(t)) { node.previous[t] = n - node.gap; } if (!node.previous.hasOwnProperty(t)) { node.previous[t] = n - node.gap; }
if (Math.abs(n - node.previous[t]) >= node.gap) { if (Math.abs(n - node.previous[t]) >= node.gap) {
if (this.func === "deadband") { if (this.func === "deadband") {
node.previous[t] = n; if (node.inout === "out") { node.previous[t] = n; }
node.send(msg); node.send(msg);
} }
} }
else { else {
if (this.func === "narrowband") { if (this.func === "narrowband") {
node.previous[t] = n; if (node.inout === "out") { node.previous[t] = n; }
node.send(msg); node.send(msg);
} }
} }
if (node.inout === "in") { node.previous[t] = n; }
} }
else { else {
node.warn(RED._("rbe.warn.nonumber")); node.warn(RED._("rbe.warn.nonumber"));

View File

@ -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});
});
});
}); });