Closed leovujanic closed 5 years ago
Hi,
sockets are not able to notice if the connection is interrupted until they send a message and this message times out. So if you interrupt your network the connection status will be true
until the client sends a new message and receives a timeout.
Thank you @mathiask88 for the response. Not sure if I'm doing something wrong but with the code bellow, Connected()
always returns true
. I'm using TS and non-blocking calls in my app, this is just a snippet to check behavior. After the first read, before the timeout fires, I disable WIFI. Second readDb
call fails but Connected
still returns true
.
const snap7 = require('node-snap7');
const S7Client = new snap7.S7Client();
function readDb(readCnt) {
const res = S7Client.DBRead(2, 10, 2);
if (res === false) {
console.error(`Unable to read from DB [${readCnt}]`);
return;
}
console.log(`Result[${readCnt}]: ${res.readUInt16BE(0)}`);
}
S7Client.ConnectTo('192.168.1.40', 0, 1, function (err) {
if (err) {
console.error(' >> Connection failed. Code #' + err + ' - ' + S7Client.ErrorText(err));
return false;
}
console.log(`Connected[1]: ${S7Client.Connected()}`);
readDb(1);
console.log(`Connected[2]: ${S7Client.Connected()}`);
setTimeout(function () {
readDb(2);
console.log(`Connected[3]: ${S7Client.Connected()}`);
}, 10000);
});
process.on('SIGINT', function () {
S7Client.Disconnect();
});
and the output is:
Connected[1]: true
Result[1]: 23
Connected[2]: true
Unable to read from DB [2]
Connected[3]: true
If I manually call Disconnect()
then Connected()
returns false
as expected, or in the case when the connection to PLC was never established.
Sorry, I've currently no test setup ready. I'll search for my S7-1500 in the cellar and test it next week :)
I think the same behavior is reported in python wrapper for snap7 - https://github.com/gijzelaerr/python-snap7/issues/111 . Their conclusion is that this is a bug in the snap7 lib. I'll check that issue is reported to snap7 lib directly. Maybe this helps you.
Can you write out the LastError()
here console.error(`Unable to read from DB [${readCnt}]`);
? Connection property is only set to false if socket errors with WSAECONNRESET
Error code is 655470
and message is: ISO: An error occurred during recv TCP : Connection timed out
.
Now we can discuss if a WSAETIMEDOUT
really is a disconnect 😃 But what you can do is to check for the timeout error code and disconnect from client side.
Yes, that's exactly what I have done, it was a minor design change. :)
I can make another test day after tomorrow and check if the client is able to read after timeout error occurs and the connection is established again. If it fails to read, from my point of view, WSAETIMEDOUT should be considered as "disconnected". What do you think? Does that make sense to you?
@leovujanic What was the result, can this be closed?
Hi @mathiask88 , sorry for not replying, I was tight with time and didn't manage to test it in an isolated environment. I will do it through the weekend and reply.
Hi @mathiask88 , I apologize for the late reply. I've made a few tests and the conclusion is that the client can recover from Connection timed out
error. But interesting thing to note is that after n time out errors (or after some time - not sure), a new error is received ISO : An error occurred during send TCP : Other Socket error (32)
, number 589856
. After that error client is unable to auto-reconnect and Connected()
method always returns true. My conclusion is that Connected()
will return false
if the initial connection to plc wasn't established or Disconnect()
is called.
This is the code:
const snap7 = require('node-snap7');
const S7Client = new snap7.S7Client();
let interval = null;
function readDb(readCnt) {
const res = S7Client.DBRead(2, 250.0, 2);
if (res === false) {
console.error(`Unable to read from DB [${readCnt}] ${S7Client.ErrorText(S7Client.LastError())} | ${S7Client.LastError()}`);
return;
}
console.log(`Result[${readCnt}]: ${res.readUInt16BE(0)}`);
}
S7Client.ConnectTo('192.168.1.40', 0, 1, function(err) {
if (err) {
console.error(' >> Connection failed. Code #' + err + ' - ' + S7Client.ErrorText(err));
console.log(`Connected[2]: ${S7Client.Connected()}`);
return false;
}
readDb(1);
console.log(`Connected[1]: ${S7Client.Connected()}`);
setTimeout(function() {
// take time to disconnect
let cnt = 2;
interval = setInterval(() => {
readDb(cnt);
console.log(`Connected[${cnt}]: ${S7Client.Connected()}`);
cnt++;
}, 1000);
}, 6000);
});
process.on('SIGINT', function() {
console.log("Caught interrupt signal");
clearInterval(interval);
S7Client.Disconnect();
});
and output example (connect -> timeout -> reconnect -> disconnect):
Result[1]: 0
Connected[1]: true
Unable to read from DB [2] ISO : An error occurred during recv TCP : Connection timed out
Connected[2]: true
Unable to read from DB [3] ISO : An error occurred during recv TCP : Connection timed out
Connected[3]: true
Unable to read from DB [4] ISO : An error occurred during recv TCP : Connection timed out
Connected[4]: true
...
Result[9]: 0
Connected[9]: true
Result[10]: 0
Connected[10]: true
Unable to read from DB [11] ISO : An error occurred during recv TCP : Connection timed out
Connected[11]: true
...
Unable to read from DB [22] ISO : An error occurred during recv TCP : Connection timed out
Connected[22]: true
Unable to read from DB [23] ISO : An error occurred during recv TCP : Connection timed out
Connected[23]: true
Unable to read from DB [24] ISO : An error occurred during send TCP : Other Socket error (32)
Connected[24]: true
Unable to read from DB [25] ISO : An error occurred during send TCP : Other Socket error (32)
Connected[25]: true
Unable to read from DB [26] ISO : An error occurred during send TCP : Other Socket error (32)
...
Hi, I'm using the latest version of node-snap7 in FUXA project and I'm looking for a valid solution to detecting the disconnection of the PLC since the Connected() method in that case don't work?
Hi, @unocelli !
I have implemented an error handler that filters socket related errors and in case of socket error, triggers reconnect mechanism. In reconnecting attempt I'm checking if Connected()
returns true and calling Disconnect()
followed by Connect()
. At the time of writing, I didn't find a more elegant way to do it. I hope this helps you.
I am closing this because it's more related to snap7 lib then this one.
@mathiask88 thank you for your support!
@leovujanic is you error handler the code above or how does it look like? Could you share it?
Hi,
I'm running the latest version of node-snap7 and having trouble with
S7Client.Connected()
method which returnstrue
in a case when the client was connected to PLC and network broke in the meanwhile (eg. turn off WIFI).