Tcp request node, host/port via flow works only once

Hi,

I use the "tcp request node" because host/port will change and this node allows to pass in both via flow. I see the following effect and believe its a bug:

  • node ist not connected
  • I pass in an empty msg with host and port correctly set
  • the node connects as expected (I use the mode "keep connection open")
  • then I pass other host/port, wrong one, node disconnects as expected
  • then pass again the correct ones, node does not connect again > problem

In other words, I can pass the correct host/port one time but thats it.
However, I need to pass it several times and node shall reconnect accordingly.
Is this behavior known?

I use node-red 0.18.5

To be honest, it's hard to say. There have been a number of fixes made to the TCP Request node since 0.18.5 was released.

Are you able to upgrade to 0.19.4 and see if you can still reproduce?

Thanks Nick
will try with 0.19.4 and come back with an info

I have now made a fresh 0.19.4 installation (still the same problem) and reduced the example (below) showing the error clearly IMHO.

There are two triggers, one passes correct msg.host and msg.port to the tcp node (node connects successfully), the other passes a port that won't work (tcp node shows error as expected).

Problem is now as follows:

  • trigger correct one > node connects
  • then trigger wrong one > node disconnects
  • then trigger correct one > node does not connect anymore !!
    Flow has to be redeployed to let it connect again.

I guess this effect can be reproduced with every open tcp port not only the one I used.

[{"id":"a3ef18b7.a999c","type":"inject","z":"b202007e.d90a8","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":480,"y":200,"wires":[["c51694de.595b3"]]},{"id":"903ca0e4.9bea1","type":"debug","z":"b202007e.d90a8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":970,"y":260,"wires":[]},{"id":"69515a20.c2559c","type":"tcp request","z":"b202007e.d90a8","server":"","port":"","out":"sit","splitc":" ","name":"","x":790,"y":260,"wires":[["903ca0e4.9bea1"]]},{"id":"c51694de.595b3","type":"function","z":"b202007e.d90a8","name":"1012","func":"msg.host = \"192.168.178.2\";\nmsg.port = 1012;\nreturn msg;","outputs":1,"noerr":0,"x":630,"y":200,"wires":[["69515a20.c2559c","9ab87057.0de5a8"]]},{"id":"298f72a8.db23fe","type":"function","z":"b202007e.d90a8","name":"1015","func":"msg.host = \"192.168.178.2\";\nmsg.port = 1015;\nreturn msg;","outputs":1,"noerr":0,"x":630,"y":320,"wires":[["69515a20.c2559c","44c039e4.3a0dc8"]]},{"id":"eb52f817.2df93","type":"inject","z":"b202007e.d90a8","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":480,"y":320,"wires":[["298f72a8.db23fe"]]},{"id":"9ab87057.0de5a8","type":"debug","z":"b202007e.d90a8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":790,"y":200,"wires":[]},{"id":"44c039e4.3a0dc8","type":"debug","z":"b202007e.d90a8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":790,"y":320,"wires":[]}]

Hello,

  1. I can't import the flow! Missing backslash at IP: \"192.168.178.2\"
  2. If tcp-request could not connect - no response after "SYN_SENDED" - it will close with error after some seconds.
  3. If you can get a connection, then the tcp-node will show green connected.
    When you send an other IP:Port, the conection remains active !!!
    You can't disconnect.

I needed to disconnect a valid connection.
My solution:
Locate the tcpin.js and add after line 503 following code:

503 node.warn(RED._("tcpin.errors.no-host"));

	//WZ added for closing connection
	for (var cl in clients) {
		if (clients[cl].hasOwnProperty("client")) {
			clients[cl].client.destroy();
		}
	}
	node.status({});
                    node.warn(RED._("tcpin.status.connection-closed"));
	//WZ//

With this modification you can close a connection by sending
msg.host = "";

Wolfgang

@Mumin you need to edit your last post and insert a line contianing three backticks before the flow and another such line after the flow. Then it will be importable.

thanks Colin, have edit and done as suggested

Wolfgang, works perfect with your added code snippet, thanks!

You should add a note to the info part in the .html and make a pull request from both changes.
From my point of view its a necessary enhancement to be able to disconnect.

Torsten

@Mumin if you can recreate on 0.19.4, then please raise an issue on github - https://github.com/node-red/node-red/issues/new - and provide the information you gave in the comment earlier today.

The ability to explicitly disconnect an existing session that @karamo proposes is a separate enhancement discussion to fixing the issue you have.

Hi @Mumin - just tried your flow above. And...for me... it mostly works... the status is indeed slightly incorrect - in that it shows error from the second inject - and remains showing that when the first inject is hit again...(which it should not). But the first connection is still connected as the node is set to not drop the connection... so the data is injected just fine and reaches the other end ok..

So to me it just looks like a cosmetic wrinkle that needs fixing.

(As Nick mentioned - being able to close one of these links then does need some more thinking about.)

Hi @dceejay - if this is the case it's even better.
I thought a displayed connection error really means it does not work. Others e.g. @karamo seems to think in the same way.
However, as I am also using the "status" node to monitor the tcp node and show on dashboard, I guess its not cosmetic only, right? Or is the state correctly handled and only wrongly shown in admin UI?

That depends on your definition of cosmetic. The node works ok, it just looks as if it isn't when you use the status.

Well the status node does report that status and can then be used to trigger things - so it ought to be accurate as it can be. So it should be fixed. But... the status can only reflect one thing... if you start using (this node) to connect to multiple hosts then the status will only reflect the last action, and you will have to track which host you are talking to and so what host the status is referring to. - it is only really intended to be a single connection.

Hi @dceejay and @Colin

