From 73063df11b3ad43ad199fd47e852a4b14bd8394d Mon Sep 17 00:00:00 2001 From: Dave Conway-Jones Date: Mon, 19 Apr 2021 13:09:13 +0100 Subject: [PATCH] Pull in RBE node and push out tail --- package.json | 3 - .../@node-red/nodes/core/function/rbe.html | 93 +++ .../@node-red/nodes/core/function/rbe.js | 97 ++++ .../@node-red/nodes/icons/rbe.png | Bin 0 -> 252 bytes .../nodes/locales/de/function/rbe.html | 40 ++ .../@node-red/nodes/locales/de/messages.json | 27 + .../nodes/locales/en-US/function/rbe.html | 41 ++ .../nodes/locales/en-US/messages.json | 27 + .../nodes/locales/ja/function/rbe.html | 31 + .../@node-red/nodes/locales/ja/messages.json | 25 + packages/node_modules/node-red/package.json | 6 +- test/nodes/core/function/rbe_spec.js | 538 ++++++++++++++++++ 12 files changed, 921 insertions(+), 7 deletions(-) create mode 100644 packages/node_modules/@node-red/nodes/core/function/rbe.html create mode 100644 packages/node_modules/@node-red/nodes/core/function/rbe.js create mode 100644 packages/node_modules/@node-red/nodes/icons/rbe.png create mode 100644 packages/node_modules/@node-red/nodes/locales/de/function/rbe.html create mode 100644 packages/node_modules/@node-red/nodes/locales/en-US/function/rbe.html create mode 100644 packages/node_modules/@node-red/nodes/locales/ja/function/rbe.html create mode 100644 test/nodes/core/function/rbe_spec.js diff --git a/package.json b/package.json index d2bbe729a..0c754d127 100644 --- a/package.json +++ b/package.json @@ -60,9 +60,6 @@ "multer": "1.4.2", "mustache": "4.2.0", "node-red-admin": "^0.2.6", - "node-red-node-rbe": "^0.5.0", - "node-red-node-sentiment": "^0.1.6", - "node-red-node-tail": "^0.3.0", "nopt": "5.0.0", "oauth2orize": "1.11.0", "on-headers": "1.0.2", diff --git a/packages/node_modules/@node-red/nodes/core/function/rbe.html b/packages/node_modules/@node-red/nodes/core/function/rbe.html new file mode 100644 index 000000000..6f8938870 --- /dev/null +++ b/packages/node_modules/@node-red/nodes/core/function/rbe.html @@ -0,0 +1,93 @@ + + + + diff --git a/packages/node_modules/@node-red/nodes/core/function/rbe.js b/packages/node_modules/@node-red/nodes/core/function/rbe.js new file mode 100644 index 000000000..4548a8c6a --- /dev/null +++ b/packages/node_modules/@node-red/nodes/core/function/rbe.js @@ -0,0 +1,97 @@ + +module.exports = function(RED) { + "use strict"; + function RbeNode(n) { + RED.nodes.createNode(this,n); + 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; + this.gap = parseFloat(this.gap); + } + this.g = this.gap; + this.property = n.property || "payload"; + this.topi = n.topi || "topic"; + this.septopics = true; + if (n.septopics !== undefined && n.septopics === false) { + this.septopics = false; + } + + var node = this; + + node.previous = {}; + this.on("input",function(msg) { + var topic; + try { + topic = RED.util.getMessageProperty(msg,node.topi); + } + catch(e) { } + if (msg.hasOwnProperty("reset")) { + if (node.septopics && topic && (typeof topic === "string") && (topic !== "")) { + delete node.previous[msg.topic]; + } + else { node.previous = {}; } + } + var value = RED.util.getMessageProperty(msg,node.property); + if (value !== undefined) { + var t = "_no_topic"; + if (node.septopics) { t = topic || t; } + if ((this.func === "rbe") || (this.func === "rbei")) { + var doSend = (this.func !== "rbei") || (node.previous.hasOwnProperty(t)) || false; + if (typeof(value) === "object") { + if (typeof(node.previous[t]) !== "object") { node.previous[t] = {}; } + if (!RED.util.compareObjects(value, node.previous[t])) { + node.previous[t] = RED.util.cloneMessage(value); + if (doSend) { node.send(msg); } + } + } + else { + if (value !== node.previous[t]) { + node.previous[t] = RED.util.cloneMessage(value); + if (doSend) { node.send(msg); } + } + } + } + else { + var n = parseFloat(value); + if (!isNaN(n)) { + if ((typeof node.previous[t] === 'undefined') && (this.func === "narrowband")) { + if (node.start === '') { node.previous[t] = n; } + else { node.previous[t] = node.start; } + } + if (node.pc) { node.gap = Math.abs(node.previous[t] * node.g / 100) || 0; } + else { node.gap = Number(node.gap); } + if ((node.previous[t] === undefined) && (node.func === "narrowbandEq")) { node.previous[t] = n; } + if (node.previous[t] === undefined) { node.previous[t] = n - node.gap - 1; } + if (Math.abs(n - node.previous[t]) === node.gap) { + if ((this.func === "deadbandEq")||(this.func === "narrowband")) { + if (node.inout === "out") { node.previous[t] = n; } + node.send(msg); + } + } + else if (Math.abs(n - node.previous[t]) > node.gap) { + if (this.func === "deadband" || this.func === "deadbandEq") { + if (node.inout === "out") { node.previous[t] = n; } + node.send(msg); + } + } + else if (Math.abs(n - node.previous[t]) < node.gap) { + if ((this.func === "narrowband")||(this.func === "narrowbandEq")) { + 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")); + } + } + } // ignore msg with no payload property. + }); + } + RED.nodes.registerType("rbe",RbeNode); +} diff --git a/packages/node_modules/@node-red/nodes/icons/rbe.png b/packages/node_modules/@node-red/nodes/icons/rbe.png new file mode 100644 index 0000000000000000000000000000000000000000..bc397210a30d8e962d2acd02cfe76ed481cbe38c GIT binary patch literal 252 zcmeAS@N?(olHy`uVBq!ia0vp^${@_a1|;QfZjJ;}Y)RhkE$%qUMt^z zH0J4s183Gfdwx?`@2S_qMAy_JWyzBsZbp+P_N1tM-sY3_aGed46oYgF-+>9nHY=Ey qw;T-#D*xW)QgvnL?u`QT6WFue4=`mGIrRV?#o+1c=d#Wzp$P!@rc(L< literal 0 HcmV?d00001 diff --git a/packages/node_modules/@node-red/nodes/locales/de/function/rbe.html b/packages/node_modules/@node-red/nodes/locales/de/function/rbe.html new file mode 100644 index 000000000..99fcd3188 --- /dev/null +++ b/packages/node_modules/@node-red/nodes/locales/de/function/rbe.html @@ -0,0 +1,40 @@ + diff --git a/packages/node_modules/@node-red/nodes/locales/de/messages.json b/packages/node_modules/@node-red/nodes/locales/de/messages.json index aabab9f79..24ff687bf 100755 --- a/packages/node_modules/@node-red/nodes/locales/de/messages.json +++ b/packages/node_modules/@node-red/nodes/locales/de/messages.json @@ -1000,5 +1000,32 @@ "too-many": "Zu viele anstehende Nachrichten im batch-Node", "unexpected": "Unerwarteter Modus", "no-parts": "Keine parts-Eigenschaft in Nachricht" + }, + "rbe": { + "rbe": "filter", + "label": { + "func": "Modus", + "init": "Sende Anfangswert", + "start": "Startwert", + "name": "Name", + "septopics": "Modus für jedes msg.topic separat anwenden" + }, + "placeholder":{ + "bandgap": "z.B. 10 oder 5%", + "start": "Leer lassen, um erste empfangenen Daten zu nutzen" + }, + "opts": { + "rbe": "Blockieren bis Wertänderung", + "rbei": "Blockieren bis Wertänderung (Anfangswert ignorieren)", + "deadband": "Blockieren bis Wertänderung ist größer als", + "deadbandEq": "Blockieren bis Wertänderung ist größer-gleich", + "narrowband": "Blockieren wenn Wertänderung ist größer als", + "narrowbandEq": "Blockieren wenn Wertänderung ist größer-gleich", + "in": "verglichen mit letzten Eingangswert", + "out": "verglichen mit letzten gültigen Ausgangswert" + }, + "warn": { + "nonumber": "Keine Zahl gefunden in den Nutzdaten (Payload)" + } } } diff --git a/packages/node_modules/@node-red/nodes/locales/en-US/function/rbe.html b/packages/node_modules/@node-red/nodes/locales/en-US/function/rbe.html new file mode 100644 index 000000000..db63cb0d2 --- /dev/null +++ b/packages/node_modules/@node-red/nodes/locales/en-US/function/rbe.html @@ -0,0 +1,41 @@ + diff --git a/packages/node_modules/@node-red/nodes/locales/en-US/messages.json b/packages/node_modules/@node-red/nodes/locales/en-US/messages.json index 17b230c69..8febb6d53 100755 --- a/packages/node_modules/@node-red/nodes/locales/en-US/messages.json +++ b/packages/node_modules/@node-red/nodes/locales/en-US/messages.json @@ -1001,5 +1001,32 @@ "too-many" : "too many pending messages in batch node", "unexpected" : "unexpected mode", "no-parts" : "no parts property in message" + }, + "rbe": { + "rbe": "filter", + "label": { + "func": "Mode", + "init": "Send initial value", + "start": "Start value", + "name": "Name", + "septopics": "Apply mode separately for each " + }, + "placeholder":{ + "bandgap": "e.g. 10 or 5%", + "start": "leave blank to use first data received" + }, + "opts": { + "rbe": "block unless value changes", + "rbei": "block unless value changes (ignore initial value)", + "deadband": "block unless value change is greater than", + "deadbandEq": "block unless value change is greater or equal to", + "narrowband": "block if value change is greater than", + "narrowbandEq": "block if value change is greater or equal to", + "in": "compared to last input value", + "out": "compared to last valid output value" + }, + "warn": { + "nonumber": "no number found in payload" + } } } diff --git a/packages/node_modules/@node-red/nodes/locales/ja/function/rbe.html b/packages/node_modules/@node-red/nodes/locales/ja/function/rbe.html new file mode 100644 index 000000000..cf2eea3e3 --- /dev/null +++ b/packages/node_modules/@node-red/nodes/locales/ja/function/rbe.html @@ -0,0 +1,31 @@ + + + diff --git a/packages/node_modules/@node-red/nodes/locales/ja/messages.json b/packages/node_modules/@node-red/nodes/locales/ja/messages.json index f8412efff..34f94a4ac 100644 --- a/packages/node_modules/@node-red/nodes/locales/ja/messages.json +++ b/packages/node_modules/@node-red/nodes/locales/ja/messages.json @@ -999,5 +999,30 @@ "too-many": "batchノード内で保持しているメッセージが多すぎます", "unexpected": "想定外のモード", "no-parts": "メッセージにpartsプロパティがありません" + }, + "rbe": { + "label": { + "func": "動作", + "init": "初期値を送付", + "start": "初期値", + "name": "名前" + }, + "placeholder": { + "bandgap": "例:10、5%", + "start": "最初に受け取った値を用いる場合は空欄" + }, + "opts": { + "rbe": "値が変化した時のみメッセージを中継", + "rbei": "値が変化した時のみメッセージを中継(初期値を無視)", + "deadband": "値が指定した変化量を超える時のみメッセージを中継", + "deadbandEq": "値が指定した変化量以上の時のみメッセージを中継", + "narrowband": "値が指定した変化量を超えない時のみメッセージを中継", + "narrowbandEq": "値が指定した変化量以上でない時のみメッセージを中継", + "in": "最後の入力値と比較", + "out": "最後の出力値と比較" + }, + "warn": { + "nonumber": "ペイロードに数値が含まれていません" + } } } diff --git a/packages/node_modules/node-red/package.json b/packages/node_modules/node-red/package.json index 68294b0c7..62bf7cede 100644 --- a/packages/node_modules/node-red/package.json +++ b/packages/node_modules/node-red/package.json @@ -40,15 +40,13 @@ "express": "4.17.1", "fs-extra": "9.1.0", "node-red-admin": "^0.2.6", - "node-red-node-rbe": "^0.5.0", - "node-red-node-tail": "^0.3.0", "nopt": "5.0.0", "semver": "7.3.5" }, "optionalDependencies": { - "bcrypt": "3.0.6" + "bcrypt": "5.0.1" }, "engines": { - "node": ">=8" + "node": ">=12" } } diff --git a/test/nodes/core/function/rbe_spec.js b/test/nodes/core/function/rbe_spec.js new file mode 100644 index 000000000..2ef005a27 --- /dev/null +++ b/test/nodes/core/function/rbe_spec.js @@ -0,0 +1,538 @@ + +var should = require("should"); +var helper = require("node-red-node-test-helper"); + +var testNode = require("nr-test-utils").require("@node-red/nodes/core/function/rbe.js"); + +describe('rbe node', function() { + "use strict"; + + beforeEach(function(done) { + helper.startServer(done); + }); + + afterEach(function(done) { + helper.unload().then(function() { + helper.stopServer(done); + }); + }); + + it("should be loaded with correct defaults", function(done) { + var flow = [{"id":"n1", "type":"rbe", "name":"rbe1", "wires":[[]]}]; + helper.load(testNode, flow, function() { + var n1 = helper.getNode("n1"); + n1.should.have.property("name", "rbe1"); + n1.should.have.property("func", "rbe"); + n1.should.have.property("gap", "0"); + done(); + }); + }); + + it('should only send output if payload changes - with multiple topics (rbe)', function(done) { + var flow = [{"id":"n1", "type":"rbe", func:"rbe", gap:"0", 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", "a"); + c+=1; + } + else if (c === 1) { + msg.should.have.a.property("payload", 2); + c+=1; + } + else if (c == 2) { + msg.should.have.a.property("payload"); + msg.payload.should.have.a.property("b",1); + msg.payload.should.have.a.property("c",2); + c+=1; + } + else if (c == 3) { + msg.should.have.a.property("payload",true); + c+=1; + } + else if (c == 4) { + msg.should.have.a.property("payload",false); + c+=1; + } + else if (c == 5) { + msg.should.have.a.property("payload",true); + c+=1; + } + else if (c == 6) { + msg.should.have.a.property("topic","a"); + msg.should.have.a.property("payload",1); + c+=1; + } + else if (c == 7) { + msg.should.have.a.property("topic","b"); + msg.should.have.a.property("payload",1); + c+=1; + } + else { + c += 1; + msg.should.have.a.property("topic","c"); + msg.should.have.a.property("payload",1); + done(); + } + }); + n1.emit("input", {payload:"a"}); + n1.emit("input", {payload:"a"}); + n1.emit("input", {payload:"a"}); + n1.emit("input", {payload:2}); + n1.emit("input", {payload:2}); + n1.emit("input", {payload:{b:1,c:2}}); + n1.emit("input", {payload:{c:2,b:1}}); + n1.emit("input", {payload:{c:2,b:1}}); + n1.emit("input", {payload:true}); + n1.emit("input", {payload:false}); + n1.emit("input", {payload:false}); + n1.emit("input", {payload:true}); + + n1.emit("input", {topic:"a",payload:1}); + n1.emit("input", {topic:"b",payload:1}); + n1.emit("input", {topic:"b",payload:1}); + n1.emit("input", {topic:"a",payload:1}); + n1.emit("input", {topic:"c",payload:1}); + + }); + }); + + it('should ignore multiple topics if told to (rbe)', function(done) { + var flow = [{id:"n1", type:"rbe", func:"rbe", gap:"0", septopics:false, 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", "a"); + c+=1; + } + else if (c === 1) { + msg.should.have.a.property("payload", 2); + c+=1; + } + else if (c == 2) { + msg.should.have.a.property("payload"); + msg.payload.should.have.a.property("b",1); + msg.payload.should.have.a.property("c",2); + c+=1; + } + else if (c == 3) { + msg.should.have.a.property("payload",true); + c+=1; + } + else if (c == 4) { + msg.should.have.a.property("payload",false); + c+=1; + } + else if (c == 5) { + msg.should.have.a.property("payload",true); + c+=1; + } + else if (c == 6) { + msg.should.have.a.property("topic","a"); + msg.should.have.a.property("payload",1); + c+=1; + } + else { + msg.should.have.a.property("topic","a"); + msg.should.have.a.property("payload",2); + done(); + } + }); + n1.emit("input", {topic:"a",payload:"a"}); + n1.emit("input", {topic:"b",payload:"a"}); + n1.emit("input", {topic:"c",payload:"a"}); + n1.emit("input", {topic:"a",payload:2}); + n1.emit("input", {topic:"b",payload:2}); + n1.emit("input", {payload:{b:1,c:2}}); + n1.emit("input", {payload:{c:2,b:1}}); + n1.emit("input", {payload:{c:2,b:1}}); + n1.emit("input", {topic:"a",payload:true}); + n1.emit("input", {topic:"b",payload:false}); + n1.emit("input", {topic:"c",payload:false}); + n1.emit("input", {topic:"d",payload:true}); + + n1.emit("input", {topic:"a",payload:1}); + n1.emit("input", {topic:"b",payload:1}); + n1.emit("input", {topic:"c",payload:1}); + n1.emit("input", {topic:"d",payload:1}); + n1.emit("input", {topic:"a",payload:2}); + + }); + }); + + it('should only send output if another chosen property changes - foo (rbe)', function(done) { + var flow = [{"id":"n1", "type":"rbe", func:"rbe", gap:"0", property:"foo", 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("foo", "a"); + c+=1; + } + else if (c === 1) { + msg.should.have.a.property("foo", "b"); + c+=1; + } + else { + msg.should.have.a.property("foo"); + msg.foo.should.have.a.property("b",1); + msg.foo.should.have.a.property("c",2); + done(); + } + }); + n1.emit("input", {foo:"a"}); + n1.emit("input", {payload:"a"}); + n1.emit("input", {foo:"a"}); + n1.emit("input", {payload:"a"}); + n1.emit("input", {foo:"a"}); + n1.emit("input", {foo:"b"}); + n1.emit("input", {foo:{b:1,c:2}}); + n1.emit("input", {foo:{c:2,b:1}}); + n1.emit("input", {payload:{c:2,b:1}}); + }); + }); + + it('should only send output if payload changes - ignoring first value (rbei)', function(done) { + var flow = [{"id":"n1", "type":"rbe", func:"rbei", gap:"0", 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", "b"); + msg.should.have.a.property("topic", "a"); + c+=1; + } + else if (c === 1) { + msg.should.have.a.property("payload", "b"); + msg.should.have.a.property("topic", "b"); + c+=1; + } + else if (c === 2) { + msg.should.have.a.property("payload", "c"); + msg.should.have.a.property("topic", "a"); + c+=1; + } + else { + msg.should.have.a.property("payload", "c"); + msg.should.have.a.property("topic", "b"); + done(); + } + + }); + n1.emit("input", {payload:"a", topic:"a"}); + n1.emit("input", {payload:"a", topic:"b"}); + n1.emit("input", {payload:"a", topic:"a"}); + n1.emit("input", {payload:"b", topic:"a"}); + n1.emit("input", {payload:"b", topic:"b"}); + n1.emit("input", {payload:"c", topic:"a"}); + n1.emit("input", {payload:"c", topic:"b"}); + }); + }); + + it('should send output if queue is reset (rbe)', function(done) { + var flow = [{"id":"n1", "type":"rbe", func:"rbe", gap:"0", 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", "a"); + c+=1; + } + else if (c === 1) { + msg.should.have.a.property("payload", "b"); + c+=1; + } + else if (c === 2) { + msg.should.have.a.property("payload", "a"); + c+=1; + } + else if (c === 3) { + msg.should.have.a.property("payload", "b"); + c+=1; + } + else if (c === 4) { + msg.should.have.a.property("payload", "b"); + c+=1; + } + else if (c === 5) { + msg.should.have.a.property("payload", "b"); + c+=1; + } + else if (c === 6) { + msg.should.have.a.property("payload", "a"); + c+=1; + } + else { + msg.should.have.a.property("payload", "c"); + done(); + } + }); + n1.emit("input", {topic:"a", payload:"a"}); + n1.emit("input", {topic:"a", payload:"a"}); + n1.emit("input", {topic:"b", payload:"b"}); + n1.emit("input", {reset:true}); // reset all + n1.emit("input", {topic:"a", payload:"a"}); + n1.emit("input", {topic:"b", payload:"b"}); + n1.emit("input", {topic:"b", payload:"b"}); + n1.emit("input", {topic:"b", reset:""}); // reset b + n1.emit("input", {topic:"b", payload:"b"}); + n1.emit("input", {topic:"a", payload:"a"}); + n1.emit("input", {reset:""}); // reset all + n1.emit("input", {topic:"b", payload:"b"}); + n1.emit("input", {topic:"a", payload:"a"}); + n1.emit("input", {topic:"c"}); // don't reset a non topic + n1.emit("input", {topic:"b", payload:"b"}); + n1.emit("input", {topic:"a", payload:"a"}); + n1.emit("input", {topic:"c", payload:"c"}); + }); + }); + + it('should only send output if x away from original value (deadbandEq)', function(done) { + var flow = [{"id":"n1", "type":"rbe", func:"deadbandEq", gap:"10", inout:"out", 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) { + c = c + 1; + if (c === 1) { + msg.should.have.a.property("payload", 0); + } + else if (c === 2) { + msg.should.have.a.property("payload", 10); + } + else if (c == 3) { + msg.should.have.a.property("payload", 20); + done(); + } + }); + n1.emit("input", {payload:0}); + n1.emit("input", {payload:2}); + n1.emit("input", {payload:4}); + n1.emit("input", {payload:6}); + n1.emit("input", {payload:8}); + n1.emit("input", {payload:10}); + n1.emit("input", {payload:15}); + n1.emit("input", {payload:20}); + }); + }); + + it('should only send output if more than x away from original value (deadband)', function(done) { + var flow = [{"id":"n1", "type":"rbe", func:"deadband", gap:"10", 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) { + c = c + 1; + //console.log(c,msg); + if (c === 1) { + msg.should.have.a.property("payload", 0); + } + else if (c === 2) { + msg.should.have.a.property("payload", 20); + } + else { + msg.should.have.a.property("payload", "5 deg"); + done(); + } + }); + n1.emit("input", {payload:0}); + n1.emit("input", {payload:2}); + n1.emit("input", {payload:4}); + n1.emit("input", {payload:"6 deg"}); + n1.emit("input", {payload:8}); + n1.emit("input", {payload:20}); + n1.emit("input", {payload:15}); + n1.emit("input", {payload:"5 deg"}); + }); + }); + + it('should only send output if more than x% away from original value (deadband)', function(done) { + var flow = [{"id":"n1", "type":"rbe", func:"deadband", gap:"10%", 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) { + c = c + 1; + if (c === 1) { + msg.should.have.a.property("payload", 100); + } + else if (c === 2) { + msg.should.have.a.property("payload", 111); + } + else if (c === 3) { + msg.should.have.a.property("payload", 135); + done(); + } + }); + n1.emit("input", {payload:100}); + n1.emit("input", {payload:95}); + n1.emit("input", {payload:105}); + n1.emit("input", {payload:111}); + n1.emit("input", {payload:120}); + n1.emit("input", {payload:135}); + }); + }); + + it('should warn if no number found in deadband mode', function(done) { + var flow = [{"id":"n1", "type":"rbe", func:"deadband", gap:"10", 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) { + c += 1; + }); + setTimeout( function() { + c.should.equal(0); + helper.log().called.should.be.true; + var logEvents = helper.log().args.filter(function (evt) { + return evt[0].type == "rbe"; + }); + logEvents.should.have.length(1); + var msg = logEvents[0][0]; + msg.should.have.property('level', helper.log().WARN); + msg.should.have.property('id', 'n1'); + msg.should.have.property('type', 'rbe'); + msg.should.have.property('msg', 'rbe.warn.nonumber'); + done(); + },50); + n1.emit("input", {payload:"banana"}); + }); + }); + + it('should not send output if x away or greater from original value (narrowbandEq)', function(done) { + var flow = [{"id":"n1", "type":"rbe", func:"narrowbandEq", gap:"10", inout:"out", 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) { + c = c + 1; + //console.log(c,msg); + if (c === 1) { + msg.should.have.a.property("payload", 0); + } + else if (c === 2) { + msg.should.have.a.property("payload", 5); + } + else if (c === 3) { + msg.should.have.a.property("payload", 10); + done(); + } + }); + n1.emit("input", {payload:0}); + n1.emit("input", {payload:10}); + n1.emit("input", {payload:5}); + n1.emit("input", {payload:15}); + n1.emit("input", {payload:10}); + n1.emit("input", {payload:20}); + n1.emit("input", {payload:25}); + }); + }); + + it('should not send output if more than x away from original value (narrowband)', function(done) { + var flow = [{"id":"n1", "type":"rbe", func:"narrowband", gap:"10", 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", 0); + } + else if (c === 1) { + msg.should.have.a.property("payload","6 deg"); + } + else { + msg.should.have.a.property("payload", "5 deg"); + done(); + } + c += 1; + }); + n1.emit("input", {payload:0}); + n1.emit("input", {payload:20}); + n1.emit("input", {payload:40}); + n1.emit("input", {payload:"6 deg"}); + n1.emit("input", {payload:18}); + n1.emit("input", {payload:20}); + n1.emit("input", {payload:50}); + n1.emit("input", {payload:"5 deg"}); + }); + }); + + it('should send output if gap is 0 and input doesnt change (narrowband)', function(done) { + var flow = [{"id":"n1", "type":"rbe", func:"narrowband", gap:"0", 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", 1); + } + else if (c === 4) { + msg.should.have.a.property("payload",1); + done(); + } + c += 1; + }); + n1.emit("input", {payload:1}); + n1.emit("input", {payload:1}); + n1.emit("input", {payload:1}); + n1.emit("input", {payload:1}); + n1.emit("input", {payload:0}); + n1.emit("input", {payload:1}); + }); + }); + + 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}); + }); + }); +});