mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
let trigger node set repeated outputs
This commit is contained in:
parent
f2235dacdc
commit
1841fc18fa
@ -25,9 +25,10 @@
|
|||||||
<select id="node-then-type" style="width:70%;">
|
<select id="node-then-type" style="width:70%;">
|
||||||
<option value="block" data-i18n="trigger.wait-reset"></option>
|
<option value="block" data-i18n="trigger.wait-reset"></option>
|
||||||
<option value="wait" data-i18n="trigger.wait-for"></option>
|
<option value="wait" data-i18n="trigger.wait-for"></option>
|
||||||
|
<option value="loop" data-i18n="trigger.wait-loop"></option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-row node-type-wait">
|
<div class="form-row node-type-duration">
|
||||||
<label></label>
|
<label></label>
|
||||||
<input type="text" id="node-input-duration" style="text-align:end; width:70px !important">
|
<input type="text" id="node-input-duration" style="text-align:end; width:70px !important">
|
||||||
<select id="node-input-units" style="width:140px !important">
|
<select id="node-input-units" style="width:140px !important">
|
||||||
@ -67,16 +68,17 @@
|
|||||||
<p>The two output states can be specified as can the duration of the timer.
|
<p>The two output states can be specified as can the duration of the timer.
|
||||||
Either output can be set to a value, or templated from the inbound
|
Either output can be set to a value, or templated from the inbound
|
||||||
<code>msg</code> using mustache syntax. <pre>The payload is {{payload}}</pre></p>
|
<code>msg</code> using mustache syntax. <pre>The payload is {{payload}}</pre></p>
|
||||||
<p>If the <code>msg.payload</code> is an object then setting the output to
|
<p>Or you can pass through either the <i>original msg</i> or the <i>latest msg</i> to arrive.</p>
|
||||||
<i>existing payload</i> will pass the complete payload object through.</p>
|
|
||||||
<p>Optionally the timer can be extended by being retriggered... or not.</p>
|
<p>Optionally the timer can be extended by being retriggered... or not.</p>
|
||||||
<p>By setting the first output to <i>nothing</i>, and selecting extend timer - a watchdog timer can be created.
|
<p>By setting the first output to <i>nothing</i>, and selecting extend timer - a watchdog timer can be created.
|
||||||
No output will happen as long as repeated inputs occur within the timeout period.</p>
|
No output will happen as long as repeated inputs occur within the timeout period.</p>
|
||||||
<p>Setting the timer to 0 creates an "infinite" timeout - the first output will happen but the second
|
<p>Setting the timer to 0 creates an "infinite" timeout - the first output will happen but the second
|
||||||
never will, and neither can the first be retriggered - so a true one shot.</p>
|
never will, and neither can the first be retriggered - so a true one shot.</p>
|
||||||
<p>If a <code>msg.reset</code> property is present, or the <code>msg.payload</code>
|
<p>If a <code>msg.reset</code> property is present, or the <code>msg.payload</code>
|
||||||
matches the optional reset value, any timeout currently in progress
|
matches the optional reset value, any timeout or repeat currently in progress
|
||||||
will be cleared and the second output will not happen.</p>
|
will be cleared and the second output will not happen.</p>
|
||||||
|
<p>The node can be set to repeat the input <code>msg</code> at regular intervals until the input changes,
|
||||||
|
or the node is reset.</p>
|
||||||
<p>The blue status icon will be visible while the node is active.</p>
|
<p>The blue status icon will be visible while the node is active.</p>
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -102,6 +104,9 @@
|
|||||||
if (this.duration > 0) {
|
if (this.duration > 0) {
|
||||||
return this.name|| this._("trigger.label.trigger")+" "+this.duration+this.units;
|
return this.name|| this._("trigger.label.trigger")+" "+this.duration+this.units;
|
||||||
}
|
}
|
||||||
|
if (this.duration < 0) {
|
||||||
|
return this.name|| this._("trigger.label.trigger-loop")+" "+(this.duration * -1)+this.units;
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
return this.name|| this._("trigger.label.trigger-block");
|
return this.name|| this._("trigger.label.trigger-block");
|
||||||
}
|
}
|
||||||
@ -113,8 +118,14 @@
|
|||||||
$("#node-then-type").change(function() {
|
$("#node-then-type").change(function() {
|
||||||
if ($(this).val() == "block") {
|
if ($(this).val() == "block") {
|
||||||
$(".node-type-wait").hide();
|
$(".node-type-wait").hide();
|
||||||
|
$(".node-type-duration").hide();
|
||||||
|
}
|
||||||
|
else if ($(this).val() == "loop") {
|
||||||
|
$(".node-type-wait").hide();
|
||||||
|
$(".node-type-duration").show();
|
||||||
} else {
|
} else {
|
||||||
$(".node-type-wait").show();
|
$(".node-type-wait").show();
|
||||||
|
$(".node-type-duration").show();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -127,7 +138,6 @@
|
|||||||
|
|
||||||
var optionNothing = {value:"nul",label:this._("trigger.output.nothing"),hasValue:false};
|
var optionNothing = {value:"nul",label:this._("trigger.output.nothing"),hasValue:false};
|
||||||
var optionPayload = {value:"pay",label:this._("trigger.output.existing"),hasValue:false}
|
var optionPayload = {value:"pay",label:this._("trigger.output.existing"),hasValue:false}
|
||||||
|
|
||||||
var optionOriginalPayload = {value:"pay",label:this._("trigger.output.original"),hasValue:false}
|
var optionOriginalPayload = {value:"pay",label:this._("trigger.output.original"),hasValue:false}
|
||||||
var optionLatestPayload = {value:"payl",label:this._("trigger.output.latest"),hasValue:false}
|
var optionLatestPayload = {value:"payl",label:this._("trigger.output.latest"),hasValue:false}
|
||||||
|
|
||||||
@ -151,6 +161,11 @@
|
|||||||
|
|
||||||
if (this.duration == "0") {
|
if (this.duration == "0") {
|
||||||
$("#node-then-type").val("block");
|
$("#node-then-type").val("block");
|
||||||
|
}
|
||||||
|
else if ((this.duration * 1) < 0) {
|
||||||
|
$("#node-then-type").val("loop");
|
||||||
|
this.duration = this.duration * -1;
|
||||||
|
$("#node-input-duration").val(this.duration);
|
||||||
} else {
|
} else {
|
||||||
$("#node-then-type").val("wait");
|
$("#node-then-type").val("wait");
|
||||||
}
|
}
|
||||||
@ -167,6 +182,9 @@
|
|||||||
if ($("#node-then-type").val() == "block") {
|
if ($("#node-then-type").val() == "block") {
|
||||||
$("#node-input-duration").val("0");
|
$("#node-input-duration").val("0");
|
||||||
}
|
}
|
||||||
|
if ($("#node-then-type").val() == "loop") {
|
||||||
|
$("#node-input-duration").val($("#node-input-duration").val() * -1);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -48,12 +48,16 @@ module.exports = function(RED) {
|
|||||||
this.units = n.units || "ms";
|
this.units = n.units || "ms";
|
||||||
this.reset = n.reset || '';
|
this.reset = n.reset || '';
|
||||||
this.duration = n.duration || 250;
|
this.duration = n.duration || 250;
|
||||||
if (this.duration <= 0) { this.duration = 0; }
|
if (this.duration < 0) {
|
||||||
else {
|
this.loop = true;
|
||||||
if (this.units == "s") { this.duration = this.duration * 1000; }
|
this.duration = this.duration * -1;
|
||||||
if (this.units == "min") { this.duration = this.duration * 1000 * 60; }
|
this.extend = false;
|
||||||
if (this.units == "hr") { this.duration = this.duration * 1000 *60 * 60; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.units == "s") { this.duration = this.duration * 1000; }
|
||||||
|
if (this.units == "min") { this.duration = this.duration * 1000 * 60; }
|
||||||
|
if (this.units == "hr") { this.duration = this.duration * 1000 *60 * 60; }
|
||||||
|
|
||||||
this.op1Templated = (this.op1type === 'str' && this.op1.indexOf("{{") != -1);
|
this.op1Templated = (this.op1type === 'str' && this.op1.indexOf("{{") != -1);
|
||||||
this.op2Templated = (this.op2type === 'str' && this.op2.indexOf("{{") != -1);
|
this.op2Templated = (this.op2type === 'str' && this.op2.indexOf("{{") != -1);
|
||||||
if ((this.op1type === "num") && (!isNaN(this.op1))) { this.op1 = Number(this.op1); }
|
if ((this.op1type === "num") && (!isNaN(this.op1))) { this.op1 = Number(this.op1); }
|
||||||
@ -69,13 +73,14 @@ module.exports = function(RED) {
|
|||||||
var tout = null;
|
var tout = null;
|
||||||
var m2;
|
var m2;
|
||||||
this.on("input", function(msg) {
|
this.on("input", function(msg) {
|
||||||
if (msg.hasOwnProperty("reset") || ((node.reset !== '')&&(msg.payload == node.reset)) ) {
|
if (msg.hasOwnProperty("reset") || ((node.reset !== '') && (msg.payload == node.reset)) ) {
|
||||||
clearTimeout(tout);
|
if (node.loop === true) { clearInterval(tout); }
|
||||||
|
else { clearTimeout(tout); }
|
||||||
tout = null;
|
tout = null;
|
||||||
node.status({});
|
node.status({});
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if ((!tout) && (tout !== 0)) {
|
if (((!tout) && (tout !== 0)) || (node.loop === true)) {
|
||||||
if (node.op2type === "pay" || node.op2type === "payl") { m2 = msg.payload; }
|
if (node.op2type === "pay" || node.op2type === "payl") { m2 = msg.payload; }
|
||||||
else if (node.op2Templated) { m2 = mustache.render(node.op2,msg); }
|
else if (node.op2Templated) { m2 = mustache.render(node.op2,msg); }
|
||||||
else if (node.op2type !== "nul") {
|
else if (node.op2type !== "nul") {
|
||||||
@ -91,6 +96,13 @@ module.exports = function(RED) {
|
|||||||
if (node.op1type !== "nul") { node.send(msg); }
|
if (node.op1type !== "nul") { node.send(msg); }
|
||||||
|
|
||||||
if (node.duration === 0) { tout = 0; }
|
if (node.duration === 0) { tout = 0; }
|
||||||
|
else if (node.loop === true) {
|
||||||
|
if (tout) { clearInterval(tout); }
|
||||||
|
if (node.op1type !== "nul") {
|
||||||
|
var msg2 = RED.util.cloneMessage(msg);
|
||||||
|
tout = setInterval(function() { node.send(msg2); },node.duration);
|
||||||
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
tout = setTimeout(function() {
|
tout = setTimeout(function() {
|
||||||
if (node.op2type !== "nul") {
|
if (node.op2type !== "nul") {
|
||||||
@ -108,7 +120,7 @@ module.exports = function(RED) {
|
|||||||
node.status({fill:"blue",shape:"dot",text:" "});
|
node.status({fill:"blue",shape:"dot",text:" "});
|
||||||
}
|
}
|
||||||
else if ((node.extend === "true" || node.extend === true) && (node.duration > 0)) {
|
else if ((node.extend === "true" || node.extend === true) && (node.duration > 0)) {
|
||||||
clearTimeout(tout);
|
if (tout) { clearTimeout(tout); }
|
||||||
if (node.op2type === "payl") { m2 = msg.payload; }
|
if (node.op2type === "payl") { m2 = msg.payload; }
|
||||||
tout = setTimeout(function() {
|
tout = setTimeout(function() {
|
||||||
if (node.op2type !== "nul") {
|
if (node.op2type !== "nul") {
|
||||||
@ -122,14 +134,17 @@ module.exports = function(RED) {
|
|||||||
tout = null;
|
tout = null;
|
||||||
node.status({});
|
node.status({});
|
||||||
},node.duration);
|
},node.duration);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
if (node.op2type === "payl") { m2 = msg.payload; }
|
if (node.op2type === "payl") { m2 = msg.payload; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.on("close", function() {
|
this.on("close", function() {
|
||||||
if (tout) {
|
if (tout) {
|
||||||
clearTimeout(tout);
|
if (node.loop === true) { clearInterval(tout); }
|
||||||
|
else { clearTimeout(tout); }
|
||||||
|
tout = null;
|
||||||
}
|
}
|
||||||
node.status({});
|
node.status({});
|
||||||
});
|
});
|
||||||
|
@ -356,7 +356,7 @@ describe('trigger node', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should be able to set infinite timeout, and clear timeout', function(done) {
|
it('should be able to set infinite timeout, and clear timeout', function(done) {
|
||||||
var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", duration:-5, wires:[["n2"]] },
|
var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", duration:0, wires:[["n2"]] },
|
||||||
{id:"n2", type:"helper"} ];
|
{id:"n2", type:"helper"} ];
|
||||||
helper.load(triggerNode, flow, function() {
|
helper.load(triggerNode, flow, function() {
|
||||||
var n1 = helper.getNode("n1");
|
var n1 = helper.getNode("n1");
|
||||||
@ -378,7 +378,7 @@ describe('trigger node', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should be able to set infinite timeout, and clear timeout by message', function(done) {
|
it('should be able to set infinite timeout, and clear timeout by message', function(done) {
|
||||||
var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", reset:"boo", duration:-5, wires:[["n2"]] },
|
var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", reset:"boo", duration:0, wires:[["n2"]] },
|
||||||
{id:"n2", type:"helper"} ];
|
{id:"n2", type:"helper"} ];
|
||||||
helper.load(triggerNode, flow, function() {
|
helper.load(triggerNode, flow, function() {
|
||||||
var n1 = helper.getNode("n1");
|
var n1 = helper.getNode("n1");
|
||||||
@ -399,4 +399,26 @@ describe('trigger node', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should be able to set a repeat, and clear loop by reset', function(done) {
|
||||||
|
var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", reset:"boo", duration:-25, wires:[["n2"]] },
|
||||||
|
{id:"n2", type:"helper"} ];
|
||||||
|
helper.load(triggerNode, flow, function() {
|
||||||
|
var n1 = helper.getNode("n1");
|
||||||
|
var n2 = helper.getNode("n2");
|
||||||
|
var c = 0;
|
||||||
|
n2.on("input", function(msg) {
|
||||||
|
c += 1;
|
||||||
|
msg.should.have.a.property("payload", "foo");
|
||||||
|
});
|
||||||
|
n1.emit("input", {payload:"foo"}); // trigger
|
||||||
|
setTimeout( function() {
|
||||||
|
n1.emit("input", {reset:true}); // reset
|
||||||
|
},90);
|
||||||
|
setTimeout( function() {
|
||||||
|
c.should.equal(4); // should send foo 4 times.
|
||||||
|
done();
|
||||||
|
},150);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user