Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

S7 Client returns invalid Connected status #51

Closed
leovujanic opened this issue Mar 28, 2019 · 15 comments
Closed

S7 Client returns invalid Connected status #51

leovujanic opened this issue Mar 28, 2019 · 15 comments

Comments

@leovujanic
Copy link

Hi,

I'm running the latest version of node-snap7 and having trouble with S7Client.Connected() method which returns true in a case when the client was connected to PLC and network broke in the meanwhile (eg. turn off WIFI).

@mathiask88
Copy link
Owner

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.

@leovujanic
Copy link
Author

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.

@mathiask88
Copy link
Owner

Sorry, I've currently no test setup ready. I'll search for my S7-1500 in the cellar and test it next week :)

@leovujanic
Copy link
Author

I think the same behavior is reported in python wrapper for snap7 - gijzelaerr/python-snap7#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.

@mathiask88
Copy link
Owner

mathiask88 commented Apr 2, 2019

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

@leovujanic
Copy link
Author

Error code is 655470 and message is: ISO: An error occurred during recv TCP : Connection timed out.

@mathiask88
Copy link
Owner

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.

@leovujanic
Copy link
Author

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?

@mathiask88
Copy link
Owner

@leovujanic What was the result, can this be closed?

@leovujanic
Copy link
Author

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.

@leovujanic
Copy link
Author

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)
...

@unocelli
Copy link

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?

@leovujanic
Copy link
Author

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.

@leovujanic
Copy link
Author

I am closing this because it's more related to snap7 lib then this one.

@mathiask88 thank you for your support!

@Apollon77
Copy link

@leovujanic is you error handler the code above or how does it look like? Could you share it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants