Closed acidos closed 5 years ago
Did you put the access rule on the plc configuration? Have you been able to do it with another client?
C# client connecting to the same PLC from the same host just fine. Actually for local connection it's not necessary to put any access rule. But I put rule anyway, because without rule, your client is generating ECONNRESET
exception. Once the rule is there, then timeout
.
Ok,
Can you try enabling debug? DEBUG=node-ads node myclient.js
on Windows I did: set DEBUG=node-ads
then I run as usual node index.js
.
No change in output, perhaps it doesn't reach your code with debug.
c:\pkg>node index.js
events.js:183
throw er; // Unhandled 'error' event
^
Error: read ECONNRESET
at _errnoException (util.js:992:11)
at TCP.onread (net.js:618:25)
My best guess would be usage of amsNetIdSource
. I never seen such parameter in any client (C++, C#).
I captured ADS traffic for your client and working client. Here is what I found.
1. (sender to target)request to create handle for symbol
2. (target to sender)returned handle
3. (sender to target)ads read request with given handle
4. (target to sender)data provided
In your client I see the following sequence:
1. (sender to target)request to create handle for symbol
2. (target to sender)returned handle
3. (sender to target)ADS Read/Write Response with error code target not found!?!?
end of messaging
It could be that the capturing program missed something, but I doubt. If you are using AmsAdsViewer, I can provide with good/bad capture files.
Routing in case of local connection is another mystery. Like I said, other clients doesn't need any routing in order to connect to PLC locally. However, your client requires explicit adding 127.0.0.1
into static routing table.
I'm including @ovi1337 so maybe he could help debug since I don't have a TC2 right now.
I have some feeling for the routing issue, that using C#, C++ client, which are using COM/DCOM communication probably directly, so they don't need routing. This theory is supporting also the fact, that I used rawcap utility to capture local traffic (127.0.0.1 and assigned IP), but couldn't see any packets while using C# client. However, I was able to see AMS packets from your client.
@acidos the amsNetIdTarget
and amsNetIdSource
can't be the same, because this is a TCP/IP socket connection and you need a clear target and a destination. You can add a new route with another TargetId in the router configuration of your PLC like 10.10.2.100.1.1
and 10.10.2.100.1.2
.
Your node-ads project is basically an own simulated PLC.
@ovi1337 it was not straight forward to add 2 routing entries with the same 127.0.0.1
. With few attempts I was able to add and read was successfull.
And now it's working for you?
Yes, although still not clear why C#/C+6 client producing AMS traffic with same sender/target ams net ID.
@acidos, could you share your config?
I'm also trying to add two entries, but can't seem to figure that one out.
@sanderd17
Note the second entry comment, it says Sub route. The comment is not added by me.
If I understood correctly, it is on the router on the PLC. I found this:
You can set up a second IPv4 on the PC and assign to this a ADS NET ID under Twincat. But you have to disable DHCP and enter all IP addresses by hand.
If you want to run Twincat System Manager and Node-ADS on the same PC, that does not work either. The LIB from Beckhoff has the same problems https://github.com/Beckhoff/ADS/issues/30. (Thanx @scelle)
Not sure if it's related to localhost restrictions, but even though I use .end
in order to clean up connection, in event viewer I always see
TCP/IP Connection: Socket to Peer Name: 127.0.0.1, Port: 17657 is connected, current socket will be closed!
after each connect->write->end cycle. Port number is different of course each time. Could it be that connection is not teardown properly?
The .end works asynchronously. I had a similar problem with node red implementation. You have to wait for the callback from .end before you start a new connection. In the Note Red implementation, I added a sleep of 1s. But I'm still surprised that it works locally at all, but I assume that the system manager is not running.
node.on('close', function (done) {
node.adsNotificationNodes = []
node.systemNodes = []
internalRestart(done)
})
function internalRestart(done) {
internalSetConnectState(adsHelpers.connectState.DISCONNECTING)
clearTimeout(conncetTimer)
if (node.adsClient) {
node.adsClient.end(function (){
internalSetConnectState(adsHelpers.connectState.DISCONNECTED)
delete (node.adsClient)
var sleep = setInterval(function () {
clearTimeout(sleep)
done()
},1000)
})
} else {
internalSetConnectState(adsHelpers.connectState.DISCONNECTED)
done()
}
}
This is an example from the implementation, done is called when the connection is down.
System manager is up and running in Run mode. Between calls there is delay of 5 minutes.
var options = {
host: "127.0.0.1",
amsNetIdTarget: "10.10.2.100.1.1",
amsNetIdSource: "10.10.2.100.1.15",
amsPortTarget: 801
}
function intervalFunc() {
PKG('http://xxx', 'yyy', 'zzz', 'TL_X', sensors, function (error, values){
if(error == null)
{
var client = ads.connect(options, function() {
WriteAds(client, values[0]).
then(() => WriteAds(client, values[1])).
then(() => WriteAds(client, values[2])).
then(() => WriteAds(client, values[3])).
then(() => WriteAds(client, values[4])).
then(() => WriteAds(client, values[5])).
then(() => WriteAds(client, values[6])).
then(() => WriteAds(client, validityHandle)).
catch((err) => {
log.error("Error writing to ADS: ", err);
}).
finally(() => ReleaseAndDisconnect(client))
})
}
else
{
log.error('Error retrieving data from web: ', error);
process.exit(1);
}
});
}
intervalFunc();
setInterval(intervalFunc, 300000);
function ReleaseAndDisconnect(client)
{
return new Promise(function(resolve, reject){
client.end()
resolve()
})
}
function WriteAds(client, h)
{
return new Promise(function(resolve, reject){
console.log('Writing: ' + h.symname)
client.write(h, function(err) {
if (err)
{
reject(err)
}
else
{
resolve()
}
})
})
}
Hmm:
client.end(function (){ resolve() })
Please try the code without running System Manager on the system. Or run by another computer, just for testing. Beckhoff does not write for nothing in his ADS-Dll documentation that the router does not support two ADS connections with the same IP. The system manager and the ADS client do not work for me on the same client. I had to give the client 2 IP addresses.
The hint of Beckhoff on the local system to use the TcAdsDll unfortunately does not work as we use ads.
I run my node client from different host, where there is no TC, with adding rule into static route, but the message is still there
TCP/IP Connection: Socket to Peer Name: <IP of remote client PC, where there is no TC>, Port: 41695 is connected, current socket will be closed!
So in the ADS capture I see ADSIGRP_SYM_RELEASEHND
messages are there, but the info message clearly tells that TCP connection is not tear down properly. Basically it's not related to local/remote host use cases.
So in the ADS capture I see ADSIGRP_SYM_RELEASEHND messages are there, but the info message clearly tells that TCP connection is not tear down properly. Basically it's not related to local/remote host use cases.
I discovered the following in end (). Maybe that's the problem:
var end = function (cb) {
var ads = this
ads.tcpClient.removeListener('data', ads.dataCallback)
releaseSymHandles.call(ads, function () {
releaseNotificationHandles.call(ads, function () {
if (ads.tcpClient) {
// ads.tcpClient.end(); // reijo removed
ads.tcpClient.destroy() // reijo added
}
if (cb !== undefined) cb.call(ads)
})
})
}
may be end for tear down?
ads.tcpClient.end(); // reijo removed
// ads.tcpClient.destroy() // reijo added
may be end for tear down?
.end
won't teardown connection, but will tidy up the stream only. Anyway, I went to node_modules/node-ads/lib/ads.js
and opened .end
. Also tried only with .end
. Still get the current socket will be closed
notification in Event Viewer.
I find this hint in the Beckhoff documentation:
How to implement an ADS client
- Close ADS channel Always close ADS channel PortClose() – be aware to release handles before !
PortClose () is a function of the C ++ implementation. But I can not find a command for the ADS. I'm still not sure if the problem is in the socket or in the communication. The handles are released, I currently use to test an old CE PLC, I unfortunately have no monitor for this.
Node.js v10.10.0 Documentation Net Socket
I only see the function end() and destroy().
I unfortunately have no monitor for this
I don't use monitor for that, only Event Viewer
My setInterval is 5 min, so the events.
Which node version do you use?
node --version
Which TwinCat version do you use?
Closing the connection is part of the socket. TCPConnectionTermination
Therefore, there is no special code. Tonight I'll see if I can copy this behavior. Im using NODE v6.14.4 on RPI under Docker and TC 2.11.2605 on PLC
c:\pkg>node --version
v8.11.3
c:\pkg>npm --version
6.4.1
TC 2.11 (build 2249)
everything on single Beckhoff industrial PC
When you start your app for the first time after a reboot and you are done for the first cycle, you will see that the system is giving exactly the same message.
TCP/IP Verbindung: Socket to Peer Name: 192.168.2.60, Port: 18180 is connected, current socket will be closed!
The same message is issued by a Beckhoff ADS client with open Systemmanager for the first and each new connection (Enter the route again in the System Manager).
TCP/IP Verbindung: Socket to Peer Name: 192.168.2.44, Port: 28383 is connected, current socket will be closed!
That the port is counted up is apparently a problem of Beckhoff. Why this is so ... ask the Beckhoff hotline. If you want to have less events just do not disconnect. Check by a cyclic query on the symtable. If the symtbale number changes, the connection must be rebuilt. Or if the query does not work.
If you set up the route, you can specify a timeout. After this time, the connection disappears. This can be seen with netstat -an
. The port is counted up as well. And the port in the system log, is not the TCP Port.
I have just tested with a CX5020 with Microsoft Windows XP Embedded. There is no system manager running on the PLC. I had to install node 5.20, because from node 6 xp is no longer supported. I had no problem with node-ads accessing the PLC via the IP with a 2nd adsid. 127.0.0.1 did not work.
@roccomuso please close
I have successfully accessed remote ads target. But if I want to access target on the same machine(node app and target are same PC), then I get timeout.
yields to
timeout
message printed only. 10.10.2.100 (and I also tried 127.0.0.1) added into static routing table.Using TC2.