In the meantime I have found out that the status node does not work either here. It shows the wrong state like the node-red admin UI. So, for me that is not a cosmetic one.

I have solved it for me now with the suggested fix Wolfgang has explained in this thread. It works but isn't very elegant to send a msg.host="" before next connect attempt.

Thus, my recommendation to the maintainer of the tcp request node is:
should be changed, so that it reconnects when a new msg.host/msg.port is received or disconnects if host/port will get "". The status information should be updated accordingly, so that the status node can really be used here to work with the current connection state of the tcp request node.

Anyway, thanks for your help!

The status fix was pushed into dev a few days ago - https://github.com/node-red/node-red/commit/f488869635fe1115f6895fdee08c6f52cea49557

*** Please advice if the following comment requires a new post - or if it is fixed and it is me actually messing up on my end ***

I am currently having the same issue as the one firstly reported by @Mumin: By using "TCP REQUEST" node I only get an output payload (in ascii/hex) once, but in my case, the messages don't stop coming from the output. I instead only get from the response only one byte (0x0A) instead of the rest of the payload.

  1. I am using "TCP REQUEST" to interface with Tektronix PA1000 utilizing straight forward IEEE 488.2 (starting pg. 37)

  2. I am able to send commands and the devices acknowledges them as expected.

  3. But the responses are always "0x0A" and very seldom the actual content I requested to begin with.

I would greatly appreciate direction, as this could well be a self inflicted error on my end. Moreover, I will be happy to assist if this is indeed a bug.

Thank you kindly in advance.

[{"id":"91134f0f.59e56","type":"tab","label":"Flow 1","disabled":false,"info":""},{"id":"ee476e69.f8ba1","type":"tcp request","z":"91134f0f.59e56","server":"10.0.0.2","port":"5025","out":"char","splitc":"\\n","name":"","x":590,"y":320,"wires":[["940dc005.ddfb","b9282c57.2a503"]]},{"id":"fdcc778a.c7c118","type":"inject","z":"91134f0f.59e56","name":"","topic":"","payload":"*IDN?","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":350,"y":320,"wires":[["ee476e69.f8ba1","940dc005.ddfb"]]},{"id":"940dc005.ddfb","type":"debug","z":"91134f0f.59e56","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":1130,"y":560,"wires":[]},{"id":"982ff998.27cf48","type":"comment","z":"91134f0f.59e56","name":"SAMPLE COMMANDS","info":"SEND Setup:\n\n :SEL:CLR\n :SEL:VLT\n :SEL:AMP\n :SEL:WAT\n :SEL:PWF\n :SEL:FRQ\n :SEL:IMP\n :SEL:RES\n :SEL:REA\n :SEL:VAR\n *IDN?\n\nREAD Measurements:\n :FRD?","x":700,"y":240,"wires":[]},{"id":"806f7115.1a8e","type":"inject","z":"91134f0f.59e56","name":"","topic":"","payload":":SEL:CLR","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":340,"y":380,"wires":[["ee476e69.f8ba1","940dc005.ddfb"]]},{"id":"273ab32e.62e51c","type":"inject","z":"91134f0f.59e56","name":"","topic":"","payload":":SEL:FRQ","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":340,"y":500,"wires":[["ee476e69.f8ba1","940dc005.ddfb"]]},{"id":"5e353b51.aa0364","type":"inject","z":"91134f0f.59e56","name":"","topic":"","payload":":FRD?","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":350,"y":560,"wires":[["ee476e69.f8ba1","940dc005.ddfb"]]},{"id":"de583ef3.c9237","type":"inject","z":"91134f0f.59e56","name":"","topic":"","payload":":SEL:VLT","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":340,"y":440,"wires":[["ee476e69.f8ba1","940dc005.ddfb"]]},{"id":"b9282c57.2a503","type":"function","z":"91134f0f.59e56","name":"ascii -> string (?)","func":"msg.payload = msg.payload.toString('utf8')\nreturn msg;","outputs":1,"noerr":0,"x":890,"y":320,"wires":[["940dc005.ddfb"]]}]

HI @ExpZeros, I did not read the previous posts but I remember seen similar issues like the one you reported.

It is worth to make a quick testing, based on this paragraph from the manual:

Commands and responses are sent as ASCII strings terminated with a line feed.

Try changing your function node from:

msg.payload = msg.payload.toString('utf8')
return msg;

to

msg.payload = msg.payload.toString('utf8')+"\n";
return msg;

or perhaps +"\n\r"

It might not be this but there was a bug in a TCP node a few months ago - are you on latest 0.19.5 version of Node-RED?

@Andrei @cymplecy

I went and created a simple local TCP server to actually see what NR dumps and sure enough every time I was injecting strings, I was not getting a termination "\n", nor "\n\r", nor "\r\n" at the end, so it was just pilling up commands endlessly on the server.

so following @Andrei advice, I added a "Function Node" between the "Injection Node" and the "TCP Request" node with this:

msg.payload = msg.payload + "\n";
return msg;

... that did the Job!!!!

NOTE: I actually tried to add (command) + "\xyz" within the injection node but it would not work like that.

Specs on my machine:
mac-mini, 2.6 Ghz i5, 8Gb Ram, Osx Mojave 10.14.2
Node-RED version: v0.19.5
Node.js version: v10.15.1
Darwin 18.2.0 x64 LE
Dashboard version 2.13.2 started at /ui

If I may:
I feel this node should have the option to append a termination character, as for example: the same way it is done on "node-red-node-serialport".... specially if one possible goal is to talk to external (measurement) devices. (and to add: I will check this on my linux machine to see if it is OSX only sometime next week, with probably same results)

1 Like

If you select the json input type rather than simple string then you can add \r \ n to the string in the inject node

2 Likes