From cf84ec78fac706f0aaf788b89684b9cdc9b1c5ff Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Mon, 28 Sep 2020 21:10:23 +0100 Subject: [PATCH 1/2] Allow trigger node delay to be overridden with msg.delay --- .../nodes/core/function/89-trigger.html | 13 +++- .../nodes/core/function/89-trigger.js | 11 +++- .../locales/en-US/function/89-trigger.html | 5 +- .../nodes/locales/en-US/messages.json | 1 + test/nodes/core/function/89-trigger_spec.js | 59 +++++++++++++++++++ 5 files changed, 83 insertions(+), 6 deletions(-) diff --git a/packages/node_modules/@node-red/nodes/core/function/89-trigger.html b/packages/node_modules/@node-red/nodes/core/function/89-trigger.html index edbb84e5a..b017dba1b 100644 --- a/packages/node_modules/@node-red/nodes/core/function/89-trigger.html +++ b/packages/node_modules/@node-red/nodes/core/function/89-trigger.html @@ -42,6 +42,10 @@ +
+ + +
@@ -89,6 +93,7 @@ op2type: {value:"val"}, duration: {value:"250",required:true,validate:RED.validators.number()}, extend: {value:"false"}, + overrideDelay: {value:"false"}, units: {value:"ms"}, reset: {value:""}, bytopic: {value:"all"}, @@ -126,7 +131,7 @@ if (this.outputs == 2) { $("#node-input-second").prop('checked', true) } else { $("#node-input-second").prop('checked', false) } - + $("#node-input-second").change(function() { if ($("#node-input-second").is(":checked")) { $("#node-input-outputs").val(2); @@ -208,7 +213,11 @@ } else { $("#node-input-extend").prop("checked",false); } - + if (this.overrideDelay === "true" || this.overrideDelay === true) { + $("#node-input-overrideDelay").prop("checked",true); + } else { + $("#node-input-overrideDelay").prop("checked",false); + } }, oneditsave: function() { if ($("#node-then-type").val() == "block") { diff --git a/packages/node_modules/@node-red/nodes/core/function/89-trigger.js b/packages/node_modules/@node-red/nodes/core/function/89-trigger.js index cda1afadf..478f772e3 100644 --- a/packages/node_modules/@node-red/nodes/core/function/89-trigger.js +++ b/packages/node_modules/@node-red/nodes/core/function/89-trigger.js @@ -48,6 +48,7 @@ module.exports = function(RED) { } } this.extend = n.extend || "false"; + this.overrideDelay = n.overrideDelay || false; this.units = n.units || "ms"; this.reset = n.reset || ''; this.duration = parseFloat(n.duration); @@ -117,12 +118,16 @@ module.exports = function(RED) { var l = Object.keys(node.topics).length; if (l === 0) { return {} } else if (l === 1) { return {fill:"blue",shape:"dot"} } - else return {fill:"blue",shape:"dot",text:l}; + else return {fill:"blue",shape:"dot",text:l}; } var processMessage = function(msg) { var topic = RED.util.getMessageProperty(msg,node.topic) || "_none"; var promise; + var delayDuration = node.duration; + if (node.overrideDelay && msg.hasOwnProperty("delay") && !isNaN(parseFloat(msg.delay))) { + delayDuration = parseFloat(msg.delay); + } if (node.bytopic === "all") { topic = "_none"; } node.topics[topic] = node.topics[topic] || {}; if (msg.hasOwnProperty("reset") || ((node.reset !== '') && msg.hasOwnProperty("payload") && (msg.payload !== null) && msg.payload.toString && (msg.payload.toString() == node.reset)) ) { @@ -217,7 +222,7 @@ module.exports = function(RED) { node.status(stat()); } - }, node.duration); + }, delayDuration); } } node.status(stat()); @@ -262,7 +267,7 @@ module.exports = function(RED) { }).catch(err => { node.error(err); }); - }, node.duration); + }, delayDuration); } // else { // if (node.op2type === "payl") {node.topics[topic].m2 = RED.util.cloneMessage(msg.payload); } diff --git a/packages/node_modules/@node-red/nodes/locales/en-US/function/89-trigger.html b/packages/node_modules/@node-red/nodes/locales/en-US/function/89-trigger.html index 1ba4e53b9..3b5d96604 100644 --- a/packages/node_modules/@node-red/nodes/locales/en-US/function/89-trigger.html +++ b/packages/node_modules/@node-red/nodes/locales/en-US/function/89-trigger.html @@ -19,6 +19,8 @@

