node-red-contrib-tcp-client
Advanced tools
Comparing version
{ | ||
"name": "node-red-contrib-tcp-client", | ||
"version": "0.0.1", | ||
"description": "Start a dynamic TCP client", | ||
"version": "0.0.2", | ||
"description": "Dynamic TCP input node", | ||
"node-red": { | ||
@@ -20,3 +20,5 @@ "nodes": { | ||
"node", | ||
"tcp" | ||
"tcp", | ||
"client", | ||
"xml" | ||
], | ||
@@ -23,0 +25,0 @@ "author": "Tiago Costa", |
# node-red-contrib-tcp-client | ||
Unlike the default node-red tcp-in node, this one allows to create a dynamic TCP client. | ||
Unlike the default node-red tcp-in node, this one allows you to create dynamic TCP connections. | ||
It also allows XML output. | ||
Allows stopping an existing connection by passing a "close" action: | ||
 | ||
Added support to XML over TCP with parsing and some options on the output. | ||
## How it works: | ||
@@ -11,6 +15,2 @@ | ||
### Future: | ||
Reset connection | ||
## To install: | ||
@@ -17,0 +17,0 @@ |
@@ -15,3 +15,3 @@ 'use strict'; | ||
this.action = config.action || "Listen"; | ||
this.action = config.action || "listen"; /* listen,close */ | ||
this.port = config.port * 1; | ||
@@ -26,3 +26,5 @@ this.topic = config.topic; | ||
const node = this; | ||
var connectionPool = {}; | ||
var server; | ||
@@ -39,143 +41,176 @@ node.on('input', function (msg, nodeSend, nodeDone) { | ||
var server = net.createServer(function (socket) { | ||
var id = node.port.toString(16); | ||
socket.setKeepAlive(true, 120000); | ||
if (typeof server === 'undefined') { | ||
if (socketTimeout !== null) { | ||
socket.setTimeout(socketTimeout); | ||
} | ||
server = net.createServer(function (socket) { | ||
var id = (1 + Math.random() * 4294967295).toString(16); | ||
connectionPool[id] = socket; | ||
var buffer = (node.datatype == 'buffer') ? Buffer.alloc(0) : ""; | ||
socket.on('data', function (data) { | ||
if (node.datatype != 'buffer') { | ||
data = data.toString(node.datatype == 'xml' ? 'utf8' : node.datatype); | ||
socket.setKeepAlive(true, 120000); | ||
if (socketTimeout !== null) { | ||
socket.setTimeout(socketTimeout); | ||
} | ||
if (node.stream) { | ||
var result = { | ||
topic: msg.topic || config.topic | ||
}; | ||
if ((typeof data) === "string" && node.newline !== "") { | ||
buffer = buffer + data; | ||
var parts = buffer.split(node.newline); | ||
for (var i = 0; i < parts.length - 1; i += 1) { | ||
result.payload = parts[i]; | ||
if (node.datatype == 'xml') { | ||
var xml2js = require('xml2js'); | ||
var parseXml = xml2js.parseString; | ||
var parseOpts = {}; | ||
parseOpts.async = true; | ||
parseOpts.attrkey = '$'; | ||
parseOpts.charkey = '_'; | ||
if (config.xmlStrip) { | ||
var stripPrefix = require('xml2js').processors.stripPrefix; | ||
parseOpts.tagNameProcessors = [ stripPrefix ]; | ||
connectionPool[id] = socket; | ||
var buffer = (node.datatype == 'buffer') ? Buffer.alloc(0) : ""; | ||
socket.on('data', function (data) { | ||
if (node.datatype != 'buffer') { | ||
data = data.toString(node.datatype == 'xml' ? 'utf8' : node.datatype); | ||
} | ||
if (node.stream) { | ||
var result = { | ||
topic: msg.topic || config.topic | ||
}; | ||
if ((typeof data) === "string" && node.newline !== "") { | ||
buffer = buffer + data; | ||
var parts = buffer.split(node.newline); | ||
for (var i = 0; i < parts.length - 1; i += 1) { | ||
result.payload = parts[i]; | ||
if (node.datatype == 'xml') { | ||
var xml2js = require('xml2js'); | ||
var parseXml = xml2js.parseString; | ||
var parseOpts = {}; | ||
parseOpts.async = true; | ||
parseOpts.attrkey = '$'; | ||
parseOpts.charkey = '_'; | ||
if (config.xmlStrip) { | ||
var stripPrefix = require('xml2js').processors.stripPrefix; | ||
parseOpts.tagNameProcessors = [ stripPrefix ]; | ||
} | ||
var parseStr = result.payload.replace(/^[\x00\s]*/g, "");//Non-whitespace before first tag | ||
parseStr += node.newline; | ||
parseXml(parseStr, parseOpts, function (parseErr, parseResult) { | ||
if (!parseErr) { | ||
result.payload = config.xmlSimplify ? simplifyXML(parseResult) : parseResult; | ||
nodeSend(result); | ||
} | ||
}); | ||
} | ||
var parseStr = result.payload.replace(/^[\x00\s]*/g, "");//Non-whitespace before first tag | ||
parseStr += node.newline; | ||
parseXml(parseStr, parseOpts, function (parseErr, parseResult) { | ||
if (!parseErr) { | ||
result.payload = config.xmlSimplify ? simplifyXML(parseResult) : parseResult; | ||
nodeSend(result); | ||
} | ||
}); | ||
else { | ||
nodeSend(result); | ||
} | ||
} | ||
else { | ||
nodeSend(result); | ||
} | ||
buffer = parts[parts.length - 1]; | ||
} | ||
buffer = parts[parts.length - 1]; | ||
else { | ||
result.payload = data; | ||
nodeSend(result); | ||
} | ||
} | ||
else { | ||
result.payload = data; | ||
nodeSend(result); | ||
if ((typeof data) === "string") { | ||
buffer = buffer + data; | ||
} | ||
else { | ||
buffer = Buffer.concat([buffer, data], buffer.length + data.length); | ||
} | ||
} | ||
} | ||
else { | ||
if ((typeof data) === "string") { | ||
buffer = buffer + data; | ||
}); | ||
socket.on('end', function () { | ||
if (!node.stream || (node.datatype === "utf8" && node.newline !== "")) { | ||
if (buffer.length > 0) { | ||
var result = { | ||
topic: msg.topic || config.topic, | ||
payload: buffer | ||
}; | ||
nodeSend(result); | ||
} | ||
buffer = null; | ||
} | ||
else { | ||
buffer = Buffer.concat([buffer, data], buffer.length + data.length); | ||
} | ||
} | ||
}); | ||
socket.on('timeout', function () { | ||
socket.end(); | ||
}); | ||
socket.on('close', function () { | ||
delete connectionPool[id]; | ||
}); | ||
socket.on('error', function (err) { | ||
node.log(err); | ||
}); | ||
}); | ||
socket.on('end', function () { | ||
if (!node.stream || (node.datatype === "utf8" && node.newline !== "")) { | ||
if (buffer.length > 0) { | ||
var result = { | ||
topic: msg.topic || config.topic, | ||
payload: buffer | ||
}; | ||
nodeSend(result); | ||
} | ||
buffer = null; | ||
server.on('error', function (err) { | ||
if (err) { | ||
node.error(err); | ||
} | ||
}); | ||
socket.on('timeout', function () { | ||
} | ||
var close = function() { | ||
if (connectionPool[id]) { | ||
var socket = connectionPool[id]; | ||
socket.end(); | ||
}); | ||
socket.on('close', function () { | ||
socket.destroy(); | ||
socket.unref(); | ||
server.close(); | ||
delete connectionPool[id]; | ||
}); | ||
socket.on('error', function (err) { | ||
node.log(err); | ||
}); | ||
}); | ||
server.on('error', function (err) { | ||
if (err) { | ||
node.error(err); | ||
} | ||
}); | ||
}; | ||
server.listen(node.port, function (err) { | ||
if (err) { | ||
node.error(err); | ||
} else { | ||
node.on('close', function () { | ||
for (var c in connectionPool) { | ||
if (connectionPool.hasOwnProperty(c)) { | ||
connectionPool[c].end(); | ||
connectionPool[c].unref(); | ||
} | ||
var listen = function() { | ||
if (typeof connectionPool[id] === 'undefined') { | ||
server.listen(node.port, function (err) { | ||
if (err) { | ||
node.error(err); | ||
} | ||
node.closing = true; | ||
server.close(); | ||
}); | ||
} | ||
}); | ||
else { | ||
node.error(`Already listening on port ${node.port}`); | ||
} | ||
}; | ||
switch (node.action.toLowerCase()) { | ||
case 'close': | ||
close(); | ||
break; | ||
default: | ||
listen(); | ||
} | ||
}); | ||
node.on("close",function() { | ||
for (var c in connectionPool) { | ||
if (connectionPool.hasOwnProperty(c)) { | ||
var socket = connectionPool[c]; | ||
socket.end(); | ||
socket.destroy(); | ||
socket.unref(); | ||
} | ||
} | ||
server.close(); | ||
connectionPool = {}; | ||
node.status({}); | ||
}); | ||
@@ -182,0 +217,0 @@ |
Sorry, the diff of this file is not supported yet
37630
32.2%8
33.33%175
17.45%