mirror of
https://github.com/node-red/node-red.git
synced 2025-03-01 10:36:34 +00:00
Merge branch '0.18' into projects
This commit is contained in:
@@ -26,6 +26,14 @@
|
||||
<input type="text" id="node-input-topic">
|
||||
</div>
|
||||
|
||||
<div class="form-row" id="node-once">
|
||||
<label for="node-input-once"> </label>
|
||||
<input type="checkbox" id="node-input-once" style="display:inline-block;width:15px;vertical-align:baseline;">
|
||||
<span data-i18n="inject.onstart"></span>
|
||||
<input type="text" id="node-input-onceDelay" placeholder="0.1" style="width:45px">
|
||||
<span data-i18n="inject.onceDelay"></span>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<label for=""><i class="fa fa-repeat"></i> <span data-i18n="inject.label.repeat"></span></label>
|
||||
<select id="inject-time-type-select">
|
||||
@@ -106,13 +114,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-row" id="node-once">
|
||||
<label> </label>
|
||||
<input type="checkbox" id="node-input-once" style="display: inline-block; width: auto; vertical-align: top;">
|
||||
<label for="node-input-once" style="width: 70%;" data-i18n="inject.onstart"></label>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
|
||||
<input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
|
||||
@@ -181,9 +182,10 @@ If you want every 20 minutes from now - use the <i>"interval"</i> option.</p>
|
||||
topic: {value:""},
|
||||
payload: {value:"", validate: RED.validators.typedInput("payloadType")},
|
||||
payloadType: {value:"date"},
|
||||
repeat: {value:""},
|
||||
repeat: {value:"", validate:function(v) { return ((v === "") || (RED.validators.number(v) && (v >= 0))) }},
|
||||
crontab: {value:""},
|
||||
once: {value:false}
|
||||
once: {value:false},
|
||||
onceDelay: {value:0.1}
|
||||
},
|
||||
icon: "inject.png",
|
||||
inputs:0,
|
||||
|
@@ -26,27 +26,35 @@ module.exports = function(RED) {
|
||||
this.repeat = n.repeat;
|
||||
this.crontab = n.crontab;
|
||||
this.once = n.once;
|
||||
this.onceDelay = (n.onceDelay || 0.1) * 1000;
|
||||
var node = this;
|
||||
this.interval_id = null;
|
||||
this.cronjob = null;
|
||||
|
||||
if (this.repeat && !isNaN(this.repeat) && this.repeat > 0) {
|
||||
node.repeaterSetup = function () {
|
||||
if (this.repeat && !isNaN(this.repeat) && this.repeat > 0) {
|
||||
this.repeat = this.repeat * 1000;
|
||||
if (RED.settings.verbose) { this.log(RED._("inject.repeat",this)); }
|
||||
this.interval_id = setInterval( function() {
|
||||
node.emit("input",{});
|
||||
}, this.repeat );
|
||||
} else if (this.crontab) {
|
||||
if (RED.settings.verbose) { this.log(RED._("inject.crontab",this)); }
|
||||
this.cronjob = new cron.CronJob(this.crontab,
|
||||
function() {
|
||||
node.emit("input",{});
|
||||
},
|
||||
null,true);
|
||||
}
|
||||
if (RED.settings.verbose) {
|
||||
this.log(RED._("inject.repeat", this));
|
||||
}
|
||||
this.interval_id = setInterval(function() {
|
||||
node.emit("input", {});
|
||||
}, this.repeat);
|
||||
} else if (this.crontab) {
|
||||
if (RED.settings.verbose) {
|
||||
this.log(RED._("inject.crontab", this));
|
||||
}
|
||||
this.cronjob = new cron.CronJob(this.crontab, function() { node.emit("input", {}); }, null, true);
|
||||
}
|
||||
};
|
||||
|
||||
if (this.once) {
|
||||
setTimeout( function() { node.emit("input",{}); }, 100 );
|
||||
this.onceTimeout = setTimeout( function() {
|
||||
node.emit("input",{});
|
||||
node.repeaterSetup();
|
||||
}, this.onceDelay);
|
||||
} else {
|
||||
node.repeaterSetup();
|
||||
}
|
||||
|
||||
this.on("input",function(msg) {
|
||||
@@ -56,7 +64,7 @@ module.exports = function(RED) {
|
||||
msg.payload = Date.now();
|
||||
} else if (this.payloadType == null) {
|
||||
msg.payload = this.payload;
|
||||
} else if (this.payloadType == 'none') {
|
||||
} else if (this.payloadType === 'none') {
|
||||
msg.payload = "";
|
||||
} else {
|
||||
msg.payload = RED.util.evaluateNodeProperty(this.payload,this.payloadType,this,msg);
|
||||
@@ -72,6 +80,9 @@ module.exports = function(RED) {
|
||||
RED.nodes.registerType("inject",InjectNode);
|
||||
|
||||
InjectNode.prototype.close = function() {
|
||||
if (this.onceTimeout) {
|
||||
clearTimeout(this.onceTimeout);
|
||||
}
|
||||
if (this.interval_id != null) {
|
||||
clearInterval(this.interval_id);
|
||||
if (RED.settings.verbose) { this.log(RED._("inject.stopped")); }
|
||||
@@ -80,7 +91,7 @@ module.exports = function(RED) {
|
||||
if (RED.settings.verbose) { this.log(RED._("inject.stopped")); }
|
||||
delete this.cronjob;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
RED.httpAdmin.post("/inject/:id", RED.auth.needsPermission("inject.write"), function(req,res) {
|
||||
var node = RED.nodes.getNode(req.params.id);
|
||||
|
@@ -6,11 +6,22 @@
|
||||
<input id="node-input-complete" type="hidden">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-console"><i class="fa fa-random"></i> <span data-i18n="debug.to"></span></label>
|
||||
<select type="text" id="node-input-console" style="display: inline-block; width: 250px; vertical-align: top;">
|
||||
<option value="false" data-i18n="debug.debtab"></option>
|
||||
<option value="true" data-i18n="debug.tabcon"></option>
|
||||
</select>
|
||||
<label for="node-input-tosidebar"><i class="fa fa-random"></i> <span data-i18n="debug.to"></span></label>
|
||||
<label for="node-input-tosidebar" style="width:70%">
|
||||
<input type="checkbox" id="node-input-tosidebar" style="display:inline-block; width:22px; vertical-align:baseline;"><span data-i18n="debug.toSidebar"></span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-console"> </label>
|
||||
<label for="node-input-console" style="width:70%">
|
||||
<input type="checkbox" id="node-input-console" style="display:inline-block; width:22px; vertical-align:baseline;"><span data-i18n="debug.toConsole"></span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-row" id="node-tostatus-line">
|
||||
<label for="node-input-tostatus"> </label>
|
||||
<label for="node-input-tostatus" style="width:70%">
|
||||
<input type="checkbox" id="node-input-tostatus" style="display:inline-block; width:22px; vertical-align:baseline;"><span data-i18n="debug.toStatus"></span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
|
||||
@@ -26,7 +37,7 @@
|
||||
<p>Alongside each message, the debug sidebar includes information about the time the message was received, the node that sent it and the type of the message.
|
||||
Clicking on the source node id will reveal that node within the workspace.</p>
|
||||
<p>The button on the node can be used to enable or disable its output. It is recommended to disable or remove any Debug nodes that are not being used.</p>
|
||||
<p>The node can also be configured to send all messages to the runtime log.</p>
|
||||
<p>The node can also be configured to send all messages to the runtime log, or to send short (32 characters) to the status text under the debug node.</p>
|
||||
</script>
|
||||
<script src="debug/view/debug-utils.js"></script>
|
||||
|
||||
@@ -38,7 +49,9 @@
|
||||
defaults: {
|
||||
name: {value:""},
|
||||
active: {value:true},
|
||||
console: {value:"false"},
|
||||
tosidebar: {value:true},
|
||||
console: {value:false},
|
||||
tostatus: {value:false},
|
||||
complete: {value:"false", required:true}
|
||||
},
|
||||
label: function() {
|
||||
@@ -100,7 +113,6 @@
|
||||
}
|
||||
},
|
||||
onpaletteadd: function() {
|
||||
|
||||
var options = {
|
||||
messageMouseEnter: function(sourceId) {
|
||||
if (sourceId) {
|
||||
@@ -148,7 +160,7 @@
|
||||
|
||||
var that = this;
|
||||
RED._debug = function(msg) {
|
||||
that.handleDebugMessage("",{
|
||||
that.handleDebugMessage("", {
|
||||
name:"debug",
|
||||
msg:msg
|
||||
});
|
||||
@@ -170,7 +182,6 @@
|
||||
var sourceNode = RED.nodes.node(o.id) || RED.nodes.node(o.z);
|
||||
if (sourceNode) {
|
||||
o._source = {id:sourceNode.id,z:sourceNode.z,name:sourceNode.name};
|
||||
|
||||
}
|
||||
RED.debug.handleDebugMessage(o);
|
||||
if (subWindow) {
|
||||
@@ -237,6 +248,15 @@
|
||||
delete RED._debug;
|
||||
},
|
||||
oneditprepare: function() {
|
||||
if (this.tosidebar === undefined) {
|
||||
this.tosidebar = true;
|
||||
$("#node-input-tosidebar").prop('checked', true);
|
||||
}
|
||||
if (typeof this.console === "string") {
|
||||
this.console = (this.console == 'true');
|
||||
$("#node-input-console").prop('checked', this.console);
|
||||
$("#node-input-tosidebar").prop('checked', true);
|
||||
}
|
||||
$("#node-input-typed-complete").typedInput({types:['msg', {value:"full",label:RED._("node-red:debug.msgobj"),hasValue:false}]});
|
||||
if (this.complete === "true" || this.complete === true) {
|
||||
// show complete message object
|
||||
@@ -252,6 +272,16 @@
|
||||
) {
|
||||
$("#node-input-typed-complete").typedInput('value','payload');
|
||||
}
|
||||
if ($("#node-input-typed-complete").typedInput('type') === 'msg') {
|
||||
$("#node-tostatus-line").show();
|
||||
}
|
||||
else { $("#node-tostatus-line").hide(); }
|
||||
});
|
||||
$("#node-input-complete").on('change',function() {
|
||||
if ($("#node-input-typed-complete").typedInput('type') === 'msg') {
|
||||
$("#node-tostatus-line").show();
|
||||
}
|
||||
else { $("#node-tostatus-line").hide(); }
|
||||
});
|
||||
},
|
||||
oneditsave: function() {
|
||||
@@ -262,7 +292,6 @@
|
||||
$("#node-input-complete").val($("#node-input-typed-complete").typedInput('value'));
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
|
@@ -5,7 +5,7 @@ module.exports = function(RED) {
|
||||
var events = require("events");
|
||||
var path = require("path");
|
||||
var safeJSONStringify = require("json-stringify-safe");
|
||||
var debuglength = RED.settings.debugMaxLength||1000;
|
||||
var debuglength = RED.settings.debugMaxLength || 1000;
|
||||
var useColors = RED.settings.debugUseColors || false;
|
||||
util.inspect.styles.boolean = "red";
|
||||
|
||||
@@ -13,26 +13,49 @@ module.exports = function(RED) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.name = n.name;
|
||||
this.complete = (n.complete||"payload").toString();
|
||||
|
||||
if (this.complete === "false") {
|
||||
this.complete = "payload";
|
||||
}
|
||||
|
||||
this.console = n.console;
|
||||
if (this.complete === "false") { this.complete = "payload"; }
|
||||
this.console = ""+(n.console || false);
|
||||
this.tostatus = n.tostatus || false;
|
||||
this.tosidebar = n.tosidebar;
|
||||
if (this.tosidebar === undefined) { this.tosidebar = true; }
|
||||
this.severity = n.severity || 40;
|
||||
this.active = (n.active === null || typeof n.active === "undefined") || n.active;
|
||||
this.status({});
|
||||
|
||||
var node = this;
|
||||
var levels = {
|
||||
off: 1,
|
||||
fatal: 10,
|
||||
error: 20,
|
||||
warn: 30,
|
||||
info: 40,
|
||||
debug: 50,
|
||||
trace: 60,
|
||||
audit: 98,
|
||||
metric: 99
|
||||
};
|
||||
var colors = {
|
||||
"0": "grey",
|
||||
"10": "grey",
|
||||
"20": "red",
|
||||
"30": "yellow",
|
||||
"40": "grey",
|
||||
"50": "green",
|
||||
"60": "blue"
|
||||
};
|
||||
|
||||
this.on("input",function(msg) {
|
||||
if (this.complete === "true") {
|
||||
// debug complete msg object
|
||||
// debug complete msg object
|
||||
if (this.console === "true") {
|
||||
node.log("\n"+util.inspect(msg, {colors:useColors, depth:10}));
|
||||
}
|
||||
if (this.active) {
|
||||
sendDebug({id:node.id,name:node.name,topic:msg.topic,msg:msg,_path:msg._path});
|
||||
if (this.active && this.tosidebar) {
|
||||
sendDebug({id:node.id, name:node.name, topic:msg.topic, msg:msg, _path:msg._path});
|
||||
}
|
||||
} else {
|
||||
// debug user defined msg property
|
||||
}
|
||||
else {
|
||||
// debug user defined msg property
|
||||
var property = "payload";
|
||||
var output = msg[property];
|
||||
if (this.complete !== "false" && typeof this.complete !== "undefined") {
|
||||
@@ -53,7 +76,15 @@ module.exports = function(RED) {
|
||||
}
|
||||
}
|
||||
if (this.active) {
|
||||
sendDebug({id:node.id,z:node.z,name:node.name,topic:msg.topic,property:property,msg:output,_path:msg._path});
|
||||
if (this.tosidebar == true) {
|
||||
sendDebug({id:node.id, z:node.z, name:node.name, topic:msg.topic, property:property, msg:output, _path:msg._path});
|
||||
}
|
||||
if (this.tostatus === true) {
|
||||
var st = util.inspect(output);
|
||||
if (st.length > 32) { st = st.substr(0,32) + "..."; }
|
||||
node.oldStatus = {fill:colors[node.severity], shape:"dot", text:st};
|
||||
node.status(node.oldStatus);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -138,7 +169,7 @@ module.exports = function(RED) {
|
||||
value = value.substring(0,debuglength)+"...";
|
||||
}
|
||||
} else if (value && value.constructor) {
|
||||
if (value.constructor.name === "Buffer") {
|
||||
if (value.type === "Buffer") {
|
||||
value.__encoded__ = true;
|
||||
value.length = value.data.length;
|
||||
if (value.length > debuglength) {
|
||||
@@ -196,9 +227,14 @@ module.exports = function(RED) {
|
||||
if (state === "enable") {
|
||||
node.active = true;
|
||||
res.sendStatus(200);
|
||||
if (node.tostatus) { node.status({}); }
|
||||
} else if (state === "disable") {
|
||||
node.active = false;
|
||||
res.sendStatus(201);
|
||||
if (node.tostatus && node.hasOwnProperty("oldStatus")) {
|
||||
node.oldStatus.shape = "ring";
|
||||
node.status(node.oldStatus);
|
||||
}
|
||||
} else {
|
||||
res.sendStatus(404);
|
||||
}
|
||||
|
@@ -75,12 +75,20 @@
|
||||
<dt>payload <span class="property-type">string</span></dt>
|
||||
<dd>the standard output of the command.</dd>
|
||||
</dl>
|
||||
<dl class="message-properties">
|
||||
<dt>rc <span class="property-type">object</span></dt>
|
||||
<dd>exec mode only, a copy of the return code object (also available on port 3)</dd>
|
||||
</dl>
|
||||
</li>
|
||||
<li>Standard error
|
||||
<dl class="message-properties">
|
||||
<dt>payload <span class="property-type">string</span></dt>
|
||||
<dd>the standard error of the command.</dd>
|
||||
</dl>
|
||||
<dl class="message-properties">
|
||||
<dt>rc <span class="property-type">object</span></dt>
|
||||
<dd>exec mode only, a copy of the return code object (also available on port 3)</dd>
|
||||
</dl>
|
||||
</li>
|
||||
<li>Return code
|
||||
<dl class="message-properties">
|
||||
|
@@ -125,14 +125,15 @@ module.exports = function(RED) {
|
||||
if (node.append.trim() !== "") { cl += " "+node.append; }
|
||||
/* istanbul ignore else */
|
||||
if (RED.settings.verbose) { node.log(cl); }
|
||||
child = exec(cl, {encoding: 'binary', maxBuffer:10000000}, function (error, stdout, stderr) {
|
||||
child = exec(cl, {encoding:'binary', maxBuffer:10000000}, function (error, stdout, stderr) {
|
||||
var msg2, msg3;
|
||||
delete msg.payload;
|
||||
if (stderr) {
|
||||
msg2 = RED.util.cloneMessage(msg);
|
||||
msg2.payload = stderr;
|
||||
}
|
||||
msg.payload = Buffer.from(stdout,"binary");
|
||||
if (isUtf8(msg.payload)) { msg.payload = msg.payload.toString(); }
|
||||
var msg2 = null;
|
||||
if (stderr) {
|
||||
msg2 = {payload: stderr};
|
||||
}
|
||||
var msg3 = null;
|
||||
node.status({});
|
||||
//console.log('[exec] stdout: ' + stdout);
|
||||
//console.log('[exec] stderr: ' + stderr);
|
||||
@@ -142,10 +143,15 @@ module.exports = function(RED) {
|
||||
if (error.code === null) { node.status({fill:"red",shape:"dot",text:"killed"}); }
|
||||
else { node.status({fill:"red",shape:"dot",text:"error:"+error.code}); }
|
||||
node.log('error:' + error);
|
||||
} else if (node.oldrc === "false") {
|
||||
}
|
||||
else if (node.oldrc === "false") {
|
||||
msg3 = {payload:{code:0}};
|
||||
}
|
||||
if (!msg3) { node.status({}); }
|
||||
else {
|
||||
msg.rc = msg3.payload;
|
||||
if (msg2) { msg2.rc = msg3.payload; }
|
||||
}
|
||||
node.send([msg,msg2,msg3]);
|
||||
if (child.tout) { clearTimeout(child.tout); }
|
||||
delete node.activeProcesses[child.pid];
|
||||
|
@@ -70,10 +70,19 @@
|
||||
label: function() {
|
||||
return this.name;
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
},
|
||||
oneditprepare: function() {
|
||||
var that = this;
|
||||
$( "#node-input-outputs" ).spinner({
|
||||
min:1
|
||||
min:1,
|
||||
change: function(event, ui) {
|
||||
var value = this.value;
|
||||
if (!value.match(/^\d+$/)) { value = 1; }
|
||||
else if (value < this.min) { value = this.min; }
|
||||
if (value !== this.value) { $(this).spinner("value", value); }
|
||||
}
|
||||
});
|
||||
|
||||
this.editor = RED.editor.createEditor({
|
||||
|
@@ -187,6 +187,13 @@ module.exports = function(RED) {
|
||||
}
|
||||
}
|
||||
};
|
||||
if (util.hasOwnProperty('promisify')) {
|
||||
sandbox.setTimeout[util.promisify.custom] = function(after, value) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
sandbox.setTimeout(function(){ resolve(value) }, after);
|
||||
});
|
||||
}
|
||||
}
|
||||
var context = vm.createContext(sandbox);
|
||||
try {
|
||||
this.script = vm.createScript(functionText);
|
||||
|
@@ -42,6 +42,7 @@
|
||||
<select id="node-input-output" style="width:180px;">
|
||||
<option value="str" data-i18n="template.label.plain"></option>
|
||||
<option value="json" data-i18n="template.label.json"></option>
|
||||
<option value="yaml" data-i18n="template.label.yaml"></option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
@@ -53,6 +54,9 @@
|
||||
<dl class="message-properties">
|
||||
<dt>msg <span class="property-type">object</span></dt>
|
||||
<dd>A msg object containing information to populate the template.</dd>
|
||||
<dt class="optional">template <span class="property-type">string</span></dt>
|
||||
<dd>A template to be populated from msg.payload. If not configured in the edit panel,
|
||||
this can be set as a property of msg.</dd>
|
||||
</dl>
|
||||
<h3>Outputs</h3>
|
||||
<dl class="message-properties">
|
||||
@@ -97,6 +101,9 @@
|
||||
label: function() {
|
||||
return this.name;
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
},
|
||||
oneditprepare: function() {
|
||||
var that = this;
|
||||
if (!this.fieldType) {
|
||||
|
@@ -17,14 +17,17 @@
|
||||
module.exports = function(RED) {
|
||||
"use strict";
|
||||
var mustache = require("mustache");
|
||||
var yaml = require("js-yaml");
|
||||
|
||||
|
||||
/**
|
||||
* Custom Mustache Context capable to resolve message property and node
|
||||
* flow and global context
|
||||
*/
|
||||
function NodeContext(msg, nodeContext,parent) {
|
||||
function NodeContext(msg, nodeContext, parent, escapeStrings) {
|
||||
this.msgContext = new mustache.Context(msg,parent);
|
||||
this.nodeContext = nodeContext;
|
||||
this.escapeStrings = escapeStrings;
|
||||
}
|
||||
|
||||
NodeContext.prototype = new mustache.Context();
|
||||
@@ -34,6 +37,14 @@ module.exports = function(RED) {
|
||||
try {
|
||||
var value = this.msgContext.lookup(name);
|
||||
if (value !== undefined) {
|
||||
if (this.escapeStrings && typeof value === "string") {
|
||||
value = value.replace(/\\/g, "\\\\");
|
||||
value = value.replace(/\n/g, "\\n");
|
||||
value = value.replace(/\t/g, "\\t");
|
||||
value = value.replace(/\r/g, "\\r");
|
||||
value = value.replace(/\f/g, "\\f");
|
||||
value = value.replace(/[\b]/g, "\\b");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -72,14 +83,31 @@ module.exports = function(RED) {
|
||||
node.on("input", function(msg) {
|
||||
try {
|
||||
var value;
|
||||
/***
|
||||
* Allow template contents to be defined externally
|
||||
* through inbound msg.template IFF node.template empty
|
||||
*/
|
||||
if (msg.hasOwnProperty("template")) {
|
||||
if (node.template == "" || node.template === null) {
|
||||
node.template = msg.template;
|
||||
}
|
||||
}
|
||||
|
||||
if (node.syntax === "mustache") {
|
||||
value = mustache.render(node.template,new NodeContext(msg, node.context()));
|
||||
if (node.outputFormat === "json") {
|
||||
value = mustache.render(node.template,new NodeContext(msg, node.context(), null, true));
|
||||
} else {
|
||||
value = mustache.render(node.template,new NodeContext(msg, node.context(), null, false));
|
||||
}
|
||||
} else {
|
||||
value = node.template;
|
||||
}
|
||||
if (node.outputFormat === "json") {
|
||||
value = JSON.parse(value);
|
||||
}
|
||||
if (node.outputFormat === "yaml") {
|
||||
value = yaml.load(value);
|
||||
}
|
||||
|
||||
if (node.fieldType === 'msg') {
|
||||
RED.util.setMessageProperty(msg,node.field,value);
|
||||
|
@@ -102,7 +102,7 @@
|
||||
<dt class="optional">delay <span class="property-type">number</span></dt>
|
||||
<dd>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
|
||||
provide the delay interval.</dd>
|
||||
override the configured default delay interval.</dd>
|
||||
<dt class="optional">reset</dt>
|
||||
<dd>If the received message has this property set to any value, all
|
||||
outstanding messages held by the node are cleared without being sent.</dd>
|
||||
@@ -129,13 +129,13 @@
|
||||
defaults: {
|
||||
name: {value:""},
|
||||
pauseType: {value:"delay", required:true},
|
||||
timeout: {value:"5", required:true, validate:RED.validators.number()},
|
||||
timeout: {value:"5", required:true, validate:function(v) { return RED.validators.number(v) && (v >= 0); }},
|
||||
timeoutUnits: {value:"seconds"},
|
||||
rate: {value:"1", required:true, validate:RED.validators.number()},
|
||||
rate: {value:"1", required:true, validate:function(v) { return RED.validators.number(v) && (v >= 0); }},
|
||||
nbRateUnits: {value:"1", required:false, validate:RED.validators.regex(/\d+|/)},
|
||||
rateUnits: {value: "second"},
|
||||
randomFirst: {value:"1", required:true, validate:RED.validators.number()},
|
||||
randomLast: {value:"5", required:true, validate:RED.validators.number()},
|
||||
randomFirst: {value:"1", required:true, validate:function(v) { return RED.validators.number(v) && (v >= 0); }},
|
||||
randomLast: {value:"5", required:true, validate:function(v) { return RED.validators.number(v) && (v >= 0); }},
|
||||
randomUnits: {value: "seconds"},
|
||||
drop: {value:false}
|
||||
},
|
||||
@@ -260,7 +260,7 @@
|
||||
$("#delay-details-for").show();
|
||||
$("#random-details").hide();
|
||||
} else if (this.value === "delayv") {
|
||||
$("#delay-details-for").hide();
|
||||
$("#delay-details-for").show();
|
||||
$("#random-details").hide();
|
||||
} else if (this.value === "random") {
|
||||
$("#delay-details-for").hide();
|
||||
|
@@ -105,7 +105,10 @@ module.exports = function(RED) {
|
||||
}
|
||||
else if (node.pauseType === "delayv") {
|
||||
node.on("input", function(msg) {
|
||||
var delayvar = Number(msg.delay || 0);
|
||||
var delayvar = Number(node.timeout);
|
||||
if (msg.hasOwnProperty("delay") && !isNaN(parseFloat(msg.delay))) {
|
||||
delayvar = parseFloat(msg.delay);
|
||||
}
|
||||
if (delayvar < 0) { delayvar = 0; }
|
||||
var id = setTimeout(function() {
|
||||
node.idList.splice(node.idList.indexOf(id),1);
|
||||
@@ -113,7 +116,7 @@ module.exports = function(RED) {
|
||||
node.send(msg);
|
||||
}, delayvar);
|
||||
node.idList.push(id);
|
||||
if ((delayvar >= 1) && (node.idList.length !== 0)) {
|
||||
if ((delayvar >= 0) && (node.idList.length !== 0)) {
|
||||
node.status({fill:"blue",shape:"dot",text:delayvar/1000+"s"});
|
||||
}
|
||||
if (msg.hasOwnProperty("reset")) { clearDelayList(); }
|
||||
|
@@ -56,6 +56,13 @@
|
||||
</ul>
|
||||
</div>
|
||||
<br/>
|
||||
<div class="form-row">
|
||||
<label data-i18n="trigger.for" for="node-input-bytopic"></label>
|
||||
<select id="node-input-bytopic">
|
||||
<option value="all" data-i18n="trigger.alltopics"></option>
|
||||
<option value="topic" data-i18n="trigger.bytopics"></option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
|
||||
<input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name"></input>
|
||||
@@ -85,7 +92,7 @@
|
||||
<p>If set to a <i>string</i> type, the node supports the mustache template syntax.</p>
|
||||
<p>If the node receives a message with a <code>reset</code> property, or a <code>payload</code>
|
||||
that matches that configured in the node, any timeout or repeat currently in
|
||||
progress will be cleared and no message triggered.</o>
|
||||
progress will be cleared and no message triggered.</p>
|
||||
<p>The node can be configured to resend a message at a regular interval until it
|
||||
is reset by a received message.</p>
|
||||
</script>
|
||||
@@ -103,6 +110,7 @@
|
||||
extend: {value:"false"},
|
||||
units: {value:"ms"},
|
||||
reset: {value:""},
|
||||
bytopic: {value: "all"},
|
||||
name: {value:""}
|
||||
},
|
||||
inputs:1,
|
||||
|
@@ -19,6 +19,7 @@ module.exports = function(RED) {
|
||||
var mustache = require("mustache");
|
||||
function TriggerNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.bytopic = n.bytopic || "all";
|
||||
this.op1 = n.op1 || "1";
|
||||
this.op2 = n.op2 || "0";
|
||||
this.op1type = n.op1type || "str";
|
||||
@@ -47,7 +48,7 @@ module.exports = function(RED) {
|
||||
this.extend = n.extend || "false";
|
||||
this.units = n.units || "ms";
|
||||
this.reset = n.reset || '';
|
||||
this.duration = parseInt(n.duration);
|
||||
this.duration = parseFloat(n.duration);
|
||||
if (isNaN(this.duration)) {
|
||||
this.duration = 250;
|
||||
}
|
||||
@@ -65,29 +66,32 @@ module.exports = function(RED) {
|
||||
this.op2Templated = (this.op2type === 'str' && this.op2.indexOf("{{") != -1);
|
||||
if ((this.op1type === "num") && (!isNaN(this.op1))) { this.op1 = Number(this.op1); }
|
||||
if ((this.op2type === "num") && (!isNaN(this.op2))) { this.op2 = Number(this.op2); }
|
||||
if (this.op1 == "null") { this.op1 = null; }
|
||||
if (this.op2 == "null") { this.op2 = null; }
|
||||
//if (this.op1 == "null") { this.op1 = null; }
|
||||
//if (this.op2 == "null") { this.op2 = null; }
|
||||
//try { this.op1 = JSON.parse(this.op1); }
|
||||
//catch(e) { this.op1 = this.op1; }
|
||||
//try { this.op2 = JSON.parse(this.op2); }
|
||||
//catch(e) { this.op2 = this.op2; }
|
||||
|
||||
var node = this;
|
||||
var tout = null;
|
||||
var m2;
|
||||
node.topics = {};
|
||||
|
||||
this.on("input", function(msg) {
|
||||
var topic = msg.topic || "_none";
|
||||
if (node.bytopic === "all") { topic = "_none"; }
|
||||
node.topics[topic] = node.topics[topic] || {};
|
||||
if (msg.hasOwnProperty("reset") || ((node.reset !== '') && (msg.payload == node.reset)) ) {
|
||||
if (node.loop === true) { clearInterval(tout); }
|
||||
else { clearTimeout(tout); }
|
||||
tout = null;
|
||||
if (node.loop === true) { clearInterval(node.topics[topic].tout); }
|
||||
else { clearTimeout(node.topics[topic].tout); }
|
||||
delete node.topics[topic];
|
||||
node.status({});
|
||||
}
|
||||
else {
|
||||
if (((!tout) && (tout !== 0)) || (node.loop === true)) {
|
||||
if (node.op2type === "pay" || node.op2type === "payl") { m2 = msg.payload; }
|
||||
else if (node.op2Templated) { m2 = mustache.render(node.op2,msg); }
|
||||
if (((!node.topics[topic].tout) && (node.topics[topic].tout !== 0)) || (node.loop === true)) {
|
||||
if (node.op2type === "pay" || node.op2type === "payl") { node.topics[topic].m2 = RED.util.cloneMessage(msg.payload); }
|
||||
else if (node.op2Templated) { node.topics[topic].m2 = mustache.render(node.op2,msg); }
|
||||
else if (node.op2type !== "nul") {
|
||||
m2 = RED.util.evaluateNodeProperty(node.op2,node.op2type,node,msg);
|
||||
node.topics[topic].m2 = RED.util.evaluateNodeProperty(node.op2,node.op2type,node,msg);
|
||||
}
|
||||
|
||||
if (node.op1type === "pay") { }
|
||||
@@ -96,58 +100,64 @@ module.exports = function(RED) {
|
||||
msg.payload = RED.util.evaluateNodeProperty(node.op1,node.op1type,node,msg);
|
||||
}
|
||||
|
||||
if (node.op1type !== "nul") { node.send(msg); }
|
||||
if (node.op1type !== "nul") { node.send(RED.util.cloneMessage(msg)); }
|
||||
|
||||
if (node.duration === 0) { tout = 0; }
|
||||
if (node.duration === 0) { node.topics[topic].tout = 0; }
|
||||
else if (node.loop === true) {
|
||||
if (tout) { clearInterval(tout); }
|
||||
if (node.topics[topic].tout) { clearInterval(node.topics[topic].tout); }
|
||||
if (node.op1type !== "nul") {
|
||||
var msg2 = RED.util.cloneMessage(msg);
|
||||
tout = setInterval(function() { node.send(msg2); },node.duration);
|
||||
node.topics[topic].tout = setInterval(function() { node.send(RED.util.cloneMessage(msg2)); }, node.duration);
|
||||
}
|
||||
}
|
||||
else {
|
||||
tout = setTimeout(function() {
|
||||
node.topics[topic].tout = setTimeout(function() {
|
||||
var msg2 = null;
|
||||
if (node.op2type !== "nul") {
|
||||
var msg2 = RED.util.cloneMessage(msg);
|
||||
msg2 = RED.util.cloneMessage(msg);
|
||||
if (node.op2type === "flow" || node.op2type === "global") {
|
||||
m2 = RED.util.evaluateNodeProperty(node.op2,node.op2type,node,msg);
|
||||
node.topics[topic].m2 = RED.util.evaluateNodeProperty(node.op2,node.op2type,node,msg);
|
||||
}
|
||||
msg2.payload = m2;
|
||||
node.send(msg2);
|
||||
msg2.payload = node.topics[topic].m2;
|
||||
}
|
||||
tout = null;
|
||||
delete node.topics[topic];
|
||||
node.status({});
|
||||
},node.duration);
|
||||
node.send(msg2);
|
||||
}, node.duration);
|
||||
}
|
||||
node.status({fill:"blue",shape:"dot",text:" "});
|
||||
}
|
||||
else if ((node.extend === "true" || node.extend === true) && (node.duration > 0)) {
|
||||
if (tout) { clearTimeout(tout); }
|
||||
if (node.op2type === "payl") { m2 = msg.payload; }
|
||||
tout = setTimeout(function() {
|
||||
if (node.op2type === "payl") { node.topics[topic].m2 = RED.util.cloneMessage(msg.payload); }
|
||||
if (node.topics[topic].tout) { clearTimeout(node.topics[topic].tout); }
|
||||
node.topics[topic].tout = setTimeout(function() {
|
||||
var msg2 = null;
|
||||
if (node.op2type !== "nul") {
|
||||
var msg2 = RED.util.cloneMessage(msg);
|
||||
if (node.op2type === "flow" || node.op2type === "global") {
|
||||
m2 = RED.util.evaluateNodeProperty(node.op2,node.op2type,node,msg);
|
||||
node.topics[topic].m2 = RED.util.evaluateNodeProperty(node.op2,node.op2type,node,msg);
|
||||
}
|
||||
if (node.topics[topic] !== undefined) {
|
||||
msg2 = RED.util.cloneMessage(msg);
|
||||
msg2.payload = node.topics[topic].m2;
|
||||
}
|
||||
msg2.payload = m2;
|
||||
node.send(msg2);
|
||||
}
|
||||
tout = null;
|
||||
delete node.topics[topic];
|
||||
node.status({});
|
||||
},node.duration);
|
||||
node.send(msg2);
|
||||
}, node.duration);
|
||||
}
|
||||
else {
|
||||
if (node.op2type === "payl") { m2 = msg.payload; }
|
||||
if (node.op2type === "payl") { node.topics[topic].m2 = RED.util.cloneMessage(msg.payload); }
|
||||
}
|
||||
}
|
||||
});
|
||||
this.on("close", function() {
|
||||
if (tout) {
|
||||
if (node.loop === true) { clearInterval(tout); }
|
||||
else { clearTimeout(tout); }
|
||||
tout = null;
|
||||
for (var t in node.topics) {
|
||||
if (node.topics[t]) {
|
||||
if (node.loop === true) { clearInterval(node.topics[t].tout); }
|
||||
else { clearTimeout(node.topics[t].tout); }
|
||||
delete node.topics[t];
|
||||
}
|
||||
}
|
||||
node.status({});
|
||||
});
|
||||
|
@@ -29,6 +29,7 @@ RED.debug = (function() {
|
||||
var messagesByNode = {};
|
||||
var sbc;
|
||||
var activeWorkspace;
|
||||
var numMessages = 100; // Hardcoded number of message to show in debug window scrollback
|
||||
|
||||
var filterVisible = false;
|
||||
|
||||
@@ -367,9 +368,24 @@ RED.debug = (function() {
|
||||
})
|
||||
menuOptionMenu.show();
|
||||
}
|
||||
function handleDebugMessage(o) {
|
||||
var msg = document.createElement("div");
|
||||
|
||||
var stack = [];
|
||||
var busy = false;
|
||||
function handleDebugMessage(o) {
|
||||
if (o) { stack.push(o); }
|
||||
if (!busy && (stack.length > 0)) {
|
||||
busy = true;
|
||||
processDebugMessage(stack.shift());
|
||||
setTimeout(function() {
|
||||
busy = false;
|
||||
handleDebugMessage();
|
||||
}, 15); // every 15mS = 66 times a second
|
||||
if (stack.length > numMessages) { stack = stack.splice(-numMessages); }
|
||||
}
|
||||
}
|
||||
|
||||
function processDebugMessage(o) {
|
||||
var msg = document.createElement("div");
|
||||
var sourceNode = o._source;
|
||||
|
||||
msg.onmouseenter = function() {
|
||||
@@ -421,7 +437,9 @@ RED.debug = (function() {
|
||||
$('<span class="debug-message-name">'+name+'</span>').appendTo(metaRow);
|
||||
}
|
||||
|
||||
if (format === 'Object' || /^array/.test(format) || format === 'boolean' || format === 'number' ) {
|
||||
if ((format === 'number') && (payload === "NaN")) {
|
||||
payload = Number.NaN;
|
||||
} else if (format === 'Object' || /^array/.test(format) || format === 'boolean' || format === 'number' ) {
|
||||
payload = JSON.parse(payload);
|
||||
} else if (/error/i.test(format)) {
|
||||
payload = JSON.parse(payload);
|
||||
@@ -495,7 +513,7 @@ RED.debug = (function() {
|
||||
}
|
||||
}
|
||||
|
||||
if (messages.length === 100) {
|
||||
if (messages.length === numMessages) {
|
||||
m = messages.shift();
|
||||
if (view === "list") {
|
||||
m.el.remove();
|
||||
@@ -528,6 +546,6 @@ RED.debug = (function() {
|
||||
init: init,
|
||||
refreshMessageList:refreshMessageList,
|
||||
handleDebugMessage: handleDebugMessage,
|
||||
clearMessageList: clearMessageList,
|
||||
clearMessageList: clearMessageList
|
||||
}
|
||||
})();
|
||||
|
Reference in New Issue
Block a user