Merge branch 'dev'

This commit is contained in:
Nick O'Leary
2020-06-30 17:46:43 +01:00
362 changed files with 11192 additions and 3496 deletions

View File

@@ -14,16 +14,14 @@
limitations under the License.
-->
<script type="text/x-red" data-template-name="inject">
<script type="text/html" data-template-name="inject">
<div class="form-row">
<label for="node-input-payload"><i class="fa fa-envelope"></i> <span data-i18n="common.label.payload"></span></label>
<input type="text" id="node-input-payload" style="width:70%">
<input type="hidden" id="node-input-payloadType">
<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">
</div>
<div class="form-row">
<label for="node-input-topic"><i class="fa fa-tasks"></i> <span data-i18n="common.label.topic"></span></label>
<input type="text" id="node-input-topic">
<div class="form-row node-input-property-container-row">
<ol id="node-input-property-container"></ol>
</div>
<div class="form-row" id="node-once">
@@ -114,12 +112,7 @@
</div>
</div>
</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">
</div>
<div class="form-tips" data-i18n="[html]inject.tip"></div>
</script>
<style>
.inject-time-row {
@@ -155,37 +148,76 @@
</style>
<script type="text/javascript">
(function() {
function resizeDialog(size) {
size = size || { height: $(".red-ui-tray-content form").height() }
var rows = $("#dialog-form>div:not(.node-input-property-container-row):visible");
var height = size.height;
for (var i=0; i<rows.length; i++) {
height -= $(rows[i]).outerHeight(true);
}
var editorRow = $("#dialog-form>div.node-input-property-container-row");
height -= (parseInt(editorRow.css("marginTop"))+parseInt(editorRow.css("marginBottom")));
height += 16;
$("#node-input-property-container").editableList('height',height);
}
RED.nodes.registerType('inject',{
category: 'common',
color:"#a6bbcf",
defaults: {
name: {value:""},
topic: {value:""},
payload: {value:"", validate: RED.validators.typedInput("payloadType")},
payloadType: {value:"date"},
props:{value:[{p:"payload"},{p:"topic",vt:"str"}]},
repeat: {value:"", validate:function(v) { return ((v === "") || (RED.validators.number(v) && (v >= 0) && (v <= 2147483))) }},
crontab: {value:""},
once: {value:false},
onceDelay: {value:0.1}
onceDelay: {value:0.1},
topic: {value:""},
payload: {value:"", validate: RED.validators.typedInput("payloadType")},
payloadType: {value:"date"},
},
icon: "inject.svg",
inputs:0,
outputs:1,
outputLabels: function(index) {
var lab = this.payloadType;
if (lab === "json") {
try {
lab = typeof JSON.parse(this.payload);
if (lab === "object") {
if (Array.isArray(JSON.parse(this.payload))) { lab = "Array"; }
}
} catch(e) {
return this._("inject.label.invalid"); }
var lab = '';
// if only payload and topic - display payload type
// if only one property - show it's type
// if more than one property (other than payload and topic) - show "x properties" where x is the number of properties.
// this.props will not be an array for legacy inject nodes until they are re-deployed
//
var props = this.props;
if (!Array.isArray(props)) {
props = [
{ p:"payload", v: this.payload, vt: this.payloadType },
{ p:"topic", v: this.topic, vt: "str" }
]
}
var name = "inject.label."+lab;
var label = this._(name);
if (name !== label) {
return label;
if (props) {
for (var i=0,l=props.length; i<l; i++) {
if (i > 0) lab += "\n";
if (i === 5) {
lab += " + "+(props.length-4);
break;
}
lab += props[i].p+": ";
var propType = props[i].p === "payload"? this.payloadType : props[i].vt;
if (propType === "json") {
try {
var parsedProp = JSON.parse(props[i].p === "payload"? this.payload : props[i].v);
propType = typeof parsedProp;
if (propType === "object" && Array.isArray(parsedProp)) {
propType = "Array";
}
} catch(e) {
propType = "invalid";
}
}
lab += this._("inject.label."+propType);
}
}
return lab;
},
@@ -201,27 +233,33 @@
}
if (this.name) {
return this.name+suffix;
} else if (this.payloadType === "string" ||
this.payloadType === "str" ||
this.payloadType === "num" ||
this.payloadType === "bool" ||
this.payloadType === "json") {
if ((this.topic !== "") && ((this.topic.length + this.payload.length) <= 32)) {
return this.topic + ":" + this.payload+suffix;
} else if (this.payload.length > 0 && this.payload.length < 24) {
return this.payload+suffix;
}
var payload = this.payload || "";
var payloadType = this.payloadType || "str";
var topic = this.topic || "";
if (payloadType === "string" ||
payloadType === "str" ||
payloadType === "num" ||
payloadType === "bool" ||
payloadType === "json") {
if ((topic !== "") && ((topic.length + payload.length) <= 32)) {
return topic + ":" + payload+suffix;
} else if (payload.length > 0 && payload.length < 24) {
return payload+suffix;
} else {
return this._("inject.inject")+suffix;
}
} else if (this.payloadType === 'date') {
if ((this.topic !== "") && (this.topic.length <= 16)) {
return this.topic + ":" + this._("inject.timestamp")+suffix;
} else if (payloadType === 'date' || payloadType === 'bin' || payloadType === 'env') {
if ((topic !== "") && (topic.length <= 16)) {
return topic + ":" + this._('inject.label.'+payloadType)+suffix;
} else {
return this._("inject.timestamp")+suffix;
return this._('inject.label.'+payloadType)+suffix;
}
} else if (this.payloadType === 'flow' || this.payloadType === 'global') {
var key = RED.utils.parseContextKey(this.payload);
return this.payloadType+"."+key.key+suffix;
} else if (payloadType === 'flow' || payloadType === 'global') {
var key = RED.utils.parseContextKey(payload);
return payloadType+"."+key.key+suffix;
} else {
return this._("inject.inject")+suffix;
}
@@ -239,13 +277,6 @@
} else if (this.payloadType === 'string' || this.payloadType === 'none') {
this.payloadType = "str";
}
$("#node-input-payloadType").val(this.payloadType);
$("#node-input-payload").typedInput({
default: 'str',
typeField: $("#node-input-payloadType"),
types:['flow','global','str','num','bool','json','bin','date','env']
});
$("#inject-time-type-select").on("change", function() {
$("#node-input-crontab").val('');
@@ -259,6 +290,11 @@
$("#node-once").hide();
$("#node-input-once").prop('checked', false);
}
// Scroll down
var scrollDiv = $("#dialog-form").parent();
scrollDiv.scrollTop(scrollDiv.prop('scrollHeight'));
resizeDialog();
});
$("#node-input-once").on("change", function() {
@@ -378,7 +414,70 @@
$("#inject-time-type-select").val(repeattype);
$("#inject-time-row-"+repeattype).show();
$("#node-input-payload").typedInput('type',this.payloadType);
/* */
$('#node-input-property-container').css('min-height','120px').css('min-width','450px').editableList({
addItem: function(container,i,opt) {
var prop = opt;
if (!prop.hasOwnProperty('p')) {
prop = {p:"",v:"",vt:"str"};
}
container.css({
overflow: 'hidden',
whiteSpace: 'nowrap'
});
var row = $('<div/>').appendTo(container);
var propertyName = $('<input/>',{class:"node-input-prop-property-name",type:"text"})
.css("width","30%")
.appendTo(row)
.typedInput({types:['msg']});
$('<div/>',{style: 'display:inline-block; padding:0px 6px;'})
.text('=')
.appendTo(row);
var propertyValue = $('<input/>',{class:"node-input-prop-property-value",type:"text"})
.css("width","calc(70% - 30px)")
.appendTo(row)
.typedInput({default:'str',types:['msg','flow','global','str','num','bool','json','bin','date','jsonata','env']});
propertyName.typedInput('value',prop.p);
propertyValue.typedInput('value',prop.v);
propertyValue.typedInput('type',prop.vt);
},
removable: true,
sortable: true
});
if (!this.props) {
var payload = {
p:'payload',
v: this.payload ? this.payload : '',
vt:this.payloadType ? this.payloadType : 'date'
};
var topic = {
p:'topic',
v: this.topic ? this.topic : '',
vt:'string'
}
this.props = [payload,topic];
}
for (var i=0; i<this.props.length; i++) {
var prop = this.props[i];
var newProp = { p: prop.p, v: prop.v, vt: prop.vt };
if (newProp.v === undefined) {
if (prop.p === 'payload') {
newProp.v = this.payload ? this.payload : '';
newProp.vt = this.payloadType ? this.payloadType : 'date';
} else if (prop.p === 'topic' && prop.vt === "str") {
newProp.v = this.topic ? this.topic : '';
}
}
$("#node-input-property-container").editableList('addItem',newProp);
}
$("#inject-time-type-select").trigger("change");
$("#inject-time-interval-time-start").trigger("change");
@@ -474,6 +573,34 @@
$("#node-input-repeat").val(repeat);
$("#node-input-crontab").val(crontab);
/* Gather the injected properties of the msg object */
var props = $("#node-input-property-container").editableList('items');
var node = this;
node.props= [];
delete node.payloadType;
delete node.payload;
node.topic = "";
props.each(function(i) {
var prop = $(this);
var p = {
p:prop.find(".node-input-prop-property-name").typedInput('value')
};
if (p.p) {
p.v = prop.find(".node-input-prop-property-value").typedInput('value');
p.vt = prop.find(".node-input-prop-property-value").typedInput('type');
if (p.p === "payload") { // save payload to old "legacy" property
node.payloadType = p.vt;
node.payload = p.v;
delete p.v;
delete p.vt;
} else if (p.p === "topic" && p.vt === "str") {
node.topic = p.v;
delete p.v;
}
node.props.push(p);
}
});
},
button: {
enabled: function() {
@@ -483,12 +610,7 @@
if (this.changed) {
return RED.notify(RED._("notification.warning", {message:RED._("notification.warnings.undeployedChanges")}),"warning");
}
var payload = this.payload;
if ((this.payloadType === 'flow') ||
(this.payloadType === 'global')) {
var key = RED.utils.parseContextKey(payload);
payload = this.payloadType+"."+key.key;
}
var label = this._def.label.call(this);
if (label.length > 30) {
label = label.substring(0,50)+"...";
@@ -514,7 +636,8 @@
}
});
}
}
},
oneditresize: resizeDialog
});
})();
</script>

View File