Inputs

+
delay number
+
Sets the delay, in milliseconds, to be applied to the message. This option only applies if the node is configured to allow the message to override the configured default delay interval. This does not apply when the node is configured to send at repeated intervals.
reset
If a message is received with this property, any timeout or repeat currently in progress will be cleared and no message triggered.
@@ -35,6 +37,7 @@ act as a watchdog timer; only sending a message if nothing is received within the set interval.

If set to a string type, the node supports the mustache template syntax.

+

The delay between sending messages can be overridden by msg.delay if that option is enabled in the node. The value must be provided in milliseconds.

If the node receives a message with a reset property, or a payload that matches that configured in the node, any timeout or repeat currently in progress will be cleared and no message triggered.

@@ -42,6 +45,6 @@ is reset by a received message.

Optionally, the node can be configured to treat messages as if they are separate streams, using a msg property to identify each stream. Default msg.topic.

-

The status indicates the node is currently active. If multiple streams are used the status +

The status indicates the node is currently active. If multiple streams are used the status indicates the number of streams being held.

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 e6d5da063..eb623ce20 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 @@ -320,6 +320,7 @@ "h": "Hours" }, "extend": " extend delay if new message arrives", + "override": "override delay with msg.delay", "second": " send second message to separate output", "label": { "trigger": "trigger", diff --git a/test/nodes/core/function/89-trigger_spec.js b/test/nodes/core/function/89-trigger_spec.js index 5502796ec..dd77b37d9 100644 --- a/test/nodes/core/function/89-trigger_spec.js +++ b/test/nodes/core/function/89-trigger_spec.js @@ -233,6 +233,65 @@ describe('trigger node', function() { }); }); + it('should ignore msg.delay if overrideDelay not set', function(done) { + var flow = [ + {"id":"n1", "type":"trigger", "name":"triggerNode", duration:"50",wires:[["n2"]] }, + {id:"n2", type:"helper"} + ]; + helper.load(triggerNode, flow, function() { + var n1 = helper.getNode("n1"); + var n2 = helper.getNode("n2"); + var c = 0; + var firstTime; + n2.on("input", function(msg) { + if (c === 0) { + firstTime = Date.now(); + } else if (c === 1) { + try { + var delta = Date.now() - firstTime; + delta.should.be.greaterThan(30); + delta.should.be.lessThan(100); + done(); + } catch(err) { + done(err); + } + } + c++; + }); + n1.emit("input", {payload:null, delay: 300}); + }); + }); + + it('should use msg.delay if overrideDelay is set', function(done) { + var flow = [ + {"id":"n1", "type":"trigger", "name":"triggerNode", overrideDelay: true, duration:"50",wires:[["n2"]] }, + {id:"n2", type:"helper"} + ]; + helper.load(triggerNode, flow, function() { + var n1 = helper.getNode("n1"); + var n2 = helper.getNode("n2"); + var c = 0; + var firstTime; + n2.on("input", function(msg) { + if (c === 0) { + firstTime = Date.now(); + } else if (c === 1) { + try { + var delta = Date.now() - firstTime; + delta.should.be.greaterThan(270); + delta.should.be.lessThan(380); + done(); + } catch(err) { + done(err); + } + } + c++; + }); + n1.emit("input", {payload:null, delay: 300}); + }); + }); + + it('should handle true and false as strings and delay of 0', function(done) { var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", op1:"true",op1type:"val",op2:"false",op2type:"val",duration:"30", wires:[["n2"]] }, {id:"n2", type:"helper"} ]; From 2962c4372cf7382eaa088443aa6b198ed299ae20 Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Tue, 29 Sep 2020 17:47:09 +0100 Subject: [PATCH 2/2] Support setting trigger loop interval with msg.delay --- .../@node-red/nodes/core/function/89-trigger.html | 5 ++++- .../@node-red/nodes/core/function/89-trigger.js | 6 +++--- .../@node-red/nodes/locales/en-US/function/89-trigger.html | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/node_modules/@node-red/nodes/core/function/89-trigger.html b/packages/node_modules/@node-red/nodes/core/function/89-trigger.html index b017dba1b..a7ab0356f 100644 --- a/packages/node_modules/@node-red/nodes/core/function/89-trigger.html +++ b/packages/node_modules/@node-red/nodes/core/function/89-trigger.html @@ -42,7 +42,7 @@
-
+
@@ -143,6 +143,7 @@ $("#node-then-type").on("change", function() { if ($(this).val() == "block") { $(".node-type-wait").hide(); + $(".node-type-override").hide(); $(".node-type-duration").hide(); $("#node-second-output").hide(); $("#node-input-second").prop('checked', false); @@ -151,6 +152,7 @@ else if ($(this).val() == "loop") { if ($("#node-input-duration").val() == 0) { $("#node-input-duration").val(250); } $(".node-type-wait").hide(); + $(".node-type-override").show(); $(".node-type-duration").show(); $("#node-second-output").hide(); $("#node-input-second").prop('checked', false); @@ -158,6 +160,7 @@ } else { if ($("#node-input-duration").val() == 0) { $("#node-input-duration").val(250); } $(".node-type-wait").show(); + $(".node-type-override").show(); $(".node-type-duration").show(); $("#node-second-output").show(); } diff --git a/packages/node_modules/@node-red/nodes/core/function/89-trigger.js b/packages/node_modules/@node-red/nodes/core/function/89-trigger.js index 478f772e3..7b5b820b7 100644 --- a/packages/node_modules/@node-red/nodes/core/function/89-trigger.js +++ b/packages/node_modules/@node-red/nodes/core/function/89-trigger.js @@ -172,14 +172,14 @@ module.exports = function(RED) { }); } return promise.then(() => { - if (node.duration === 0) { node.topics[topic].tout = 0; } + if (delayDuration === 0) { node.topics[topic].tout = 0; } else if (node.loop === true) { /* istanbul ignore else */ if (node.topics[topic].tout) { clearInterval(node.topics[topic].tout); } /* istanbul ignore else */ if (node.op1type !== "nul") { var msg2 = RED.util.cloneMessage(msg); - node.topics[topic].tout = setInterval(function() { node.send(RED.util.cloneMessage(msg2)); }, node.duration); + node.topics[topic].tout = setInterval(function() { node.send(RED.util.cloneMessage(msg2)); }, delayDuration); } } else { @@ -230,7 +230,7 @@ module.exports = function(RED) { }); }); } - else if ((node.extend === "true" || node.extend === true) && (node.duration > 0)) { + else if ((node.extend === "true" || node.extend === true) && (delayDuration > 0)) { /* istanbul ignore else */ if (node.op2type === "payl") { node.topics[topic].m2 = RED.util.cloneMessage(msg.payload); } /* istanbul ignore else */ diff --git a/packages/node_modules/@node-red/nodes/locales/en-US/function/89-trigger.html b/packages/node_modules/@node-red/nodes/locales/en-US/function/89-trigger.html index 3b5d96604..081b0c7a1 100644 --- a/packages/node_modules/@node-red/nodes/locales/en-US/function/89-trigger.html +++ b/packages/node_modules/@node-red/nodes/locales/en-US/function/89-trigger.html @@ -20,7 +20,7 @@

Inputs

delay number
-
Sets the delay, in milliseconds, to be applied to the message. This option only applies if the node is configured to allow the message to override the configured default delay interval. This does not apply when the node is configured to send at repeated intervals.
+
Sets the delay, in milliseconds, to be applied to the message. This option only applies if the node is configured to allow the message to override the configured default delay interval.
reset
If a message is received with this property, any timeout or repeat currently in progress will be cleared and no message triggered.