@node-red/nodes 2.2.2 → 2.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/core/common/20-inject.js +3 -2
- package/core/common/21-debug.js +5 -2
- package/core/function/10-function.html +1 -1
- package/core/function/15-change.js +2 -2
- package/core/function/89-delay.js +13 -9
- package/core/network/10-mqtt.html +21 -1
- package/core/network/10-mqtt.js +140 -45
- package/core/network/21-httprequest.html +12 -0
- package/core/network/21-httprequest.js +4 -0
- package/core/network/22-websocket.js +16 -13
- package/core/network/31-tcpin.js +17 -19
- package/core/parsers/70-CSV.js +5 -2
- package/core/parsers/70-JSON.html +1 -1
- package/core/sequence/17-split.js +4 -2
- package/core/sequence/19-batch.html +1 -1
- package/examples/function/delay/06 - Simple Queue with release +149 -0
- package/locales/en-US/messages.json +2 -1
- package/locales/ja/function/10-function.html +1 -1
- package/locales/ja/network/10-mqtt.html +1 -1
- package/package.json +1 -1
package/core/common/20-inject.js
CHANGED
|
@@ -109,9 +109,10 @@ module.exports = function(RED) {
|
|
|
109
109
|
if (!property) return;
|
|
110
110
|
|
|
111
111
|
if (valueType === "jsonata") {
|
|
112
|
-
if (p.
|
|
112
|
+
if (p.v) {
|
|
113
113
|
try {
|
|
114
|
-
var
|
|
114
|
+
var exp = RED.util.prepareJSONataExpression(p.v, node);
|
|
115
|
+
var val = RED.util.evaluateJSONataExpression(exp, msg);
|
|
115
116
|
RED.util.setMessageProperty(msg, property, val, true);
|
|
116
117
|
}
|
|
117
118
|
catch (err) {
|
package/core/common/21-debug.js
CHANGED
|
@@ -108,7 +108,9 @@ module.exports = function(RED) {
|
|
|
108
108
|
}
|
|
109
109
|
})
|
|
110
110
|
this.on("input", function(msg, send, done) {
|
|
111
|
-
if (hasOwnProperty.call(msg, "status") &&
|
|
111
|
+
if (hasOwnProperty.call(msg, "status") && msg.status &&
|
|
112
|
+
hasOwnProperty.call(msg.status, "source") && msg.status.source &&
|
|
113
|
+
hasOwnProperty.call(msg.status.source, "id") && (msg.status.source.id === node.id)) {
|
|
112
114
|
done();
|
|
113
115
|
return;
|
|
114
116
|
}
|
|
@@ -129,7 +131,8 @@ module.exports = function(RED) {
|
|
|
129
131
|
fill = "red";
|
|
130
132
|
st = msg.error.message;
|
|
131
133
|
}
|
|
132
|
-
if (hasOwnProperty.call(msg, "status")
|
|
134
|
+
if (hasOwnProperty.call(msg, "status") &&
|
|
135
|
+
msg.status) {
|
|
133
136
|
fill = msg.status.fill || "grey";
|
|
134
137
|
shape = msg.status.shape || "ring";
|
|
135
138
|
st = msg.status.text || "";
|
|
@@ -399,7 +399,7 @@
|
|
|
399
399
|
$("#func-tabs-content").children().hide();
|
|
400
400
|
$("#" + tab.id).show();
|
|
401
401
|
let editor = $("#" + tab.id).find('.monaco-editor').first();
|
|
402
|
-
|
|
402
|
+
if(editor.length) {
|
|
403
403
|
if(that.editor.nodered && that.editor.type == "monaco") {
|
|
404
404
|
that.editor.nodered.refreshModuleLibs(getLibsList());
|
|
405
405
|
}
|
|
@@ -168,9 +168,9 @@ module.exports = function(RED) {
|
|
|
168
168
|
return getFromValueType(RED.util.getMessageProperty(msg,rule.from),done);
|
|
169
169
|
} else if (rule.fromt === 'flow' || rule.fromt === 'global') {
|
|
170
170
|
var contextKey = RED.util.parseContextStore(rule.from);
|
|
171
|
-
if (/\[msg\./.test(
|
|
171
|
+
if (/\[msg\./.test(contextKey.key)) {
|
|
172
172
|
// The key has a nest msg. reference to evaluate first
|
|
173
|
-
|
|
173
|
+
contextKey.key = RED.util.normalisePropertyExpression(contextKey.key,msg,true);
|
|
174
174
|
}
|
|
175
175
|
node.context()[rule.fromt].get(contextKey.key, contextKey.store, (err,fromValue) => {
|
|
176
176
|
if (err) {
|
|
@@ -275,18 +275,22 @@ module.exports = function(RED) {
|
|
|
275
275
|
if (msg.hasOwnProperty("flush")) {
|
|
276
276
|
var len = node.buffer.length;
|
|
277
277
|
if (typeof(msg.flush) == 'number') { len = Math.min(Math.floor(msg.flush),len); }
|
|
278
|
-
|
|
279
|
-
const msgInfo = node.buffer.shift();
|
|
280
|
-
if (Object.keys(msgInfo.msg).length > 1) {
|
|
281
|
-
node.send(msgInfo.msg);
|
|
282
|
-
msgInfo.done();
|
|
283
|
-
}
|
|
284
|
-
len = len - 1;
|
|
285
|
-
}
|
|
286
|
-
if (node.buffer.length === 0) {
|
|
278
|
+
if (len === 0) {
|
|
287
279
|
clearInterval(node.intervalID);
|
|
288
280
|
node.intervalID = -1;
|
|
289
281
|
}
|
|
282
|
+
else {
|
|
283
|
+
while (len > 0) {
|
|
284
|
+
const msgInfo = node.buffer.shift();
|
|
285
|
+
if (Object.keys(msgInfo.msg).length > 1) {
|
|
286
|
+
node.send(msgInfo.msg);
|
|
287
|
+
msgInfo.done();
|
|
288
|
+
}
|
|
289
|
+
len = len - 1;
|
|
290
|
+
}
|
|
291
|
+
clearInterval(node.intervalID);
|
|
292
|
+
node.intervalID = setInterval(sendMsgFromBuffer, node.rate);
|
|
293
|
+
}
|
|
290
294
|
node.status({fill:"blue",shape:"dot",text:node.buffer.length});
|
|
291
295
|
done();
|
|
292
296
|
}
|
|
@@ -442,7 +442,17 @@
|
|
|
442
442
|
}
|
|
443
443
|
return defaultContentType || 'none'
|
|
444
444
|
}
|
|
445
|
-
|
|
445
|
+
/**
|
|
446
|
+
* Test a topic string is valid for publishing
|
|
447
|
+
* @param {string} topic
|
|
448
|
+
* @returns `true` if it is a valid topic
|
|
449
|
+
*/
|
|
450
|
+
function validateMQTTPublishTopic(topic, opts) {
|
|
451
|
+
if(!topic || topic == "" || !/[\+#\b\f\n\r\t\v\0]/.test(topic)) {
|
|
452
|
+
return true;
|
|
453
|
+
}
|
|
454
|
+
return RED._("node-red:mqtt.errors.invalid-topic");
|
|
455
|
+
}
|
|
446
456
|
RED.nodes.registerType('mqtt-broker',{
|
|
447
457
|
category: 'config',
|
|
448
458
|
defaults: {
|
|
@@ -480,6 +490,7 @@
|
|
|
480
490
|
willRetain: {value:false},
|
|
481
491
|
willPayload: {value:""},
|
|
482
492
|
willMsg: { value: {}},
|
|
493
|
+
userProps: { value: ""},
|
|
483
494
|
sessionExpiry: {value:0}
|
|
484
495
|
},
|
|
485
496
|
credentials: {
|
|
@@ -609,6 +620,7 @@
|
|
|
609
620
|
default: !this.userProps ? 'none':'json',
|
|
610
621
|
types: [typedInputNoneOpt, 'json']
|
|
611
622
|
});
|
|
623
|
+
$("#node-config-input-userProps").typedInput('value',this.userProps);
|
|
612
624
|
if (typeof this.keepalive === 'undefined') {
|
|
613
625
|
this.keepalive = 15;
|
|
614
626
|
$("#node-config-input-keepalive").val(this.keepalive);
|
|
@@ -718,6 +730,14 @@
|
|
|
718
730
|
}
|
|
719
731
|
|
|
720
732
|
if (v5) {
|
|
733
|
+
this.userProps = "";
|
|
734
|
+
const userPropsType = $("#node-config-input-userProps").typedInput("type");
|
|
735
|
+
if(userPropsType == "json") {
|
|
736
|
+
const userProps = $("#node-config-input-userProps").val();
|
|
737
|
+
if (userProps && typeof userProps === "string") {
|
|
738
|
+
this.userProps = userProps.trim();
|
|
739
|
+
}
|
|
740
|
+
}
|
|
721
741
|
this.birthMsg = saveV5Message("birth");
|
|
722
742
|
this.closeMsg = saveV5Message("close");
|
|
723
743
|
this.willMsg = saveV5Message("will");
|
package/core/network/10-mqtt.js
CHANGED
|
@@ -68,12 +68,21 @@ module.exports = function(RED) {
|
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
/**
|
|
71
|
-
* Test a topic string is valid
|
|
71
|
+
* Test a topic string is valid for subscription
|
|
72
72
|
* @param {string} topic
|
|
73
73
|
* @returns `true` if it is a valid topic
|
|
74
74
|
*/
|
|
75
75
|
function isValidSubscriptionTopic(topic) {
|
|
76
|
-
return /^(#$|(\+|[^+#]*)(\/(\+|[^+#]*))*(\/(\+|#|[^+#]*))?$)/.test(topic)
|
|
76
|
+
return /^(#$|(\+|[^+#]*)(\/(\+|[^+#]*))*(\/(\+|#|[^+#]*))?$)/.test(topic);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Test a topic string is valid for publishing
|
|
81
|
+
* @param {string} topic
|
|
82
|
+
* @returns `true` if it is a valid topic
|
|
83
|
+
*/
|
|
84
|
+
function isValidPublishTopic(topic) {
|
|
85
|
+
return !/[\+#\b\f\n\r\t\v\0]/.test(topic);
|
|
77
86
|
}
|
|
78
87
|
|
|
79
88
|
/**
|
|
@@ -103,7 +112,7 @@ module.exports = function(RED) {
|
|
|
103
112
|
if(src[propName] === "true" || src[propName] === true) {
|
|
104
113
|
dst[propName] = true;
|
|
105
114
|
} else if(src[propName] === "false" || src[propName] === false) {
|
|
106
|
-
dst[propName] =
|
|
115
|
+
dst[propName] = false;
|
|
107
116
|
}
|
|
108
117
|
} else {
|
|
109
118
|
if(def != undefined) dst[propName] = def;
|
|
@@ -288,7 +297,7 @@ module.exports = function(RED) {
|
|
|
288
297
|
//TODO: delete msg.responseTopic - to prevent it being resent?
|
|
289
298
|
}
|
|
290
299
|
}
|
|
291
|
-
topicOK = topicOK &&
|
|
300
|
+
topicOK = topicOK && isValidPublishTopic(msg.topic);
|
|
292
301
|
|
|
293
302
|
if (topicOK) {
|
|
294
303
|
node.brokerConn.publish(msg, done); // send the message
|
|
@@ -391,6 +400,7 @@ module.exports = function(RED) {
|
|
|
391
400
|
node.options = {};
|
|
392
401
|
node.queue = [];
|
|
393
402
|
node.subscriptions = {};
|
|
403
|
+
node.clientListeners = []
|
|
394
404
|
/** @type {mqtt.MqttClient}*/ this.client;
|
|
395
405
|
node.setOptions = function(opts, init) {
|
|
396
406
|
if(!opts || typeof opts !== "object") {
|
|
@@ -415,8 +425,12 @@ module.exports = function(RED) {
|
|
|
415
425
|
setIfHasProperty(opts, node, "topicAliasMaximum", init);
|
|
416
426
|
setIfHasProperty(opts, node, "maximumPacketSize", init);
|
|
417
427
|
setIfHasProperty(opts, node, "receiveMaximum", init);
|
|
418
|
-
|
|
419
|
-
|
|
428
|
+
//https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901116
|
|
429
|
+
if (hasProperty(opts, "userProperties")) {
|
|
430
|
+
node.userProperties = opts.userProperties;
|
|
431
|
+
} else if (hasProperty(opts, "userProps")) {
|
|
432
|
+
node.userProperties = opts.userProps;
|
|
433
|
+
}
|
|
420
434
|
|
|
421
435
|
function createLWT(topic, payload, qos, retain, v5opts, v5SubPropName) {
|
|
422
436
|
let message = undefined;
|
|
@@ -465,7 +479,7 @@ module.exports = function(RED) {
|
|
|
465
479
|
};
|
|
466
480
|
if(hasProperty(opts, "willTopic")) {
|
|
467
481
|
//will v5 properties must be set in the "properties" sub object
|
|
468
|
-
node.options.will = createLWT(opts.willTopic, opts.willPayload, opts.willQos, opts.willRetain, opts.willMsg, "
|
|
482
|
+
node.options.will = createLWT(opts.willTopic, opts.willPayload, opts.willQos, opts.willRetain, opts.willMsg, "properties");
|
|
469
483
|
};
|
|
470
484
|
} else {
|
|
471
485
|
//update options
|
|
@@ -525,7 +539,7 @@ module.exports = function(RED) {
|
|
|
525
539
|
// Only for ws or wss, check if proxy env var for additional configuration
|
|
526
540
|
if (node.brokerurl.indexOf("wss://") > -1 || node.brokerurl.indexOf("ws://") > -1) {
|
|
527
541
|
// check if proxy is set in env
|
|
528
|
-
let prox, noprox;
|
|
542
|
+
let prox, noprox, noproxy;
|
|
529
543
|
if (process.env.http_proxy) { prox = process.env.http_proxy; }
|
|
530
544
|
if (process.env.HTTP_PROXY) { prox = process.env.HTTP_PROXY; }
|
|
531
545
|
if (process.env.no_proxy) { noprox = process.env.no_proxy.split(","); }
|
|
@@ -652,11 +666,16 @@ module.exports = function(RED) {
|
|
|
652
666
|
setStatusConnecting(node, true);
|
|
653
667
|
try {
|
|
654
668
|
node.serverProperties = {};
|
|
669
|
+
if(node.client) {
|
|
670
|
+
//belt and braces to avoid left over clients
|
|
671
|
+
node.client.end(true);
|
|
672
|
+
node._clientRemoveListeners();
|
|
673
|
+
}
|
|
655
674
|
node.client = mqtt.connect(node.brokerurl, node.options);
|
|
656
675
|
node.client.setMaxListeners(0);
|
|
657
|
-
let callbackDone = false; //prevent re-connects causing node.
|
|
676
|
+
let callbackDone = false; //prevent re-connects causing node._clientOn('connect' firing callback multiple times
|
|
658
677
|
// Register successful connect or reconnect handler
|
|
659
|
-
node.
|
|
678
|
+
node._clientOn('connect', function (connack) {
|
|
660
679
|
node.closing = false;
|
|
661
680
|
node.connecting = false;
|
|
662
681
|
node.connected = true;
|
|
@@ -688,7 +707,7 @@ module.exports = function(RED) {
|
|
|
688
707
|
}
|
|
689
708
|
setStatusConnected(node, true);
|
|
690
709
|
// Remove any existing listeners before resubscribing to avoid duplicates in the event of a re-connection
|
|
691
|
-
node.
|
|
710
|
+
node._clientRemoveListeners('message');
|
|
692
711
|
|
|
693
712
|
// Re-subscribe to stored topics
|
|
694
713
|
for (var s in node.subscriptions) {
|
|
@@ -700,7 +719,7 @@ module.exports = function(RED) {
|
|
|
700
719
|
if (node.subscriptions[s].hasOwnProperty(r)) {
|
|
701
720
|
qos = Math.max(qos,node.subscriptions[s][r].qos);
|
|
702
721
|
_options = node.subscriptions[s][r].options;
|
|
703
|
-
node.
|
|
722
|
+
node._clientOn('message',node.subscriptions[s][r].handler);
|
|
704
723
|
}
|
|
705
724
|
}
|
|
706
725
|
_options.qos = _options.qos || qos;
|
|
@@ -713,11 +732,11 @@ module.exports = function(RED) {
|
|
|
713
732
|
node.publish(node.birthMessage);
|
|
714
733
|
}
|
|
715
734
|
});
|
|
716
|
-
node.
|
|
735
|
+
node._clientOn("reconnect", function() {
|
|
717
736
|
setStatusConnecting(node, true);
|
|
718
737
|
});
|
|
719
738
|
//Broker Disconnect - V5 event
|
|
720
|
-
node.
|
|
739
|
+
node._clientOn("disconnect", function(packet) {
|
|
721
740
|
//Emitted after receiving disconnect packet from broker. MQTT 5.0 feature.
|
|
722
741
|
const rc = (packet && packet.properties && packet.reasonCode) || packet.reasonCode;
|
|
723
742
|
const rs = packet && packet.properties && packet.properties.reasonString || "";
|
|
@@ -731,7 +750,7 @@ module.exports = function(RED) {
|
|
|
731
750
|
setStatusDisconnected(node, true);
|
|
732
751
|
});
|
|
733
752
|
// Register disconnect handlers
|
|
734
|
-
node.
|
|
753
|
+
node._clientOn('close', function () {
|
|
735
754
|
if (node.connected) {
|
|
736
755
|
node.connected = false;
|
|
737
756
|
node.log(RED._("mqtt.state.disconnected",{broker:(node.clientid?node.clientid+"@":"")+node.brokerurl}));
|
|
@@ -743,39 +762,59 @@ module.exports = function(RED) {
|
|
|
743
762
|
|
|
744
763
|
// Register connect error handler
|
|
745
764
|
// The client's own reconnect logic will take care of errors
|
|
746
|
-
node.
|
|
765
|
+
node._clientOn('error', function (error) {
|
|
747
766
|
});
|
|
748
767
|
}catch(err) {
|
|
749
768
|
console.log(err);
|
|
750
769
|
}
|
|
751
770
|
}
|
|
752
771
|
};
|
|
772
|
+
|
|
753
773
|
node.disconnect = function (callback) {
|
|
754
|
-
const _callback = function (
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
node.closing = true;
|
|
758
|
-
node.connecting = false;
|
|
759
|
-
node.connected = false;
|
|
774
|
+
const _callback = function () {
|
|
775
|
+
if(node.connected || node.connecting) {
|
|
776
|
+
setStatusDisconnected(node, true);
|
|
760
777
|
}
|
|
778
|
+
if(node.client) { node._clientRemoveListeners(); }
|
|
779
|
+
node.connecting = false;
|
|
780
|
+
node.connected = false;
|
|
761
781
|
callback && typeof callback == "function" && callback();
|
|
762
782
|
};
|
|
783
|
+
if(!node.client) { return _callback(); }
|
|
784
|
+
if(node.closing) { return _callback(); }
|
|
763
785
|
|
|
764
|
-
|
|
765
|
-
return
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
786
|
+
let waitEnd = (client, ms) => {
|
|
787
|
+
return new Promise( (resolve, reject) => {
|
|
788
|
+
node.closing = true;
|
|
789
|
+
if(!client) {
|
|
790
|
+
resolve();
|
|
791
|
+
} else {
|
|
792
|
+
const t = setTimeout(() => {
|
|
793
|
+
//clean end() has exceeded WAIT_END, lets force end!
|
|
794
|
+
client && client.end(true);
|
|
795
|
+
reject();
|
|
796
|
+
}, ms);
|
|
797
|
+
client.end(() => {
|
|
798
|
+
clearTimeout(t);
|
|
799
|
+
resolve()
|
|
800
|
+
});
|
|
801
|
+
}
|
|
802
|
+
});
|
|
803
|
+
};
|
|
769
804
|
if(node.connected && node.closeMessage) {
|
|
770
805
|
node.publish(node.closeMessage, function (err) {
|
|
771
|
-
node.client.
|
|
772
|
-
|
|
806
|
+
waitEnd(node.client, 2000).then(() => {
|
|
807
|
+
_callback();
|
|
808
|
+
}).catch((e) => {
|
|
809
|
+
_callback();
|
|
810
|
+
})
|
|
773
811
|
});
|
|
774
|
-
} else if(node.connected) {
|
|
775
|
-
node.client.end(endCallBack);
|
|
776
|
-
_callback(true);
|
|
777
812
|
} else {
|
|
778
|
-
|
|
813
|
+
waitEnd(node.client, 2000).then(() => {
|
|
814
|
+
_callback();
|
|
815
|
+
}).catch((e) => {
|
|
816
|
+
_callback();
|
|
817
|
+
})
|
|
779
818
|
}
|
|
780
819
|
}
|
|
781
820
|
node.subscriptionIds = {};
|
|
@@ -812,7 +851,7 @@ module.exports = function(RED) {
|
|
|
812
851
|
};
|
|
813
852
|
node.subscriptions[topic][ref] = sub;
|
|
814
853
|
if (node.connected) {
|
|
815
|
-
node.
|
|
854
|
+
node._clientOn('message',sub.handler);
|
|
816
855
|
node.client.subscribe(topic, options);
|
|
817
856
|
}
|
|
818
857
|
};
|
|
@@ -823,7 +862,7 @@ module.exports = function(RED) {
|
|
|
823
862
|
if (sub) {
|
|
824
863
|
if (sub[ref]) {
|
|
825
864
|
if(node.client) {
|
|
826
|
-
node.
|
|
865
|
+
node._clientRemoveListeners('message',sub[ref].handler);
|
|
827
866
|
}
|
|
828
867
|
delete sub[ref];
|
|
829
868
|
}
|
|
@@ -857,8 +896,18 @@ module.exports = function(RED) {
|
|
|
857
896
|
qos: msg.qos || 0,
|
|
858
897
|
retain: msg.retain || false
|
|
859
898
|
};
|
|
899
|
+
let topicOK = hasProperty(msg, "topic") && (typeof msg.topic === "string") && (isValidPublishTopic(msg.topic));
|
|
860
900
|
//https://github.com/mqttjs/MQTT.js/blob/master/README.md#mqttclientpublishtopic-message-options-callback
|
|
861
901
|
if(node.options.protocolVersion == 5) {
|
|
902
|
+
const bsp = node.serverProperties || {};
|
|
903
|
+
if (msg.userProperties && typeof msg.userProperties !== "object") {
|
|
904
|
+
delete msg.userProperties;
|
|
905
|
+
}
|
|
906
|
+
if (hasProperty(msg, "topicAlias") && !isNaN(Number(msg.topicAlias))) {
|
|
907
|
+
msg.topicAlias = parseInt(msg.topicAlias);
|
|
908
|
+
} else {
|
|
909
|
+
delete msg.topicAlias;
|
|
910
|
+
}
|
|
862
911
|
options.properties = options.properties || {};
|
|
863
912
|
setStrProp(msg, options.properties, "responseTopic");
|
|
864
913
|
setBufferProp(msg, options.properties, "correlationData");
|
|
@@ -868,31 +917,75 @@ module.exports = function(RED) {
|
|
|
868
917
|
setIntProp(msg, options.properties, "topicAlias", 1, node.serverProperties.topicAliasMaximum || 0);
|
|
869
918
|
setBoolProp(msg, options.properties, "payloadFormatIndicator");
|
|
870
919
|
//FUTURE setIntProp(msg, options.properties, "subscriptionIdentifier", 1, 268435455);
|
|
871
|
-
|
|
872
|
-
|
|
920
|
+
|
|
921
|
+
//check & sanitise topic
|
|
922
|
+
if (topicOK && options.properties.topicAlias) {
|
|
923
|
+
let aliasValid = (bsp.topicAliasMaximum && bsp.topicAliasMaximum >= options.properties.topicAlias);
|
|
924
|
+
if (!aliasValid) {
|
|
873
925
|
done("Invalid topicAlias");
|
|
874
926
|
return
|
|
875
927
|
}
|
|
876
928
|
if (node.topicAliases[options.properties.topicAlias] === msg.topic) {
|
|
877
|
-
msg.topic = ""
|
|
929
|
+
msg.topic = "";
|
|
878
930
|
} else {
|
|
879
|
-
node.topicAliases[options.properties.topicAlias] = msg.topic
|
|
931
|
+
node.topicAliases[options.properties.topicAlias] = msg.topic;
|
|
880
932
|
}
|
|
933
|
+
} else if (!msg.topic && options.properties.responseTopic) {
|
|
934
|
+
msg.topic = msg.responseTopic;
|
|
935
|
+
topicOK = isValidPublishTopic(msg.topic);
|
|
936
|
+
delete msg.responseTopic; //prevent responseTopic being resent?
|
|
881
937
|
}
|
|
882
938
|
}
|
|
883
939
|
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
940
|
+
if (topicOK) {
|
|
941
|
+
node.client.publish(msg.topic, msg.payload, options, function(err) {
|
|
942
|
+
done && done(err);
|
|
943
|
+
return
|
|
944
|
+
});
|
|
945
|
+
} else {
|
|
946
|
+
const error = new Error(RED._("mqtt.errors.invalid-topic"));
|
|
947
|
+
error.warn = true;
|
|
948
|
+
done(error);
|
|
949
|
+
}
|
|
888
950
|
}
|
|
889
951
|
};
|
|
890
952
|
|
|
891
953
|
node.on('close', function(done) {
|
|
892
|
-
node.
|
|
893
|
-
|
|
954
|
+
node.disconnect(function() {
|
|
955
|
+
done();
|
|
956
|
+
});
|
|
894
957
|
});
|
|
895
958
|
|
|
959
|
+
/**
|
|
960
|
+
* Add event handlers to the MQTT.js client and track them so that
|
|
961
|
+
* we do not remove any handlers that the MQTT client uses internally.
|
|
962
|
+
* Use {@link node._clientRemoveListeners `node._clientRemoveListeners`} to remove handlers
|
|
963
|
+
* @param {string} event The name of the event
|
|
964
|
+
* @param {function} handler The handler for this event
|
|
965
|
+
*/
|
|
966
|
+
node._clientOn = function(event, handler) {
|
|
967
|
+
node.clientListeners.push({event, handler})
|
|
968
|
+
node.client.on(event, handler)
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
/**
|
|
972
|
+
* Remove event handlers from the MQTT.js client & only the events
|
|
973
|
+
* that we attached in {@link node._clientOn `node._clientOn`}.
|
|
974
|
+
* * If `event` is omitted, then all events matching `handler` are removed
|
|
975
|
+
* * If `handler` is omitted, then all events named `event` are removed
|
|
976
|
+
* * If both parameters are omitted, then all events are removed
|
|
977
|
+
* @param {string} [event] The name of the event (optional)
|
|
978
|
+
* @param {function} [handler] The handler for this event (optional)
|
|
979
|
+
*/
|
|
980
|
+
node._clientRemoveListeners = function(event, handler) {
|
|
981
|
+
node.clientListeners = node.clientListeners.filter((l) => {
|
|
982
|
+
if (event && event !== l.event) { return true; }
|
|
983
|
+
if (handler && handler !== l.handler) { return true; }
|
|
984
|
+
node.client.removeListener(l.event, l.handler)
|
|
985
|
+
return false; //found and removed, filter out this one
|
|
986
|
+
})
|
|
987
|
+
}
|
|
988
|
+
|
|
896
989
|
}
|
|
897
990
|
|
|
898
991
|
RED.nodes.registerType("mqtt-broker",MQTTBrokerNode,{
|
|
@@ -1067,6 +1160,7 @@ module.exports = function(RED) {
|
|
|
1067
1160
|
node.brokerConn.unsubscribe(node.topic,node.id, removed);
|
|
1068
1161
|
}
|
|
1069
1162
|
node.brokerConn.deregister(node, done);
|
|
1163
|
+
node.brokerConn = null;
|
|
1070
1164
|
} else {
|
|
1071
1165
|
done();
|
|
1072
1166
|
}
|
|
@@ -1131,6 +1225,7 @@ module.exports = function(RED) {
|
|
|
1131
1225
|
node.on('close', function(done) {
|
|
1132
1226
|
if (node.brokerConn) {
|
|
1133
1227
|
node.brokerConn.deregister(node,done);
|
|
1228
|
+
node.brokerConn = null;
|
|
1134
1229
|
} else {
|
|
1135
1230
|
done();
|
|
1136
1231
|
}
|
|
@@ -91,6 +91,11 @@
|
|
|
91
91
|
<label for="node-input-senderr" style="width: auto" data-i18n="httpin.senderr"></label>
|
|
92
92
|
</div>
|
|
93
93
|
|
|
94
|
+
<div class="form-row">
|
|
95
|
+
<input type="checkbox" id="node-input-insecureHTTPParser" style="display: inline-block; width: auto; vertical-align: top;">
|
|
96
|
+
<label for="node-input-insecureHTTPParser", style="width: auto;" data-i18n="httpin.insecureHTTPParser"></label>
|
|
97
|
+
</div>
|
|
98
|
+
|
|
94
99
|
|
|
95
100
|
<div class="form-row">
|
|
96
101
|
<label for="node-input-ret"><i class="fa fa-arrow-left"></i> <span data-i18n="httpin.label.return"></span></label>
|
|
@@ -120,6 +125,7 @@
|
|
|
120
125
|
tls: {type:"tls-config",required: false},
|
|
121
126
|
persist: {value:false},
|
|
122
127
|
proxy: {type:"http proxy",required: false},
|
|
128
|
+
insecureHTTPParser: {value: false},
|
|
123
129
|
authType: {value: ""},
|
|
124
130
|
senderr: {value: false}
|
|
125
131
|
},
|
|
@@ -224,6 +230,12 @@
|
|
|
224
230
|
} else {
|
|
225
231
|
$("#node-input-useProxy").prop("checked", false);
|
|
226
232
|
}
|
|
233
|
+
|
|
234
|
+
if (node.insecureHTTPParser) {
|
|
235
|
+
$("node-intput-insecureHTTPParser").prop("checked", true)
|
|
236
|
+
} else {
|
|
237
|
+
$("node-intput-insecureHTTPParser").prop("checked", false)
|
|
238
|
+
}
|
|
227
239
|
updateProxyOptions();
|
|
228
240
|
$("#node-input-useProxy").on("click", function() {
|
|
229
241
|
updateProxyOptions();
|
|
@@ -35,8 +35,6 @@ module.exports = function(RED) {
|
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
var listenerNodes = {};
|
|
38
|
-
var activeListenerNodes = 0;
|
|
39
|
-
|
|
40
38
|
|
|
41
39
|
// A node red node that sets up a local websocket server
|
|
42
40
|
function WebSocketListenerNode(n) {
|
|
@@ -166,7 +164,6 @@ module.exports = function(RED) {
|
|
|
166
164
|
}
|
|
167
165
|
|
|
168
166
|
if (node.isServer) {
|
|
169
|
-
activeListenerNodes++;
|
|
170
167
|
if (!serverUpgradeAdded) {
|
|
171
168
|
RED.server.on('upgrade', handleServerUpgrade);
|
|
172
169
|
serverUpgradeAdded = true
|
|
@@ -210,7 +207,7 @@ module.exports = function(RED) {
|
|
|
210
207
|
startconn(); // start outbound connection
|
|
211
208
|
}
|
|
212
209
|
|
|
213
|
-
node.on("close", function() {
|
|
210
|
+
node.on("close", function(done) {
|
|
214
211
|
if (node.heartbeatInterval) {
|
|
215
212
|
clearInterval(node.heartbeatInterval);
|
|
216
213
|
}
|
|
@@ -218,19 +215,25 @@ module.exports = function(RED) {
|
|
|
218
215
|
delete listenerNodes[node.fullPath];
|
|
219
216
|
node.server.close();
|
|
220
217
|
node._inputNodes = [];
|
|
221
|
-
activeListenerNodes--;
|
|
222
|
-
// if (activeListenerNodes === 0 && serverUpgradeAdded) {
|
|
223
|
-
// RED.server.removeListener('upgrade', handleServerUpgrade);
|
|
224
|
-
// serverUpgradeAdded = false;
|
|
225
|
-
// }
|
|
226
218
|
}
|
|
227
219
|
else {
|
|
228
220
|
node.closing = true;
|
|
229
221
|
node.server.close();
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
222
|
+
//wait 20*50 (1000ms max) for ws to close.
|
|
223
|
+
//call done when readyState === ws.CLOSED (or 1000ms, whichever comes fist)
|
|
224
|
+
const closeMonitorInterval = 20;
|
|
225
|
+
let closeMonitorCount = 50;
|
|
226
|
+
let si = setInterval(() => {
|
|
227
|
+
if(node.server.readyState === ws.CLOSED || closeMonitorCount <= 0) {
|
|
228
|
+
if (node.tout) {
|
|
229
|
+
clearTimeout(node.tout);
|
|
230
|
+
node.tout = null;
|
|
231
|
+
}
|
|
232
|
+
clearInterval(si);
|
|
233
|
+
return done();
|
|
234
|
+
}
|
|
235
|
+
closeMonitorCount--;
|
|
236
|
+
}, closeMonitorInterval);
|
|
234
237
|
}
|
|
235
238
|
});
|
|
236
239
|
}
|
package/core/network/31-tcpin.js
CHANGED
|
@@ -135,7 +135,7 @@ module.exports = function(RED) {
|
|
|
135
135
|
buffer = buffer+data;
|
|
136
136
|
var parts = buffer.split(node.newline);
|
|
137
137
|
for (var i = 0; i<parts.length-1; i+=1) {
|
|
138
|
-
msg = {topic:node.topic, payload:parts[i]
|
|
138
|
+
msg = {topic:node.topic, payload:parts[i]};
|
|
139
139
|
msg._session = {type:"tcp",id:id};
|
|
140
140
|
node.send(msg);
|
|
141
141
|
}
|
|
@@ -229,7 +229,7 @@ module.exports = function(RED) {
|
|
|
229
229
|
buffer = buffer+data;
|
|
230
230
|
var parts = buffer.split(node.newline);
|
|
231
231
|
for (var i = 0; i<parts.length-1; i+=1) {
|
|
232
|
-
msg = {topic:node.topic, payload:parts[i]
|
|
232
|
+
msg = {topic:node.topic, payload:parts[i], ip:socket.remoteAddress, port:socket.remotePort};
|
|
233
233
|
msg._session = {type:"tcp",id:id};
|
|
234
234
|
node.send(msg);
|
|
235
235
|
}
|
|
@@ -432,7 +432,7 @@ module.exports = function(RED) {
|
|
|
432
432
|
});
|
|
433
433
|
}
|
|
434
434
|
else {
|
|
435
|
-
|
|
435
|
+
const connectedSockets = new Set();
|
|
436
436
|
node.status({text:RED._("tcpin.status.connections",{count:0})});
|
|
437
437
|
let srv = net;
|
|
438
438
|
let connOpts;
|
|
@@ -453,16 +453,16 @@ module.exports = function(RED) {
|
|
|
453
453
|
});
|
|
454
454
|
socket.on('close',function() {
|
|
455
455
|
node.log(RED._("tcpin.status.connection-closed",{host:socket.remoteAddress, port:socket.remotePort}));
|
|
456
|
-
connectedSockets.
|
|
457
|
-
node.status({text:RED._("tcpin.status.connections",{count:connectedSockets.
|
|
456
|
+
connectedSockets.delete(socket);
|
|
457
|
+
node.status({text:RED._("tcpin.status.connections",{count:connectedSockets.size})});
|
|
458
458
|
});
|
|
459
459
|
socket.on('error',function() {
|
|
460
460
|
node.log(RED._("tcpin.errors.socket-error",{host:socket.remoteAddress, port:socket.remotePort}));
|
|
461
|
-
connectedSockets.
|
|
462
|
-
node.status({text:RED._("tcpin.status.connections",{count:connectedSockets.
|
|
461
|
+
connectedSockets.delete(socket);
|
|
462
|
+
node.status({text:RED._("tcpin.status.connections",{count:connectedSockets.size})});
|
|
463
463
|
});
|
|
464
|
-
connectedSockets.
|
|
465
|
-
node.status({text:RED._("tcpin.status.connections",{count:connectedSockets.
|
|
464
|
+
connectedSockets.add(socket);
|
|
465
|
+
node.status({text:RED._("tcpin.status.connections",{count:connectedSockets.size})});
|
|
466
466
|
});
|
|
467
467
|
|
|
468
468
|
node.on("input", function(msg, nodeSend, nodeDone) {
|
|
@@ -475,10 +475,10 @@ module.exports = function(RED) {
|
|
|
475
475
|
} else {
|
|
476
476
|
buffer = Buffer.from(""+msg.payload);
|
|
477
477
|
}
|
|
478
|
-
|
|
479
|
-
if (node.doend === true) {
|
|
480
|
-
else {
|
|
481
|
-
}
|
|
478
|
+
connectedSockets.forEach(soc => {
|
|
479
|
+
if (node.doend === true) { soc.end(buffer); }
|
|
480
|
+
else { soc.write(buffer); }
|
|
481
|
+
})
|
|
482
482
|
}
|
|
483
483
|
nodeDone();
|
|
484
484
|
});
|
|
@@ -495,12 +495,10 @@ module.exports = function(RED) {
|
|
|
495
495
|
} else {
|
|
496
496
|
node.log(RED._("tcpin.status.listening-port",{port:node.port}));
|
|
497
497
|
node.on('close', function() {
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
}
|
|
503
|
-
}
|
|
498
|
+
connectedSockets.forEach(soc => {
|
|
499
|
+
soc.end();
|
|
500
|
+
soc.unref();
|
|
501
|
+
})
|
|
504
502
|
server.close();
|
|
505
503
|
node.log(RED._("tcpin.status.stopped-listening",{port:node.port}));
|
|
506
504
|
});
|
package/core/parsers/70-CSV.js
CHANGED
|
@@ -89,6 +89,9 @@ module.exports = function(RED) {
|
|
|
89
89
|
else if (msg.payload[s][t].toString().indexOf(node.sep) !== -1) { // add quotes if any "commas"
|
|
90
90
|
msg.payload[s][t] = node.quo + msg.payload[s][t].toString() + node.quo;
|
|
91
91
|
}
|
|
92
|
+
else if (msg.payload[s][t].toString().indexOf("\n") !== -1) { // add quotes if any "\n"
|
|
93
|
+
msg.payload[s][t] = node.quo + msg.payload[s][t].toString() + node.quo;
|
|
94
|
+
}
|
|
92
95
|
}
|
|
93
96
|
ou += msg.payload[s].join(node.sep) + node.ret;
|
|
94
97
|
}
|
|
@@ -112,7 +115,7 @@ module.exports = function(RED) {
|
|
|
112
115
|
q = q.replace(/"/g, '""');
|
|
113
116
|
ou += node.quo + q + node.quo + node.sep;
|
|
114
117
|
}
|
|
115
|
-
else if (q.indexOf(node.sep) !== -1) { // add quotes if any "commas"
|
|
118
|
+
else if (q.indexOf(node.sep) !== -1 || p.indexOf("\n") !== -1) { // add quotes if any "commas" or "\n"
|
|
116
119
|
ou += node.quo + q + node.quo + node.sep;
|
|
117
120
|
}
|
|
118
121
|
else { ou += q + node.sep; } // otherwise just add
|
|
@@ -134,7 +137,7 @@ module.exports = function(RED) {
|
|
|
134
137
|
p = p.replace(/"/g, '""');
|
|
135
138
|
ou += node.quo + p + node.quo + node.sep;
|
|
136
139
|
}
|
|
137
|
-
else if (p.indexOf(node.sep) !== -1) { // add quotes if any "commas"
|
|
140
|
+
else if (p.indexOf(node.sep) !== -1 || p.indexOf("\n") !== -1) { // add quotes if any "commas" or "\n"
|
|
138
141
|
ou += node.quo + p + node.quo + node.sep;
|
|
139
142
|
}
|
|
140
143
|
else { ou += p + node.sep; } // otherwise just add
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
<label style="width:100%;"><span data-i18n="json.label.o2j"></span></label>
|
|
22
22
|
</div>
|
|
23
23
|
<div class="form-row node-json-to-json-options" style="padding-left: 20px;">
|
|
24
|
-
<input style="width:20px; vertical-align:top; margin-right: 5px;" type="checkbox" id="node-input-pretty"><label style="width: auto;" for="node-input-pretty" data-i18n="json.label.pretty"></
|
|
24
|
+
<input style="width:20px; vertical-align:top; margin-right: 5px;" type="checkbox" id="node-input-pretty"><label style="width: auto;" for="node-input-pretty" data-i18n="json.label.pretty"></label>
|
|
25
25
|
</div>
|
|
26
26
|
</script>
|
|
27
27
|
|
|
@@ -314,11 +314,13 @@ module.exports = function(RED) {
|
|
|
314
314
|
if (err) {
|
|
315
315
|
return done(err);
|
|
316
316
|
}
|
|
317
|
-
msgInfo.
|
|
317
|
+
msgInfo.msg.payload = result;
|
|
318
|
+
msgInfo.send(msgInfo.msg);
|
|
318
319
|
done();
|
|
319
320
|
});
|
|
320
321
|
} else {
|
|
321
|
-
msgInfo.
|
|
322
|
+
msgInfo.msg.payload = result;
|
|
323
|
+
msgInfo.send(msgInfo.msg);
|
|
322
324
|
done();
|
|
323
325
|
}
|
|
324
326
|
} else {
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
<div class="form-row">
|
|
48
48
|
<input type="checkbox" id="node-input-allowEmptySequence" style="margin-left:20px; margin-right: 10px; vertical-align:top; width:auto;">
|
|
49
49
|
<label for="node-input-allowEmptySequence" style="width:auto;" data-i18n="batch.interval.empty"></label>
|
|
50
|
-
|
|
50
|
+
</div>
|
|
51
51
|
</div>
|
|
52
52
|
|
|
53
53
|
<div class="node-row-msg-concat">
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"id": "48d660b3a4109400",
|
|
4
|
+
"type": "inject",
|
|
5
|
+
"z": "9e5f48c16729e4f0",
|
|
6
|
+
"name": "inject",
|
|
7
|
+
"props": [
|
|
8
|
+
{
|
|
9
|
+
"p": "payload"
|
|
10
|
+
}
|
|
11
|
+
],
|
|
12
|
+
"repeat": "",
|
|
13
|
+
"crontab": "",
|
|
14
|
+
"once": false,
|
|
15
|
+
"onceDelay": 0.1,
|
|
16
|
+
"topic": "",
|
|
17
|
+
"payload": "",
|
|
18
|
+
"payloadType": "date",
|
|
19
|
+
"x": 185,
|
|
20
|
+
"y": 795,
|
|
21
|
+
"wires": [
|
|
22
|
+
[
|
|
23
|
+
"e0f9e206681f3504"
|
|
24
|
+
]
|
|
25
|
+
]
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"id": "e0f9e206681f3504",
|
|
29
|
+
"type": "delay",
|
|
30
|
+
"z": "9e5f48c16729e4f0",
|
|
31
|
+
"name": "",
|
|
32
|
+
"pauseType": "rate",
|
|
33
|
+
"timeout": "5",
|
|
34
|
+
"timeoutUnits": "seconds",
|
|
35
|
+
"rate": "1",
|
|
36
|
+
"nbRateUnits": "30",
|
|
37
|
+
"rateUnits": "second",
|
|
38
|
+
"randomFirst": "1",
|
|
39
|
+
"randomLast": "5",
|
|
40
|
+
"randomUnits": "seconds",
|
|
41
|
+
"drop": false,
|
|
42
|
+
"allowrate": false,
|
|
43
|
+
"outputs": 1,
|
|
44
|
+
"x": 430,
|
|
45
|
+
"y": 795,
|
|
46
|
+
"wires": [
|
|
47
|
+
[
|
|
48
|
+
"e470f1d794e1bef9",
|
|
49
|
+
"af7cea1dfb797a75"
|
|
50
|
+
]
|
|
51
|
+
]
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"id": "943543cf7a1958e4",
|
|
55
|
+
"type": "change",
|
|
56
|
+
"z": "9e5f48c16729e4f0",
|
|
57
|
+
"name": "set flush to 1",
|
|
58
|
+
"rules": [
|
|
59
|
+
{
|
|
60
|
+
"t": "set",
|
|
61
|
+
"p": "flush",
|
|
62
|
+
"pt": "msg",
|
|
63
|
+
"to": "1",
|
|
64
|
+
"tot": "num"
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"t": "delete",
|
|
68
|
+
"p": "payload",
|
|
69
|
+
"pt": "msg"
|
|
70
|
+
}
|
|
71
|
+
],
|
|
72
|
+
"action": "",
|
|
73
|
+
"property": "",
|
|
74
|
+
"from": "",
|
|
75
|
+
"to": "",
|
|
76
|
+
"reg": false,
|
|
77
|
+
"x": 510,
|
|
78
|
+
"y": 915,
|
|
79
|
+
"wires": [
|
|
80
|
+
[
|
|
81
|
+
"e0f9e206681f3504"
|
|
82
|
+
]
|
|
83
|
+
]
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"id": "e470f1d794e1bef9",
|
|
87
|
+
"type": "function",
|
|
88
|
+
"z": "9e5f48c16729e4f0",
|
|
89
|
+
"name": "Do something that takes a few seconds",
|
|
90
|
+
"func": "\n//send on the message between 3 and 6 seconds later\nsetTimeout(\n function() { \n node.send(msg) \n }, \n Math.random() * 3000 + 3000\n);\nreturn null;",
|
|
91
|
+
"outputs": 1,
|
|
92
|
+
"noerr": 0,
|
|
93
|
+
"initialize": "",
|
|
94
|
+
"finalize": "",
|
|
95
|
+
"libs": [],
|
|
96
|
+
"x": 760,
|
|
97
|
+
"y": 795,
|
|
98
|
+
"wires": [
|
|
99
|
+
[
|
|
100
|
+
"943543cf7a1958e4",
|
|
101
|
+
"859258551b8389b7"
|
|
102
|
+
]
|
|
103
|
+
]
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
"id": "af7cea1dfb797a75",
|
|
107
|
+
"type": "debug",
|
|
108
|
+
"z": "9e5f48c16729e4f0",
|
|
109
|
+
"name": "IN",
|
|
110
|
+
"active": true,
|
|
111
|
+
"tosidebar": true,
|
|
112
|
+
"console": false,
|
|
113
|
+
"tostatus": false,
|
|
114
|
+
"complete": "payload",
|
|
115
|
+
"targetType": "msg",
|
|
116
|
+
"statusVal": "",
|
|
117
|
+
"statusType": "auto",
|
|
118
|
+
"x": 710,
|
|
119
|
+
"y": 735,
|
|
120
|
+
"wires": []
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
"id": "859258551b8389b7",
|
|
124
|
+
"type": "debug",
|
|
125
|
+
"z": "9e5f48c16729e4f0",
|
|
126
|
+
"name": "OUT",
|
|
127
|
+
"active": true,
|
|
128
|
+
"tosidebar": true,
|
|
129
|
+
"console": false,
|
|
130
|
+
"tostatus": false,
|
|
131
|
+
"complete": "payload",
|
|
132
|
+
"targetType": "msg",
|
|
133
|
+
"statusVal": "",
|
|
134
|
+
"statusType": "auto",
|
|
135
|
+
"x": 895,
|
|
136
|
+
"y": 735,
|
|
137
|
+
"wires": []
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
"id": "ecaaf26326da10ee",
|
|
141
|
+
"type": "comment",
|
|
142
|
+
"z": "9e5f48c16729e4f0",
|
|
143
|
+
"name": "Simple Queue with release",
|
|
144
|
+
"info": "This example shows how to use a delay node set to rate limit mode as a simple queue to feed a\nprocess that may take some time to complete. Once that process completes the feedback is then\nset to flush out the next message - thus running the \"loop\" as fast as possible with no overlaps.\n\n**Note**: only the `msg.flush` property msut be set - otherwise the other properties that are fed \nback will be added as another new message to the queue.",
|
|
145
|
+
"x": 235,
|
|
146
|
+
"y": 915,
|
|
147
|
+
"wires": []
|
|
148
|
+
}
|
|
149
|
+
]
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
<p>返却/sendの対象は次のとおりです:</p>
|
|
29
29
|
<ul>
|
|
30
30
|
<li>単一メッセージオブジェクト - 最初の出力に接続されたノードに渡されます</li>
|
|
31
|
-
<li>メッセージオブジェクトの配列 - 対応する出力に接続されたノードに渡されます</li>
|
|
31
|
+
<li>メッセージオブジェクトの配列 - 対応する出力に接続されたノードに渡されます</li>
|
|
32
32
|
</ul>
|
|
33
33
|
<p>注: 初期化処理の実行はノードの初期化中に行われます。そのため、初期化処理タブにsendを記述した場合に後続ノードでメッセージを受け取れないことがあります。</p>
|
|
34
34
|
<p>配列要素が配列の場合には、複数のメッセージを対応する出力に送出します。</p>
|
|
@@ -89,7 +89,7 @@
|
|
|
89
89
|
<dt class="optional">userProperties <span class="property-type">オブジェクト</span></dt>
|
|
90
90
|
<dd><b>MQTTv5</b>: メッセージのユーザプロパティ</dd>
|
|
91
91
|
<dt class="optional">messageExpiryInterval <span class="property-type">数値</span></dt>
|
|
92
|
-
<dd><b>MQTTv5</b>: 秒単位のメッセージの有効期限</dd>
|
|
92
|
+
<dd><b>MQTTv5</b>: 秒単位のメッセージの有効期限</dd>
|
|
93
93
|
<dt class="optional">topicAlias <span class="property-type">数値</span></dt>
|
|
94
94
|
<dd><b>MQTTv5</b>: 使用するMQTTトピックエイリアス</dd>
|
|
95
95
|
</dl>
|