@@ -20,9 +20,32 @@ module.exports = function(RED) {
function InjectNode(n) {
RED.nodes.createNode(this,n);
this.topic = n.topic;
this.payload = n.payload;
this.payloadType = n.payloadType;
/* Handle legacy */
if(!Array.isArray(n.props)){
n.props = [];
n.props.push({
p:'payload',
v:n.payload,
vt:n.payloadType
});
n.props.push({
p:'topic',
v:n.topic,
vt:'str'
});
} else {
for (var i=0,l=n.props.length; i<l; i++) {
if (n.props[i].p === 'payload' && !n.props[i].hasOwnProperty('v')) {
n.props[i].v = n.payload;
n.props[i].vt = n.payloadType;
} else if (n.props[i].p === 'topic' && n.props[i].vt === 'str' && !n.props[i].hasOwnProperty('v')) {
n.props[i].v = n.topic;
}
}
}
this.props = n.props;
this.repeat = n.repeat;
this.crontab = n.crontab;
this.once = n.once;
@@ -31,65 +54,83 @@ module.exports = function(RED) {
this.cronjob = null;
var node = this;
node.props.forEach(function (prop) {
if (prop.vt === "jsonata") {
try {
var val = prop.v ? prop.v : "";
prop.exp = RED.util.prepareJSONataExpression(val, node);
}
catch (err) {
node.error(RED._("inject.errors.invalid-expr", {error:err.message}));
prop.exp = null;
}
}
});
if (node.repeat > 2147483) {
node.error(RED._("inject.errors.toolong", this));
delete node.repeat;
}
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));
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);
}
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) {
this.onceTimeout = setTimeout( function() {
node.emit("input",{});
node.repeaterSetup();
node.emit("input",{});
node.repeaterSetup();
}, this.onceDelay);
} else {
node.repeaterSetup();
node.repeaterSetup();
}
this.on("input",function(msg) {
msg.topic = this.topic;
if (this.payloadType !== 'flow' && this.payloadType !== 'global') {
try {
if ( (this.payloadType == null && this.payload === "") || this.payloadType === "date") {
msg.payload = Date.now();
} else if (this.payloadType == null) {
msg.payload = this.payload;
} else if (this.payloadType === 'none') {
msg.payload = "";
} else {
msg.payload = RED.util.evaluateNodeProperty(this.payload,this.payloadType,this,msg);
}
this.send(msg);
msg = null;
} catch(err) {
this.error(err,msg);
}
} else {
RED.util.evaluateNodeProperty(this.payload,this.payloadType,this,msg, function(err,res) {
if (err) {
node.error(err,msg);
} else {
msg.payload = res;
node.send(msg);
}
this.on("input", function(msg) {
var errors = [];
});
this.props.forEach(p => {
var property = p.p;
var value = p.v ? p.v : '';
var valueType = p.vt ? p.vt : 'str';
if (!property) return;
if (valueType === "jsonata") {
if (p.exp) {
try {
var val = RED.util.evaluateJSONataExpression(p.exp, msg);
RED.util.setMessageProperty(msg, property, val, true);
}
catch (err) {
errors.push(err.message);
}
}
return;
}
try {
RED.util.setMessageProperty(msg,property,RED.util.evaluateNodeProperty(value, valueType, this, msg),true);
} catch (err) {
errors.push(err.toString());
}
});
if (errors.length) {
node.error(errors.join('; '), msg);
} else {
node.send(msg);
}
});
}

View File

@@ -1,30 +1,35 @@
<script type="text/x-red" data-template-name="debug">
<script type="text/html" data-template-name="debug">
<div class="form-row">
<label for="node-input-typed-complete"><i class="fa fa-list"></i> <span data-i18n="debug.output"></span></label>
<input id="node-input-typed-complete" type="text" style="width: 70%">
<input id="node-input-complete" type="hidden">
<input id="node-input-targetType" type="hidden">
</div>
<div class="form-row">
<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>
<input type="checkbox" id="node-input-tosidebar" style="display:inline-block; width:22px; vertical-align:top;"><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>
<input type="checkbox" id="node-input-console" style="display:inline-block; width:22px; vertical-align:top;"><span data-i18n="debug.toConsole"></span>
</label>
</div>
<div class="form-row" id="node-tostatus-line">
<div class="form-row">
<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>
<input type="checkbox" id="node-input-tostatus" style="display:inline-block; width:22px; vertical-align:top;"><span data-i18n="debug.toStatus"></span>
</label>
</div>
<div class="form-row" id="node-tostatus-line">
<label for="node-input-typed-status"><i class="fa fa-ellipsis-h"></i> <span data-i18n="debug.status"></span></label>
<input id="node-input-typed-status" type="text" style="width: 70%">
<input id="node-input-statusVal" type="hidden">
<input id="node-input-statusType" type="hidden">
</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">
@@ -36,6 +41,36 @@
<script type="text/javascript">
(function() {
var subWindow = null;
function activateAjaxCall(node, active, successCallback) {
var url;
var body;
if (Array.isArray(node)) {
url = "debug/"+(active?"enable":"disable");
body = {nodes: node.map(function(n) { return n.id})}
node = node[0];
} else {
url = "debug/"+node.id+"/"+(active?"enable":"disable");
}
$.ajax({
url: url,
type: "POST",
data: body,
success: successCallback,
error: function(jqXHR,textStatus,errorThrown) {
if (jqXHR.status == 404) {
RED.notify(node._("common.notification.error", {message: node._("common.notification.errors.not-deployed")}),"error");
} else if (jqXHR.status === 0) {
RED.notify(node._("common.notification.error", {message: node._("common.notification.errors.no-response")}),"error");
} else {
// TODO where is the err.status comming from?
RED.notify(node._("common.notification.error",{message:node._("common.notification.errors.unexpected",{status:err.status,message:err.response})}),"error");
}
}
});
}
RED.nodes.registerType('debug',{
category: 'common',
defaults: {
@@ -45,7 +80,9 @@
console: {value:false},
tostatus: {value:false},
complete: {value:"false", required:true},
targetType: {value:undefined}
targetType: {value:undefined},
statusVal: {value:""},
statusType: {value:"auto"}
},
label: function() {
var suffix = "";
@@ -73,38 +110,28 @@
onclick: function() {
var label = this.name||"debug";
var node = this;
$.ajax({
url: "debug/"+this.id+"/"+(this.active?"enable":"disable"),
type: "POST",
success: function(resp, textStatus, xhr) {
var historyEvent = {
t:'edit',
node:node,
changes:{
active:!node.active
},
dirty:node.dirty,
changed:node.changed
};
node.changed = true;
node.dirty = true;
RED.nodes.dirty(true);
RED.history.push(historyEvent);
RED.view.redraw();
if (xhr.status == 200) {
RED.notify(node._("debug.notification.activated",{label:label}),"success");
} else if (xhr.status == 201) {
RED.notify(node._("debug.notification.deactivated",{label:label}),"success");
}
},
error: function(jqXHR,textStatus,errorThrown) {
if (jqXHR.status == 404) {
RED.notify(node._("common.notification.error", {message: node._("common.notification.errors.not-deployed")}),"error");
} else if (jqXHR.status === 0) {
RED.notify(node._("common.notification.error", {message: node._("common.notification.errors.no-response")}),"error");
} else {
RED.notify(node._("common.notification.error",{message:node._("common.notification.errors.unexpected",{status:err.status,message:err.response})}),"error");
activateAjaxCall(node, node.active, function(resp, textStatus, xhr) {
var historyEvent = {
t:'edit',
node:node,
changes:{
active:!node.active
},
dirty:node.dirty,
changed:node.changed,
callback: function(ev) {
activateAjaxCall(ev.node, ev.node.active);
}
};
node.changed = true;
node.dirty = true;
RED.nodes.dirty(true);
RED.history.push(historyEvent);
RED.view.redraw();
if (xhr.status == 200) {
RED.notify(node._("debug.notification.activated",{label:label}),"success");
} else if (xhr.status == 201) {
RED.notify(node._("debug.notification.deactivated",{label:label}),"success");
}
});
}
@@ -266,6 +293,78 @@
RED.events.on("project:change", this.clearMessageList);
RED.actions.add("core:clear-debug-messages", function() { RED.debug.clearMessageList(true) });
RED.actions.add("core:activate-selected-debug-nodes", function() { setDebugNodeState(getSelectedDebugNodes(true), true); });
RED.actions.add("core:activate-all-debug-nodes", function() { setDebugNodeState(getMatchingDebugNodes(true, true),true); });
RED.actions.add("core:activate-all-flow-debug-nodes", function() { setDebugNodeState(getMatchingDebugNodes(true, false),true); });
RED.actions.add("core:deactivate-selected-debug-nodes", function() { setDebugNodeState(getSelectedDebugNodes(false), false); });
RED.actions.add("core:deactivate-all-debug-nodes", function() { setDebugNodeState(getMatchingDebugNodes(false, true),false); });
RED.actions.add("core:deactivate-all-flow-debug-nodes", function() { setDebugNodeState(getMatchingDebugNodes(false, false),false); });
function getSelectedDebugNodes(state) {
var nodes = [];
var selection = RED.view.selection();
if (selection.nodes) {
selection.nodes.forEach(function(n) {
if (RED.nodes.subflow(n.z)) {
return;
}
if (n.type === 'debug' && n.active !== state) {
nodes.push(n);
} else if (n.type === 'group') {
nodes = nodes.concat( RED.group.getNodes(n,true).filter(function(n) {
return n.type === 'debug' && n.active !== state
}));
}
});
}
return nodes;
}
function getMatchingDebugNodes(state,globally) {
var nodes = [];
var filter = {type:"debug"};
if (!globally) {
filter.z = RED.workspaces.active();
}
var candidateNodes = RED.nodes.filterNodes(filter);
nodes = candidateNodes.filter(function(n) {
return n.active !== state && !RED.nodes.subflow(n.z)
})
return nodes;
}
function setDebugNodeState(nodes,state) {
var historyEvents = [];
if (nodes.length > 0) {
activateAjaxCall(nodes,false, function(resp, textStatus, xhr) {
nodes.forEach(function(n) {
historyEvents.push({
t: "edit",
node: n,
changed: n.changed,
changes: {
active: n.active
}
});
n.active = state;
n.changed = true;
n.dirty = true;
})
RED.history.push({
t: "multi",
events: historyEvents,
dirty: RED.nodes.dirty(),
callback: function() {
activateAjaxCall(nodes,nodes[0].active);
}
});
RED.nodes.dirty(true);
RED.view.redraw();
});
}
}
$("#red-ui-sidebar-debug-open").on("click", function(e) {
e.preventDefault();
subWindow = window.open(document.location.toString().replace(/[?#].*$/,"")+"debug/view/view.html"+document.location.search,"nodeREDDebugView","menubar=no,location=no,toolbar=no,chrome,height=500,width=600");
@@ -308,10 +407,20 @@
window.removeEventListener("message",this.handleWindowMessage);
RED.actions.remove("core:show-debug-tab");
RED.actions.remove("core:clear-debug-messages");
delete RED._debug;
},
oneditprepare: function() {
var autoType = {
value: "auto",
label: RED._("node-red:debug.autostatus"),
hasValue: false
};
$("#node-input-typed-status").typedInput({
default: "auto",
types:[autoType, "msg", "jsonata"],
typeField: $("#node-input-statusType")
});
var that = this;
var none = {
value: "none",
label: RED._("node-red:debug.none"),
@@ -321,6 +430,14 @@
this.tosidebar = true;
$("#node-input-tosidebar").prop('checked', true);
}
if (this.statusVal === undefined) {
this.statusVal = (this.complete === "false") ? "payload" : ((this.complete === "true") ? "payload" : this.complete+"");
$("#node-input-typed-status").typedInput('value',this.statusVal || "");
}
if (this.statusType === undefined) {
this.statusType = this.targetType;
$("#node-input-typed-status").typedInput('type',this.statusType || "auto");
}
if (typeof this.console === "string") {
this.console = (this.console == 'true');
$("#node-input-console").prop('checked', this.console);
@@ -331,6 +448,7 @@
label: RED._("node-red:debug.msgobj"),
hasValue: false
};
$("#node-input-typed-complete").typedInput({
default: "msg",
types:['msg', fullType, "jsonata"],
@@ -354,17 +472,29 @@
) {
$("#node-input-typed-complete").typedInput('value','payload');
}
if ($("#node-input-typed-complete").typedInput('type') === 'full') {
$("#node-tostatus-line").hide();
} else {
});
$("#node-input-tostatus").on('change',function() {
if ($(this).is(":checked")) {
if (!that.hasOwnProperty("statusVal") || that.statusVal === "") {
var type = $("#node-input-typed-complete").typedInput('type');
var comp = "payload";
if (type !== 'full') {
comp = $("#node-input-typed-complete").typedInput('value');
}
that.statusType = "auto";
that.statusVal = comp;
}
$("#node-input-typed-status").typedInput('type',that.statusType);
$("#node-input-typed-status").typedInput('value',that.statusVal);
$("#node-tostatus-line").show();
}
});
$("#node-input-complete").on('change',function() {
if ($("#node-input-typed-complete").typedInput('type') === 'full') {
else {
$("#node-tostatus-line").hide();
} else {
$("#node-tostatus-line").show();
that.statusType = "auto";
that.statusVal = "";
$("#node-input-typed-status").typedInput('type',that.statusType);
$("#node-input-typed-status").typedInput('value',that.statusVal);
}
});
},
@@ -375,6 +505,7 @@
} else {
$("#node-input-complete").val($("#node-input-typed-complete").typedInput('value'));
}
$("#node-input-statusVal").val($("#node-input-typed-status").typedInput('value'));
}
});
})();

View File

@@ -2,7 +2,7 @@ module.exports = function(RED) {
"use strict";
var util = require("util");
var events = require("events");
var path = require("path");
//var path = require("path");
var debuglength = RED.settings.debugMaxLength || 1000;
var useColors = RED.settings.debugUseColors || false;
util.inspect.styles.boolean = "red";
@@ -15,36 +15,20 @@ module.exports = function(RED) {
this.complete = hasEditExpression ? null : (n.complete||"payload").toString();
if (this.complete === "false") { this.complete = "payload"; }
this.console = ""+(n.console || false);
this.tostatus = (this.complete !== "true") && (n.tostatus || false);
this.tostatus = n.tostatus || false;
this.statusType = n.statusType || "auto";
this.statusVal = n.statusVal || this.complete;
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;
if (this.tostatus) { this.status({fill:"grey", shape:"ring"}); }
else { this.status({}); }
var hasStatExpression = (n.statusType === "jsonata");
var statExpression = hasStatExpression ? n.statusVal : null;
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"
};
var preparedEditExpression = null;
var preparedStatExpression = null;
if (editExpression) {
try {
preparedEditExpression = RED.util.prepareJSONataExpression(editExpression, this);
@@ -54,16 +38,22 @@ module.exports = function(RED) {
return;
}
}
if (statExpression) {
try {
preparedStatExpression = RED.util.prepareJSONataExpression(statExpression, this);
}
catch (e) {
node.error(RED._("debug.invalid-exp", {error: editExpression}));
return;
}
}
function prepareValue(msg, done) {
// Either apply the jsonata expression or...
if (preparedEditExpression) {
RED.util.evaluateJSONataExpression(preparedEditExpression, msg, (err, value) => {
if (err) {
done(RED._("debug.invalid-exp", {error: editExpression}));
} else {
done(null,{id:node.id, z:node.z, _alias: node._alias, path:node._flow.path, name:node.name, topic:msg.topic, msg:value});
}
if (err) { done(RED._("debug.invalid-exp", {error: editExpression})); }
else { done(null,{id:node.id, z:node.z, _alias: node._alias, path:node._flow.path, name:node.name, topic:msg.topic, msg:value}); }
});
} else {
// Extract the required message property
@@ -71,17 +61,67 @@ module.exports = function(RED) {
var output = msg[property];
if (node.complete !== "false" && typeof node.complete !== "undefined") {
property = node.complete;
try {
output = RED.util.getMessageProperty(msg,node.complete);
} catch(err) {
output = undefined;
}
try { output = RED.util.getMessageProperty(msg,node.complete); }
catch(err) { output = undefined; }
}
done(null,{id:node.id, z:node.z, _alias: node._alias, path:node._flow.path, name:node.name, topic:msg.topic, property:property, msg:output});
}
}
function prepareStatus(msg, done) {
if (node.statusType === "auto") {
if (node.complete === "true") {
done(null,{msg:msg.payload});
}
else {
prepareValue(msg,function(err,debugMsg) {
if (err) { node.error(err); return; }
done(null,{msg:debugMsg.msg});
});
}
}
else {
// Either apply the jsonata expression or...
if (preparedStatExpression) {
RED.util.evaluateJSONataExpression(preparedStatExpression, msg, (err, value) => {
if (err) { done(RED._("debug.invalid-exp", {error:editExpression})); }
else { done(null,{msg:value}); }
});
}
else {
// Extract the required message property
var output;
try { output = RED.util.getMessageProperty(msg,node.statusVal); }
catch(err) { output = undefined; }
done(null,{msg:output});
}
}
}
this.on("input", function(msg, send, done) {
if (node.tostatus === true) {
prepareStatus(msg, function(err,debugMsg) {
if (err) { node.error(err); return; }
var output = debugMsg.msg;
var st = (typeof output === 'string') ? output : util.inspect(output);
var fill = "grey";
var shape = "dot";
if (node.statusType === "auto") {
if (msg.hasOwnProperty("error")) {
fill = "red";
st = msg.error.message;
}
if (msg.hasOwnProperty("status")) {
if (msg.status.hasOwnProperty("fill")) { fill = msg.status.fill; }
if (msg.status.hasOwnProperty("shape")) { shape = msg.status.shape; }
if (msg.status.hasOwnProperty("text")) { st = msg.status.text; }
}
}
if (st.length > 32) { st = st.substr(0,32) + "..."; }
node.status({fill:fill, shape:shape, text:st});
});
}
if (this.complete === "true") {
// debug complete msg object
if (this.console === "true") {
@@ -91,7 +131,8 @@ module.exports = function(RED) {
sendDebug({id:node.id, z:node.z, _alias: node._alias, path:node._flow.path, name:node.name, topic:msg.topic, msg:msg});
}
done();
} else {
}
else {
prepareValue(msg,function(err,debugMsg) {
if (err) {
node.error(err);
@@ -107,12 +148,6 @@ module.exports = function(RED) {
node.log(util.inspect(output, {colors:useColors}));
}
}
if (node.tostatus === true) {
var st = (typeof output === 'string')?output:util.inspect(output);
var severity = node.severity;
if (st.length > 32) { st = st.substr(0,32) + "..."; }
node.status({fill:colors[severity], shape:"dot", text:st});
}
if (node.active) {
if (node.tosidebar == true) {
sendDebug(debugMsg);
@@ -150,24 +185,49 @@ module.exports = function(RED) {
});
RED.log.addHandler(DebugNode.logHandler);
RED.httpAdmin.post("/debug/:id/:state", RED.auth.needsPermission("debug.write"), function(req,res) {
var node = RED.nodes.getNode(req.params.id);
var state = req.params.state;
if (node !== null && typeof node !== "undefined" ) {
if (state === "enable") {
node.active = true;
res.sendStatus(200);
if (node.tostatus) { node.status({fill:"grey", shape:"dot"}); }
} else if (state === "disable") {
node.active = false;
res.sendStatus(201);
if (node.tostatus && node.hasOwnProperty("oldStatus")) {
node.oldStatus.shape = "dot";
node.status(node.oldStatus);
}
} else {
res.sendStatus(404);
function setNodeState(node,state) {
if (state) {
node.active = true;
if (node.tostatus) { node.status({fill:"grey", shape:"dot"}); }
} else {
node.active = false;
if (node.tostatus && node.hasOwnProperty("oldStatus")) {
node.oldStatus.shape = "dot";
node.status(node.oldStatus);
}
}
}
RED.httpAdmin.post("/debug/:state", RED.auth.needsPermission("debug.write"), function(req,res) {
var state = req.params.state;
if (state !== 'enable' && state !== 'disable') {
res.sendStatus(404);
return;
}
var nodes = req.body && req.body.nodes;
if (Array.isArray(nodes)) {
nodes.forEach(function(id) {
var node = RED.nodes.getNode(id);
if (node !== null && typeof node !== "undefined" ) {
setNodeState(node, state === "enable");
}
})
res.sendStatus(state === "enable" ? 200 : 201);
} else {
res.sendStatus(400);
}
})
RED.httpAdmin.post("/debug/:id/:state", RED.auth.needsPermission("debug.write"), function(req,res) {
var state = req.params.state;
if (state !== 'enable' && state !== 'disable') {
res.sendStatus(404);
return;
}
var node = RED.nodes.getNode(req.params.id);
if (node !== null && typeof node !== "undefined" ) {
setNodeState(node,state === "enable");
res.sendStatus(state === "enable" ? 200 : 201);
} else {
res.sendStatus(404);
}

View File

@@ -1,8 +1,9 @@
<script type="text/x-red" data-template-name="complete">
<script type="text/html" data-template-name="complete">
<div class="form-row node-input-target-row">
<button id="node-input-complete-target-select" class="red-ui-button" data-i18n="common.label.selectNodes"></button>
</div>
<div class="form-row node-input-target-row node-input-target-list-row" style="min-height: 100px">
<div class="form-row node-input-target-row node-input-target-list-row" style="position: relative; min-height: 100px">
<div style="position: absolute; top: -30px; right: 0;"><input type="text" id="node-input-complete-target-filter"></div>
<div id="node-input-complete-target-container-div"></div>
</div>
@@ -45,6 +46,22 @@
var editorRow = $("#dialog-form>div.node-input-target-list-row");
editorRow.css("height",height+"px");
};
var search = $("#node-input-complete-target-filter").searchBox({
style: "compact",
delay: 300,
change: function() {
var val = $(this).val().trim().toLowerCase();
if (val === "") {
dirList.treeList("filter", null);
search.searchBox("count","");
} else {
var count = dirList.treeList("filter", function(item) {
return item.label.toLowerCase().indexOf(val) > -1 || item.node.type.toLowerCase().indexOf(val) > -1
});
search.searchBox("count",count+" / "+candidateNodes.length);
}
}
});
var dirList = $("#node-input-complete-target-container-div").css({width: "100%", height: "100%"})
.treeList({multi:true}).on("treelistitemmouseover", function(e, item) {
@@ -89,7 +106,8 @@
node: n,
label: label,
sublabel: sublabel,
selected: isChecked
selected: isChecked,
checkbox: true
};
items.push(nodeItemMap[n.id]);
});

View File

@@ -1,5 +1,5 @@
<script type="text/x-red" data-template-name="catch">
<script type="text/html" data-template-name="catch">
<div class="form-row">
<label style="width: auto" for="node-input-scope" data-i18n="catch.label.source"></label>
<select id="node-input-scope-select">
@@ -14,7 +14,8 @@
<div class="form-row node-input-target-row">
<button id="node-input-catch-target-select" class="red-ui-button" data-i18n="common.label.selectNodes"></button>
</div>
<div class="form-row node-input-target-row node-input-target-list-row" style="min-height: 100px">
<div class="form-row node-input-target-row node-input-target-list-row" style="position: relative; min-height: 100px">
<div style="position: absolute; top: -30px; right: 0;"><input type="text" id="node-input-catch-target-filter"></div>
<div id="node-input-catch-target-container-div"></div>
</div>
@@ -60,7 +61,22 @@
var editorRow = $("#dialog-form>div.node-input-target-list-row");
editorRow.css("height",height+"px");
};
var search = $("#node-input-catch-target-filter").searchBox({
style: "compact",
delay: 300,
change: function() {
var val = $(this).val().trim().toLowerCase();
if (val === "") {
dirList.treeList("filter", null);
search.searchBox("count","");
} else {
var count = dirList.treeList("filter", function(item) {
return item.label.toLowerCase().indexOf(val) > -1 || item.node.type.toLowerCase().indexOf(val) > -1
});
search.searchBox("count",count+" / "+candidateNodes.length);
}
}
});
var dirList = $("#node-input-catch-target-container-div").css({width: "100%", height: "100%"})
.treeList({multi:true}).on("treelistitemmouseover", function(e, item) {
item.node.highlighted = true;
@@ -104,7 +120,8 @@
node: n,
label: label,
sublabel: sublabel,
selected: isChecked
selected: isChecked,
checkbox: true
};
items.push(nodeItemMap[n.id]);
});

View File

@@ -1,5 +1,5 @@
<script type="text/x-red" data-template-name="status">
<script type="text/html" data-template-name="status">
<div class="form-row">
<label style="width: auto" for="node-input-scope" data-i18n="status.label.source"></label>
<select id="node-input-scope-select">
@@ -10,7 +10,8 @@
<div class="form-row node-input-target-row">
<button id="node-input-status-target-select" class="red-ui-button" data-i18n="common.label.selectNodes"></button>
</div>
<div class="form-row node-input-target-row node-input-target-list-row" style="min-height: 100px">
<div class="form-row node-input-target-row node-input-target-list-row" style="position: relative; min-height: 100px">
<div style="position: absolute; top: -30px; right: 0;"><input type="text" id="node-input-status-target-filter"></div>
<div id="node-input-status-target-container-div"></div>
</div>
<div class="form-row">
@@ -48,6 +49,22 @@
var editorRow = $("#dialog-form>div.node-input-target-list-row");
editorRow.css("height",height+"px");
};
var search = $("#node-input-status-target-filter").searchBox({
style: "compact",
delay: 300,
change: function() {
var val = $(this).val().trim().toLowerCase();
if (val === "") {
dirList.treeList("filter", null);
search.searchBox("count","");
} else {
var count = dirList.treeList("filter", function(item) {
return item.label.toLowerCase().indexOf(val) > -1 || item.node.type.toLowerCase().indexOf(val) > -1
});
search.searchBox("count",count+" / "+candidateNodes.length);
}
}
});
var dirList = $("#node-input-status-target-container-div").css({width: "100%", height: "100%"})
.treeList({multi:true}).on("treelistitemmouseover", function(e, item) {
@@ -92,7 +109,8 @@
node: n,
label: label,
sublabel: sublabel,
selected: isChecked
selected: isChecked,
checkbox: true
};
items.push(nodeItemMap[n.id]);
});

View File

@@ -1,16 +1,18 @@
<script type="text/x-red" data-template-name="link in">
<script type="text/html" data-template-name="link in">
<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">
</div>
<div style="position:relative; height: 30px; text-align: right;"><div style="display:inline-block"><input type="text" id="node-input-link-target-filter"></div></div>
<div class="form-row node-input-link-row"></div>
</script>
<script type="text/x-red" data-template-name="link out">
<script type="text/html" data-template-name="link out">
<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">
</div>
<div style="position:relative; height: 30px; text-align: right;"><div style="display:inline-block"><input type="text" id="node-input-link-target-filter"></div></div>
<div class="form-row node-input-link-row"></div>
</script>
@@ -47,6 +49,24 @@
});
var candidateNodes = RED.nodes.filterNodes({type:targetType});
var search = $("#node-input-link-target-filter").searchBox({
style: "compact",
delay: 300,
change: function() {
var val = $(this).val().trim().toLowerCase();
if (val === "") {
treeList.treeList("filter", null);
search.searchBox("count","");
} else {
var count = treeList.treeList("filter", function(item) {
return item.label.toLowerCase().indexOf(val) > -1 || (item.node && item.node.type.toLowerCase().indexOf(val) > -1)
});
search.searchBox("count",count+" / "+candidateNodes.length);
}
}
});
var flows = [];
var flowMap = {};
@@ -83,7 +103,8 @@
id: n.id,
node: n,
label: n.name||n.id,
selected: isChecked
selected: isChecked,
checkbox: true
})
}
});

View File

@@ -1,5 +1,5 @@
<script type="text/x-red" data-template-name="comment">
<script type="text/html" data-template-name="comment">
<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">

View File

@@ -1,5 +1,5 @@
<script type="text/x-red" data-template-name="unknown">
<script type="text/html" data-template-name="unknown">
<div class="form-tips"><span data-i18n="[html]unknown.tip"></span></div>
</script>

View File

@@ -1,22 +1,57 @@
<script type="text/x-red" data-template-name="function">
<script type="text/html" data-template-name="function">
<div class="form-row">
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
<div style="display: inline-block; width: calc(100% - 105px)"><input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name"></div>
</div>
<div class="form-row" style="margin-bottom: 0px;">
<label for="node-input-func"><i class="fa fa-wrench"></i> <span data-i18n="function.label.function"></span></label>
<input type="hidden" id="node-input-func" autofocus="autofocus">
<input type="hidden" id="node-input-noerr">
<div class="form-row">
<ul style="min-width: 600px; margin-bottom: 20px;" id="func-tabs"></ul>
</div>
<div class="form-row node-text-editor-row" style="position:relative">
<div style="position: absolute; right:0; bottom:calc(100% + 3px);"><button id="node-function-expand-js" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button></div>
<div style="height: 250px; min-height:150px;" class="node-text-editor" id="node-input-func-editor" ></div>
</div>
<div class="form-row" style="margin-bottom: 0px">
<label for="node-input-outputs"><i class="fa fa-random"></i> <span data-i18n="function.label.outputs"></span></label>
<input id="node-input-outputs" style="width: 60px;" value="1">
<div id="func-tabs-content" style="min-height: calc(100% - 95px);">
<div id="func-tab-init" style="display:none">
<div class="form-row" style="margin-bottom: 0px;">
<input type="hidden" id="node-input-initialize" autofocus="autofocus">
</div>
<div class="form-row node-text-editor-row" style="position:relative">
<div style="position: absolute; right:0; bottom: calc(100% + 3px);"><button id="node-init-expand-js" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button></div>
<div style="height: 250px; min-height:150px; margin-top: 30px;" class="node-text-editor" id="node-input-init-editor" ></div>
</div>
</div>
<div id="func-tab-body" style="display:none">
<div class="form-row" style="margin-bottom: 0px;">
<input type="hidden" id="node-input-func" autofocus="autofocus">
<input type="hidden" id="node-input-noerr">
</div>
<div class="form-row node-text-editor-row" style="position:relative">
<div style="position: absolute; right:0; bottom: calc(100% + 3px);"><button id="node-function-expand-js" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button></div>
<div style="height: 220px; min-height:120px; margin-top: 30px;" class="node-text-editor" id="node-input-func-editor" ></div>
</div>
<div class="form-row" style="margin-bottom: 0px">
<label for="node-input-outputs"><i class="fa fa-random"></i> <span data-i18n="function.label.outputs"></span></label>
<input id="node-input-outputs" style="width: 60px;" value="1">
</div>
</div>
<div id="func-tab-finalize" style="display:none">
<div class="form-row" style="margin-bottom: 0px;">
<input type="hidden" id="node-input-finalize" autofocus="autofocus">
</div>
<div class="form-row node-text-editor-row" style="position:relative">
<div style="position: absolute; right:0; bottom: calc(100% + 3px);"><button id="node-finalize-expand-js" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button></div>
<div style="height: 250px; min-height:150px; margin-top: 30px;" class="node-text-editor" id="node-input-finalize-editor" ></div>
</div>
</div>
</div>
</script>
<script type="text/javascript">
@@ -27,7 +62,9 @@
name: {value:""},
func: {value:"\nreturn msg;"},
outputs: {value:1},
noerr: {value:0,required:true,validate:function(v) { return !v; }}
noerr: {value:0,required:true,validate:function(v) { return !v; }},
initialize: {value:""},
finalize: {value:""}
},
inputs:1,
outputs:1,
@@ -40,6 +77,28 @@
},
oneditprepare: function() {
var that = this;
var tabs = RED.tabs.create({
id: "func-tabs",
onchange: function(tab) {
$("#func-tabs-content").children().hide();
$("#" + tab.id).show();
}
});
tabs.addTab({
id: "func-tab-init",
label: that._("function.label.initialize")
});
tabs.addTab({
id: "func-tab-body",
label: that._("function.label.function")
});
tabs.addTab({
id: "func-tab-finalize",
label: that._("function.label.finalize")
});
tabs.activateTab("func-tab-body");
$( "#node-input-outputs" ).spinner({
min:0,
change: function(event, ui) {
@@ -50,74 +109,147 @@
}
});
this.editor = RED.editor.createEditor({
id: 'node-input-func-editor',
mode: 'ace/mode/nrjavascript',
value: $("#node-input-func").val(),
globals: {
msg:true,
context:true,
RED: true,
util: true,
flow: true,
global: true,
console: true,
Buffer: true,
setTimeout: true,
clearTimeout: true,
setInterval: true,
clearInterval: true
var buildEditor = function(id, value, defaultValue) {
var editor = RED.editor.createEditor({
id: id,
mode: 'ace/mode/nrjavascript',
value: value || defaultValue || "",
globals: {
msg:true,
context:true,
RED: true,
util: true,
flow: true,
global: true,
console: true,
Buffer: true,
setTimeout: true,
clearTimeout: true,
setInterval: true,
clearInterval: true
}
});
if (defaultValue && value === "") {
editor.moveCursorTo(defaultValue.split("\n").length - 1, 0);
}
});
return editor;
}
this.initEditor = buildEditor('node-input-init-editor',$("#node-input-initialize").val(),RED._("node-red:function.text.initialize"))
this.editor = buildEditor('node-input-func-editor',$("#node-input-func").val())
this.finalizeEditor = buildEditor('node-input-finalize-editor',$("#node-input-finalize").val(),RED._("node-red:function.text.finalize"))
RED.library.create({
url:"functions", // where to get the data from
type:"function", // the type of object the library is for
editor:this.editor, // the field name the main text body goes to
mode:"ace/mode/nrjavascript",
fields:['name','outputs'],
fields:[
'name', 'outputs',
{
name: 'initialize',
get: function() {
return that.initEditor.getValue();
},
set: function(v) {
that.initEditor.setValue(v||RED._("node-red:function.text.initialize"), -1);
}
},
{
name: 'finalize',
get: function() {
return that.finalizeEditor.getValue();
},
set: function(v) {
that.finalizeEditor.setValue(v||RED._("node-red:function.text.finalize"), -1);
}
},
{
name: 'info',
get: function() {
return that.infoEditor.getValue();
},
set: function(v) {
that.infoEditor.setValue(v||"", -1);
}
}
],
ext:"js"
});
this.editor.focus();
RED.popover.tooltip($("#node-function-expand-js"), RED._("node-red:common.label.expand"));
$("#node-function-expand-js").on("click", function(e) {
e.preventDefault();
var value = that.editor.getValue();
RED.editor.editJavaScript({
value: value,
width: "Infinity",
cursor: that.editor.getCursorPosition(),
mode: "ace/mode/nrjavascript",
complete: function(v,cursor) {
that.editor.setValue(v, -1);
that.editor.gotoLine(cursor.row+1,cursor.column,false);
setTimeout(function() {
that.editor.focus();
},300);
}
})
})
},
oneditsave: function() {
var annot = this.editor.getSession().getAnnotations();
this.noerr = 0;
$("#node-input-noerr").val(0);
for (var k=0; k < annot.length; k++) {
//console.log(annot[k].type,":",annot[k].text, "on line", annot[k].row);
if (annot[k].type === "error") {
$("#node-input-noerr").val(annot.length);
this.noerr = annot.length;
var expandButtonClickHandler = function(editor) {
return function(e) {
e.preventDefault();
var value = editor.getValue();
RED.editor.editJavaScript({
value: value,
width: "Infinity",
cursor: editor.getCursorPosition(),
mode: "ace/mode/nrjavascript",
complete: function(v,cursor) {
editor.setValue(v, -1);
editor.gotoLine(cursor.row+1,cursor.column,false);
setTimeout(function() {
editor.focus();
},300);
}
})
}
}
$("#node-input-func").val(this.editor.getValue());
this.editor.destroy();
delete this.editor;
$("#node-init-expand-js").on("click", expandButtonClickHandler(this.initEditor));
$("#node-function-expand-js").on("click", expandButtonClickHandler(this.editor));
$("#node-finalize-expand-js").on("click", expandButtonClickHandler(this.finalizeEditor));
RED.popover.tooltip($("#node-init-expand-js"), RED._("node-red:common.label.expand"));
RED.popover.tooltip($("#node-function-expand-js"), RED._("node-red:common.label.expand"));
RED.popover.tooltip($("#node-finalize-expand-js"), RED._("node-red:common.label.expand"));
},
oneditsave: function() {
var node = this;
var noerr = 0;
$("#node-input-noerr").val(0);
var disposeEditor = function(editorName,targetName,defaultValue) {
var editor = node[editorName];
var annot = editor.getSession().getAnnotations();
for (var k=0; k < annot.length; k++) {
if (annot[k].type === "error") {
noerr += annot.length;
break;
}
}
var val = editor.getValue();
if (defaultValue) {
if (val.trim() == defaultValue.trim()) {
val = "";
}
}
editor.destroy();
delete node[editorName];
$("#"+targetName).val(val);
}
disposeEditor("editor","node-input-func");
disposeEditor("initEditor","node-input-initialize", RED._("node-red:function.text.initialize"));
disposeEditor("finalizeEditor","node-input-finalize", RED._("node-red:function.text.finalize"));
$("#node-input-noerr").val(noerr);
this.noerr = noerr;
},
oneditcancel: function() {
this.editor.destroy();
delete this.editor;
var node = this;
node.editor.destroy();
delete node.editor;
node.initEditor.destroy();
delete node.initEditor;
node.finalizeEditor.destroy();
delete node.finalizeEditor;
},
oneditresize: function(size) {
var rows = $("#dialog-form>div:not(.node-text-editor-row)");
@@ -129,6 +261,16 @@
height -= (parseInt(editorRow.css("marginTop"))+parseInt(editorRow.css("marginBottom")));
$(".node-text-editor").css("height",height+"px");
this.editor.resize();
var height = size.height;
$("#node-input-init-editor").css("height", (height -105)+"px");
$("#node-input-func-editor").css("height", (height -145)+"px");
$("#node-input-finalize-editor").css("height", (height -105)+"px");
this.initEditor.resize();
this.editor.resize();
this.finalizeEditor.resize();
}
});
</script>

View File

@@ -57,22 +57,55 @@ module.exports = function(RED) {
}
}
function createVMOpt(node, kind) {
var opt = {
filename: 'Function node'+kind+':'+node.id+(node.name?' ['+node.name+']':''), // filename for stack traces
displayErrors: true
// Using the following options causes node 4/6 to not include the line number
// in the stack output. So don't use them.
// lineOffset: -11, // line number offset to be used for stack traces
// columnOffset: 0, // column number offset to be used for stack traces
};
return opt;
}
function updateErrorInfo(err) {
if (err.stack) {
var stack = err.stack.toString();
var m = /^([^:]+):([^:]+):(\d+).*/.exec(stack);
if (m) {
var line = parseInt(m[3]) -1;
var kind = "body:";
if (/setup/.exec(m[1])) {
kind = "setup:";
}
if (/cleanup/.exec(m[1])) {
kind = "cleanup:";
}
err.message += " ("+kind+"line "+line+")";
}
}
}
function FunctionNode(n) {
RED.nodes.createNode(this,n);
var node = this;
this.name = n.name;
this.func = n.func;
node.name = n.name;
node.func = n.func;
node.ini = n.initialize ? n.initialize.trim() : "";
node.fin = n.finalize ? n.finalize.trim() : "";
var handleNodeDoneCall = true;
// Check to see if the Function appears to call `node.done()`. If so,
// we will assume it is well written and does actually call node.done().
// Otherwise, we will call node.done() after the function returns regardless.
if (/node\.done\s*\(\s*\)/.test(this.func)) {
if (/node\.done\s*\(\s*\)/.test(node.func)) {
handleNodeDoneCall = false;
}
var functionText = "var results = null;"+
"results = (function(msg,__send__,__done__){ "+
"results = (async function(msg,__send__,__done__){ "+
"var __msgid__ = msg._msgid;"+
"var node = {"+
"id:__node__.id,"+
@@ -87,11 +120,13 @@ module.exports = function(RED) {
"send:function(msgs,cloneMsg){ __node__.send(__send__,__msgid__,msgs,cloneMsg);},"+
"done:__done__"+
"};\n"+
this.func+"\n"+
node.func+"\n"+
"})(msg,send,done);";
this.topic = n.topic;
this.outstandingTimers = [];
this.outstandingIntervals = [];
var finScript = null;
var finOpt = null;
node.topic = n.topic;
node.outstandingTimers = [];
node.outstandingIntervals = [];
var sandbox = {
console:console,
util:util,
@@ -182,12 +217,12 @@ module.exports = function(RED) {
arguments[0] = function() {
sandbox.clearTimeout(timerId);
try {
func.apply(this,arguments);
func.apply(node,arguments);
} catch(err) {
node.error(err,{});
}
};
timerId = setTimeout.apply(this,arguments);
timerId = setTimeout.apply(node,arguments);
node.outstandingTimers.push(timerId);
return timerId;
},
@@ -203,12 +238,12 @@ module.exports = function(RED) {
var timerId;
arguments[0] = function() {
try {
func.apply(this,arguments);
func.apply(node,arguments);
} catch(err) {
node.error(err,{});
}
};
timerId = setInterval.apply(this,arguments);
timerId = setInterval.apply(node,arguments);
node.outstandingIntervals.push(timerId);
return timerId;
},
@@ -226,37 +261,48 @@ module.exports = function(RED) {
sandbox.setTimeout(function(){ resolve(value); }, after);
});
};
sandbox.promisify = util.promisify;
}
var context = vm.createContext(sandbox);
try {
this.script = vm.createScript(functionText, {
filename: 'Function node:'+this.id+(this.name?' ['+this.name+']':''), // filename for stack traces
displayErrors: true
// Using the following options causes node 4/6 to not include the line number
// in the stack output. So don't use them.
// lineOffset: -11, // line number offset to be used for stack traces
// columnOffset: 0, // column number offset to be used for stack traces
});
this.on("input", function(msg,send,done) {
try {
var start = process.hrtime();
context.msg = msg;
context.send = send;
context.done = done;
var iniScript = null;
var iniOpt = null;
if (node.ini && (node.ini !== "")) {
var iniText = "(async function () {\n"+node.ini +"\n})();";
iniOpt = createVMOpt(node, " setup");
iniScript = new vm.Script(iniText, iniOpt);
}
node.script = vm.createScript(functionText, createVMOpt(node, ""));
if (node.fin && (node.fin !== "")) {
var finText = "(function () {\n"+node.fin +"\n})();";
finOpt = createVMOpt(node, " cleanup");
finScript = new vm.Script(finText, finOpt);
}
var promise = Promise.resolve();
if (iniScript) {
promise = iniScript.runInContext(context, iniOpt);
}
this.script.runInContext(context);
sendResults(this,send,msg._msgid,context.results,false);
function processMessage(msg, send, done) {
var start = process.hrtime();
context.msg = msg;
context.send = send;
context.done = done;
node.script.runInContext(context);
context.results.then(function(results) {
sendResults(node,send,msg._msgid,results,false);
if (handleNodeDoneCall) {
done();
}
var duration = process.hrtime(start);
var converted = Math.floor((duration[0] * 1e9 + duration[1])/10000)/100;
this.metric("duration", msg, converted);
node.metric("duration", msg, converted);
if (process.env.NODE_RED_FUNCTION_TIME) {
this.status({fill:"yellow",shape:"dot",text:""+converted});
node.status({fill:"yellow",shape:"dot",text:""+converted});
}
} catch(err) {
}).catch(err => {
if ((typeof err === "object") && err.hasOwnProperty("stack")) {
//remove unwanted part
var index = err.stack.search(/\n\s*at ContextifyScript.Script.runInContext/);
@@ -294,23 +340,67 @@ module.exports = function(RED) {
else {
done(JSON.stringify(err));
}
});
}
const RESOLVING = 0;
const RESOLVED = 1;
const ERROR = 2;
var state = RESOLVING;
var messages = [];
node.on("input", function(msg,send,done) {
if(state === RESOLVING) {
messages.push({msg:msg, send:send, done:done});
}
else if(state === RESOLVED) {
processMessage(msg, send, done);
}
});
this.on("close", function() {
node.on("close", function() {
if (finScript) {
try {
finScript.runInContext(context, finOpt);
}
catch (err) {
node.error(err);
}
}
while (node.outstandingTimers.length > 0) {
clearTimeout(node.outstandingTimers.pop());
}
while (node.outstandingIntervals.length > 0) {
clearInterval(node.outstandingIntervals.pop());
}
this.status({});
node.status({});
});
} catch(err) {
promise.then(function (v) {
var msgs = messages;
messages = [];
while (msgs.length > 0) {
msgs.forEach(function (s) {
processMessage(s.msg, s.send, s.done);
});
msgs = messages;
messages = [];
}
state = RESOLVED;
}).catch((error) => {
messages = [];
state = ERROR;
node.error(error);
});
}
catch(err) {
// eg SyntaxError - which v8 doesn't include line number information
// so we can't do better than this
this.error(err);
updateErrorInfo(err);
node.error(err);
}
}
RED.nodes.registerType("function",FunctionNode);
RED.library.register("functions");
};

View File

@@ -253,7 +253,7 @@ module.exports = function(RED) {
for (var i=0; i<this.rules.length; i+=1) {
var rule = this.rules[i];
needsCount = needsCount || ((rule.t === "tail") || (rule.t === "jsonata_exp"));
needsCount = needsCount || ((rule.t === "tail"));
if (!rule.vt) {
if (!isNaN(Number(rule.v))) {
rule.vt = 'num';

View File

@@ -215,7 +215,9 @@ module.exports = function(RED) {
if (rule.t === 'delete') {
RED.util.setMessageProperty(msg,property,undefined);
} else if (rule.t === 'set') {
RED.util.setMessageProperty(msg,property,value);
if (!RED.util.setMessageProperty(msg,property,value)) {
node.warn(RED._("change.errors.no-override",{property:property}));
}
} else if (rule.t === 'change') {
current = RED.util.getMessageProperty(msg,property);
if (typeof current === 'string') {

View File

@@ -1,5 +1,5 @@
<script type="text/x-red" data-template-name="range">
<script type="text/html" data-template-name="range">
<div class="form-row">
<label for="node-input-property"><i class="fa fa-ellipsis-h"></i> <span data-i18n="common.label.property"></span></label>
<input type="text" id="node-input-property" style="width:calc(70% - 1px)"/>

View File

@@ -1,5 +1,5 @@
<script type="text/x-red" data-template-name="template">
<script type="text/html" data-template-name="template">
<div class="form-row">
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
<div style="display: inline-block; width: calc(100% - 105px)"><input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name"></div>

View File

@@ -14,7 +14,7 @@
limitations under the License.
-->
<script type="text/x-red" data-template-name="delay">
<script type="text/html" data-template-name="delay">
<div class="form-row">
<label for="node-input-delay-action"><i class="fa fa-tasks"></i> <span data-i18n="delay.action"></span></label>
<select id="node-input-delay-action" style="width:270px !important">

View File

@@ -158,6 +158,7 @@ module.exports = function(RED) {
clearInterval(node.intervalID);
node.intervalID = -1;
}
delete node.lastSent;
node.buffer = [];
node.status({text:"reset"});
return;

View File

@@ -47,6 +47,10 @@
<input type="hidden" id="node-input-op2type">
<input style="width:70%" type="text" id="node-input-op2" placeholder="0">
</div>
<div class="form-row" id="node-second-output">
<label></label>
<input type="checkbox" id="node-input-second" style="margin-left: 0px; vertical-align: top; width: auto !important;"> <label style="width:auto !important;" for="node-input-second" data-i18n="trigger.second"></label>
</div>
<div class="form-row">
<label data-i18n="trigger.label.reset" style="width:auto"></label>
<div style="display:inline-block; width:70%;vertical-align:top">
@@ -58,14 +62,18 @@
<br/>
<div class="form-row">
<label data-i18n="trigger.for" for="node-input-bytopic"></label>
<select id="node-input-bytopic">
<select id="node-input-bytopic" style="width:120px;">
<option value="all" data-i18n="trigger.alltopics"></option>
<option value="topic" data-i18n="trigger.bytopics"></option>
</select>
<span class="form-row" id="node-stream-topic">
<input type="text" id="node-input-topic" style="width:46%;"/>
</span>
</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>
<input type="hidden" id="node-input-outputs" value="1">
</div>
</script>
@@ -74,6 +82,7 @@
category: 'function',
color:"#E6E0F8",
defaults: {
name: {value:""},
op1: {value:"1", validate: RED.validators.typedInput("op1type")},
op2: {value:"0", validate: RED.validators.typedInput("op2type")},
op1type: {value:"val"},
@@ -82,8 +91,9 @@
extend: {value:"false"},
units: {value:"ms"},
reset: {value:""},
bytopic: {value: "all"},
name: {value:""}
bytopic: {value:"all"},
topic: {value:"topic",required:true},
outputs: {value:1}
},
inputs:1,
outputs:1,
@@ -103,19 +113,48 @@
return this.name?"node_label_italic":"";
},
oneditprepare: function() {
var that = this;
if (this.topic === undefined) { $("#node-input-topic").val("topic"); }
$("#node-input-topic").typedInput({default:'msg',types:['msg']});
$("#node-input-bytopic").on("change", function() {
if ($("#node-input-bytopic").val() === "all") {
$("#node-stream-topic").hide();
} else {
$("#node-stream-topic").show();
}
});
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);
}
else {
$("#node-input-outputs").val(1);
}
});
$("#node-then-type").on("change", function() {
if ($(this).val() == "block") {
$(".node-type-wait").hide();
$(".node-type-duration").hide();
$("#node-second-output").hide();
$("#node-input-second").prop('checked', false);
$("#node-input-outputs").val(1);
}
else if ($(this).val() == "loop") {
if ($("#node-input-duration").val() == 0) { $("#node-input-duration").val(250); }
$(".node-type-wait").hide();
$(".node-type-duration").show();
$("#node-second-output").hide();
$("#node-input-second").prop('checked', false);
$("#node-input-outputs").val(1);
} else {
if ($("#node-input-duration").val() == 0) { $("#node-input-duration").val(250); }
$(".node-type-wait").show();
$(".node-type-duration").show();
$("#node-second-output").show();
}
});
@@ -177,7 +216,7 @@
}
if ($("#node-then-type").val() == "loop") {
$("#node-input-duration").val($("#node-input-duration").val() * -1);
}
}
}
});
</script>

View File

@@ -24,6 +24,8 @@ module.exports = function(RED) {
this.op2 = n.op2 || "0";
this.op1type = n.op1type || "str";
this.op2type = n.op2type || "str";
this.second = (n.outputs == 2) ? true : false;
this.topic = n.topic || "topic";
if (this.op1type === 'val') {
if (this.op1 === 'true' || this.op1 === 'false') {
@@ -111,8 +113,15 @@ module.exports = function(RED) {
processMessageQueue(msg);
});
var stat = function() {
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};
}
var processMessage = function(msg) {
var topic = msg.topic || "_none";
var topic = RED.util.getMessageProperty(msg,node.topic) || "_none";
var promise;
if (node.bytopic === "all") { topic = "_none"; }
node.topics[topic] = node.topics[topic] || {};
@@ -120,7 +129,7 @@ module.exports = function(RED) {
if (node.loop === true) { clearInterval(node.topics[topic].tout); }
else { clearTimeout(node.topics[topic].tout); }
delete node.topics[topic];
node.status({});
node.status(stat());
}
else {
if (node.op2type === "payl") { npay[topic] = RED.util.cloneMessage(msg); }
@@ -189,27 +198,29 @@ module.exports = function(RED) {
}
promise.then(() => {
if (node.op2type === "payl") {
node.send(npay[topic]);
if (node.second === true) { node.send([null,npay[topic]]); }
else { node.send(npay[topic]); }
delete npay[topic];
}
else {
else {
msg2.payload = node.topics[topic].m2;
node.send(msg2);
if (node.second === true) { node.send([null,msg2]); }
else { node.send(msg2); }
}
delete node.topics[topic];
node.status({});
node.status(stat());
}).catch(err => {
node.error(err);
});
} else {
delete node.topics[topic];
node.status({});
node.status(stat());
}
}, node.duration);
}
}
node.status({fill:"blue",shape:"dot",text:" "});
node.status(stat());
if (node.op1type !== "nul") { node.send(RED.util.cloneMessage(msg)); }
});
});
@@ -245,13 +256,17 @@ module.exports = function(RED) {
}
}
delete node.topics[topic];
node.status({});
node.send(msg2);
node.status(stat());
if (node.second === true) { node.send([null,msg2]); }
else { node.send(msg2); }
}).catch(err => {
node.error(err);
});
}, node.duration);
}
// else {
// if (node.op2type === "payl") {node.topics[topic].m2 = RED.util.cloneMessage(msg.payload); }
// }
}
return Promise.resolve();
}
@@ -264,7 +279,7 @@ module.exports = function(RED) {
delete node.topics[t];
}
}
node.status({});
node.status(stat());
});
}
RED.nodes.registerType("trigger",TriggerNode);

View File

@@ -14,7 +14,7 @@
limitations under the License.
-->
<script type="text/x-red" data-template-name="exec">
<script type="text/html" data-template-name="exec">
<div class="form-row">
<label for="node-input-command"><i class="fa fa-file"></i> <span data-i18n="exec.label.command"></span></label>
<input type="text" id="node-input-command" data-i18n="[placeholder]exec.label.command">
@@ -70,7 +70,7 @@
},
icon: "cog.svg",
label: function() {
return this.name||this.command||(this.useSpawn=="true"?this._("exec.spawn"):this._("exec.exec"));
return this.name||this.command.replace(/\\n /g,"\\\\n ")||(this.useSpawn=="true"?this._("exec.spawn"):this._("exec.exec"));
},
labelStyle: function() {
return this.name?"node_label_italic":"";

View File

@@ -14,7 +14,7 @@
limitations under the License.
-->
<script type="text/x-red" data-template-name="tls-config">
<script type="text/html" data-template-name="tls-config">
<div class="form-row" class="hide" id="node-config-row-uselocalfiles">
<input type="checkbox" id="node-config-input-uselocalfiles" style="display: inline-block; width: auto; vertical-align: top;">
<label for="node-config-input-uselocalfiles" style="width: 70%;"><span data-i18n="tls.label.use-local-files"></label>

View File

@@ -14,7 +14,7 @@
limitations under the License.
-->
<script type="text/x-red" data-template-name="http proxy">
<script type="text/html" data-template-name="http proxy">
<div class="form-row">
<label for="node-config-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
<input type="text" id="node-config-input-name">

View File

@@ -11,7 +11,7 @@
limitations under the License.
-->
<script type="text/x-red" data-template-name="mqtt in">
<script type="text/html" data-template-name="mqtt in">
<div class="form-row">
<label for="node-input-broker"><i class="fa fa-globe"></i> <span data-i18n="mqtt.label.broker"></span></label>
<input type="text" id="node-input-broker">
@@ -75,7 +75,7 @@
});
</script>
<script type="text/x-red" data-template-name="mqtt out">
<script type="text/html" data-template-name="mqtt out">
<div class="form-row">
<label for="node-input-broker"><i class="fa fa-globe"></i> <span data-i18n="mqtt.label.broker"></span></label>
<input type="text" id="node-input-broker">
@@ -303,7 +303,7 @@
return this.name;
}
var b = this.broker;
if (b === "") { b = "undefined"; }
if (!b) { b = "undefined"; }
var lab = "";
lab = (this.clientid?this.clientid+"@":"")+b;
if (b.indexOf("://") === -1){

View File

@@ -14,7 +14,7 @@
limitations under the License.
-->
<script type="text/x-red" data-template-name="http in">
<script type="text/html" data-template-name="http in">
<div class="form-row">
<label for="node-input-method"><i class="fa fa-tasks"></i> <span data-i18n="httpin.label.method"></span></label>
<select type="text" id="node-input-method" style="width:70%;">
@@ -45,7 +45,7 @@
<div id="node-input-tip" class="form-tips"><span data-i18n="httpin.tip.in"></span><code><span id="node-input-path"></span></code>.</div>
</script>
<script type="text/x-red" data-template-name="http response">
<script type="text/html" data-template-name="http response">
<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">

View File

@@ -14,7 +14,7 @@
limitations under the License.
-->
<script type="text/x-red" data-template-name="http request">
<script type="text/html" data-template-name="http request">
<div class="form-row">
<label for="node-input-method"><i class="fa fa-tasks"></i> <span data-i18n="httpin.label.method"></span></label>
<select type="text" id="node-input-method" style="width:70%;">
@@ -33,8 +33,12 @@
</div>
<div class="form-row node-input-paytoqs-row">
<input type="checkbox" id="node-input-paytoqs" style="display: inline-block; width: auto; vertical-align: top;">
<label for="node-input-paytoqs" style="width: auto" data-i18n="httpin.label.paytoqs"></label>
<label for="node-input-paytoqs"><span data-i18n="common.label.payload"></span></label>
<select id="node-input-paytoqs" style="width: 70%;">
<option value="ignore" data-i18n="httpin.label.paytoqs.ignore"></option>
<option value="query" data-i18n="httpin.label.paytoqs.query"></option>
<option value="body" data-i18n="httpin.label.paytoqs.body"></option>
</select>
</div>
<div class="form-row">
@@ -168,6 +172,13 @@
$(".node-input-paytoqs-row").hide();
}
});
if (this.paytoqs === true || this.paytoqs == "query") {
$("#node-input-paytoqs").val("query");
} else if (this.paytoqs === "body") {
$("#node-input-paytoqs").val("body");
} else {
$("#node-input-paytoqs").val("ignore");
}
if (this.authType) {
$('#node-input-useAuth').prop('checked', true);
$("#node-input-authType-select").val(this.authType);

View File

@@ -28,7 +28,8 @@ module.exports = function(RED) {
var nodeUrl = n.url;
var isTemplatedUrl = (nodeUrl||"").indexOf("{{") != -1;
var nodeMethod = n.method || "GET";
var paytoqs = n.paytoqs;
var paytoqs = false;
var paytobody = false;
var nodeHTTPPersistent = n["persist"];
if (n.tls) {
var tlsNode = RED.nodes.getNode(n.tls);
@@ -38,6 +39,10 @@ module.exports = function(RED) {
if (RED.settings.httpRequestTimeout) { this.reqTimeout = parseInt(RED.settings.httpRequestTimeout) || 120000; }
else { this.reqTimeout = 120000; }
if (n.paytoqs === true || n.paytoqs === "query") { paytoqs = true; }
else if (n.paytoqs === "body") { paytobody = true; }
var prox, noprox;
if (process.env.http_proxy) { prox = process.env.http_proxy; }
if (process.env.HTTP_PROXY) { prox = process.env.HTTP_PROXY; }
@@ -277,6 +282,14 @@ module.exports = function(RED) {
node.error(RED._("httpin.errors.invalid-payload"),msg);
nodeDone();
return;
}
} else if ( method == "GET" && typeof msg.payload !== "undefined" && paytobody) {
if (typeof msg.payload === "object") {
opts.body = JSON.stringify(msg.payload);
} else if (typeof msg.payload == "number") {
opts.body = msg.payload+"";
} else if (typeof msg.payload === "string" || Buffer.isBuffer(msg.payload)) {
opts.body = msg.payload;
}
}

View File

@@ -14,7 +14,7 @@
limitations under the License.
-->
<!-- WebSocket Input Node -->
<script type="text/x-red" data-template-name="websocket in">
<script type="text/html" data-template-name="websocket in">
<div class="form-row">
<label for="node-input-mode"><i class="fa fa-dot-circle-o"></i> <span data-i18n="websocket.label.type"></span></label>
<select id="node-input-mode">
@@ -148,10 +148,12 @@
if (root.slice(-1) != "/") {
root = root+"/";
}
if (this.path.charAt(0) == "/") {
root += this.path.slice(1);
} else {
root += this.path;
if (this.path) {
if (this.path.charAt(0) == "/") {
root += this.path.slice(1);
} else {
root += this.path;
}
}
return root;
},
@@ -198,7 +200,7 @@
</script>
<!-- WebSocket out Node -->
<script type="text/x-red" data-template-name="websocket out">
<script type="text/html" data-template-name="websocket out">
<div class="form-row">
<label for="node-input-mode"><i class="fa fa-dot-circle-o"></i> <span data-i18n="websocket.label.type"></span></label>
<select id="node-input-mode">
@@ -221,7 +223,7 @@
</script>
<!-- WebSocket Server configuration node -->
<script type="text/x-red" data-template-name="websocket-listener">
<script type="text/html" data-template-name="websocket-listener">
<div class="form-row">
<label for="node-config-input-path"><i class="fa fa-bookmark"></i> <span data-i18n="websocket.label.path"></span></label>
<input id="node-config-input-path" type="text" placeholder="/ws/example">
@@ -240,7 +242,7 @@
</script>
<!-- WebSocket Client configuration node -->
<script type="text/x-red" data-template-name="websocket-client">
<script type="text/html" data-template-name="websocket-client">
<div class="form-row">
<label for="node-config-input-path"><i class="fa fa-bookmark"></i> <span data-i18n="websocket.label.url"></span></label>
<input id="node-config-input-path" type="text" placeholder="ws://example.com/ws">

View File

@@ -14,7 +14,7 @@
limitations under the License.
-->
<script type="text/x-red" data-template-name="tcp in">
<script type="text/html" data-template-name="tcp in">
<div class="form-row">
<label for="node-input-server"><i class="fa fa-dot-circle-o"></i> <span data-i18n="tcpin.label.type"></span></label>
<select id="node-input-server" style="width:120px; margin-right:5px;">
@@ -108,7 +108,7 @@
</script>
<script type="text/x-red" data-template-name="tcp out">
<script type="text/html" data-template-name="tcp out">
<div class="form-row">
<label for="node-input-beserver"><i class="fa fa-dot-circle-o"></i> <span data-i18n="tcpin.label.type"></span></label>
<select id="node-input-beserver" style="width:150px; margin-right:5px;">
@@ -187,7 +187,7 @@
</script>
<script type="text/x-red" data-template-name="tcp request">
<script type="text/html" data-template-name="tcp request">
<div class="form-row">
<label for="node-input-server"><i class="fa fa-globe"></i> <span data-i18n="tcpin.label.server"></span></label>
<input type="text" id="node-input-server" placeholder="ip.address" style="width:45%">

View File

@@ -74,7 +74,7 @@ module.exports = function(RED) {
buffer = (node.datatype == 'buffer') ? Buffer.alloc(0) : "";
node.connected = true;
node.log(RED._("tcpin.status.connected",{host:node.host,port:node.port}));
node.status({fill:"green",shape:"dot",text:"common.status.connected"});
node.status({fill:"green",shape:"dot",text:"common.status.connected",_session:{type:"tcp",id:id}});
});
client.setKeepAlive(true,120000);
connectionPool[id] = client;
@@ -121,7 +121,7 @@ module.exports = function(RED) {
client.on('close', function() {
delete connectionPool[id];
node.connected = false;
node.status({fill:"red",shape:"ring",text:"common.status.disconnected"});
node.status({fill:"red",shape:"ring",text:"common.status.disconnected",_session:{type:"tcp",id:id}});
if (!node.closing) {
if (end) { // if we were asked to close then try to reconnect once very quick.
end = false;
@@ -199,7 +199,7 @@ module.exports = function(RED) {
}
});
socket.on('end', function() {
if (!node.stream || (node.datatype === "utf8" && node.newline !== "")) {
if (!node.stream || (node.datatype === "utf8" && node.newline !== "") || (node.datatype === "base64")) {
if (buffer.length > 0) {
var msg = {topic:node.topic, payload:buffer, ip:fromi, port:fromp};
msg._session = {type:"tcp",id:id};

View File

@@ -15,7 +15,7 @@
-->
<!-- The Input Node -->
<script type="text/x-red" data-template-name="udp in">
<script type="text/html" data-template-name="udp in">
<div class="form-row">
<label for="node-input-port"><i class="fa fa-sign-in"></i> <span data-i18n="udp.label.listen"></span></label>
<select id="node-input-multicast" style='width:70%'>
@@ -115,7 +115,7 @@
<!-- The Output Node -->
<script type="text/x-red" data-template-name="udp out">
<script type="text/html" data-template-name="udp out">
<div class="form-row">
<label for="node-input-port"><i class="fa fa-envelope"></i> <span data-i18n="udp.label.send"></span></label>
<select id="node-input-multicast" style="width:40%">

View File

@@ -1,5 +1,5 @@
<script type="text/x-red" data-template-name="csv">
<script type="text/html" data-template-name="csv">
<div class="form-row">
<label for="node-input-temp"><i class="fa fa-list"></i> <span data-i18n="csv.label.columns"></span></label>
<input type="text" id="node-input-temp" data-i18n="[placeholder]csv.placeholder.columns">
@@ -28,11 +28,15 @@
</div>
<div class="form-row" style="padding-left:20px;">
<label><i class="fa fa-sign-in"></i> <span data-i18n="csv.label.input"></span></label>
<span data-i18n="csv.label.skip-s"></span>&nbsp;<input type="text" id="node-input-skip" style="width:30px; height:25px;"/>&nbsp;<span data-i18n="csv.label.skip-e"></span><br/>
<span data-i18n="csv.label.skip-s"></span>&nbsp;<input type="text" id="node-input-skip" style="width:40px; height:25px;"/>&nbsp;<span data-i18n="csv.label.skip-e"></span><br/>
<label>&nbsp;</label>
<input style="width:20px; vertical-align:baseline; margin-right:5px;" type="checkbox" id="node-input-hdrin"><label style="width:auto; margin-top:7px;" for="node-input-hdrin"><span data-i18n="csv.label.firstrow"></span></label><br/>
<label>&nbsp;</label>
<input style="width:20px; vertical-align:baseline; margin-right:5px;" type="checkbox" id="node-input-strings"><label style="width:auto; margin-top:7px;" for="node-input-strings"><span data-i18n="csv.label.usestrings"></span></label><br/>
<label>&nbsp;</label>
<input style="width:20px; vertical-align:baseline; margin-right:5px;" type="checkbox" id="node-input-include_empty_strings"><label style="width:auto; margin-top:7px;" for="node-input-include_empty_strings"><span data-i18n="csv.label.include_empty_strings"></span></label><br/>
<label>&nbsp;</label>
<input style="width:20px; vertical-align:baseline; margin-right:5px;" type="checkbox" id="node-input-include_null_values"><label style="width:auto; margin-top:7px;" for="node-input-include_null_values"><span data-i18n="csv.label.include_null_values"></span></label><br/>
</div>
<div class="form-row" style="padding-left:20px;">
<label><i class="fa fa-sign-out"></i> <span data-i18n="csv.label.output"></span></label>
@@ -45,8 +49,13 @@
<label style="width:100%;"><span data-i18n="csv.label.o2c"></span></label>
</div>
<div class="form-row" style="padding-left:20px;">
<label><i class="fa fa-sign-in"></i> <span data-i18n="csv.label.output"></span></label>
<input style="width:20px; vertical-align:top; margin-right:5px;" type="checkbox" id="node-input-hdrout"><label style="width:auto;" for="node-input-hdrout"><span data-i18n="csv.label.includerow"></span></span>
<label><i class="fa fa-sign-out"></i> <span data-i18n="csv.label.output"></span></label>
<!-- <input style="width:20px; vertical-align:top; margin-right:5px;" type="checkbox" id="node-input-hdrout"><label style="width:auto;" for="node-input-hdrout"><span data-i18n="csv.label.includerow"></span></span> -->
<select style="width:60%" id="node-input-hdrout">
<option value="none" data-i18n="csv.hdrout.none"></option>
<option value="all" data-i18n="csv.hdrout.all"></option>
<option value="once" data-i18n="csv.hdrout.once"></option>
</select>
</div>
<div class="form-row" style="padding-left:20px;">
<label></label>
@@ -69,12 +78,14 @@
sep: {value:',',required:true,validate:RED.validators.regex(/^.{1,2}$/)},
//quo: {value:'"',required:true},
hdrin: {value:""},
hdrout: {value:""},
hdrout: {value:"none"},
multi: {value:"one",required:true},
ret: {value:'\\n'},
temp: {value:""},
skip: {value:"0"},
strings: {value:true}
strings: {value:true},
include_empty_strings: {value:""},
include_null_values: {value:""}
},
inputs:1,
outputs:1,
@@ -86,6 +97,8 @@
return this.name?"node_label_italic":"";
},
oneditprepare: function() {
if (this.hdrout === false) { this.hdrout = "none"; $("#node-input-hdrout").val("none"); }
if (this.hdrout === true) { this.hdrout = "all"; $("#node-input-hdrout").val("all");}
if (this.strings === undefined) { this.strings = true; $("#node-input-strings").prop('checked', true); }
if (this.skip === undefined) { this.skip = 0; $("#node-input-skip").val("0");}
$("#node-input-skip").spinner({ min:0 });

View File

@@ -26,12 +26,16 @@ module.exports = function(RED) {
this.lineend = "\n";
this.multi = n.multi || "one";
this.hdrin = n.hdrin || false;
this.hdrout = n.hdrout || false;
this.hdrout = n.hdrout || "none";
this.goodtmpl = true;
this.skip = parseInt(n.skip || 0);
this.store = [];
this.parsestrings = n.strings;
this.include_empty_strings = n.include_empty_strings || false;
this.include_null_values = n.include_null_values || false;
if (this.parsestrings === undefined) { this.parsestrings = true; }
if (this.hdrout === false) { this.hdrout = "none"; }
if (this.hdrout === true) { this.hdrout = "all"; }
var tmpwarn = true;
var node = this;
@@ -49,14 +53,22 @@ module.exports = function(RED) {
return col;
}
node.template = clean(node.template);
node.hdrSent = false;
this.on("input", function(msg) {
if (msg.hasOwnProperty("reset")) {
node.hdrSent = false;
}
if (msg.hasOwnProperty("payload")) {
if (typeof msg.payload == "object") { // convert object to CSV string
try {
var ou = "";
if (node.hdrout) {
if (node.hdrout !== "none" && node.hdrSent === false) {
if ((node.template.length === 1) && (node.template[0] === '') && (msg.hasOwnProperty("columns"))) {
node.template = clean((msg.columns || "").split(","));
}
ou += node.template.join(node.sep) + node.ret;
if (node.hdrout === "once") { node.hdrSent = true; }
}
if (!Array.isArray(msg.payload)) { msg.payload = [ msg.payload ]; }
for (var s = 0; s < msg.payload.length; s++) {
@@ -75,13 +87,15 @@ module.exports = function(RED) {
ou += msg.payload[s].join(node.sep) + node.ret;
}
else {
if ((node.template.length === 1) && (node.template[0] === '') && (msg.hasOwnProperty("columns"))) {
node.template = clean((msg.columns || "").split(","));
}
if ((node.template.length === 1) && (node.template[0] === '')) {
/* istanbul ignore else */
if (tmpwarn === true) { // just warn about missing template once
node.warn(RED._("csv.errors.obj_csv"));
tmpwarn = false;
}
ou = "";
for (var p in msg.payload[0]) {
/* istanbul ignore else */
if (msg.payload[0].hasOwnProperty(p)) {
@@ -125,6 +139,7 @@ module.exports = function(RED) {
}
}
msg.payload = ou;
msg.columns = node.template.join(',');
if (msg.payload !== '') { node.send(msg); }
}
catch(e) { node.error(e,msg); }
@@ -173,20 +188,29 @@ module.exports = function(RED) {
}
else if ((line[i] === node.sep) && f) { // if it is the end of the line then finish
if (!node.goodtmpl) { node.template[j] = "col"+(j+1); }
if ( node.template[j] && (node.template[j] !== "") && (k[j] !== "" ) ) {
if ( (node.parsestrings === true) && reg.test(k[j]) ) { k[j] = parseFloat(k[j]); }
o[node.template[j]] = k[j];
if ( node.template[j] && (node.template[j] !== "") ) {
// if no value between separators ('1,,"3"...') or if the line beings with separator (',1,"2"...') treat value as null
if (line[i-1] === node.sep || line[i-1].includes('\n','\r')) k[j] = null;
if ( (k[j] !== null && node.parsestrings === true) && reg.test(k[j]) ) { k[j] = parseFloat(k[j]); }
if (node.include_null_values && k[j] === null) o[node.template[j]] = k[j];
if (node.include_empty_strings && k[j] === "") o[node.template[j]] = k[j];
if (k[j] !== null && k[j] !== "") o[node.template[j]] = k[j];
}
j += 1;
k[j] = "";
// if separator is last char in processing string line (without end of line), add null value at the end - example: '1,2,3\n3,"3",'
k[j] = line.length - 1 === i ? null : "";
}
else if ((line[i] === "\n") || (line[i] === "\r")) { // handle multiple lines
else if (((line[i] === "\n") || (line[i] === "\r")) && f) { // handle multiple lines
//console.log(j,k,o,k[j]);
if (!node.goodtmpl) { node.template[j] = "col"+(j+1); }
if ( node.template[j] && (node.template[j] !== "") && (k[j] !== "") ) {
if ( (node.parsestrings === true) && reg.test(k[j]) ) { k[j] = parseFloat(k[j]); }
else { k[j].replace(/\r$/,''); }
o[node.template[j]] = k[j];
if ( node.template[j] && (node.template[j] !== "") ) {
// if separator before end of line, set null value ie. '1,2,"3"\n1,2,\n1,2,3'
if (line[i-1] === node.sep) k[j] = null;
if ( (k[j] !== null && node.parsestrings === true) && reg.test(k[j]) ) { k[j] = parseFloat(k[j]); }
else { if (k[j] !== null) k[j].replace(/\r$/,''); }
if (node.include_null_values && k[j] === null) o[node.template[j]] = k[j];
if (node.include_empty_strings && k[j] === "") o[node.template[j]] = k[j];
if (k[j] !== null && k[j] !== "") o[node.template[j]] = k[j];
}
if (JSON.stringify(o) !== "{}") { // don't send empty objects
a.push(o); // add to the array
@@ -202,17 +226,21 @@ module.exports = function(RED) {
}
}
// Finished so finalize and send anything left
//console.log(j,k,o,k[j]);
if (f === false) { node.warn(RED._("csv.errors.bad_csv")); }
if (!node.goodtmpl) { node.template[j] = "col"+(j+1); }
if ( node.template[j] && (node.template[j] !== "") && (k[j] !== "") ) {
if ( (node.parsestrings === true) && reg.test(k[j]) ) { k[j] = parseFloat(k[j]); }
else { k[j].replace(/\r$/,''); }
o[node.template[j]] = k[j];
if ( node.template[j] && (node.template[j] !== "") ) {
if ( (k[j] !== null && node.parsestrings === true) && reg.test(k[j]) ) { k[j] = parseFloat(k[j]); }
else { if (k[j] !== null) k[j].replace(/\r$/,''); }
if (node.include_null_values && k[j] === null) o[node.template[j]] = k[j];
if (node.include_empty_strings && k[j] === "") o[node.template[j]] = k[j];
if (k[j] !== null && k[j] !== "") o[node.template[j]] = k[j];
}
if (JSON.stringify(o) !== "{}") { // don't send empty objects
a.push(o); // add to the array
}
var has_parts = msg.hasOwnProperty("parts");
if (node.multi !== "one") {
msg.payload = a;
if (has_parts) {
@@ -221,12 +249,14 @@ module.exports = function(RED) {
}
if (msg.parts.index + 1 === msg.parts.count) {
msg.payload = node.store;
msg.columns = node.template.filter(val => val).join(',');
delete msg.parts;
node.send(msg);
node.store = [];
}
}
else {
msg.columns = node.template.filter(val => val).join(',');
node.send(msg); // finally send the array
}
}
@@ -234,6 +264,7 @@ module.exports = function(RED) {
var len = a.length;
for (var i = 0; i < len; i++) {
var newMessage = RED.util.cloneMessage(msg);
newMessage.columns = node.template.filter(val => val).join(',');
newMessage.payload = a[i];
if (!has_parts) {
newMessage.parts = {
@@ -259,7 +290,11 @@ module.exports = function(RED) {
}
else { node.warn(RED._("csv.errors.csv_js")); }
}
else { node.send(msg); } // If no payload - just pass it on.
else {
if (!msg.hasOwnProperty("reset")) {
node.send(msg); // If no payload and not reset - just pass it on.
}
}
});
}
RED.nodes.registerType("csv",CSVNode);

View File

@@ -1,5 +1,5 @@
<script type="text/x-red" data-template-name="html">
<script type="text/html" data-template-name="html">
<div class="form-row">
<label for="node-input-property"><i class="fa fa-ellipsis-h"></i> <span data-i18n="common.label.property"></span></label>
<input type="text" id="node-input-property" style="width:70%">

View File

@@ -1,5 +1,5 @@
<script type="text/x-red" data-template-name="json">
<script type="text/html" data-template-name="json">
<div class="form-row">
<label for="node-input-action"><i class="fa fa-dot-circle-o"></i> <span data-i18n="json.label.action"></span></label>
<select style="width:70%" id="node-input-action">

View File

@@ -1,5 +1,5 @@
<script type="text/x-red" data-template-name="xml">
<script type="text/html" data-template-name="xml">
<div class="form-row">
<label for="node-input-property"><i class="fa fa-ellipsis-h"></i> <span data-i18n="common.label.property"></span></label>
<input type="text" id="node-input-property" style="width:70%;"/>

View File

@@ -1,5 +1,5 @@
<script type="text/x-red" data-template-name="yaml">
<script type="text/html" data-template-name="yaml">
<div class="form-row">
<label for="node-input-property"><i class="fa fa-ellipsis-h"></i> <span data-i18n="common.label.property"></span></label>
<input type="text" id="node-input-property" style="width:70%;"/>

View File

@@ -446,7 +446,7 @@ module.exports = function(RED) {
buffers.push(joinBuffer);
bufferLen += joinBuffer.length;
}
if (!Buffer.isBuffer(group.payload[i])) {
if (!Buffer.isBuffer(group.payload[i])) {
group.payload[i] = Buffer.from(group.payload[i]);
}
buffers.push(group.payload[i]);
@@ -573,7 +573,15 @@ module.exports = function(RED) {
}
}
if (msg.hasOwnProperty("reset")) { if (inflight[partId]) { delete inflight[partId] }; return; }
if (msg.hasOwnProperty("reset")) {
if (inflight[partId]) {
if (inflight[partId].timeout) {
clearTimeout(inflight[partId].timeout);
}
delete inflight[partId]
}
return
}
if ((payloadType === 'object') && (propertyKey === null || propertyKey === undefined || propertyKey === "")) {
if (node.mode === "auto") {

View File

@@ -14,7 +14,7 @@
limitations under the License.
-->
<script type="text/x-red" data-template-name="sort">
<script type="text/html" data-template-name="sort">
<div class="form-row">
<label for="node-input-target"><i class="fa fa-dot-circle-o"></i> <span data-i18n="sort.target"></span></label>

View File

@@ -179,6 +179,11 @@ module.exports = function(RED) {
}
node.pending = [];
this.on("input", function(msg) {
if (msg.hasOwnProperty("reset")) {
node.pending = [];
node.pending_count = 0;
return;
}
var queue = node.pending;
queue.push(msg);
node.pending_count++;
@@ -204,11 +209,26 @@ module.exports = function(RED) {
var interval = Number(n.interval || "0") *1000;
var allow_empty_seq = n.allowEmptySequence;
node.pending = []
var timer = setInterval(function() {
function msgHandler() {
send_interval(node, allow_empty_seq);
node.pending_count = 0;
}, interval);
}
var timer = undefined;
if (interval > 0) {
timer = setInterval(msgHandler, interval);
}
this.on("input", function(msg) {
if (msg.hasOwnProperty("reset")) {
if (timer !== undefined) {
clearInterval(timer);
}
node.pending = [];
node.pending_count = 0;
if (interval > 0) {
timer = setInterval(msgHandler, interval);
}
return;
}
node.pending.push(msg);
node.pending_count++;
var max_msgs = max_kept_msgs_count(node);
@@ -219,7 +239,9 @@ module.exports = function(RED) {
}
});
this.on("close", function() {
clearInterval(timer);
if (timer !== undefined) {
clearInterval(timer);
}
node.pending = [];
node.pending_count = 0;
});
@@ -230,6 +252,11 @@ module.exports = function(RED) {
});
node.pending = {};
this.on("input", function(msg) {
if (msg.hasOwnProperty("reset")) {
node.pending = {};
node.pending_count = 0;
return;
}
concat_msg(node, msg);
});
this.on("close", function() {

View File

@@ -14,7 +14,7 @@
limitations under the License.
-->
<script type="text/x-red" data-template-name="watch">
<script type="text/html" data-template-name="watch">
<div class="form-row node-input-filename">
<label for="node-input-files"><i class="fa fa-file"></i> <span data-i18n="watch.label.files"></span></label>
<input id="node-input-files" type="text" tabindex="1" data-i18n="[placeholder]watch.placeholder.files">

View File

@@ -0,0 +1 @@
[{"id":"d1073c30.cb321","type":"inject","z":"f7ca1653.2d17b8","name":"","topic":"","payload":"Hello, World!","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":230,"y":160,"wires":[["7bab9134.35ad"]]},{"id":"f96f0ba7.cfe008","type":"debug","z":"f7ca1653.2d17b8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":550,"y":200,"wires":[]},{"id":"3ea03953.25a1a6","type":"comment","z":"f7ca1653.2d17b8","name":"Example: Catch Node","info":"Catch node can catch error caused by specified nodes or all nodes in a flow. It receives input of target node.","x":160,"y":60,"wires":[]},{"id":"d6a15623.056d18","type":"comment","z":"f7ca1653.2d17b8","name":"Catch error of a node","info":"","x":200,"y":120,"wires":[]},{"id":"7e1c072c.bc1cc8","type":"comment","z":"f7ca1653.2d17b8","name":"Catch error caused by function node","info":"","x":480,"y":240,"wires":[]},{"id":"b45ca54e.eca208","type":"catch","z":"f7ca1653.2d17b8","name":"","scope":["7bab9134.35ad"],"uncaught":false,"x":400,"y":200,"wires":[["f96f0ba7.cfe008"]]},{"id":"7bab9134.35ad","type":"function","z":"f7ca1653.2d17b8","name":"Error","func":"throw new Error(\"Error Occured!\")","outputs":0,"noerr":0,"x":390,"y":160,"wires":[]}]

View File

@@ -0,0 +1 @@
[{"id":"9df3290f.c6d2e8","type":"inject","z":"238b1aa0.fa96f6","name":"","topic":"","payload":"Hello, World!","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":210,"y":140,"wires":[["96f1096b.2f82a8"]]},{"id":"96f1096b.2f82a8","type":"debug","z":"238b1aa0.fa96f6","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":390,"y":140,"wires":[]},{"id":"23811105.474c6e","type":"complete","z":"238b1aa0.fa96f6","name":"","scope":["96f1096b.2f82a8"],"uncaught":false,"x":390,"y":180,"wires":[["f06a3fc9.6bab7"]]},{"id":"f06a3fc9.6bab7","type":"debug","z":"238b1aa0.fa96f6","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":580,"y":180,"wires":[]},{"id":"34d5ef47.79e72","type":"comment","z":"238b1aa0.fa96f6","name":"Example: Complete Node","info":"Complete node can catch completion of specified nodes. It receives input of target node.","x":150,"y":40,"wires":[]},{"id":"6ed443a1.a0c3cc","type":"comment","z":"238b1aa0.fa96f6","name":"Catch completion of a node","info":"","x":200,"y":100,"wires":[]},{"id":"70b28e37.84edd","type":"comment","z":"238b1aa0.fa96f6","name":"Catch completion of 1st debug node","info":"","x":460,"y":220,"wires":[]}]

View File

@@ -0,0 +1 @@
[{"id":"87bd706a.aec93","type":"comment","z":"3ae4b3d9.1f77bc","name":"Output payload value to debug sidebar","info":"Debug node can be used to output payload value to debug sidebar.","x":230,"y":60,"wires":[]},{"id":"8035b07f.7547e","type":"inject","z":"3ae4b3d9.1f77bc","name":"","props":[{"p":"payload","v":"Hello, World!","vt":"str"},{"p":"topic","v":"","vt":"string"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"Hello, World!","payloadType":"str","x":210,"y":100,"wires":[["20d1344f.931e3c"]]},{"id":"20d1344f.931e3c","type":"debug","z":"3ae4b3d9.1f77bc","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":450,"y":100,"wires":[]}]

View File

@@ -0,0 +1 @@
[{"id":"8c66d039.44465","type":"comment","z":"e6956267.5d174","name":"Output complete object","info":"Debug node can be used to output whole object value to debug sidebar.","x":160,"y":60,"wires":[]},{"id":"dac87e40.90376","type":"inject","z":"e6956267.5d174","name":"","props":[{"p":"payload","v":"Hello, World!","vt":"str"},{"p":"topic","v":"Sample","vt":"string"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"Sample","payload":"Hello, World!","payloadType":"str","x":220,"y":100,"wires":[["a77fa5e3.fac248"]]},{"id":"a77fa5e3.fac248","type":"debug","z":"e6956267.5d174","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":410,"y":100,"wires":[]}]

View File

@@ -0,0 +1 @@
[{"id":"fb1c3ce9.c29ee","type":"comment","z":"395f4b0d.8a8774","name":"Output to console","info":"Debug node can be used to output values to console.","x":130,"y":60,"wires":[]},{"id":"3c24e746.9ff6a8","type":"inject","z":"395f4b0d.8a8774","name":"","repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"Hello, World!","payloadType":"str","x":170,"y":100,"wires":[["66cc7b44.82ba74"]]},{"id":"66cc7b44.82ba74","type":"debug","z":"395f4b0d.8a8774","name":"","active":true,"tosidebar":false,"console":true,"tostatus":false,"complete":"payload","targetType":"msg","x":420,"y":100,"wires":[]}]

View File

@@ -0,0 +1 @@
[{"id":"33791e6a.973502","type":"comment","z":"55587092.1f2b4","name":"Output to node status area","info":"Debug node can be used to output values to status area below the node.","x":170,"y":60,"wires":[]},{"id":"a5d8e744.a034e8","type":"inject","z":"55587092.1f2b4","name":"","repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"Hello, World!","payloadType":"str","x":190,"y":100,"wires":[["b0646a4d.db4bc8"]]},{"id":"b0646a4d.db4bc8","type":"debug","z":"55587092.1f2b4","name":"","active":true,"tosidebar":false,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","x":430,"y":100,"wires":[]}]

View File

@@ -0,0 +1 @@
[{"id":"30ed0a73.fcef86","type":"comment","z":"61feb619.5e3d68","name":"Formatting output using JSONata","info":"Debug node can format output value using JSONata expression.","x":200,"y":60,"wires":[]},{"id":"6f477e7d.3a8da","type":"inject","z":"61feb619.5e3d68","name":"","props":[{"p":"payload","v":"Hello, World!","vt":"str"},{"p":"topic","v":"Sample","vt":"string"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"Sample","payload":"Hello, World!","payloadType":"str","x":220,"y":100,"wires":[["19c9408d.ac6d4f"]]},{"id":"19c9408d.ac6d4f","type":"debug","z":"61feb619.5e3d68","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"\"[\" & topic & \"] \" & payload","targetType":"jsonata","x":420,"y":100,"wires":[]}]

View File

@@ -0,0 +1 @@
[{"id":"eca30de2.7f1b1","type":"comment","z":"6e4ff5ca.fbc3ec","name":"Trigger a flow whenever Node-RED starts","info":"Inject node can be used to trigger a flow whenever Node-RED starts.\n\n*This could be used to initialise context variables, or to send a notification that Node-RED has been restarted.*\n\nSee Node-RED cookbook [item](https://cookbook.nodered.org/basic/trigger-on-start).","x":220,"y":60,"wires":[]},{"id":"8189f250.ddfb2","type":"inject","z":"6e4ff5ca.fbc3ec","name":"","topic":"","payload":"Started!","payloadType":"str","repeat":"","crontab":"","once":true,"onceDelay":"","x":200,"y":120,"wires":[["9a0150e8.6d0b3"]]},{"id":"9a0150e8.6d0b3","type":"debug","z":"6e4ff5ca.fbc3ec","name":"","active":true,"console":"false","complete":"false","x":470,"y":120,"wires":[]}]

View File

@@ -0,0 +1 @@
[{"id":"64c1d7b3.a65b38","type":"comment","z":"bfaec8ca.105278","name":"Trigger a flow at regular intervals","info":"Inject node can be used to trigger a flow at regular intervals. \n\nSee Node-RED cookbook [item](https://cookbook.nodered.org/basic/trigger-at-interval).","x":190,"y":60,"wires":[]},{"id":"7c820e88.2db33","type":"inject","z":"bfaec8ca.105278","name":"","topic":"","payload":"","payloadType":"date","repeat":"5","crontab":"","once":false,"x":190,"y":120,"wires":[["8f135212.6a9a9"]]},{"id":"8f135212.6a9a9","type":"debug","z":"bfaec8ca.105278","name":"","active":true,"console":"false","complete":"false","x":450,"y":120,"wires":[]}]

View File

@@ -0,0 +1 @@
[{"id":"a4060d5d.a3c92","type":"comment","z":"568c3a2a.5efbf4","name":"Trigger a flow at a specific time","info":"Inject node can be used to trigger a flow at a specific time. \n\nSee Node-RED cookbook [item](https://cookbook.nodered.org/basic/trigger-at-time).","x":190,"y":60,"wires":[]},{"id":"468db06c.bafdd","type":"inject","z":"568c3a2a.5efbf4","name":"","topic":"","payload":"It is 4pm on a weekday!","payloadType":"str","repeat":"","crontab":"00 16 * * 1,2,3,4,5","once":false,"x":250,"y":120,"wires":[["1ccc3174.cb926f"]]},{"id":"1ccc3174.cb926f","type":"debug","z":"568c3a2a.5efbf4","name":"","active":true,"console":"false","complete":"false","x":470,"y":120,"wires":[]}]

View File

@@ -0,0 +1 @@
[{"id":"a30d20e6.ec6dc","type":"link in","z":"2f2d9fa4.be6fc","name":"","links":["70d6f012.8fe6d"],"x":235,"y":240,"wires":[["6bf52c5c.d301c4"]]},{"id":"70d6f012.8fe6d","type":"link out","z":"2f2d9fa4.be6fc","name":"","links":["a30d20e6.ec6dc"],"x":315,"y":180,"wires":[]},{"id":"353c85ce.993d0a","type":"inject","z":"2f2d9fa4.be6fc","name":"","topic":"","payload":"Hello, World!","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":210,"y":180,"wires":[["70d6f012.8fe6d"]]},{"id":"6bf52c5c.d301c4","type":"debug","z":"2f2d9fa4.be6fc","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":370,"y":240,"wires":[]},{"id":"62ea32aa.d73aac","type":"comment","z":"2f2d9fa4.be6fc","name":"Example: Link Node","info":"Output of link out node can be connected to input of link in node. The connection between links in/out is not shown, so the flow representation can be simplified.","x":130,"y":40,"wires":[]},{"id":"85133fcc.e482","type":"comment","z":"2f2d9fa4.be6fc","name":"Link output of inject node to input of debug node","info":"","x":260,"y":100,"wires":[]},{"id":"c588bc36.87fec","type":"comment","z":"2f2d9fa4.be6fc","name":"↓ connect to link in node","info":"","x":410,"y":140,"wires":[]},{"id":"8abca900.6dfe78","type":"comment","z":"2f2d9fa4.be6fc","name":"↑ connect from link out node","info":"","x":340,"y":280,"wires":[]}]

View File

@@ -0,0 +1 @@
[{"id":"f51b8a1a.95b448","type":"tab","label":"TAB: 1st","disabled":false,"info":""},{"id":"ec5fae59.42a3b","type":"tab","label":"TAB: 2nd","disabled":false,"info":""},{"id":"fcd2b35a.6a7c4","type":"link out","z":"f51b8a1a.95b448","name":"","links":["f5fead9.12cdf5","cc961da1.25402"],"x":335,"y":200,"wires":[]},{"id":"41a35965.1b4ed8","type":"inject","z":"f51b8a1a.95b448","name":"","topic":"","payload":"Hello, World!","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":230,"y":200,"wires":[["fcd2b35a.6a7c4"]]},{"id":"5b4e5338.81ce5c","type":"comment","z":"f51b8a1a.95b448","name":"Example: Link Node across tabs","info":"Output of link out node can be connected to input of link in node. The connection between links in/out is not shown, so the flow representation can be simplified.","x":190,"y":60,"wires":[]},{"id":"6cc2116d.b2d41","type":"comment","z":"f51b8a1a.95b448","name":"Link output of inject node to input of debug node in 2nd tab","info":"","x":320,"y":120,"wires":[]},{"id":"bdc2bf14.e00a6","type":"comment","z":"f51b8a1a.95b448","name":"↓ connect to link in node in 2nd tab","info":"","x":460,"y":160,"wires":[]},{"id":"cc961da1.25402","type":"link in","z":"ec5fae59.42a3b","name":"","links":["fcd2b35a.6a7c4"],"x":155,"y":180,"wires":[["ce8b8ea5.364cb"]]},{"id":"ce8b8ea5.364cb","type":"debug","z":"ec5fae59.42a3b","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":290,"y":180,"wires":[]},{"id":"64752acd.6cfcb4","type":"comment","z":"ec5fae59.42a3b","name":"↑ connect from link out node in 1st tab","info":"","x":290,"y":220,"wires":[]},{"id":"299b832b.6db7dc","type":"comment","z":"ec5fae59.42a3b","name":"Example: Link Node across tabs","info":"Output of link out node can be connected to input of link in node. The connection between links in/out is not shown, so the flow representation can be simplified.","x":190,"y":60,"wires":[]},{"id":"aa11903.1daf77","type":"comment","z":"ec5fae59.42a3b","name":"Link output of inject node in 1st tab to input of debug node","info":"","x":310,"y":120,"wires":[]}]

View File

@@ -0,0 +1 @@
[{"id":"cf27351f.392d88","type":"inject","z":"17d58bdd.2ab8c4","name":"","topic":"","payload":"Hello, World!","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":270,"y":160,"wires":[["75eaadfb.bed014"]]},{"id":"cd1ac74a.a149a8","type":"debug","z":"17d58bdd.2ab8c4","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":590,"y":220,"wires":[]},{"id":"fc2e6dfc.2b0e9","type":"comment","z":"17d58bdd.2ab8c4","name":"Example: Status Node","info":"Status node can catch change of status message of specified nodes or all nodes in a flow. It receives metadata of status message.","x":200,"y":60,"wires":[]},{"id":"d97b97d0.c4cfe8","type":"comment","z":"17d58bdd.2ab8c4","name":"Catch status message","info":"","x":240,"y":120,"wires":[]},{"id":"a1914d09.e7ba2","type":"comment","z":"17d58bdd.2ab8c4","name":"Catch status message of 1st debug node","info":"","x":540,"y":260,"wires":[]},{"id":"75fefe32.3e47d","type":"status","z":"17d58bdd.2ab8c4","name":"","scope":["cf27351f.392d88","75eaadfb.bed014"],"x":440,"y":220,"wires":[["cd1ac74a.a149a8"]]},{"id":"75eaadfb.bed014","type":"debug","z":"17d58bdd.2ab8c4","name":"","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","x":450,"y":160,"wires":[]}]

View File

@@ -0,0 +1 @@
[{"id":"87bd706a.aec93","type":"comment","z":"3ae4b3d9.1f77bc","name":"Set message property to a fixed value","info":"Change node can set value to message payload.\n\nSee Node-RED cookbook [item](https://cookbook.nodered.org/basic/set-message-property-fixed).","x":210,"y":60,"wires":[]},{"id":"ac4c748f.fd1bc8","type":"inject","z":"3ae4b3d9.1f77bc","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":180,"y":120,"wires":[["67974c84.7ca2c4"]]},{"id":"67974c84.7ca2c4","type":"change","z":"3ae4b3d9.1f77bc","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"Hello World!","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":380,"y":120,"wires":[["6b23a342.86d9cc"]]},{"id":"6b23a342.86d9cc","type":"debug","z":"3ae4b3d9.1f77bc","name":"","active":true,"console":"false","complete":"false","x":590,"y":120,"wires":[]}]

View File

@@ -0,0 +1 @@
[{"id":"26e7643f.13ebcc","type":"comment","z":"f4cb1920.4d58c8","name":"Set any property value","info":"Change node can set value to any message property.","x":160,"y":60,"wires":[]},{"id":"4da2494d.9aff68","type":"inject","z":"f4cb1920.4d58c8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":180,"y":120,"wires":[["5111e689.62e838"]]},{"id":"58ea5868.0596e8","type":"debug","z":"f4cb1920.4d58c8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":530,"y":120,"wires":[]},{"id":"5111e689.62e838","type":"change","z":"f4cb1920.4d58c8","name":"set payload & topic","rules":[{"t":"set","p":"payload","pt":"msg","to":"Hello, World!","tot":"str"},{"t":"set","p":"topic","pt":"msg","to":"Title","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":360,"y":120,"wires":[["58ea5868.0596e8"]]}]

View File

@@ -0,0 +1 @@
[{"id":"a9039cda.3649e","type":"comment","z":"a808932c.4ca77","name":"Set value using JSONata","info":"Change node can set value to using JSONata expression.","x":170,"y":60,"wires":[]},{"id":"bdcdd579.cfe668","type":"inject","z":"a808932c.4ca77","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":180,"y":120,"wires":[["28d110a7.ce3e2"]]},{"id":"c6677fa5.8c111","type":"debug","z":"a808932c.4ca77","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":530,"y":120,"wires":[]},{"id":"28d110a7.ce3e2","type":"change","z":"a808932c.4ca77","name":"use JSONata","rules":[{"t":"set","p":"payload","pt":"msg","to":"Hello","tot":"str"},{"t":"set","p":"payload","pt":"msg","to":"payload & \", World!\"","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":340,"y":120,"wires":[["c6677fa5.8c111"]]}]

View File

@@ -0,0 +1 @@
[{"id":"e9143349.a64f7","type":"comment","z":"a32e6d69.1b13b","name":"Set value from environment variable","info":"Change node can set value from environment variable.","x":200,"y":60,"wires":[]},{"id":"a7c2725.a631f9","type":"inject","z":"a32e6d69.1b13b","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":180,"y":120,"wires":[["e455c302.2f795"]]},{"id":"6f203119.21895","type":"debug","z":"a32e6d69.1b13b","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":530,"y":120,"wires":[]},{"id":"e455c302.2f795","type":"change","z":"a32e6d69.1b13b","name":"set env var","rules":[{"t":"set","p":"payload","pt":"msg","to":"HOME","tot":"env"}],"action":"","property":"","from":"","to":"","reg":false,"x":340,"y":120,"wires":[["6f203119.21895"]]}]

View File

@@ -0,0 +1 @@
[{"id":"6ecac54d.c43ffc","type":"comment","z":"87ace6c0.f01da8","name":"Set flow context","info":"Change node can set flow context.","x":140,"y":60,"wires":[]},{"id":"80e966d3.9d7a78","type":"inject","z":"87ace6c0.f01da8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":200,"y":234,"wires":[["abaee298.2d77e"]]},{"id":"60ab671d.b0bbf8","type":"debug","z":"87ace6c0.f01da8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":570,"y":234,"wires":[]},{"id":"abaee298.2d77e","type":"change","z":"87ace6c0.f01da8","name":"increment count","rules":[{"t":"set","p":"count","pt":"flow","to":"$flowContext(\"count\")+1\t","tot":"jsonata"},{"t":"set","p":"payload","pt":"msg","to":"count","tot":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":380,"y":234,"wires":[["60ab671d.b0bbf8"]]},{"id":"2de2bb38.f20ff4","type":"inject","z":"87ace6c0.f01da8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":200,"y":140,"wires":[["7b96521e.a3cb0c"]]},{"id":"597b63cd.b3218c","type":"debug","z":"87ace6c0.f01da8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":570,"y":140,"wires":[]},{"id":"7b96521e.a3cb0c","type":"change","z":"87ace6c0.f01da8","name":"set count to 0","rules":[{"t":"set","p":"count","pt":"flow","to":"0","tot":"num"},{"t":"set","p":"payload","pt":"msg","to":"count","tot":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":380,"y":140,"wires":[["597b63cd.b3218c"]]},{"id":"3d8cdc6d.2620e4","type":"comment","z":"87ace6c0.f01da8","name":"↓ Initialize","info":"","x":200,"y":100,"wires":[]},{"id":"d8069121.80de7","type":"comment","z":"87ace6c0.f01da8","name":"↓ Count up","info":"","x":200,"y":194,"wires":[]}]

View File

@@ -0,0 +1 @@
[{"id":"670fff8d.c60e2","type":"comment","z":"f000890e.5078a8","name":"Delete message property","info":"Change node can delete a message property.\n\nSee Node-RED cookbook [item](https://cookbook.nodered.org/basic/delete-message-property).","x":170,"y":60,"wires":[]},{"id":"6708b393.04895c","type":"inject","z":"f000890e.5078a8","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":180,"y":120,"wires":[["d8757f71.765a9"]]},{"id":"d8757f71.765a9","type":"change","z":"f000890e.5078a8","name":"","rules":[{"t":"delete","p":"payload","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":390,"y":120,"wires":[["20c077b.e11c188"]]},{"id":"20c077b.e11c188","type":"debug","z":"f000890e.5078a8","name":"","active":true,"console":"false","complete":"false","x":590,"y":120,"wires":[]}]

View File

@@ -0,0 +1 @@
[{"id":"6e779a3b.4fdc24","type":"comment","z":"e4c6d5fb.1fd618","name":"Move message property","info":"Change node can move a message property to a different property.\n\nSee Node-RED cookbook [item](https://cookbook.nodered.org/basic/move-message-property).","x":170,"y":60,"wires":[]},{"id":"bae6cb28.2ac588","type":"inject","z":"e4c6d5fb.1fd618","name":"","topic":"Hello","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":200,"y":120,"wires":[["436d3311.248cdc"]]},{"id":"436d3311.248cdc","type":"change","z":"e4c6d5fb.1fd618","name":"","rules":[{"t":"move","p":"topic","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":400,"y":120,"wires":[["7865b104.64061"]]},{"id":"7865b104.64061","type":"debug","z":"e4c6d5fb.1fd618","name":"","active":true,"console":"false","complete":"false","x":590,"y":120,"wires":[]}]

View File

@@ -0,0 +1 @@
[{"id":"87bd706a.aec93","type":"comment","z":"3ae4b3d9.1f77bc","name":"Delay message","info":"Delay node can delay sending input message to output port by a specified amount of time.","x":160,"y":60,"wires":[]},{"id":"1d17715c.34170f","type":"inject","z":"3ae4b3d9.1f77bc","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"Hello, World!","payloadType":"str","x":210,"y":120,"wires":[["26b43de5.4df8f2","9930fecd.ee0c8"]]},{"id":"9930fecd.ee0c8","type":"debug","z":"3ae4b3d9.1f77bc","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":410,"y":120,"wires":[]},{"id":"26b43de5.4df8f2","type":"delay","z":"3ae4b3d9.1f77bc","name":"","pauseType":"delay","timeout":"3","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":400,"y":180,"wires":[["c8c2796c.dcb9f8"]]},{"id":"c8c2796c.dcb9f8","type":"change","z":"3ae4b3d9.1f77bc","name":"Goodbye, World!","rules":[{"t":"set","p":"payload","pt":"msg","to":"Goodbye, World!","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":590,"y":180,"wires":[["c58a290e.2fa438"]]},{"id":"c58a290e.2fa438","type":"debug","z":"3ae4b3d9.1f77bc","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":790,"y":180,"wires":[]}]

View File

@@ -0,0 +1 @@
[{"id":"c15b8c3e.955ed","type":"comment","z":"6f1773ed.b7c2fc","name":"Delay message by message property","info":"Delay node can delay sending input message to output port by a specified amount of time by `msg.delay` property.","x":210,"y":60,"wires":[]},{"id":"a5ed5817.9df448","type":"inject","z":"6f1773ed.b7c2fc","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"},{"p":"delay","v":"1000","vt":"num"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"delay 1s","payloadType":"str","x":180,"y":120,"wires":[["5cf53f4.25b7ec","59b7b67a.a8e888"]]},{"id":"59b7b67a.a8e888","type":"debug","z":"6f1773ed.b7c2fc","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":390,"y":120,"wires":[]},{"id":"5cf53f4.25b7ec","type":"delay","z":"6f1773ed.b7c2fc","name":"","pauseType":"delayv","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":380,"y":180,"wires":[["fc989f41.c4114"]]},{"id":"fc989f41.c4114","type":"change","z":"6f1773ed.b7c2fc","name":"Goodbye, World!","rules":[{"t":"set","p":"payload","pt":"msg","to":"Goodbye, World!","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":570,"y":180,"wires":[["74ba3d1c.666034"]]},{"id":"74ba3d1c.666034","type":"debug","z":"6f1773ed.b7c2fc","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":770,"y":180,"wires":[]},{"id":"6cdf7297.bf5a8c","type":"inject","z":"6f1773ed.b7c2fc","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"},{"p":"delay","v":"10000","vt":"num"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"delay 10s","payloadType":"str","x":180,"y":180,"wires":[["59b7b67a.a8e888","5cf53f4.25b7ec"]]}]

View File

@@ -0,0 +1 @@
[{"id":"b0200f61.5efa5","type":"comment","z":"86a4fcf3.9f442","name":"Reset or flush pending message","info":"Delay node can reset or flush delayed message by sending it a message with `reset` or `flush` property.","x":170,"y":60,"wires":[]},{"id":"d5cd8991.e6d2e8","type":"inject","z":"86a4fcf3.9f442","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"Hello, World!","payloadType":"str","x":170,"y":120,"wires":[["607f556b.3ec5fc","fd14cb.2044db38"]]},{"id":"fd14cb.2044db38","type":"debug","z":"86a4fcf3.9f442","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":370,"y":120,"wires":[]},{"id":"607f556b.3ec5fc","type":"delay","z":"86a4fcf3.9f442","name":"","pauseType":"delay","timeout":"1","timeoutUnits":"minutes","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":360,"y":180,"wires":[["d1fc6763.2a30c8"]]},{"id":"d1fc6763.2a30c8","type":"change","z":"86a4fcf3.9f442","name":"Goodbye, World!","rules":[{"t":"set","p":"payload","pt":"msg","to":"Goodbye, World!","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":550,"y":180,"wires":[["15486d4a.80c6f3"]]},{"id":"15486d4a.80c6f3","type":"debug","z":"86a4fcf3.9f442","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":750,"y":180,"wires":[]},{"id":"2b8b28c7.4c8978","type":"inject","z":"86a4fcf3.9f442","name":"reset","props":[{"p":"topic","vt":"str"},{"p":"reset","v":"true","vt":"bool"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":150,"y":180,"wires":[["607f556b.3ec5fc"]]},{"id":"3a7e1bec.8bc3d4","type":"inject","z":"86a4fcf3.9f442","name":"flush","props":[{"p":"topic","vt":"str"},{"p":"flush","v":"true","vt":"bool"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":150,"y":240,"wires":[["607f556b.3ec5fc"]]}]

View File

@@ -0,0 +1 @@
[{"id":"2d14f1a7.e776ce","type":"comment","z":"39759fee.3ffb6","name":"Slow down messages passing through a flow","info":"Delay node can be used to slow down messages passing through a flow.\n\nSee Node-RED cookbook [item](https://cookbook.nodered.org/basic/rate-limit-messages).","x":230,"y":80,"wires":[]},{"id":"af78b43e.9817d8","type":"inject","z":"39759fee.3ffb6","name":"Inject Array","repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"[0,1,2,3,4,5,6,7,8,9]","payloadType":"json","x":190,"y":140,"wires":[["a35943e3.eaf0a"]]},{"id":"a35943e3.eaf0a","type":"split","z":"39759fee.3ffb6","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":330,"y":140,"wires":[["23eacc60.7290a4"]]},{"id":"23eacc60.7290a4","type":"delay","z":"39759fee.3ffb6","name":"","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":470,"y":140,"wires":[["b5b7746a.53bf88"]]},{"id":"b5b7746a.53bf88","type":"debug","z":"39759fee.3ffb6","name":"Debug","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":610,"y":140,"wires":[]}]

View File

@@ -0,0 +1 @@
[{"id":"3dc5015b.96c97e","type":"comment","z":"73c00795.a13908","name":"Limit rate of message transfer for each topic","info":"Delay node can limit of message transmission from input to output port by a specified number of message per a specified time.\nIf `For each topic` is selected, messages are grouped by `msg.topic` value. When grouping messages by topic, intermediate messages are dropped and the last messages received sent.","x":210,"y":60,"wires":[]},{"id":"bdafe4c6.4d5658","type":"inject","z":"73c00795.a13908","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"[{\"topic\":\"apple\",\"payload\":1},{\"topic\":\"apple\",\"payload\":2},{\"topic\":\"apple\",\"payload\":3},{\"topic\":\"orange\",\"payload\":1},{\"topic\":\"orange\",\"payload\":2},{\"topic\":\"orange\",\"payload\":3},{\"topic\":\"banana\",\"payload\":1},{\"topic\":\"banana\",\"payload\":2},{\"topic\":\"banana\",\"payload\":3}]","payloadType":"json","x":150,"y":120,"wires":[["f86dc462.195818"]]},{"id":"e0bdfcc1.cdf48","type":"delay","z":"73c00795.a13908","name":"","pauseType":"timed","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"2","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"x":690,"y":120,"wires":[["29d8beea.6b37f2"]]},{"id":"29d8beea.6b37f2","type":"debug","z":"73c00795.a13908","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":890,"y":120,"wires":[]},{"id":"f86dc462.195818","type":"split","z":"73c00795.a13908","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":290,"y":120,"wires":[["9feb3aac.616c38"]]},{"id":"9feb3aac.616c38","type":"change","z":"73c00795.a13908","name":"set topic&payload","rules":[{"t":"set","p":"topic","pt":"msg","to":"payload.topic","tot":"msg"},{"t":"set","p":"payload","pt":"msg","to":"payload.payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":470,"y":120,"wires":[["e0bdfcc1.cdf48"]]},{"id":"949199e8.89bc88","type":"comment","z":"73c00795.a13908","name":"↑ pass last message of each topic","info":"","x":740,"y":160,"wires":[]}]

View File

@@ -0,0 +1 @@
[{"id":"6a5f26a9.0cc2d8","type":"inject","z":"835cc8cc.b8cca8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"Hello World!","payloadType":"str","x":190,"y":160,"wires":[["fc2b343c.bbe2f8"]]},{"id":"fc2b343c.bbe2f8","type":"exec","z":"835cc8cc.b8cca8","command":"echo","addpay":true,"append":"","useSpawn":"false","timer":"","oldrc":false,"name":"","x":330,"y":160,"wires":[["2f3bcd73.6fedf2"],[],["3280586e.4e3d28"]]},{"id":"2f3bcd73.6fedf2","type":"debug","z":"835cc8cc.b8cca8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":510,"y":160,"wires":[]},{"id":"2b7bc9f1.ab36a6","type":"comment","z":"835cc8cc.b8cca8","name":"Execute external command appending additional args","info":"Exec node can execute external command and can receive its standard output as a payload of first message. Standard error output can be received from second message. The exit code of the command can be obtained from `code` property of third message payload.\n\nIf `Append msg.payload` checkbox is selected, payload value of the input message is appended to command string.\n","x":260,"y":60,"wires":[]},{"id":"3280586e.4e3d28","type":"debug","z":"835cc8cc.b8cca8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":510,"y":220,"wires":[]},{"id":"feba83da.8f227","type":"comment","z":"835cc8cc.b8cca8","name":"↓ execute echo command","info":"","x":390,"y":115,"wires":[]}]

View File

@@ -0,0 +1 @@
[{"id":"f507b27c.fff1","type":"inject","z":"462f83a6.d3c3cc","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":140,"y":180,"wires":[["28b4f75a.eae548"]]},{"id":"28b4f75a.eae548","type":"exec","z":"462f83a6.d3c3cc","command":"/non/existing/command","addpay":false,"append":"","useSpawn":"false","timer":"","oldrc":false,"name":"","x":350,"y":180,"wires":[[],["27992c1f.a1c964"],["6e7ff001.2412d"]]},{"id":"6e7ff001.2412d","type":"debug","z":"462f83a6.d3c3cc","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":570,"y":240,"wires":[]},{"id":"27992c1f.a1c964","type":"debug","z":"462f83a6.d3c3cc","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":570,"y":180,"wires":[]},{"id":"77e85c7c.a560d4","type":"comment","z":"462f83a6.d3c3cc","name":"Execute external command and get error output","info":"Exec node can execute external command and can receive its standard output as a payload of first message. Standard error output can be received from second message. The exit code of the command can be obtained from `code` property of third message payload.\n","x":220,"y":80,"wires":[]},{"id":"c188c28c.f7d34","type":"comment","z":"462f83a6.d3c3cc","name":"↓ try to execute non-existing command","info":"","x":390,"y":134,"wires":[]}]

View File

@@ -0,0 +1 @@
[{"id":"2e7be550.92ddfa","type":"inject","z":"a7f52169.f6c4","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":180,"y":160,"wires":[["53a714a8.1214dc"]]},{"id":"53a714a8.1214dc","type":"exec","z":"a7f52169.f6c4","command":"/bin/sh -c \"while true; do echo Hello; sleep 2; done\"","addpay":false,"append":"","useSpawn":"true","timer":"","oldrc":false,"name":"Repeat message output","x":410,"y":160,"wires":[["d1815f06.463f3"],["322d9b72.fc9194"],["2dbf8e03.2d6a52"]]},{"id":"7f351806.547908","type":"comment","z":"a7f52169.f6c4","name":"Execute external command in spawn mode","info":"Exec node can execute external command and can receive its standard output as a payload of first message. Standard error output can be received from second message. The exit code of the command can be obtained from `code` property of third message payload.\n\nIf `spawn mode` is selected, exec node returns the output as the command runs. \n\nSending `msg.kill` will kill a active process.\n\n*This example only works on UNIX flavored system.*","x":230,"y":60,"wires":[]},{"id":"2dbf8e03.2d6a52","type":"debug","z":"a7f52169.f6c4","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":690,"y":200,"wires":[]},{"id":"d1815f06.463f3","type":"debug","z":"a7f52169.f6c4","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":690,"y":120,"wires":[]},{"id":"28467ba9.c96284","type":"comment","z":"a7f52169.f6c4","name":"↓ spawn mode: repeat message output","info":"","x":450,"y":114,"wires":[]},{"id":"322d9b72.fc9194","type":"debug","z":"a7f52169.f6c4","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":690,"y":160,"wires":[]},{"id":"d5a990ce.c660b","type":"inject","z":"a7f52169.f6c4","name":"Kill process","props":[{"p":"kill","v":"","vt":"date"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":190,"y":220,"wires":[["53a714a8.1214dc"]]}]

View File

@@ -0,0 +1 @@
[{"id":"ec5a531b.68b65","type":"inject","z":"90acd374.2feda","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"World","payloadType":"str","x":150,"y":100,"wires":[["961abba6.04a028"]]},{"id":"1b0f8c3e.1fd7e4","type":"debug","z":"90acd374.2feda","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":530,"y":100,"wires":[]},{"id":"4e5bf6b2.b4dd58","type":"comment","z":"90acd374.2feda","name":"send a message to output port","info":"Function node can be used to write JavaScript code to handle messages.\nThe input message can be referrenced by `msg` variable. \nA message returned from body of the function is sent to output port.\n\nSee Node-RED user guide about [functions](https://nodered.org/docs/user-guide/writing-functions).","x":170,"y":40,"wires":[]},{"id":"961abba6.04a028","type":"function","z":"90acd374.2feda","name":"return a message","func":"// returning message send it to output port\nmsg.payload = \"Hello, \"+msg.payload +\"!\";\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":330,"y":100,"wires":[["1b0f8c3e.1fd7e4"]]}]

View File

@@ -0,0 +1 @@
[{"id":"c2b3b0f1.62189","type":"inject","z":"b4c03214.fa42e","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":160,"y":100,"wires":[["7241db1e.8946c4"]]},{"id":"c6191361.0f3c","type":"debug","z":"b4c03214.fa42e","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":590,"y":80,"wires":[]},{"id":"3aa5727c.e5019e","type":"comment","z":"b4c03214.fa42e","name":"send multiple message","info":"Function node can send multiple messages to output ports by returning an array of messages. \n\nSee Node-RED user guide about [functions](https://nodered.org/docs/user-guide/writing-functions).","x":140,"y":40,"wires":[]},{"id":"7241db1e.8946c4","type":"function","z":"b4c03214.fa42e","name":"return array of messages","func":"// returning array of message send elements to output ports\nvar msg1 = { payload:\"first out of output 1\" };\nvar msg2 = { payload:\"second out of output 1\" };\nvar msg3 = { payload:\"third out of output 1\" };\nvar msg4 = { payload:\"only message from output 2\" };\nreturn [ [ msg1, msg2, msg3 ], msg4 ];","outputs":2,"noerr":0,"initialize":"","finalize":"","x":370,"y":100,"wires":[["c6191361.0f3c"],["23a53d00.c89b74"]]},{"id":"23a53d00.c89b74","type":"debug","z":"b4c03214.fa42e","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":590,"y":120,"wires":[]}]

View File

@@ -0,0 +1 @@
[{"id":"cc74476e.cbdf68","type":"inject","z":"e099b273.21259","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"Hello, World!","payloadType":"str","x":190,"y":100,"wires":[["7d90286.706e9d8"]]},{"id":"909906c3.ea9f58","type":"debug","z":"e099b273.21259","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":650,"y":100,"wires":[]},{"id":"d5fc0512.4cd9c8","type":"comment","z":"e099b273.21259","name":"sending messages asynchronously","info":"Function node can asynchronously send a messages to output ports by calling `node.send` function.\n\nSee Node-RED user guide about [functions](https://nodered.org/docs/user-guide/writing-functions).","x":200,"y":40,"wires":[]},{"id":"7d90286.706e9d8","type":"function","z":"e099b273.21259","name":"wait 2s then send message","func":"// setTimeout calls calls specified callback function asynchronously after a specified time\nsetTimeout(function () {\n node.send(msg);\n}, 2*1000);\n","outputs":1,"noerr":0,"initialize":"","finalize":"","x":420,"y":100,"wires":[["909906c3.ea9f58"]]}]

View File

@@ -0,0 +1 @@
[{"id":"64470964.a291a8","type":"inject","z":"d9fbb64b.577e08","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":180,"y":120,"wires":[["ee4f5964.5cdae8"]]},{"id":"ed028c2f.924b","type":"debug","z":"d9fbb64b.577e08","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":530,"y":120,"wires":[]},{"id":"b1686e70.a9f6d","type":"comment","z":"d9fbb64b.577e08","name":"logging events","info":"In body of function node code, following logging functions can be used to log events:\n- `node.log`\n- `node.warn`\n- `node.error`\n- `node.trace`\n- `node.debug`\n\nSee Node-RED user guide about [functions](https://nodered.org/docs/user-guide/writing-functions).","x":140,"y":60,"wires":[]},{"id":"ee4f5964.5cdae8","type":"function","z":"d9fbb64b.577e08","name":"log events","func":"// In function node, node.log, node.warn, and node.error functions can be used for logging\n// See debug sidebar and console output\nnode.log(\"Something happened\");\nnode.warn(\"Something happened you should know about\");\nnode.error(\"Oh no, something bad happened\");\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":350,"y":120,"wires":[["ed028c2f.924b"]]}]

View File

@@ -0,0 +1 @@
[{"id":"89c17d21.15da2","type":"inject","z":"dca895d.18be468","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":180,"y":120,"wires":[["1bcca7af.619428"]]},{"id":"3b9cd70e.8e66e8","type":"debug","z":"dca895d.18be468","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":530,"y":120,"wires":[]},{"id":"f76ea68a.6f3c58","type":"comment","z":"dca895d.18be468","name":"handling errors","info":"Calling `node.error` function with the original message as a second argument, function node can trigger a catch node in the same tab.\n\nSee Node-RED user guide about [functions](https://nodered.org/docs/user-guide/writing-functions).","x":140,"y":60,"wires":[]},{"id":"1bcca7af.619428","type":"function","z":"dca895d.18be468","name":"report error","func":"// In function node, calling node.error functions with the original input message as its second argument triggers catch node\n// See debug sidebar and console output\nnode.error(\"Oh no, something bad happened\", msg);\n// execution should stops here","outputs":1,"noerr":0,"initialize":"","finalize":"","x":350,"y":120,"wires":[["3b9cd70e.8e66e8"]]},{"id":"74854950.d99558","type":"catch","z":"dca895d.18be468","name":"","scope":["1bcca7af.619428"],"uncaught":false,"x":330,"y":180,"wires":[["32743f74.e718a"]]},{"id":"32743f74.e718a","type":"debug","z":"dca895d.18be468","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":510,"y":180,"wires":[]},{"id":"fb884166.e42f3","type":"comment","z":"dca895d.18be468","name":"↑ error information can be found in msg.error","info":"","x":630,"y":220,"wires":[]}]

View File

@@ -0,0 +1 @@
[{"id":"a3a635eb.191188","type":"inject","z":"97cd77e0.37c268","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":180,"y":100,"wires":[["77f57d92.06fa14"]]},{"id":"1a218bea.61ae04","type":"debug","z":"97cd77e0.37c268","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":510,"y":100,"wires":[]},{"id":"a56bde3a.330e1","type":"comment","z":"97cd77e0.37c268","name":"storing data in context","info":"The function node code can store data in the context store.\n\nSee Node-RED user guide about [functions](https://nodered.org/docs/user-guide/writing-functions) and [context store](https://nodered.org/docs/user-guide/context).","x":160,"y":40,"wires":[]},{"id":"77f57d92.06fa14","type":"function","z":"97cd77e0.37c268","name":"counter","func":"// initialise the counter to 0 if it doesn't exist already\nvar count = context.get('count')||0;\ncount += 1;\n// store the value back\ncontext.set('count',count);\n// make it part of the outgoing msg object\nmsg.payload = count;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":340,"y":100,"wires":[["1a218bea.61ae04"]]}]

View File

@@ -0,0 +1 @@
[{"id":"ce0b7cca.34817","type":"inject","z":"b8ceafb9.9c135","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"red","payloadType":"str","x":150,"y":100,"wires":[["a4a6c205.8afd4"]]},{"id":"c98c52d0.ab51f","type":"comment","z":"b8ceafb9.9c135","name":"showing status information","info":"The function node code can provide status decoration by calling `node.status` function.\n\nSee Node-RED user guide about [functions](https://nodered.org/docs/user-guide/writing-functions).","x":150,"y":40,"wires":[]},{"id":"a4a6c205.8afd4","type":"function","z":"b8ceafb9.9c135","name":"show status","func":"// calling node.status show status information below the function node\nswitch (msg.payload) {\n case \"red\":\n node.status({fill:\"red\",shape:\"ring\",text:\"disconnected\"});\n break;\n case \"green\":\n node.status({fill:\"green\",shape:\"dot\",text:\"connected\"});\n break;\n case \"text\":\n node.status({text:\"Just text status\"});\n break;\n case \"clear\":\n node.status({}); // to clear the status \n break;\n}\n\n","outputs":0,"noerr":0,"initialize":"","finalize":"","x":330,"y":100,"wires":[]},{"id":"9f29ae74.8dd11","type":"inject","z":"b8ceafb9.9c135","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"green","payloadType":"str","x":150,"y":140,"wires":[["a4a6c205.8afd4"]]},{"id":"83fc1404.ec0b98","type":"inject","z":"b8ceafb9.9c135","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"text","payloadType":"str","x":150,"y":180,"wires":[["a4a6c205.8afd4"]]},{"id":"517a869c.0ceab8","type":"inject","z":"b8ceafb9.9c135","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"clear","payloadType":"str","x":150,"y":220,"wires":[["a4a6c205.8afd4"]]}]

View File

@@ -0,0 +1 @@
[{"id":"3ece1efd.306c22","type":"inject","z":"1b8d1c9a.2dae03","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":180,"y":120,"wires":[["c9100743.673598"]]},{"id":"ed3da95d.62ee98","type":"debug","z":"1b8d1c9a.2dae03","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":550,"y":120,"wires":[]},{"id":"85b5b8ad.0717d8","type":"comment","z":"1b8d1c9a.2dae03","name":"using external modules\\n(needs change in settings.js - see details on node description of this node) ","info":"The function node can use external node modules using global context value.\n\nAdditional node modules must be loaded in `settings.js` file and added to the `functionGlobalContext` property. \n\nFor example, following definition in `settings.js` load `os` module on start up of Node-RED. \n\n```\nfunctionGlobalContext: {\n os: require(\"os\")\n}\n```\n\nThe `os` module can be accessed in a function blocks as:\n```\nglobal.get(\"os\")\n```\n\nSee Node-RED user guide about [functions](https://nodered.org/docs/user-guide/writing-functions) and [context store](https://nodered.org/docs/user-guide/context).","x":320,"y":60,"wires":[]},{"id":"c9100743.673598","type":"function","z":"1b8d1c9a.2dae03","name":"use os module","func":"// use external os module to access OS information\nvar os = global.get(\"os\");\nmsg.payload = { \n hostname: os.hostname(),\n arch: os.arch(),\n platform: os.platform(),\n release: os.release(),\n free: os.freemem()\n};\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":360,"y":120,"wires":[["ed3da95d.62ee98"]]}]

View File

@@ -0,0 +1 @@
[{"id":"e397736b.a96af","type":"inject","z":"4829bfa2.a23c5","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":180,"y":120,"wires":[["900ad01c.561f"]]},{"id":"1e2a78d6.33f617","type":"debug","z":"4829bfa2.a23c5","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":510,"y":120,"wires":[]},{"id":"83d3f2fd.593b4","type":"comment","z":"4829bfa2.a23c5","name":"setup and close","info":"The function node code provide setup and closecode. \nThe `Setup` tab contains code that will be run whenever the node is started. The `Close` tab contains code that will be run when the node is stopped.\n\nSee Node-RED user guide about [functions](https://nodered.org/docs/user-guide/writing-functions).","x":140,"y":60,"wires":[]},{"id":"900ad01c.561f","type":"function","z":"4829bfa2.a23c5","name":"counter","func":"// get value of global counter\nvar count = global.get('count');\ncount += 1;\n// store the value back\nglobal.set('count',count);\n// make it part of the outgoing msg object\nmsg.payload = count;\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"// initialize global counter\nglobal.set('count', 0);","finalize":"// report current counter to console\nvar count = global.get('count');\nconsole.log(\"count:\", count);","x":340,"y":120,"wires":[["1e2a78d6.33f617"]]}]

View File

@@ -0,0 +1 @@
[{"id":"89904b80.4fcd08","type":"inject","z":"d44bc7c8.48eca8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":190,"y":100,"wires":[["22c235a0.acb41a"]]},{"id":"20fa70dc.7107f","type":"debug","z":"d44bc7c8.48eca8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":550,"y":100,"wires":[]},{"id":"cddf88c9.9df018","type":"comment","z":"d44bc7c8.48eca8","name":"asynchronous setup","info":"The `Setup` code that performs asynchronous work can return a promise object of the work. The completion of the promise is waited before starting function body.\n\nSee Node-RED user guide about [functions](https://nodered.org/docs/user-guide/writing-functions).","x":150,"y":40,"wires":[]},{"id":"22c235a0.acb41a","type":"function","z":"d44bc7c8.48eca8","name":"async. setup","func":"// retrieve message value\nmsg.payload = global.get('message');\nreturn msg;","outputs":1,"noerr":0,"initialize":"// set initial value of message\nglobal.set(\"message\", \"Initializing, World!\");\n// create promise for async work\nvar promise = new Promise((resolve, reject) => {\n // async work: wait 1s, then set message\n setTimeout(() => {\n global.set(\"message\", \"Hello, World!\");\n // report this work successfuly ended\n resolve();\n }, 1000);\n});\n// return the promise that should be executed before function code\nreturn promise;","finalize":"","x":370,"y":100,"wires":[["20fa70dc.7107f"]]}]

View File

@@ -0,0 +1 @@
[{"id":"827a48c0.912d88","type":"comment","z":"ff17dfa9.8fa6d","name":"Map property between different numeric ranges","info":"Range node can scale a number from one numeric range to another.\n\nSee Node-RED cookbook [item](https://cookbook.nodered.org/basic/map-between-different-number-ranges).","x":240,"y":60,"wires":[]},{"id":"bb23bd77.ce725","type":"inject","z":"ff17dfa9.8fa6d","name":"","repeat":"","crontab":"","once":false,"topic":"","payload":"0","payloadType":"num","x":170,"y":120,"wires":[["42ed281c.790b38"]]},{"id":"42ed281c.790b38","type":"range","z":"ff17dfa9.8fa6d","minin":"0","maxin":"1023","minout":"0","maxout":"5","action":"clamp","round":false,"name":"","x":390,"y":160,"wires":[["56e6dd0f.436c24"]]},{"id":"54659d5c.0283e4","type":"inject","z":"ff17dfa9.8fa6d","name":"","repeat":"","crontab":"","once":false,"topic":"","payload":"512","payloadType":"num","x":170,"y":160,"wires":[["42ed281c.790b38"]]},{"id":"85ce0127.07b06","type":"inject","z":"ff17dfa9.8fa6d","name":"","repeat":"","crontab":"","once":false,"topic":"","payload":"1023","payloadType":"num","x":170,"y":200,"wires":[["42ed281c.790b38"]]},{"id":"56e6dd0f.436c24","type":"debug","z":"ff17dfa9.8fa6d","name":"","active":true,"console":"false","complete":"false","x":590,"y":160,"wires":[]}]

View File

@@ -0,0 +1 @@
[{"id":"990f33d3.3ffe2","type":"comment","z":"db89ae0c.f52b5","name":"Scale input value & round result to integer","info":"Range node can map input value to output value according to mapping specification.\nThe result value is rounded to nearest integer if `Round result to the nearest integer?` checkbox is checked.","x":240,"y":60,"wires":[]},{"id":"b2639501.5ad638","type":"inject","z":"db89ae0c.f52b5","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"0","payloadType":"num","x":190,"y":120,"wires":[["dc4509ee.773038"]]},{"id":"dc4509ee.773038","type":"range","z":"db89ae0c.f52b5","minin":"0","maxin":"9","minout":"0","maxout":"128","action":"scale","round":true,"property":"payload","name":"","x":360,"y":120,"wires":[["50991e7e.2ed24"]]},{"id":"50991e7e.2ed24","type":"debug","z":"db89ae0c.f52b5","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":520,"y":120,"wires":[]},{"id":"335e877f.d24e98","type":"inject","z":"db89ae0c.f52b5","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"10","payloadType":"num","x":190,"y":160,"wires":[["dc4509ee.773038"]]},{"id":"5d88207d.4189","type":"inject","z":"db89ae0c.f52b5","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"99","payloadType":"num","x":190,"y":200,"wires":[["dc4509ee.773038"]]}]

View File

@@ -0,0 +1 @@
[{"id":"f0bc6a80.d52578","type":"comment","z":"bdb79f11.23e1d","name":"Limit input value","info":"Range node can map input value to output value according to mapping specification.\nThe result value is limited to specified range if `Scale and limit to the target range` is selected.","x":140,"y":60,"wires":[]},{"id":"69652849.749198","type":"inject","z":"bdb79f11.23e1d","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"0","payloadType":"num","x":170,"y":120,"wires":[["104f6f14.1c72e1"]]},{"id":"104f6f14.1c72e1","type":"range","z":"bdb79f11.23e1d","minin":"0","maxin":"100","minout":"0","maxout":"90","action":"clamp","round":false,"property":"payload","name":"","x":330,"y":120,"wires":[["10fcbed4.9c8d71"]]},{"id":"10fcbed4.9c8d71","type":"debug","z":"bdb79f11.23e1d","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":500,"y":120,"wires":[]},{"id":"93bb4526.7d6e28","type":"inject","z":"bdb79f11.23e1d","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"10","payloadType":"num","x":170,"y":160,"wires":[["104f6f14.1c72e1"]]},{"id":"6892dfd8.42386","type":"inject","z":"bdb79f11.23e1d","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"100","payloadType":"num","x":170,"y":200,"wires":[["104f6f14.1c72e1"]]}]

View File

@@ -0,0 +1 @@
[{"id":"808e354d.8de148","type":"comment","z":"b1446352.d689e","name":"Scale and wrap input value","info":"Range node can map input value to output value according to mapping specification.\nThe result value is wrapped if `Scale and wrap within the target range` is selected.","x":170,"y":60,"wires":[]},{"id":"2f033c72.51dcc4","type":"inject","z":"b1446352.d689e","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"0","payloadType":"num","x":170,"y":120,"wires":[["cdaa82c4.820de"]]},{"id":"cdaa82c4.820de","type":"range","z":"b1446352.d689e","minin":"0","maxin":"9","minout":"0","maxout":"90","action":"roll","round":false,"property":"payload","name":"","x":330,"y":120,"wires":[["77f8872b.2a9968"]]},{"id":"77f8872b.2a9968","type":"debug","z":"b1446352.d689e","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":500,"y":120,"wires":[]},{"id":"84ac6a7e.77b8d8","type":"inject","z":"b1446352.d689e","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"10","payloadType":"num","x":170,"y":160,"wires":[["cdaa82c4.820de"]]},{"id":"92f554c3.b08ad8","type":"inject","z":"b1446352.d689e","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"100","payloadType":"num","x":170,"y":200,"wires":[["cdaa82c4.820de"]]}]

View File

@@ -0,0 +1 @@
[{"id":"87bd706a.aec93","type":"comment","z":"3ae4b3d9.1f77bc","name":"Select output port based on input message value","info":"Switch node can route input message according to predefined rules.\n","x":260,"y":60,"wires":[]},{"id":"ec0f4187.0bf9e","type":"switch","z":"3ae4b3d9.1f77bc","name":"","property":"payload","propertyType":"msg","rules":[{"t":"lt","v":"0","vt":"num"},{"t":"eq","v":"0","vt":"num"},{"t":"gt","v":"0","vt":"num"}],"checkall":"true","repair":false,"outputs":3,"x":330,"y":140,"wires":[["e3d35f5a.ff33"],["91114621.cdd9b8"],["bcbd960b.2f4f48"]]},{"id":"903f0813.e99318","type":"debug","z":"3ae4b3d9.1f77bc","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":650,"y":100,"wires":[]},{"id":"bcbd960b.2f4f48","type":"change","z":"3ae4b3d9.1f77bc","name":"Positive","rules":[{"t":"set","p":"payload","pt":"msg","to":"positive","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":480,"y":180,"wires":[["efb63613.b0aa08"]]},{"id":"91114621.cdd9b8","type":"change","z":"3ae4b3d9.1f77bc","name":"Zero","rules":[{"t":"set","p":"payload","pt":"msg","to":"zero","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":470,"y":140,"wires":[["6d4214c1.524a9c"]]},{"id":"e3d35f5a.ff33","type":"change","z":"3ae4b3d9.1f77bc","name":"Negative","rules":[{"t":"set","p":"payload","pt":"msg","to":"negative","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":480,"y":100,"wires":[["903f0813.e99318"]]},{"id":"6d4214c1.524a9c","type":"debug","z":"3ae4b3d9.1f77bc","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":650,"y":140,"wires":[]},{"id":"efb63613.b0aa08","type":"debug","z":"3ae4b3d9.1f77bc","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":650,"y":180,"wires":[]},{"id":"398299e.aab0b66","type":"inject","z":"3ae4b3d9.1f77bc","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"-10","payloadType":"num","x":190,"y":100,"wires":[["ec0f4187.0bf9e"]]},{"id":"dba0f204.13c4b","type":"inject","z":"3ae4b3d9.1f77bc","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"0","payloadType":"num","x":190,"y":140,"wires":[["ec0f4187.0bf9e"]]},{"id":"bcc219f0.48d8e8","type":"inject","z":"3ae4b3d9.1f77bc","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"10","payloadType":"num","x":190,"y":180,"wires":[["ec0f4187.0bf9e"]]}]

View File

@@ -0,0 +1 @@
[{"id":"6ec19fc7.a32ae","type":"comment","z":"e482b0ab.b1b43","name":"Check all rules","info":"Switch node apply all rules if `checking all rules` is selected in settings panel.","x":120,"y":60,"wires":[]},{"id":"1644e138.f8d1ef","type":"switch","z":"e482b0ab.b1b43","name":"","property":"payload","propertyType":"msg","rules":[{"t":"lt","v":"10","vt":"num"},{"t":"gt","v":"-10","vt":"num"}],"checkall":"true","repair":false,"outputs":2,"x":290,"y":140,"wires":[["624b4e9f.37fee"],["a89d6432.b68318"]]},{"id":"a7f64dbf.3e27b","type":"debug","z":"e482b0ab.b1b43","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":590,"y":100,"wires":[]},{"id":"a89d6432.b68318","type":"change","z":"e482b0ab.b1b43","name":">-10","rules":[{"t":"set","p":"payload","pt":"msg","to":">-10","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":430,"y":180,"wires":[["f1136da2.23516"]]},{"id":"624b4e9f.37fee","type":"change","z":"e482b0ab.b1b43","name":"<10","rules":[{"t":"set","p":"payload","pt":"msg","to":"<10","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":430,"y":100,"wires":[["a7f64dbf.3e27b"]]},{"id":"f1136da2.23516","type":"debug","z":"e482b0ab.b1b43","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":590,"y":180,"wires":[]},{"id":"c7e952e9.88e5e","type":"inject","z":"e482b0ab.b1b43","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"-10","payloadType":"num","x":150,"y":100,"wires":[["1644e138.f8d1ef"]]},{"id":"8cf8babd.b43db8","type":"inject","z":"e482b0ab.b1b43","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"10","payloadType":"num","x":150,"y":180,"wires":[["1644e138.f8d1ef"]]},{"id":"6a43ae86.b92ed","type":"inject","z":"e482b0ab.b1b43","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"0","payloadType":"num","x":150,"y":140,"wires":[["1644e138.f8d1ef"]]}]

View File

@@ -0,0 +1 @@
[{"id":"a12a5708.195688","type":"comment","z":"74b5d6de.372b18","name":"Stop after first match","info":"Switch node stops application of rules if `stopping after first match` is selected in settings panel and a rule evaluates to `true`.","x":160,"y":60,"wires":[]},{"id":"8aebdebf.5d7f2","type":"switch","z":"74b5d6de.372b18","name":"","property":"payload","propertyType":"msg","rules":[{"t":"lt","v":"10","vt":"num"},{"t":"gt","v":"-10","vt":"num"}],"checkall":"false","repair":false,"outputs":2,"x":310,"y":140,"wires":[["5d1851c.a9c5db"],["e8228605.f32018"]]},{"id":"60248c98.69fd44","type":"debug","z":"74b5d6de.372b18","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":610,"y":100,"wires":[]},{"id":"e8228605.f32018","type":"change","z":"74b5d6de.372b18","name":">-10","rules":[{"t":"set","p":"payload","pt":"msg","to":">-10","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":450,"y":180,"wires":[["e9a51608.c322b8"]]},{"id":"5d1851c.a9c5db","type":"change","z":"74b5d6de.372b18","name":"<10","rules":[{"t":"set","p":"payload","pt":"msg","to":"<10","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":450,"y":100,"wires":[["60248c98.69fd44"]]},{"id":"e9a51608.c322b8","type":"debug","z":"74b5d6de.372b18","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":610,"y":180,"wires":[]},{"id":"49222b4b.647a84","type":"inject","z":"74b5d6de.372b18","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"-10","payloadType":"num","x":170,"y":100,"wires":[["8aebdebf.5d7f2"]]},{"id":"39e8c133.a56f7e","type":"inject","z":"74b5d6de.372b18","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"10","payloadType":"num","x":170,"y":180,"wires":[["8aebdebf.5d7f2"]]},{"id":"3a22ec96.965a14","type":"inject","z":"74b5d6de.372b18","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"0","payloadType":"num","x":170,"y":140,"wires":[["8aebdebf.5d7f2"]]}]

View File

@@ -0,0 +1 @@
[{"id":"6dfd4381.eae2ec","type":"comment","z":"7d002985.82f928","name":"Select output based on type of payload value","info":"Switch node can route input message based on type of payload value.","x":210,"y":40,"wires":[]},{"id":"b139dacf.a0d818","type":"switch","z":"7d002985.82f928","name":"","property":"payload","propertyType":"msg","rules":[{"t":"istype","v":"string","vt":"string"},{"t":"istype","v":"number","vt":"number"}],"checkall":"false","repair":false,"outputs":2,"x":330,"y":120,"wires":[["7c5cd60c.e66b28"],["86cf5262.20f18"]]},{"id":"ca403f12.477a8","type":"debug","z":"7d002985.82f928","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":630,"y":160,"wires":[]},{"id":"7c5cd60c.e66b28","type":"change","z":"7d002985.82f928","name":"String","rules":[{"t":"set","p":"payload","pt":"msg","to":"string","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":470,"y":80,"wires":[["d9669648.1177e8"]]},{"id":"86cf5262.20f18","type":"change","z":"7d002985.82f928","name":"Number","rules":[{"t":"set","p":"payload","pt":"msg","to":"number","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":480,"y":160,"wires":[["ca403f12.477a8"]]},{"id":"d9669648.1177e8","type":"debug","z":"7d002985.82f928","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":630,"y":80,"wires":[]},{"id":"d3f1c718.dc67e8","type":"inject","z":"7d002985.82f928","name":"Number:128","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"128","payloadType":"num","x":170,"y":80,"wires":[["b139dacf.a0d818"]]},{"id":"a59e275e.6d48c8","type":"inject","z":"7d002985.82f928","name":"String:128","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"128","payloadType":"str","x":160,"y":160,"wires":[["b139dacf.a0d818"]]}]

View File

@@ -0,0 +1 @@
[{"id":"175ceb0d.8dbe45","type":"comment","z":"17f634f4.e4bc9b","name":"Use JSONata expression for rules","info":"Switch node can use JSONata expression for calculating complex conditions.","x":200,"y":60,"wires":[]},{"id":"d89491c3.793a3","type":"switch","z":"17f634f4.e4bc9b","name":"","property":"payload","propertyType":"msg","rules":[{"t":"jsonata_exp","v":"(payload % 2) = 0","vt":"jsonata"},{"t":"jsonata_exp","v":"(payload % 2) = 1","vt":"jsonata"}],"checkall":"false","repair":false,"outputs":2,"x":310,"y":140,"wires":[["d6cb78a6.872908"],["1f0c62bb.c3d52d"]]},{"id":"9ae9a2aa.a895c","type":"debug","z":"17f634f4.e4bc9b","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":610,"y":100,"wires":[]},{"id":"1f0c62bb.c3d52d","type":"change","z":"17f634f4.e4bc9b","name":"Odd","rules":[{"t":"set","p":"payload","pt":"msg","to":"odd","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":450,"y":180,"wires":[["34b0a9fb.bafdb6"]]},{"id":"d6cb78a6.872908","type":"change","z":"17f634f4.e4bc9b","name":"Even","rules":[{"t":"set","p":"payload","pt":"msg","to":"even","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":450,"y":100,"wires":[["9ae9a2aa.a895c"]]},{"id":"34b0a9fb.bafdb6","type":"debug","z":"17f634f4.e4bc9b","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":610,"y":180,"wires":[]},{"id":"7beb0333.a55bac","type":"inject","z":"17f634f4.e4bc9b","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"7","payloadType":"num","x":170,"y":100,"wires":[["d89491c3.793a3"]]},{"id":"a8db47cf.58ba18","type":"inject","z":"17f634f4.e4bc9b","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"8","payloadType":"num","x":170,"y":180,"wires":[["d89491c3.793a3"]]}]

View File

@@ -0,0 +1 @@
[{"id":"1c09dc33.934504","type":"comment","z":"166069bc.648516","name":"Use JSONata expression for switch value","info":"Switch node can use JSONata expression for calculating complex switch value.","x":200,"y":60,"wires":[]},{"id":"c7ca4974.d638f8","type":"switch","z":"166069bc.648516","name":"","property":"(payload % 2) = 0","propertyType":"jsonata","rules":[{"t":"true"},{"t":"false"}],"checkall":"false","repair":false,"outputs":2,"x":290,"y":140,"wires":[["ac921b1d.c0dbe8"],["89adcfcc.53d6d"]]},{"id":"ab8972e0.e98b7","type":"debug","z":"166069bc.648516","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":590,"y":100,"wires":[]},{"id":"89adcfcc.53d6d","type":"change","z":"166069bc.648516","name":"Odd","rules":[{"t":"set","p":"payload","pt":"msg","to":"odd","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":430,"y":180,"wires":[["426c68cf.64f0e8"]]},{"id":"ac921b1d.c0dbe8","type":"change","z":"166069bc.648516","name":"Even","rules":[{"t":"set","p":"payload","pt":"msg","to":"even","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":430,"y":100,"wires":[["ab8972e0.e98b7"]]},{"id":"426c68cf.64f0e8","type":"debug","z":"166069bc.648516","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":590,"y":180,"wires":[]},{"id":"63377f1c.2fbfc","type":"inject","z":"166069bc.648516","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"7","payloadType":"num","x":150,"y":100,"wires":[["c7ca4974.d638f8"]]},{"id":"ea2fa596.ff1638","type":"inject","z":"166069bc.648516","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"8","payloadType":"num","x":150,"y":180,"wires":[["c7ca4974.d638f8"]]}]

View File

@@ -0,0 +1 @@
[{"id":"61ee9b5c.b9e474","type":"comment","z":"c7e3a049.f68d8","name":"Recreate message sequence","info":"Switch node can recreate message sequence from input message sequence for each output port.","x":160,"y":60,"wires":[]},{"id":"e3a71ee7.ec465","type":"switch","z":"c7e3a049.f68d8","name":"","property":"payload","propertyType":"msg","rules":[{"t":"gt","v":"0","vt":"str"},{"t":"else"}],"checkall":"true","repair":true,"outputs":2,"x":490,"y":140,"wires":[["f5f59cc2.a358f"],["ea61fc1e.afc62"]]},{"id":"5fd951bb.c150e","type":"debug","z":"c7e3a049.f68d8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":810,"y":100,"wires":[]},{"id":"cc02b428.9abb38","type":"debug","z":"c7e3a049.f68d8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":810,"y":180,"wires":[]},{"id":"5ad82808.648ef8","type":"inject","z":"c7e3a049.f68d8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"[3, -2, -1, 1, -3, 2]","payloadType":"json","x":180,"y":140,"wires":[["5f435601.bb9ef8"]]},{"id":"5f435601.bb9ef8","type":"split","z":"c7e3a049.f68d8","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":350,"y":140,"wires":[["e3a71ee7.ec465"]]},{"id":"f5f59cc2.a358f","type":"join","z":"c7e3a049.f68d8","name":"Positive","mode":"auto","build":"string","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":640,"y":100,"wires":[["5fd951bb.c150e"]]},{"id":"ea61fc1e.afc62","type":"join","z":"c7e3a049.f68d8","name":"Negative","mode":"auto","build":"string","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":640,"y":180,"wires":[["cc02b428.9abb38"]]}]

View File

@@ -0,0 +1 @@
[{"id":"7ca55649.268c78","type":"comment","z":"7e4b3910.6cefb8","name":"Route a message based on one of its properties","info":"Switch node can route a message to different flows according to the value of any property (e.g. `msg.topic`).\n\nSee Node-RED cookbook [item](https://cookbook.nodered.org/basic/route-on-property).","x":240,"y":60,"wires":[]},{"id":"f2cbd8ce.34c4c8","type":"switch","z":"7e4b3910.6cefb8","name":"Route ","property":"topic","propertyType":"msg","rules":[{"t":"eq","v":"temperature","vt":"str"},{"t":"eq","v":"humidity","vt":"str"},{"t":"eq","v":"pressure","vt":"str"}],"checkall":"true","repair":false,"outputs":3,"x":370,"y":160,"wires":[["50651c06.281524"],["2786389.31cc5c8"],["e4db256d.a80ca8"]]},{"id":"c4de36a5.f14bc8","type":"inject","z":"7e4b3910.6cefb8","name":"","repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"temperature","payload":"27","payloadType":"num","x":180,"y":120,"wires":[["f2cbd8ce.34c4c8"]]},{"id":"96073ecd.9207f","type":"inject","z":"7e4b3910.6cefb8","name":"","repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"humidity","payload":"45","payloadType":"num","x":170,"y":160,"wires":[["f2cbd8ce.34c4c8"]]},{"id":"50651c06.281524","type":"debug","z":"7e4b3910.6cefb8","name":"Temperature","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":550,"y":120,"wires":[]},{"id":"2786389.31cc5c8","type":"debug","z":"7e4b3910.6cefb8","name":"Humidity","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":540,"y":160,"wires":[]},{"id":"e4db256d.a80ca8","type":"debug","z":"7e4b3910.6cefb8","name":"Pressure","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":540,"y":200,"wires":[]},{"id":"11b023ef.147c9c","type":"inject","z":"7e4b3910.6cefb8","name":"","repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"pressure","payload":"1001","payloadType":"num","x":170,"y":200,"wires":[["f2cbd8ce.34c4c8"]]}]

View File

@@ -0,0 +1 @@
[{"id":"c619693c.5d47e8","type":"comment","z":"1851d301.c01c2d","name":"Route a message based on a context value","info":"Switch node can route a message to different flows according to the current value of a flow context property.\n\nSee Node-RED cookbook [item](https://cookbook.nodered.org/basic/route-on-context).","x":220,"y":60,"wires":[]},{"id":"fd7378.4448ec88","type":"inject","z":"1851d301.c01c2d","name":"Inject","repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":190,"y":180,"wires":[["85c9adae.e7d27"]]},{"id":"85c9adae.e7d27","type":"switch","z":"1851d301.c01c2d","name":"Context based routing","property":"state","propertyType":"flow","rules":[{"t":"eq","v":"1","vt":"num"},{"t":"eq","v":"2","vt":"num"},{"t":"eq","v":"3","vt":"num"}],"checkall":"true","repair":false,"outputs":3,"x":400,"y":180,"wires":[["beb75c77.48c8c"],["ec521bae.6d9da8"],["46b7be29.5ee9b"]]},{"id":"beb75c77.48c8c","type":"debug","z":"1851d301.c01c2d","name":"Output 1","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","x":640,"y":120,"wires":[]},{"id":"ec521bae.6d9da8","type":"debug","z":"1851d301.c01c2d","name":"Output 2","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","x":640,"y":180,"wires":[]},{"id":"46b7be29.5ee9b","type":"debug","z":"1851d301.c01c2d","name":"Output 3","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","x":640,"y":240,"wires":[]},{"id":"20591916.597ac6","type":"inject","z":"1851d301.c01c2d","name":"Set state 0","repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"0","payloadType":"num","x":200,"y":260,"wires":[["d2c4662.6f8e098"]]},{"id":"22bf9e89.7f55f2","type":"inject","z":"1851d301.c01c2d","name":"Set state 1","repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"1","payloadType":"num","x":200,"y":300,"wires":[["d2c4662.6f8e098"]]},{"id":"c2e46f80.42ee5","type":"inject","z":"1851d301.c01c2d","name":"Set state 2","repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"2","payloadType":"num","x":200,"y":340,"wires":[["d2c4662.6f8e098"]]},{"id":"ff766a3e.5c5fe8","type":"inject","z":"1851d301.c01c2d","name":"Set state 3","repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"3","payloadType":"num","x":200,"y":380,"wires":[["d2c4662.6f8e098"]]},{"id":"d2c4662.6f8e098","type":"change","z":"1851d301.c01c2d","name":"Set flow.state","rules":[{"t":"set","p":"state","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":420,"y":300,"wires":[[]]}]

View File

@@ -0,0 +1 @@
[{"id":"eaf91a6b.a55da8","type":"comment","z":"73a69428.bf4fec","name":"Advanced mustache example","info":"Template node can create a string value using [Mustache](http://mustache.github.io/mustache.5.html) syntax.","x":200,"y":80,"wires":[]},{"id":"61fbfe34.14a02","type":"inject","z":"73a69428.bf4fec","name":"Price of fruits","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"Fruits","payload":"[{\"name\":\"apple\",\"price\":100},{\"name\":\"orange\",\"price\":80},{\"name\":\"banana\",\"price\":210}]","payloadType":"json","x":210,"y":140,"wires":[["bf0cb02.d8e4b5"]]},{"id":"bf0cb02.d8e4b5","type":"template","z":"73a69428.bf4fec","name":"","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"# Price List of {{topic}}\n\n{{! outputs list of prices }}\n{{#payload}}\n- {{name}}: {{price}}\n{{/payload}}\n","output":"str","x":380,"y":140,"wires":[["153eb0ff.5622df"]]},{"id":"153eb0ff.5622df","type":"debug","z":"73a69428.bf4fec","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":550,"y":140,"wires":[]}]

View File

@@ -0,0 +1 @@
[{"id":"fe821493.2e0e28","type":"comment","z":"1e6bd604.afc8fa","name":"Parse result as JSON","info":"Template node can create a string value using [Mustache](http://mustache.github.io/mustache.5.html) syntax.\nIf `Partsed JSON` output is selected, the created string is parsed as JSON format and JavaScript object is send as an output payload value.","x":160,"y":60,"wires":[]},{"id":"931f94e8.592cd8","type":"inject","z":"1e6bd604.afc8fa","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"message","payload":"Hello, World!","payloadType":"str","x":220,"y":120,"wires":[["bb2b0dad.b24b5"]]},{"id":"bb2b0dad.b24b5","type":"template","z":"1e6bd604.afc8fa","name":"JSON template","field":"payload","fieldType":"msg","format":"json","syntax":"mustache","template":"{\n \"key\" : \"{{topic}}\",\n \"value\": \"{{payload}}\"\n}\n","output":"json","x":440,"y":120,"wires":[["baf2e48.2b97418"]]},{"id":"baf2e48.2b97418","type":"debug","z":"1e6bd604.afc8fa","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":630,"y":120,"wires":[]}]

View File

@@ -0,0 +1 @@
[{"id":"6ad06659.a1e4e8","type":"comment","z":"369312e8.ba755e","name":"Parse result as YAML","info":"Template node can create a string value using [Mustache](http://mustache.github.io/mustache.5.html) syntax.\nIf `Partsed YAML` output is selected, the created string is parsed as YAML format and JavaScript object is send as an output payload value.","x":180,"y":60,"wires":[]},{"id":"8d6be9a2.c3fa58","type":"inject","z":"369312e8.ba755e","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"message","payload":"Hello, World!","payloadType":"str","x":240,"y":120,"wires":[["69369c3.4a98164"]]},{"id":"69369c3.4a98164","type":"template","z":"369312e8.ba755e","name":"YAML template","field":"payload","fieldType":"msg","format":"yaml","syntax":"mustache","template":"key: {{topic}}\nvalue: {{payload}}","output":"yaml","x":460,"y":120,"wires":[["11fb2934.f5de27"]]},{"id":"11fb2934.f5de27","type":"debug","z":"369312e8.ba755e","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":650,"y":120,"wires":[]}]

View File

@@ -0,0 +1 @@
[{"id":"ec5a531b.68b65","type":"inject","z":"90acd374.2feda","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":160,"y":100,"wires":[["cb5e0c78.4bf3d"]]},{"id":"1b0f8c3e.1fd7e4","type":"debug","z":"90acd374.2feda","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":490,"y":100,"wires":[]},{"id":"cb5e0c78.4bf3d","type":"trigger","z":"90acd374.2feda","name":"","op1":"1","op2":"0","op1type":"str","op2type":"str","duration":"2","extend":false,"units":"s","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":320,"y":100,"wires":[["1b0f8c3e.1fd7e4"]]},{"id":"4e5bf6b2.b4dd58","type":"comment","z":"90acd374.2feda","name":"Oputputs two values with interval","info":"Outputs 1. Then output 0 after a certain period of time.\n\n*This could be used, for example, to blink an LED attached to a Raspberry Pi GPIO pin.*","x":170,"y":40,"wires":[]}]

View File

@@ -0,0 +1 @@
[{"id":"87bd706a.aec93","type":"comment","z":"3ae4b3d9.1f77bc","name":"Trigger a flow if a message isn't received after a defined time","info":"Trigger node can be used to wait a specified amount of time to send a message.\n\nSee Node-RED [cookbook](https://cookbook.nodered.org/basic/trigger-timeout).","x":300,"y":60,"wires":[]},{"id":"b1b5829a.b43ff","type":"debug","z":"3ae4b3d9.1f77bc","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":550,"y":120,"wires":[]},{"id":"e4820019.7741b","type":"inject","z":"3ae4b3d9.1f77bc","name":"","repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":200,"y":120,"wires":[["cf16fb34.738f28","b1b5829a.b43ff"]]},{"id":"cf16fb34.738f28","type":"trigger","z":"3ae4b3d9.1f77bc","name":"Watchdog","op1":"","op2":"timeout","op1type":"nul","op2type":"str","duration":"5","extend":true,"units":"s","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":370,"y":160,"wires":[["124f656.5f0c09b"]]},{"id":"124f656.5f0c09b","type":"debug","z":"3ae4b3d9.1f77bc","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":550,"y":160,"wires":[]}]

View File

@@ -0,0 +1 @@
[{"id":"d55745be.e4ecd8","type":"inject","z":"bab6594e.d2a3d8","name":"","repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":160,"y":140,"wires":[["ecac46bf.9751c8","cf35bbed.ce1298"]]},{"id":"ecac46bf.9751c8","type":"debug","z":"bab6594e.d2a3d8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":670,"y":140,"wires":[]},{"id":"cf35bbed.ce1298","type":"trigger","z":"bab6594e.d2a3d8","name":"","op1":"reset","op2":"true","op1type":"str","op2type":"bool","duration":"2","extend":true,"units":"s","reset":"","bytopic":"all","outputs":1,"x":320,"y":180,"wires":[["febbebba.455238"]]},{"id":"febbebba.455238","type":"trigger","z":"bab6594e.d2a3d8","name":"","op1":"0","op2":"0","op1type":"num","op2type":"str","duration":"-2","extend":false,"units":"s","reset":"reset","bytopic":"all","outputs":1,"x":480,"y":180,"wires":[["ecac46bf.9751c8"]]},{"id":"4bad6a7.9a1d194","type":"comment","z":"bab6594e.d2a3d8","name":"Send placeholder messages when a stream stops sending","info":"Trigger node can be used to detect when a message has not arrived after a defined interval and a second Trigger node to send the placeholder messages at a regular interval..\n\nSee Node-RED [cookbook](https://cookbook.nodered.org/basic/trigger-placeholder).","x":250,"y":80,"wires":[]}]

View File

@@ -0,0 +1 @@
[{"id":"d24083e7.fedc7","type":"comment","z":"58cb85a8.82904c","name":"Timeout processing using trigger node","info":"It is possible to configure timeout processing by combining two Trigger nodes. \n\nIn the first Trigger node settings panel, `send second message to separate output` checkbox is checked. With this specification, this trigger node will have two output ports. When the node receives an input message, it outputs the message to the first port, and after a specified period of time, it outputs the specified message to the second port.\n\nThe second trigger node is specified to handle each message ID (`msg._msgid`). This means that only the first received message among the messages with the same ID is transmitted. The time specified for it represents the retention time of information for message filtering and must be longer than the processing time for the timeout.\n","x":190,"y":60,"wires":[]},{"id":"8dcb51d5.90fbb","type":"inject","z":"58cb85a8.82904c","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"1","payloadType":"num","x":150,"y":160,"wires":[["69b526f1.347808"]]},{"id":"3b2238f8.71f6c8","type":"debug","z":"58cb85a8.82904c","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":870,"y":200,"wires":[]},{"id":"69b526f1.347808","type":"trigger","z":"58cb85a8.82904c","name":"","op1":"","op2":"0","op1type":"pay","op2type":"str","duration":"3","extend":false,"units":"s","reset":"","bytopic":"all","topic":"topic","outputs":2,"x":320,"y":200,"wires":[["3802c45b.84121c"],["a3c01d51.86cbb"]]},{"id":"7096b59a.c265fc","type":"trigger","z":"58cb85a8.82904c","name":"","op1":"","op2":"","op1type":"pay","op2type":"nul","duration":"10","extend":false,"units":"s","reset":"","bytopic":"topic","topic":"_msgid","outputs":1,"x":690,"y":200,"wires":[["3b2238f8.71f6c8"]]},{"id":"3802c45b.84121c","type":"function","z":"58cb85a8.82904c","name":"Target Process","func":"// Wait for a specified time period, then send a message.\n// Must preserve incoming message id.\nvar wait = msg.payload;\nsetTimeout(function() {\n msg.payload = \"done: \"+wait+\"s\";\n node.send(msg);\n}, wait*1000);\n","outputs":1,"noerr":0,"initialize":"","finalize":"","x":500,"y":120,"wires":[["7096b59a.c265fc"]]},{"id":"a3c01d51.86cbb","type":"change","z":"58cb85a8.82904c","name":"Set timeout flag","rules":[{"t":"set","p":"payload","pt":"msg","to":"timeout","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":500,"y":240,"wires":[["7096b59a.c265fc"]]},{"id":"ae217597.bedf88","type":"inject","z":"58cb85a8.82904c","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"5","payloadType":"num","x":150,"y":240,"wires":[["69b526f1.347808"]]},{"id":"dc6f5bbe.dc8bd8","type":"comment","z":"58cb85a8.82904c","name":"↓ target process","info":"","x":500,"y":80,"wires":[]},{"id":"fe41a803.a14158","type":"comment","z":"58cb85a8.82904c","name":"↓ send second message after specified time","info":"","x":430,"y":160,"wires":[]},{"id":"fbb2dff0.0bacb","type":"comment","z":"58cb85a8.82904c","name":"↓ pass first message with same ID","info":"","x":760,"y":160,"wires":[]}]

View File

@@ -0,0 +1 @@
[{"id":"74853568.22b87c","type":"batch","z":"703dac02.e61e64","name":"","mode":"count","count":"5","overlap":0,"interval":"5","allowEmptySequence":false,"topics":[],"x":410,"y":260,"wires":[["8f4f683.99d1998"]]},{"id":"3d208473.f31e1c","type":"comment","z":"703dac02.e61e64","name":"Group 5 consecutive messages","info":"","x":210,"y":88,"wires":[]},{"id":"8f4f683.99d1998","type":"join","z":"703dac02.e61e64","name":"","mode":"auto","build":"string","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":"false","timeout":"","count":"","reduceRight":false,"x":550,"y":260,"wires":[["6c47ccb3.bb0184"]]},{"id":"6c47ccb3.bb0184","type":"debug","z":"703dac02.e61e64","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":710,"y":260,"wires":[]},{"id":"49c2ac1.59a9354","type":"comment","z":"703dac02.e61e64","name":"↑ create message sequence with 5 messages","info":"","x":530,"y":300,"wires":[]},{"id":"311dd6b4.5aeb7a","type":"comment","z":"703dac02.e61e64","name":"↓ join sequence to array","info":"","x":600,"y":220,"wires":[]},{"id":"e27c55b0.18e9c8","type":"inject","z":"703dac02.e61e64","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":180,"y":180,"wires":[["9e65f29a.69ca2"]]},{"id":"9e65f29a.69ca2","type":"function","z":"703dac02.e61e64","name":"send: 0-29","func":"for(var x = 0; x < 30; x++) {\n node.send({payload: x});\n}","outputs":1,"noerr":0,"x":350,"y":180,"wires":[["74853568.22b87c"]]},{"id":"817acbfb.452af8","type":"comment","z":"703dac02.e61e64","name":"↓ send sequence: 0-29","info":"","x":380,"y":140,"wires":[]},{"id":"53645699.a35c48","type":"batch","z":"703dac02.e61e64","name":"","mode":"count","count":"5","overlap":"1","interval":"5","allowEmptySequence":false,"topics":[],"x":410,"y":528,"wires":[["4cb873e6.f9996c"]]},{"id":"ecff527d.d64cb","type":"comment","z":"703dac02.e61e64","name":"Group 5 consecutive messages with overlap of 1 msg","info":"","x":280,"y":356,"wires":[]},{"id":"4cb873e6.f9996c","type":"join","z":"703dac02.e61e64","name":"","mode":"auto","build":"string","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":"false","timeout":"","count":"","reduceRight":false,"x":550,"y":528,"wires":[["51089be3.4ecbf4"]]},{"id":"51089be3.4ecbf4","type":"debug","z":"703dac02.e61e64","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":710,"y":528,"wires":[]},{"id":"84c34533.6284a8","type":"comment","z":"703dac02.e61e64","name":"↑ create message sequence with 5 messages with overlap of 1 msg","info":"","x":600,"y":568,"wires":[]},{"id":"c7241026.18245","type":"comment","z":"703dac02.e61e64","name":"↓ join sequence to array","info":"","x":600,"y":488,"wires":[]},{"id":"67d24449.028eec","type":"inject","z":"703dac02.e61e64","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":180,"y":448,"wires":[["5d909bfb.6faf44"]]},{"id":"5d909bfb.6faf44","type":"function","z":"703dac02.e61e64","name":"send: 0-29","func":"for(var x = 0; x < 30; x++) {\n node.send({payload: x});\n}","outputs":1,"noerr":0,"x":350,"y":448,"wires":[["53645699.a35c48"]]},{"id":"e7af9fbb.f30ad","type":"comment","z":"703dac02.e61e64","name":"↓ send sequence: 0-29","info":"","x":380,"y":408,"wires":[]},{"id":"f4a38f7b.8d62f","type":"comment","z":"703dac02.e61e64","name":"Example: Number-based Group Mode","info":"*Number-based Group mode* of batch node can be used to create new message sequences from incoming messages. Recently received *N*-messages are grouped to a sequence. Creating message sequences that has overwrap with adjacent message group is possible.\n","x":190,"y":40,"wires":[]}]

Some files were not shown because too many files have changed in this diff Show More