diff --git a/function/rbe/locales/en-US/rbe.json b/function/rbe/locales/en-US/rbe.json index 4a714a11..e7b24b59 100644 --- a/function/rbe/locales/en-US/rbe.json +++ b/function/rbe/locales/en-US/rbe.json @@ -2,14 +2,17 @@ "rbe": { "label": { "func": "Mode", + "start": "Start value", "name": "Name" }, "placeholder":{ - "bandgap": "e.g. 10 or 5%" + "bandgap": "e.g. 10 or 5%", + "start": "leave blank to use first data received" }, "opts": { "rbe": "block unless value changes", - "deadband": "block unless changes by more than" + "deadband": "block unless value changes by more than", + "narrowband": "block if value changes by more than" }, "warn": { "nonumber": "no number found in payload" diff --git a/function/rbe/package.json b/function/rbe/package.json index dbf83596..316a780e 100644 --- a/function/rbe/package.json +++ b/function/rbe/package.json @@ -1,6 +1,6 @@ { "name" : "node-red-node-rbe", - "version" : "0.1.1", + "version" : "0.1.2", "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 abf2e83d..9f0e013a 100644 --- a/function/rbe/rbe.html +++ b/function/rbe/rbe.html @@ -20,12 +20,17 @@
+
+ + +
@@ -35,11 +40,14 @@ @@ -51,7 +59,8 @@ defaults: { name: {value:""}, func: {value:"rbe"}, - gap: {value:"",validate:RED.validators.regex(/^(\d*[.]*\d*|)(%|)$/)} + gap: {value:"",validate:RED.validators.regex(/^(\d*[.]*\d*|)(%|)$/)}, + start: {value:""} }, inputs:1, outputs:1, @@ -70,6 +79,11 @@ } else { $("#node-bandgap").show(); } + if ($("#node-input-func").val() === "narrowband") { + $("#node-startvalue").show(); + } else { + $("#node-startvalue").hide(); + } }); } }); diff --git a/function/rbe/rbe.js b/function/rbe/rbe.js index 3c0b4269..53cda99e 100644 --- a/function/rbe/rbe.js +++ b/function/rbe/rbe.js @@ -1,5 +1,5 @@ /** - * Copyright 2014, 2015 IBM Corp. + * Copyright 2014, 2016 IBM Corp. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,7 @@ module.exports = function(RED) { RED.nodes.createNode(this,n); this.func = n.func || "rbe"; this.gap = n.gap || "0"; + this.start = n.start || ''; this.pc = false; if (this.gap.substr(-1) === "%") { this.pc = true; @@ -33,19 +34,40 @@ module.exports = function(RED) { if (msg.hasOwnProperty("payload")) { var t = msg.topic || "_no_topic"; if (this.func === "rbe") { - if (msg.payload != node.previous[t]) { - node.previous[t] = msg.payload; - node.send(msg); + if (typeof(msg.payload) === "object") { + if (typeof(node.previous[t]) !== "object") { node.previous[t] = {}; } + if (!RED.util.compareObjects(msg.payload, node.previous[t])) { + node.previous[t] = msg.payload; + node.send(msg); + } + } + else { + if (msg.payload !== node.previous[t]) { + node.previous[t] = msg.payload; + node.send(msg); + } } } else { var n = parseFloat(msg.payload); 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 = (node.previous[t] * node.g / 100) || 0; } if (!node.previous.hasOwnProperty(t)) { node.previous[t] = n - node.gap; } if (Math.abs(n - node.previous[t]) >= node.gap) { - node.previous[t] = n; - node.send(msg); + if (this.func === "deadband") { + node.previous[t] = n; + node.send(msg); + } + } + else { + if (this.func === "narrowband") { + node.previous[t] = n; + node.send(msg); + } } } else { diff --git a/test/function/rbe/rbe_spec.js b/test/function/rbe/rbe_spec.js index ba70ce27..b934411e 100644 --- a/test/function/rbe/rbe_spec.js +++ b/test/function/rbe/rbe_spec.js @@ -1,5 +1,5 @@ /** - * Copyright 2015 IBM Corp. + * Copyright 2015,2016 IBM Corp. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -42,7 +42,7 @@ describe('rbe node', function() { }); }); - it('should only send output if payload changes', function(done) { + it('should only send output if payload changes (rbe)', function(done) { var flow = [{"id":"n1", "type":"rbe", func:"rbe", gap:"0", wires:[["n2"]] }, {id:"n2", type:"helper"} ]; helper.load(testNode, flow, function() { @@ -54,8 +54,14 @@ describe('rbe node', function() { msg.should.have.a.property("payload", "a"); c+=1; } - else { + else if (c === 1) { msg.should.have.a.property("payload", "b"); + c+=1; + } + else { + msg.should.have.a.property("payload"); + msg.payload.should.have.a.property("b",1); + msg.payload.should.have.a.property("c",2); done(); } }); @@ -65,12 +71,14 @@ describe('rbe node', function() { n1.emit("input", {payload:"a"}); n1.emit("input", {payload:"a"}); n1.emit("input", {payload:"b"}); - n1.emit("input", {payload:"b"}); + n1.emit("input", {payload:{b:1,c:2}}); + n1.emit("input", {payload:{c:2,b:1}}); + n1.emit("input", {payload:{c:2,b:1}}); }); }); - it('should only send output if more than x away from original value', function(done) { - var flow = [{"id":"n1", "type":"rbe", func:"gap", gap:"10", wires:[["n2"]] }, + 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"); @@ -100,8 +108,8 @@ describe('rbe node', function() { }); }); - it('should only send output if more than x% away from original value', function(done) { - var flow = [{"id":"n1", "type":"rbe", func:"gap", gap:"10%", wires:[["n2"]] }, + 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"); @@ -129,8 +137,8 @@ describe('rbe node', function() { }); }); - it('should warn if no number found in gap mode', function(done) { - var flow = [{"id":"n1", "type":"rbe", func:"gap", gap:"10", wires:[["n2"]] }, + 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"); @@ -157,4 +165,36 @@ describe('rbe node', function() { }); }); + + 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"}); + }); + }); + });