@node-red/nodes 2.1.5 → 2.2.1
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/LICENSE +1 -1
- package/core/common/20-inject.html +1 -1
- package/core/common/20-inject.js +2 -8
- package/core/common/21-debug.js +6 -5
- package/core/function/10-function.js +4 -0
- package/core/function/89-delay.html +2 -1
- package/core/function/90-exec.js +3 -3
- package/core/network/10-mqtt.js +11 -5
- package/core/network/21-httprequest.js +4 -4
- package/core/network/22-websocket.html +6 -2
- package/core/network/22-websocket.js +7 -1
- package/core/network/31-tcpin.html +126 -20
- package/core/network/31-tcpin.js +162 -29
- package/core/parsers/70-JSON.js +5 -1
- package/core/storage/10-file.js +1 -3
- package/locales/de/messages.json +2 -1
- package/locales/en-US/messages.json +10 -6
- package/locales/ja/messages.json +11 -6
- package/locales/ko/messages.json +2 -1
- package/locales/ru/messages.json +2 -1
- package/locales/zh-CN/messages.json +2 -1
- package/locales/zh-TW/messages.json +2 -1
- package/package.json +7 -7
package/LICENSE
CHANGED
package/core/common/20-inject.js
CHANGED
|
@@ -75,16 +75,12 @@ module.exports = function(RED) {
|
|
|
75
75
|
node.repeaterSetup = function () {
|
|
76
76
|
if (this.repeat && !isNaN(this.repeat) && this.repeat > 0) {
|
|
77
77
|
this.repeat = this.repeat * 1000;
|
|
78
|
-
|
|
79
|
-
this.log(RED._("inject.repeat", this));
|
|
80
|
-
}
|
|
78
|
+
this.debug(RED._("inject.repeat", this));
|
|
81
79
|
this.interval_id = setInterval(function() {
|
|
82
80
|
node.emit("input", {});
|
|
83
81
|
}, this.repeat);
|
|
84
82
|
} else if (this.crontab) {
|
|
85
|
-
|
|
86
|
-
this.log(RED._("inject.crontab", this));
|
|
87
|
-
}
|
|
83
|
+
this.debug(RED._("inject.crontab", this));
|
|
88
84
|
this.cronjob = scheduleTask(this.crontab,() => { node.emit("input", {})});
|
|
89
85
|
}
|
|
90
86
|
};
|
|
@@ -148,10 +144,8 @@ module.exports = function(RED) {
|
|
|
148
144
|
}
|
|
149
145
|
if (this.interval_id != null) {
|
|
150
146
|
clearInterval(this.interval_id);
|
|
151
|
-
if (RED.settings.verbose) { this.log(RED._("inject.stopped")); }
|
|
152
147
|
} else if (this.cronjob != null) {
|
|
153
148
|
this.cronjob.stop();
|
|
154
|
-
if (RED.settings.verbose) { this.log(RED._("inject.stopped")); }
|
|
155
149
|
delete this.cronjob;
|
|
156
150
|
}
|
|
157
151
|
};
|
package/core/common/21-debug.js
CHANGED
|
@@ -7,6 +7,7 @@ module.exports = function(RED) {
|
|
|
7
7
|
var debuglength = RED.settings.debugMaxLength || 1000;
|
|
8
8
|
var useColors = RED.settings.debugUseColors || false;
|
|
9
9
|
util.inspect.styles.boolean = "red";
|
|
10
|
+
const { hasOwnProperty } = Object.prototype;
|
|
10
11
|
|
|
11
12
|
function DebugNode(n) {
|
|
12
13
|
var hasEditExpression = (n.targetType === "jsonata");
|
|
@@ -107,7 +108,7 @@ module.exports = function(RED) {
|
|
|
107
108
|
}
|
|
108
109
|
})
|
|
109
110
|
this.on("input", function(msg, send, done) {
|
|
110
|
-
if (
|
|
111
|
+
if (hasOwnProperty.call(msg, "status") && hasOwnProperty.call(msg.status, "source") && hasOwnProperty.call(msg.status.source, "id") && (msg.status.source.id === node.id)) {
|
|
111
112
|
done();
|
|
112
113
|
return;
|
|
113
114
|
}
|
|
@@ -118,17 +119,17 @@ module.exports = function(RED) {
|
|
|
118
119
|
var st = (typeof output === 'string') ? output : util.inspect(output);
|
|
119
120
|
var fill = "grey";
|
|
120
121
|
var shape = "dot";
|
|
121
|
-
if (typeof output === 'object' &&
|
|
122
|
+
if (typeof output === 'object' && hasOwnProperty.call(output, "fill") && hasOwnProperty.call(output, "shape") && hasOwnProperty.call(output, "text")) {
|
|
122
123
|
fill = output.fill;
|
|
123
124
|
shape = output.shape;
|
|
124
125
|
st = output.text;
|
|
125
126
|
}
|
|
126
127
|
if (node.statusType === "auto") {
|
|
127
|
-
if (
|
|
128
|
+
if (hasOwnProperty.call(msg, "error")) {
|
|
128
129
|
fill = "red";
|
|
129
130
|
st = msg.error.message;
|
|
130
131
|
}
|
|
131
|
-
if (
|
|
132
|
+
if (hasOwnProperty.call(msg, "status")) {
|
|
132
133
|
fill = msg.status.fill || "grey";
|
|
133
134
|
shape = msg.status.shape || "ring";
|
|
134
135
|
st = msg.status.text || "";
|
|
@@ -194,7 +195,7 @@ module.exports = function(RED) {
|
|
|
194
195
|
|
|
195
196
|
function sendDebug(msg) {
|
|
196
197
|
// don't put blank errors in sidebar (but do add to logs)
|
|
197
|
-
//if ((msg.msg === "") && (
|
|
198
|
+
//if ((msg.msg === "") && (hasOwnProperty.call(msg, "level")) && (msg.level === 20)) { return; }
|
|
198
199
|
msg = RED.util.encodeObject(msg,{maxLength:debuglength});
|
|
199
200
|
RED.comms.publish("debug",msg);
|
|
200
201
|
}
|
|
@@ -112,6 +112,7 @@ module.exports = function(RED) {
|
|
|
112
112
|
"var node = {"+
|
|
113
113
|
"id:__node__.id,"+
|
|
114
114
|
"name:__node__.name,"+
|
|
115
|
+
"path:__node__.path,"+
|
|
115
116
|
"outputCount:__node__.outputCount,"+
|
|
116
117
|
"log:__node__.log,"+
|
|
117
118
|
"error:__node__.error,"+
|
|
@@ -163,6 +164,7 @@ module.exports = function(RED) {
|
|
|
163
164
|
__node__: {
|
|
164
165
|
id: node.id,
|
|
165
166
|
name: node.name,
|
|
167
|
+
path: node._path,
|
|
166
168
|
outputCount: node.outputs,
|
|
167
169
|
log: function() {
|
|
168
170
|
node.log.apply(node, arguments);
|
|
@@ -344,6 +346,7 @@ module.exports = function(RED) {
|
|
|
344
346
|
var node = {
|
|
345
347
|
id:__node__.id,
|
|
346
348
|
name:__node__.name,
|
|
349
|
+
path:__node__.path,
|
|
347
350
|
outputCount:__node__.outputCount,
|
|
348
351
|
log:__node__.log,
|
|
349
352
|
error:__node__.error,
|
|
@@ -366,6 +369,7 @@ module.exports = function(RED) {
|
|
|
366
369
|
var node = {
|
|
367
370
|
id:__node__.id,
|
|
368
371
|
name:__node__.name,
|
|
372
|
+
path:__node__.path,
|
|
369
373
|
outputCount:__node__.outputCount,
|
|
370
374
|
log:__node__.log,
|
|
371
375
|
error:__node__.error,
|
|
@@ -114,7 +114,8 @@
|
|
|
114
114
|
timeout: {value:"5", required:true, validate:function(v) { return RED.validators.number(v) && (v >= 0); }},
|
|
115
115
|
timeoutUnits: {value:"seconds"},
|
|
116
116
|
rate: {value:"1", required:true, validate:function(v) { return RED.validators.number(v) && (v >= 0); }},
|
|
117
|
-
nbRateUnits: {value:"1", required:false,
|
|
117
|
+
nbRateUnits: {value:"1", required:false,
|
|
118
|
+
validate:function(v) { return v === undefined || (RED.validators.number(v) && (v >= 0)); }},
|
|
118
119
|
rateUnits: {value: "second"},
|
|
119
120
|
randomFirst: {value:"1", required:true, validate:function(v) { return RED.validators.number(v) && (v >= 0); }},
|
|
120
121
|
randomLast: {value:"5", required:true, validate:function(v) { return RED.validators.number(v) && (v >= 0); }},
|
package/core/function/90-exec.js
CHANGED
|
@@ -86,7 +86,7 @@ module.exports = function(RED) {
|
|
|
86
86
|
});
|
|
87
87
|
var cmd = arg.shift();
|
|
88
88
|
/* istanbul ignore else */
|
|
89
|
-
|
|
89
|
+
node.debug(cmd+" ["+arg+"]");
|
|
90
90
|
child = spawn(cmd,arg,node.spawnOpt);
|
|
91
91
|
node.status({fill:"blue",shape:"dot",text:"pid:"+child.pid});
|
|
92
92
|
var unknownCommand = (child.pid === undefined);
|
|
@@ -136,7 +136,7 @@ module.exports = function(RED) {
|
|
|
136
136
|
}
|
|
137
137
|
else {
|
|
138
138
|
/* istanbul ignore else */
|
|
139
|
-
|
|
139
|
+
node.debug(arg);
|
|
140
140
|
child = exec(arg, node.execOpt, function (error, stdout, stderr) {
|
|
141
141
|
var msg2, msg3;
|
|
142
142
|
delete msg.payload;
|
|
@@ -155,7 +155,7 @@ module.exports = function(RED) {
|
|
|
155
155
|
if (error.signal) { msg3.payload.signal = error.signal; }
|
|
156
156
|
if (error.code === null) { node.status({fill:"red",shape:"dot",text:"killed"}); }
|
|
157
157
|
else { node.status({fill:"red",shape:"dot",text:"error:"+error.code}); }
|
|
158
|
-
|
|
158
|
+
node.debug('error:' + error);
|
|
159
159
|
}
|
|
160
160
|
else if (node.oldrc === "false") {
|
|
161
161
|
msg3 = RED.util.cloneMessage(msg);
|
package/core/network/10-mqtt.js
CHANGED
|
@@ -288,7 +288,7 @@ module.exports = function(RED) {
|
|
|
288
288
|
//TODO: delete msg.responseTopic - to prevent it being resent?
|
|
289
289
|
}
|
|
290
290
|
}
|
|
291
|
-
topicOK = topicOK && !/[
|
|
291
|
+
topicOK = topicOK && !/[\+#\b\f\n\r\t\v\0]/.test(msg.topic);
|
|
292
292
|
|
|
293
293
|
if (topicOK) {
|
|
294
294
|
node.brokerConn.publish(msg, done); // send the message
|
|
@@ -730,12 +730,18 @@ module.exports = function(RED) {
|
|
|
730
730
|
node.client.on("reconnect", function() {
|
|
731
731
|
setStatusConnecting(node, true);
|
|
732
732
|
});
|
|
733
|
-
//
|
|
733
|
+
//Broker Disconnect - V5 event
|
|
734
734
|
node.client.on("disconnect", function(packet) {
|
|
735
735
|
//Emitted after receiving disconnect packet from broker. MQTT 5.0 feature.
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
736
|
+
const rc = (packet && packet.properties && packet.reasonCode) || packet.reasonCode;
|
|
737
|
+
const rs = packet && packet.properties && packet.properties.reasonString || "";
|
|
738
|
+
const details = {
|
|
739
|
+
broker: (node.clientid?node.clientid+"@":"")+node.brokerurl,
|
|
740
|
+
reasonCode: rc,
|
|
741
|
+
reasonString: rs
|
|
742
|
+
}
|
|
743
|
+
node.log(RED._("mqtt.state.broker-disconnected", details));
|
|
744
|
+
setStatusDisconnected(node, true);
|
|
739
745
|
});
|
|
740
746
|
// Register disconnect handlers
|
|
741
747
|
node.client.on('close', function () {
|
|
@@ -264,7 +264,7 @@ in your Node-RED user directory (${RED.settings.userDir}).
|
|
|
264
264
|
if (opts.headers.hasOwnProperty('cookie')) {
|
|
265
265
|
var cookies = cookie.parse(opts.headers.cookie, {decode:String});
|
|
266
266
|
for (var name in cookies) {
|
|
267
|
-
opts.cookieJar.
|
|
267
|
+
opts.cookieJar.setCookieSync(cookie.serialize(name, cookies[name], {encode:String}), url, {ignoreError: true});
|
|
268
268
|
}
|
|
269
269
|
delete opts.headers.cookie;
|
|
270
270
|
}
|
|
@@ -277,13 +277,13 @@ in your Node-RED user directory (${RED.settings.userDir}).
|
|
|
277
277
|
} else if (typeof msg.cookies[name] === 'object') {
|
|
278
278
|
if(msg.cookies[name].encode === false){
|
|
279
279
|
// If the encode option is false, the value is not encoded.
|
|
280
|
-
opts.cookieJar.
|
|
280
|
+
opts.cookieJar.setCookieSync(cookie.serialize(name, msg.cookies[name].value, {encode: String}), url, {ignoreError: true});
|
|
281
281
|
} else {
|
|
282
282
|
// The value is encoded by encodeURIComponent().
|
|
283
|
-
opts.cookieJar.
|
|
283
|
+
opts.cookieJar.setCookieSync(cookie.serialize(name, msg.cookies[name].value), url, {ignoreError: true});
|
|
284
284
|
}
|
|
285
285
|
} else {
|
|
286
|
-
opts.cookieJar.
|
|
286
|
+
opts.cookieJar.setCookieSync(cookie.serialize(name, msg.cookies[name]), url, {ignoreError: true});
|
|
287
287
|
}
|
|
288
288
|
}
|
|
289
289
|
}
|
|
@@ -177,7 +177,8 @@
|
|
|
177
177
|
path: {value:"",required:true,validate:RED.validators.regex(/^((?!\/debug\/ws).)*$/)},
|
|
178
178
|
tls: {type:"tls-config",required: false},
|
|
179
179
|
wholemsg: {value:"false"},
|
|
180
|
-
hb: {value: "", validate: RED.validators.number(/*blank allowed*/true) }
|
|
180
|
+
hb: {value: "", validate: RED.validators.number(/*blank allowed*/true) },
|
|
181
|
+
subprotocol: {value:"",required: false}
|
|
181
182
|
},
|
|
182
183
|
inputs:0,
|
|
183
184
|
outputs:0,
|
|
@@ -265,7 +266,10 @@
|
|
|
265
266
|
<label for="node-config-input-tls" data-i18n="httpin.tls-config"></label>
|
|
266
267
|
<input type="text" id="node-config-input-tls">
|
|
267
268
|
</div>
|
|
268
|
-
|
|
269
|
+
<div class="form-row">
|
|
270
|
+
<label for="node-config-input-subprotocol"><i class="fa fa-tag"></i> <span data-i18n="websocket.label.subprotocol"></span></label>
|
|
271
|
+
<input type="text" id="node-config-input-subprotocol">
|
|
272
|
+
</div>
|
|
269
273
|
<div class="form-row">
|
|
270
274
|
<label for="node-config-input-wholemsg" data-i18n="websocket.sendrec"></label>
|
|
271
275
|
<select type="text" id="node-config-input-wholemsg" style="width: 70%;">
|
|
@@ -46,6 +46,12 @@ module.exports = function(RED) {
|
|
|
46
46
|
|
|
47
47
|
// Store local copies of the node configuration (as defined in the .html)
|
|
48
48
|
node.path = n.path;
|
|
49
|
+
if (typeof n.subprotocol === "string") {
|
|
50
|
+
// Split the string on comma and trim each result
|
|
51
|
+
node.subprotocol = n.subprotocol.split(",").map(v => v.trim())
|
|
52
|
+
} else {
|
|
53
|
+
node.subprotocol = [];
|
|
54
|
+
}
|
|
49
55
|
node.wholemsg = (n.wholemsg === "true");
|
|
50
56
|
|
|
51
57
|
node._inputNodes = []; // collection of nodes that want to receive events
|
|
@@ -92,7 +98,7 @@ module.exports = function(RED) {
|
|
|
92
98
|
tlsNode.addTLSOptions(options);
|
|
93
99
|
}
|
|
94
100
|
}
|
|
95
|
-
var socket = new ws(node.path,options);
|
|
101
|
+
var socket = new ws(node.path,node.subprotocol,options);
|
|
96
102
|
socket.setMaxListeners(0);
|
|
97
103
|
node.server = socket; // keep for closing
|
|
98
104
|
handleConnection(socket);
|
|
@@ -23,9 +23,17 @@
|
|
|
23
23
|
</select>
|
|
24
24
|
<span data-i18n="tcpin.label.port"></span> <input type="text" id="node-input-port" style="width:65px">
|
|
25
25
|
</div>
|
|
26
|
-
<div class="form-row hidden" id="node-input-host-row" style="padding-left:
|
|
26
|
+
<div class="form-row hidden" id="node-input-host-row" style="padding-left:110px;">
|
|
27
27
|
<span data-i18n="tcpin.label.host"></span> <input type="text" id="node-input-host" placeholder="localhost" style="width: 60%;">
|
|
28
28
|
</div>
|
|
29
|
+
<div class="form-row" id="node-input-tls-enable">
|
|
30
|
+
<label> </label>
|
|
31
|
+
<input type="checkbox" id="node-input-usetls" style="display: inline-block; width:auto; vertical-align:top;">
|
|
32
|
+
<label for="node-input-usetls" style="width:auto" data-i18n="httpin.use-tls"></label>
|
|
33
|
+
<div id="node-row-tls" class="hide">
|
|
34
|
+
<label style="width:auto; margin-left:20px; margin-right:10px;" for="node-input-tls"><span data-i18n="httpin.tls-config"></span></label><input type="text" style="width: 300px" id="node-input-tls">
|
|
35
|
+
</div>
|
|
36
|
+
</div>
|
|
29
37
|
|
|
30
38
|
<div class="form-row">
|
|
31
39
|
<label><i class="fa fa-sign-out"></i> <span data-i18n="tcpin.label.output"></span></label>
|
|
@@ -42,7 +50,7 @@
|
|
|
42
50
|
</div>
|
|
43
51
|
|
|
44
52
|
<div id="node-row-newline" class="form-row hidden" style="padding-left:110px;">
|
|
45
|
-
<span data-i18n="tcpin.label.delimited"></span> <input type="text" id="node-input-newline" style="width:110px;">
|
|
53
|
+
<span data-i18n="tcpin.label.delimited"></span> <input type="text" id="node-input-newline" style="width:110px;" data-i18n="[placeholder]tcpin.label.optional">
|
|
46
54
|
</div>
|
|
47
55
|
|
|
48
56
|
<div class="form-row">
|
|
@@ -58,17 +66,18 @@
|
|
|
58
66
|
<script type="text/javascript">
|
|
59
67
|
RED.nodes.registerType('tcp in',{
|
|
60
68
|
category: 'network',
|
|
61
|
-
color:"Silver",
|
|
69
|
+
color: "Silver",
|
|
62
70
|
defaults: {
|
|
63
71
|
name: {value:""},
|
|
64
|
-
server: {value:"server",required:true},
|
|
65
|
-
host: {value:"",validate:function(v) { return (this.server == "server")||v.length > 0;} },
|
|
66
|
-
port: {value:"",required:true,validate:RED.validators.number()},
|
|
72
|
+
server: {value:"server", required:true},
|
|
73
|
+
host: {value:"", validate:function(v) { return (this.server == "server")||v.length > 0;} },
|
|
74
|
+
port: {value:"", required:true, validate:RED.validators.number()},
|
|
67
75
|
datamode:{value:"stream"},
|
|
68
76
|
datatype:{value:"buffer"},
|
|
69
77
|
newline:{value:""},
|
|
70
78
|
topic: {value:""},
|
|
71
|
-
base64: {/*deprecated*/ value:false,required:true}
|
|
79
|
+
base64: {/*deprecated*/ value:false, required:true},
|
|
80
|
+
tls: {type:"tls-config", value:'', required:false}
|
|
72
81
|
},
|
|
73
82
|
inputs:0,
|
|
74
83
|
outputs:1,
|
|
@@ -77,7 +86,7 @@
|
|
|
77
86
|
return this.name || "tcp:"+(this.host?this.host+":":"")+this.port;
|
|
78
87
|
},
|
|
79
88
|
labelStyle: function() {
|
|
80
|
-
return this.name?"node_label_italic":"";
|
|
89
|
+
return this.name ? "node_label_italic" : "";
|
|
81
90
|
},
|
|
82
91
|
oneditprepare: function() {
|
|
83
92
|
var updateOptions = function() {
|
|
@@ -103,6 +112,27 @@
|
|
|
103
112
|
$("#node-input-server").change(updateOptions);
|
|
104
113
|
$("#node-input-datatype").change(updateOptions);
|
|
105
114
|
$("#node-input-datamode").change(updateOptions);
|
|
115
|
+
function updateTLSOptions() {
|
|
116
|
+
if ($("#node-input-usetls").is(':checked')) {
|
|
117
|
+
$("#node-row-tls").show();
|
|
118
|
+
} else {
|
|
119
|
+
$("#node-row-tls").hide();
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
if (this.tls) {
|
|
123
|
+
$('#node-input-usetls').prop('checked', true);
|
|
124
|
+
} else {
|
|
125
|
+
$('#node-input-usetls').prop('checked', false);
|
|
126
|
+
}
|
|
127
|
+
updateTLSOptions();
|
|
128
|
+
$("#node-input-usetls").on("click",function() {
|
|
129
|
+
updateTLSOptions();
|
|
130
|
+
});
|
|
131
|
+
},
|
|
132
|
+
oneditsave: function() {
|
|
133
|
+
if (!$("#node-input-usetls").is(':checked')) {
|
|
134
|
+
$("#node-input-tls").val("_ADD_");
|
|
135
|
+
}
|
|
106
136
|
}
|
|
107
137
|
});
|
|
108
138
|
</script>
|
|
@@ -123,6 +153,15 @@
|
|
|
123
153
|
<span data-i18n="tcpin.label.host"></span> <input type="text" id="node-input-host" style="width: 60%;">
|
|
124
154
|
</div>
|
|
125
155
|
|
|
156
|
+
<div class="form-row" id="node-input-tls-enable">
|
|
157
|
+
<label> </label>
|
|
158
|
+
<input type="checkbox" id="node-input-usetls" style="display: inline-block; width: auto; vertical-align: top;">
|
|
159
|
+
<label for="node-input-usetls" style="width: auto" data-i18n="httpin.use-tls"></label>
|
|
160
|
+
<div id="node-row-tls" class="hide">
|
|
161
|
+
<label style="width: auto; margin-left: 20px; margin-right: 10px;" for="node-input-tls"><span data-i18n="httpin.tls-config"></span></label><input type="text" style="width: 300px" id="node-input-tls">
|
|
162
|
+
</div>
|
|
163
|
+
</div>
|
|
164
|
+
|
|
126
165
|
<div class="form-row hidden" id="node-input-end-row">
|
|
127
166
|
<label> </label>
|
|
128
167
|
<input type="checkbox" id="node-input-end" style="display: inline-block; width: auto; vertical-align: top;">
|
|
@@ -144,14 +183,15 @@
|
|
|
144
183
|
<script type="text/javascript">
|
|
145
184
|
RED.nodes.registerType('tcp out',{
|
|
146
185
|
category: 'network',
|
|
147
|
-
color:"Silver",
|
|
186
|
+
color: "Silver",
|
|
148
187
|
defaults: {
|
|
188
|
+
name: {value:""},
|
|
149
189
|
host: {value:"",validate:function(v) { return (this.beserver != "client")||v.length > 0;} },
|
|
150
190
|
port: {value:"",validate:function(v) { return (this.beserver == "reply")||RED.validators.number()(v); } },
|
|
151
|
-
beserver: {value:"client",required:true},
|
|
152
|
-
base64: {value:false,required:true},
|
|
153
|
-
end: {value:false,required:true},
|
|
154
|
-
|
|
191
|
+
beserver: {value:"client", required:true},
|
|
192
|
+
base64: {value:false, required:true},
|
|
193
|
+
end: {value:false, required:true},
|
|
194
|
+
tls: {type:"tls-config", value:'', required:false}
|
|
155
195
|
},
|
|
156
196
|
inputs:1,
|
|
157
197
|
outputs:0,
|
|
@@ -170,18 +210,42 @@
|
|
|
170
210
|
$("#node-input-port-row").hide();
|
|
171
211
|
$("#node-input-host-row").hide();
|
|
172
212
|
$("#node-input-end-row").hide();
|
|
213
|
+
$("#node-input-tls-enable").hide();
|
|
173
214
|
} else if (sockettype == "client"){
|
|
174
215
|
$("#node-input-port-row").show();
|
|
175
216
|
$("#node-input-host-row").show();
|
|
176
217
|
$("#node-input-end-row").show();
|
|
218
|
+
$("#node-input-tls-enable").show();
|
|
177
219
|
} else {
|
|
178
220
|
$("#node-input-port-row").show();
|
|
179
221
|
$("#node-input-host-row").hide();
|
|
180
222
|
$("#node-input-end-row").show();
|
|
223
|
+
$("#node-input-tls-enable").show();
|
|
181
224
|
}
|
|
182
225
|
};
|
|
183
226
|
updateOptions();
|
|
184
227
|
$("#node-input-beserver").change(updateOptions);
|
|
228
|
+
function updateTLSOptions() {
|
|
229
|
+
if ($("#node-input-usetls").is(':checked')) {
|
|
230
|
+
$("#node-row-tls").show();
|
|
231
|
+
} else {
|
|
232
|
+
$("#node-row-tls").hide();
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
if (this.tls) {
|
|
236
|
+
$('#node-input-usetls').prop('checked', true);
|
|
237
|
+
} else {
|
|
238
|
+
$('#node-input-usetls').prop('checked', false);
|
|
239
|
+
}
|
|
240
|
+
updateTLSOptions();
|
|
241
|
+
$("#node-input-usetls").on("click",function() {
|
|
242
|
+
updateTLSOptions();
|
|
243
|
+
});
|
|
244
|
+
},
|
|
245
|
+
oneditsave: function() {
|
|
246
|
+
if (!$("#node-input-usetls").is(':checked')) {
|
|
247
|
+
$("#node-input-tls").val("_ADD_");
|
|
248
|
+
}
|
|
185
249
|
}
|
|
186
250
|
});
|
|
187
251
|
</script>
|
|
@@ -194,15 +258,23 @@
|
|
|
194
258
|
<span data-i18n="tcpin.label.port"></span>
|
|
195
259
|
<input type="text" id="node-input-port" style="width:60px">
|
|
196
260
|
</div>
|
|
261
|
+
<div class="form-row" id="node-input-tls-enable">
|
|
262
|
+
<label> </label>
|
|
263
|
+
<input type="checkbox" id="node-input-usetls" style="display: inline-block; width: auto; vertical-align: top;">
|
|
264
|
+
<label for="node-input-usetls" style="width: auto" data-i18n="httpin.use-tls"></label>
|
|
265
|
+
<div id="node-row-tls" class="hide">
|
|
266
|
+
<label style="width: auto; margin-left: 20px; margin-right: 10px;" for="node-input-tls"><span data-i18n="httpin.tls-config"></span></label><input type="text" style="width: 300px" id="node-input-tls">
|
|
267
|
+
</div>
|
|
268
|
+
</div>
|
|
197
269
|
<div class="form-row">
|
|
198
|
-
<label for="node-input-
|
|
270
|
+
<label for="node-input-ret"><i class="fa fa-sign-out"></i> <span data-i18n="tcpin.label.return"></span></label>
|
|
199
271
|
<select type="text" id="node-input-ret" style="width:54%;">
|
|
200
272
|
<option value="buffer" data-i18n="tcpin.output.buffer"></option>
|
|
201
273
|
<option value="string" data-i18n="tcpin.output.string"></option>
|
|
202
274
|
</select>
|
|
203
275
|
</div>
|
|
204
276
|
<div class="form-row">
|
|
205
|
-
<label for="node-input-out">
|
|
277
|
+
<label for="node-input-out"><i class="fa fa-sign-out fa-rotate-90"></i> <span data-i18n="tcpin.label.close"></span></label>
|
|
206
278
|
<select type="text" id="node-input-out" style="width:54%;">
|
|
207
279
|
<option value="time" data-i18n="tcpin.return.timeout"></option>
|
|
208
280
|
<option value="char" data-i18n="tcpin.return.character"></option>
|
|
@@ -213,6 +285,9 @@
|
|
|
213
285
|
<input type="text" id="node-input-splitc" style="width:50px;">
|
|
214
286
|
<span id="node-units"></span>
|
|
215
287
|
</div>
|
|
288
|
+
<div id="node-row-newline" class="form-row hidden" style="padding-left:162px;">
|
|
289
|
+
<span data-i18n="tcpin.label.delimited"></span> <input type="text" id="node-input-newline" style="width:110px;" data-i18n="[placeholder]tcpin.label.optional">
|
|
290
|
+
</div>
|
|
216
291
|
<div class="form-row">
|
|
217
292
|
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
|
|
218
293
|
<input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
|
|
@@ -222,14 +297,16 @@
|
|
|
222
297
|
<script type="text/javascript">
|
|
223
298
|
RED.nodes.registerType('tcp request',{
|
|
224
299
|
category: 'network',
|
|
225
|
-
color:"Silver",
|
|
300
|
+
color: "Silver",
|
|
226
301
|
defaults: {
|
|
302
|
+
name: {value:""},
|
|
227
303
|
server: {value:""},
|
|
228
|
-
port: {value:"",validate:RED.validators.regex(/^(\d*|)$/)},
|
|
229
|
-
out: {value:"time",required:true},
|
|
304
|
+
port: {value:"", validate:RED.validators.regex(/^(\d*|)$/)},
|
|
305
|
+
out: {value:"time", required:true},
|
|
230
306
|
ret: {value:"buffer"},
|
|
231
|
-
splitc: {value:"0",required:true},
|
|
232
|
-
|
|
307
|
+
splitc: {value:"0", required:true},
|
|
308
|
+
newline: {value:""},
|
|
309
|
+
tls: {type:"tls-config", value:'', required:false}
|
|
233
310
|
},
|
|
234
311
|
inputs:1,
|
|
235
312
|
outputs:1,
|
|
@@ -246,6 +323,14 @@
|
|
|
246
323
|
$("#node-input-ret").val("buffer");
|
|
247
324
|
this.ret = "buffer";
|
|
248
325
|
}
|
|
326
|
+
$("#node-input-ret").on("change", function() {
|
|
327
|
+
if ($("#node-input-ret").val() === "string" && $("#node-input-out").val() === "sit") { $("#node-row-newline").show(); }
|
|
328
|
+
else { $("#node-row-newline").hide(); }
|
|
329
|
+
});
|
|
330
|
+
$("#node-input-out").on("change", function() {
|
|
331
|
+
if ($("#node-input-ret").val() === "string" && $("#node-input-out").val() === "sit") { $("#node-row-newline").show(); }
|
|
332
|
+
else { $("#node-row-newline").hide(); }
|
|
333
|
+
});
|
|
249
334
|
$("#node-input-out").on('focus', function () { previous = this.value; }).on("change", function() {
|
|
250
335
|
$("#node-input-splitc").show();
|
|
251
336
|
if (previous === null) { previous = $("#node-input-out").val(); }
|
|
@@ -272,6 +357,27 @@
|
|
|
272
357
|
$("#node-input-splitc").hide();
|
|
273
358
|
}
|
|
274
359
|
});
|
|
360
|
+
function updateTLSOptions() {
|
|
361
|
+
if ($("#node-input-usetls").is(':checked')) {
|
|
362
|
+
$("#node-row-tls").show();
|
|
363
|
+
} else {
|
|
364
|
+
$("#node-row-tls").hide();
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
if (this.tls) {
|
|
368
|
+
$('#node-input-usetls').prop('checked', true);
|
|
369
|
+
} else {
|
|
370
|
+
$('#node-input-usetls').prop('checked', false);
|
|
371
|
+
}
|
|
372
|
+
updateTLSOptions();
|
|
373
|
+
$("#node-input-usetls").on("click",function() {
|
|
374
|
+
updateTLSOptions();
|
|
375
|
+
});
|
|
376
|
+
},
|
|
377
|
+
oneditsave: function() {
|
|
378
|
+
if (!$("#node-input-usetls").is(':checked')) {
|
|
379
|
+
$("#node-input-tls").val("_ADD_");
|
|
380
|
+
}
|
|
275
381
|
}
|
|
276
382
|
});
|
|
277
383
|
</script>
|
package/core/network/31-tcpin.js
CHANGED
|
@@ -16,13 +16,46 @@
|
|
|
16
16
|
|
|
17
17
|
module.exports = function(RED) {
|
|
18
18
|
"use strict";
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
let reconnectTime = RED.settings.socketReconnectTime || 10000;
|
|
20
|
+
let socketTimeout = RED.settings.socketTimeout || null;
|
|
21
21
|
const msgQueueSize = RED.settings.tcpMsgQueueSize || 1000;
|
|
22
22
|
const Denque = require('denque');
|
|
23
|
-
|
|
23
|
+
const net = require('net');
|
|
24
|
+
const tls = require('tls');
|
|
25
|
+
|
|
26
|
+
let connectionPool = {};
|
|
27
|
+
|
|
28
|
+
function normalizeConnectArgs(listArgs) {
|
|
29
|
+
const args = net._normalizeArgs(listArgs);
|
|
30
|
+
const options = args[0];
|
|
31
|
+
const cb = args[1];
|
|
32
|
+
|
|
33
|
+
// If args[0] was options, then normalize dealt with it.
|
|
34
|
+
// If args[0] is port, or args[0], args[1] is host, port, we need to
|
|
35
|
+
// find the options and merge them in, normalize's options has only
|
|
36
|
+
// the host/port/path args that it knows about, not the tls options.
|
|
37
|
+
// This means that options.host overrides a host arg.
|
|
38
|
+
if (listArgs[1] !== null && typeof listArgs[1] === 'object') {
|
|
39
|
+
ObjectAssign(options, listArgs[1]);
|
|
40
|
+
} else if (listArgs[2] !== null && typeof listArgs[2] === 'object') {
|
|
41
|
+
ObjectAssign(options, listArgs[2]);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return cb ? [options, cb] : [options];
|
|
45
|
+
}
|
|
24
46
|
|
|
25
|
-
|
|
47
|
+
function getAllowUnauthorized() {
|
|
48
|
+
const allowUnauthorized = process.env.NODE_TLS_REJECT_UNAUTHORIZED === '0';
|
|
49
|
+
|
|
50
|
+
if (allowUnauthorized) {
|
|
51
|
+
process.emitWarning(
|
|
52
|
+
'Setting the NODE_TLS_REJECT_UNAUTHORIZED ' +
|
|
53
|
+
'environment variable to \'0\' makes TLS connections ' +
|
|
54
|
+
'and HTTPS requests insecure by disabling ' +
|
|
55
|
+
'certificate verification.');
|
|
56
|
+
}
|
|
57
|
+
return allowUnauthorized;
|
|
58
|
+
}
|
|
26
59
|
|
|
27
60
|
/**
|
|
28
61
|
* Enqueue `item` in `queue`
|
|
@@ -53,13 +86,14 @@ module.exports = function(RED) {
|
|
|
53
86
|
this.topic = n.topic;
|
|
54
87
|
this.stream = (!n.datamode||n.datamode=='stream'); /* stream,single*/
|
|
55
88
|
this.datatype = n.datatype||'buffer'; /* buffer,utf8,base64 */
|
|
56
|
-
this.newline = (n.newline||"").replace("\\n","\n").replace("\\r","\r");
|
|
89
|
+
this.newline = (n.newline||"").replace("\\n","\n").replace("\\r","\r").replace("\\t","\t");
|
|
57
90
|
this.base64 = n.base64;
|
|
58
91
|
this.server = (typeof n.server == 'boolean')?n.server:(n.server == "server");
|
|
59
92
|
this.closing = false;
|
|
60
93
|
this.connected = false;
|
|
61
94
|
var node = this;
|
|
62
95
|
var count = 0;
|
|
96
|
+
if (n.tls) { var tlsNode = RED.nodes.getNode(n.tls); }
|
|
63
97
|
|
|
64
98
|
if (!node.server) {
|
|
65
99
|
var buffer = null;
|
|
@@ -70,13 +104,25 @@ module.exports = function(RED) {
|
|
|
70
104
|
node.log(RED._("tcpin.status.connecting",{host:node.host,port:node.port}));
|
|
71
105
|
node.status({fill:"grey",shape:"dot",text:"common.status.connecting"});
|
|
72
106
|
var id = RED.util.generateId();
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
107
|
+
var connOpts = {host: node.host};
|
|
108
|
+
if (n.tls) {
|
|
109
|
+
var connOpts = tlsNode.addTLSOptions({host: node.host});
|
|
110
|
+
client = tls.connect(node.port, connOpts, function() {
|
|
111
|
+
buffer = (node.datatype == 'buffer') ? Buffer.alloc(0) : "";
|
|
112
|
+
node.connected = true;
|
|
113
|
+
node.log(RED._("status.connected", {host: node.host, port: node.port}));
|
|
114
|
+
node.status({fill:"green",shape:"dot",text:"common.status.connected",_session:{type:"tcp",id:id}});
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
client = net.connect(node.port, node.host, function() {
|
|
119
|
+
buffer = (node.datatype == 'buffer') ? Buffer.alloc(0) : "";
|
|
120
|
+
node.connected = true;
|
|
121
|
+
node.log(RED._("tcpin.status.connected",{host:node.host,port:node.port}));
|
|
122
|
+
node.status({fill:"green",shape:"dot",text:"common.status.connected",_session:{type:"tcp",id:id}});
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
client.setKeepAlive(true, 120000);
|
|
80
126
|
connectionPool[id] = client;
|
|
81
127
|
|
|
82
128
|
client.on('data', function (data) {
|
|
@@ -89,7 +135,7 @@ module.exports = function(RED) {
|
|
|
89
135
|
buffer = buffer+data;
|
|
90
136
|
var parts = buffer.split(node.newline);
|
|
91
137
|
for (var i = 0; i<parts.length-1; i+=1) {
|
|
92
|
-
msg = {topic:node.topic, payload:parts[i]};
|
|
138
|
+
msg = {topic:node.topic, payload:parts[i] + node.newline.trimEnd()};
|
|
93
139
|
msg._session = {type:"tcp",id:id};
|
|
94
140
|
node.send(msg);
|
|
95
141
|
}
|
|
@@ -150,7 +196,13 @@ module.exports = function(RED) {
|
|
|
150
196
|
});
|
|
151
197
|
}
|
|
152
198
|
else {
|
|
153
|
-
|
|
199
|
+
let srv = net;
|
|
200
|
+
let connOpts;
|
|
201
|
+
if (n.tls) {
|
|
202
|
+
srv = tls;
|
|
203
|
+
connOpts = tlsNode.addTLSOptions({});
|
|
204
|
+
}
|
|
205
|
+
var server = srv.createServer(connOpts, function (socket) {
|
|
154
206
|
socket.setKeepAlive(true,120000);
|
|
155
207
|
if (socketTimeout !== null) { socket.setTimeout(socketTimeout); }
|
|
156
208
|
var id = RED.util.generateId();
|
|
@@ -177,7 +229,7 @@ module.exports = function(RED) {
|
|
|
177
229
|
buffer = buffer+data;
|
|
178
230
|
var parts = buffer.split(node.newline);
|
|
179
231
|
for (var i = 0; i<parts.length-1; i+=1) {
|
|
180
|
-
msg = {topic:node.topic, payload:parts[i], ip:socket.remoteAddress, port:socket.remotePort};
|
|
232
|
+
msg = {topic:node.topic, payload:parts[i] + node.newline.trimEnd(), ip:socket.remoteAddress, port:socket.remotePort};
|
|
181
233
|
msg._session = {type:"tcp",id:id};
|
|
182
234
|
node.send(msg);
|
|
183
235
|
}
|
|
@@ -269,8 +321,9 @@ module.exports = function(RED) {
|
|
|
269
321
|
this.closing = false;
|
|
270
322
|
this.connected = false;
|
|
271
323
|
var node = this;
|
|
324
|
+
if (n.tls) { var tlsNode = RED.nodes.getNode(n.tls); }
|
|
272
325
|
|
|
273
|
-
if (!node.beserver||node.beserver=="client") {
|
|
326
|
+
if (!node.beserver || node.beserver == "client") {
|
|
274
327
|
var reconnectTimeout;
|
|
275
328
|
var client = null;
|
|
276
329
|
var end = false;
|
|
@@ -278,11 +331,24 @@ module.exports = function(RED) {
|
|
|
278
331
|
var setupTcpClient = function() {
|
|
279
332
|
node.log(RED._("tcpin.status.connecting",{host:node.host,port:node.port}));
|
|
280
333
|
node.status({fill:"grey",shape:"dot",text:"common.status.connecting"});
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
334
|
+
if (n.tls) {
|
|
335
|
+
// connOpts = tlsNode.addTLSOptions(connOpts);
|
|
336
|
+
// client = tls.connect(connOpts, function() {
|
|
337
|
+
var connOpts = tlsNode.addTLSOptions({host: node.host});
|
|
338
|
+
client = tls.connect(node.port, connOpts, function() {
|
|
339
|
+
// buffer = (node.datatype == 'buffer') ? Buffer.alloc(0) : "";
|
|
340
|
+
node.connected = true;
|
|
341
|
+
node.log(RED._("status.connected", {host: node.host, port: node.port}));
|
|
342
|
+
node.status({fill:"green",shape:"dot",text:"common.status.connected"});
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
else {
|
|
346
|
+
client = net.connect(node.port, node.host, function() {
|
|
347
|
+
node.connected = true;
|
|
348
|
+
node.log(RED._("tcpin.status.connected",{host:node.host,port:node.port}));
|
|
349
|
+
node.status({fill:"green",shape:"dot",text:"common.status.connected"});
|
|
350
|
+
});
|
|
351
|
+
}
|
|
286
352
|
client.setKeepAlive(true,120000);
|
|
287
353
|
client.on('error', function (err) {
|
|
288
354
|
node.log(RED._("tcpin.errors.error",{error:err.toString()}));
|
|
@@ -368,7 +434,13 @@ module.exports = function(RED) {
|
|
|
368
434
|
else {
|
|
369
435
|
var connectedSockets = [];
|
|
370
436
|
node.status({text:RED._("tcpin.status.connections",{count:0})});
|
|
371
|
-
|
|
437
|
+
let srv = net;
|
|
438
|
+
let connOpts;
|
|
439
|
+
if (n.tls) {
|
|
440
|
+
srv = tls;
|
|
441
|
+
connOpts = tlsNode.addTLSOptions({});
|
|
442
|
+
}
|
|
443
|
+
var server = srv.createServer(connOpts, function (socket) {
|
|
372
444
|
socket.setKeepAlive(true,120000);
|
|
373
445
|
if (socketTimeout !== null) { socket.setTimeout(socketTimeout); }
|
|
374
446
|
node.log(RED._("tcpin.status.connection-from",{host:socket.remoteAddress, port:socket.remotePort}));
|
|
@@ -445,7 +517,11 @@ module.exports = function(RED) {
|
|
|
445
517
|
this.port = Number(n.port);
|
|
446
518
|
this.out = n.out;
|
|
447
519
|
this.ret = n.ret || "buffer";
|
|
520
|
+
this.newline = (n.newline||"").replace("\\n","\n").replace("\\r","\r").replace("\\t","\t");
|
|
448
521
|
this.splitc = n.splitc;
|
|
522
|
+
if (n.tls) {
|
|
523
|
+
var tlsNode = RED.nodes.getNode(n.tls);
|
|
524
|
+
}
|
|
449
525
|
|
|
450
526
|
if (this.out === "immed") { this.splitc = -1; this.out = "time"; }
|
|
451
527
|
if (this.out !== "char") { this.splitc = Number(this.splitc); }
|
|
@@ -500,12 +576,48 @@ module.exports = function(RED) {
|
|
|
500
576
|
}
|
|
501
577
|
else { buf = Buffer.alloc(65536); } // set it to 64k... hopefully big enough for most TCP packets.... but only hopefully
|
|
502
578
|
|
|
503
|
-
|
|
579
|
+
var connOpts = {host:host, port:port};
|
|
580
|
+
if (n.tls) {
|
|
581
|
+
connOpts = tlsNode.addTLSOptions(connOpts);
|
|
582
|
+
const allowUnauthorized = getAllowUnauthorized();
|
|
583
|
+
|
|
584
|
+
let options = {
|
|
585
|
+
rejectUnauthorized: !allowUnauthorized,
|
|
586
|
+
ciphers: tls.DEFAULT_CIPHERS,
|
|
587
|
+
checkServerIdentity: tls.checkServerIdentity,
|
|
588
|
+
minDHSize: 1024,
|
|
589
|
+
...connOpts
|
|
590
|
+
};
|
|
591
|
+
|
|
592
|
+
if (!options.keepAlive) { options.singleUse = true; }
|
|
593
|
+
|
|
594
|
+
const context = options.secureContext || tls.createSecureContext(options);
|
|
595
|
+
|
|
596
|
+
clients[connection_id].client = new tls.TLSSocket(options.socket, {
|
|
597
|
+
allowHalfOpen: options.allowHalfOpen,
|
|
598
|
+
pipe: !!options.path,
|
|
599
|
+
secureContext: context,
|
|
600
|
+
isServer: false,
|
|
601
|
+
requestCert: false, // true,
|
|
602
|
+
rejectUnauthorized: false, // options.rejectUnauthorized !== false,
|
|
603
|
+
session: options.session,
|
|
604
|
+
ALPNProtocols: options.ALPNProtocols,
|
|
605
|
+
requestOCSP: options.requestOCSP,
|
|
606
|
+
enableTrace: options.enableTrace,
|
|
607
|
+
pskCallback: options.pskCallback,
|
|
608
|
+
highWaterMark: options.highWaterMark,
|
|
609
|
+
onread: options.onread,
|
|
610
|
+
signal: options.signal,
|
|
611
|
+
});
|
|
612
|
+
}
|
|
613
|
+
else {
|
|
614
|
+
clients[connection_id].client = net.Socket();
|
|
615
|
+
}
|
|
504
616
|
if (socketTimeout !== null) { clients[connection_id].client.setTimeout(socketTimeout);}
|
|
505
617
|
|
|
506
618
|
if (host && port) {
|
|
507
619
|
clients[connection_id].connecting = true;
|
|
508
|
-
clients[connection_id].client.connect(
|
|
620
|
+
clients[connection_id].client.connect(connOpts, function() {
|
|
509
621
|
//node.log(RED._("tcpin.errors.client-connected"));
|
|
510
622
|
node.status({fill:"green",shape:"dot",text:"common.status.connected"});
|
|
511
623
|
if (clients[connection_id] && clients[connection_id].client) {
|
|
@@ -528,17 +640,32 @@ module.exports = function(RED) {
|
|
|
528
640
|
else {
|
|
529
641
|
node.warn(RED._("tcpin.errors.no-host"));
|
|
530
642
|
}
|
|
531
|
-
|
|
643
|
+
var chunk = "";
|
|
532
644
|
clients[connection_id].client.on('data', function(data) {
|
|
533
645
|
if (node.out === "sit") { // if we are staying connected just send the buffer
|
|
534
646
|
if (clients[connection_id]) {
|
|
535
647
|
const msg = clients[connection_id].lastMsg || {};
|
|
536
648
|
msg.payload = RED.util.cloneMessage(data);
|
|
537
649
|
if (node.ret === "string") {
|
|
538
|
-
try {
|
|
539
|
-
|
|
650
|
+
try {
|
|
651
|
+
if (node.newline && node.newline !== "" ) {
|
|
652
|
+
chunk += msg.payload.toString();
|
|
653
|
+
let parts = chunk.split(node.newline);
|
|
654
|
+
for (var p=0; p<parts.length-1; p+=1) {
|
|
655
|
+
let m = RED.util.cloneMessage(msg);
|
|
656
|
+
m.payload = parts[p] + node.newline.trimEnd();
|
|
657
|
+
nodeSend(m);
|
|
658
|
+
}
|
|
659
|
+
chunk = parts[parts.length-1];
|
|
660
|
+
}
|
|
661
|
+
else {
|
|
662
|
+
msg.payload = msg.payload.toString();
|
|
663
|
+
nodeSend(msg);
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
catch(e) { node.error(RED._("tcpin.errors.bad-string"), msg); }
|
|
540
667
|
}
|
|
541
|
-
nodeSend(msg);
|
|
668
|
+
else { nodeSend(msg); }
|
|
542
669
|
}
|
|
543
670
|
}
|
|
544
671
|
// else if (node.splitc === 0) {
|
|
@@ -675,7 +802,13 @@ module.exports = function(RED) {
|
|
|
675
802
|
//node.warn(RED._("tcpin.errors.connect-timeout"));
|
|
676
803
|
if (clients[connection_id].client) {
|
|
677
804
|
clients[connection_id].connecting = true;
|
|
678
|
-
|
|
805
|
+
|
|
806
|
+
var connOpts = {host:host, port:port};
|
|
807
|
+
if (n.tls) {
|
|
808
|
+
connOpts = tlsNode.addTLSOptions(connOpts);
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
clients[connection_id].client.connect(connOpts, function() {
|
|
679
812
|
clients[connection_id].connected = true;
|
|
680
813
|
clients[connection_id].connecting = false;
|
|
681
814
|
node.status({fill:"green",shape:"dot",text:"common.status.connected"});
|
package/core/parsers/70-JSON.js
CHANGED
|
@@ -49,7 +49,11 @@ module.exports = function(RED) {
|
|
|
49
49
|
}
|
|
50
50
|
var value = RED.util.getMessageProperty(msg,node.property);
|
|
51
51
|
if (value !== undefined) {
|
|
52
|
-
if (typeof value === "string") {
|
|
52
|
+
if (typeof value === "string" || Buffer.isBuffer(value)) {
|
|
53
|
+
// if (Buffer.isBuffer(value) && node.action !== "obj") {
|
|
54
|
+
// node.warn(RED._("json.errors.dropped")); done();
|
|
55
|
+
// }
|
|
56
|
+
// else
|
|
53
57
|
if (node.action === "" || node.action === "obj") {
|
|
54
58
|
try {
|
|
55
59
|
RED.util.setMessageProperty(msg,node.property,JSON.parse(value));
|
package/core/storage/10-file.js
CHANGED
|
@@ -71,9 +71,7 @@ module.exports = function(RED) {
|
|
|
71
71
|
node.error(RED._("file.errors.deletefail",{error:err.toString()}),msg);
|
|
72
72
|
}
|
|
73
73
|
else {
|
|
74
|
-
|
|
75
|
-
node.log(RED._("file.status.deletedfile",{file:filename}));
|
|
76
|
-
}
|
|
74
|
+
node.debug(RED._("file.status.deletedfile",{file:filename}));
|
|
77
75
|
nodeSend(msg);
|
|
78
76
|
}
|
|
79
77
|
done();
|
package/locales/de/messages.json
CHANGED
|
@@ -442,7 +442,8 @@
|
|
|
442
442
|
"state": {
|
|
443
443
|
"connected": "Connected to broker: __broker__",
|
|
444
444
|
"disconnected": "Disconnected from broker: __broker__",
|
|
445
|
-
"connect-failed": "Connection failed to broker: __broker__"
|
|
445
|
+
"connect-failed": "Connection failed to broker: __broker__",
|
|
446
|
+
"broker-disconnected": "Broker __broker__ disconnected client: __reasonCode__ __reasonString__"
|
|
446
447
|
},
|
|
447
448
|
"retain": "Retain",
|
|
448
449
|
"output": {
|
|
@@ -530,7 +531,8 @@
|
|
|
530
531
|
"label": {
|
|
531
532
|
"type": "Type",
|
|
532
533
|
"path": "Path",
|
|
533
|
-
"url": "URL"
|
|
534
|
+
"url": "URL",
|
|
535
|
+
"subprotocol": "Subprotocol"
|
|
534
536
|
},
|
|
535
537
|
"listenon": "Listen on",
|
|
536
538
|
"connectto": "Connect to",
|
|
@@ -579,7 +581,9 @@
|
|
|
579
581
|
"server": "Server",
|
|
580
582
|
"return": "Return",
|
|
581
583
|
"ms": "ms",
|
|
582
|
-
"chars": "chars"
|
|
584
|
+
"chars": "chars",
|
|
585
|
+
"close": "Close",
|
|
586
|
+
"optional": "(optional)"
|
|
583
587
|
},
|
|
584
588
|
"type": {
|
|
585
589
|
"listen": "Listen on",
|
|
@@ -596,7 +600,7 @@
|
|
|
596
600
|
"return": {
|
|
597
601
|
"timeout": "after a fixed timeout of",
|
|
598
602
|
"character": "when character received is",
|
|
599
|
-
"number": "a fixed number of
|
|
603
|
+
"number": "after a fixed number of characters",
|
|
600
604
|
"never": "never - keep connection open",
|
|
601
605
|
"immed": "immediately - don't wait for reply"
|
|
602
606
|
},
|
|
@@ -616,11 +620,11 @@
|
|
|
616
620
|
"timeout": "timeout closed socket port __port__",
|
|
617
621
|
"cannot-listen": "unable to listen on port __port__, error: __error__",
|
|
618
622
|
"error": "error: __error__",
|
|
619
|
-
|
|
620
623
|
"socket-error": "socket error from __host__:__port__",
|
|
621
624
|
"no-host": "Host and/or port not set",
|
|
622
625
|
"connect-timeout": "connect timeout",
|
|
623
|
-
"connect-fail": "connect failed"
|
|
626
|
+
"connect-fail": "connect failed",
|
|
627
|
+
"bad-string": "failed to convert to string"
|
|
624
628
|
}
|
|
625
629
|
},
|
|
626
630
|
"udp": {
|
package/locales/ja/messages.json
CHANGED
|
@@ -291,8 +291,8 @@
|
|
|
291
291
|
"hour": "時間",
|
|
292
292
|
"days": "日",
|
|
293
293
|
"day": "日",
|
|
294
|
-
"between": "
|
|
295
|
-
"and": "
|
|
294
|
+
"between": "範囲",
|
|
295
|
+
"and": "〜",
|
|
296
296
|
"rate": "流量",
|
|
297
297
|
"msgper": "メッセージ/",
|
|
298
298
|
"queuemsg": "中間メッセージをキューに追加",
|
|
@@ -442,7 +442,8 @@
|
|
|
442
442
|
"state": {
|
|
443
443
|
"connected": "ブローカへ接続しました: __broker__",
|
|
444
444
|
"disconnected": "ブローカから切断されました: __broker__",
|
|
445
|
-
"connect-failed": "ブローカへの接続に失敗しました: __broker__"
|
|
445
|
+
"connect-failed": "ブローカへの接続に失敗しました: __broker__",
|
|
446
|
+
"broker-disconnected": "ブローカ __broker__ がクライアントを切断しました: __reasonCode__ __reasonString__"
|
|
446
447
|
},
|
|
447
448
|
"retain": "保持",
|
|
448
449
|
"output": {
|
|
@@ -530,7 +531,8 @@
|
|
|
530
531
|
"label": {
|
|
531
532
|
"type": "種類",
|
|
532
533
|
"path": "パス",
|
|
533
|
-
"url": "URL"
|
|
534
|
+
"url": "URL",
|
|
535
|
+
"subprotocol": "サブプロトコル"
|
|
534
536
|
},
|
|
535
537
|
"listenon": "待ち受け",
|
|
536
538
|
"connectto": "接続",
|
|
@@ -579,7 +581,9 @@
|
|
|
579
581
|
"server": "サーバ",
|
|
580
582
|
"return": "戻り値",
|
|
581
583
|
"ms": "ミリ秒",
|
|
582
|
-
"chars": "文字"
|
|
584
|
+
"chars": "文字",
|
|
585
|
+
"close": "終了",
|
|
586
|
+
"optional": "(任意)"
|
|
583
587
|
},
|
|
584
588
|
"type": {
|
|
585
589
|
"listen": "待ち受け",
|
|
@@ -618,7 +622,8 @@
|
|
|
618
622
|
"socket-error": "__host__:__port__ にてソケットのエラーが生じました",
|
|
619
623
|
"no-host": "ホスト名またはポートが設定されていません",
|
|
620
624
|
"connect-timeout": "接続がタイムアウトしました",
|
|
621
|
-
"connect-fail": "接続に失敗しました"
|
|
625
|
+
"connect-fail": "接続に失敗しました",
|
|
626
|
+
"bad-string": "文字列への変換に失敗しました"
|
|
622
627
|
}
|
|
623
628
|
},
|
|
624
629
|
"udp": {
|
package/locales/ko/messages.json
CHANGED
package/locales/ru/messages.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@node-red/nodes",
|
|
3
|
-
"version": "2.1
|
|
3
|
+
"version": "2.2.1",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -17,12 +17,12 @@
|
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"acorn": "8.7.0",
|
|
19
19
|
"acorn-walk": "8.2.0",
|
|
20
|
-
"ajv": "8.
|
|
20
|
+
"ajv": "8.10.0",
|
|
21
21
|
"body-parser": "1.19.1",
|
|
22
22
|
"cheerio": "1.0.0-rc.10",
|
|
23
23
|
"content-type": "1.0.4",
|
|
24
24
|
"cookie-parser": "1.4.6",
|
|
25
|
-
"cookie": "0.4.
|
|
25
|
+
"cookie": "0.4.2",
|
|
26
26
|
"cors": "2.8.5",
|
|
27
27
|
"cronosjs": "1.7.1",
|
|
28
28
|
"denque": "2.0.1",
|
|
@@ -36,14 +36,14 @@
|
|
|
36
36
|
"is-utf8": "0.2.1",
|
|
37
37
|
"js-yaml": "3.14.1",
|
|
38
38
|
"media-typer": "1.1.0",
|
|
39
|
-
"mqtt": "4.3.
|
|
40
|
-
"multer": "1.4.
|
|
39
|
+
"mqtt": "4.3.5",
|
|
40
|
+
"multer": "1.4.4",
|
|
41
41
|
"mustache": "4.2.0",
|
|
42
42
|
"on-headers": "1.0.2",
|
|
43
|
-
"raw-body": "2.4.
|
|
43
|
+
"raw-body": "2.4.3",
|
|
44
44
|
"tough-cookie": "4.0.0",
|
|
45
45
|
"uuid": "8.3.2",
|
|
46
|
-
"ws": "7.5.
|
|
46
|
+
"ws": "7.5.6",
|
|
47
47
|
"xml2js": "0.4.23",
|
|
48
48
|
"iconv-lite": "0.6.3"
|
|
49
49
|
}
|