plcpeople / nodeS7

Node.JS library for communication to Siemens S7 PLCs
MIT License
358 stars 121 forks source link

Node-RED crashes while reading data #69

Closed pabaxx closed 5 years ago

pabaxx commented 5 years ago

Hello, i'm working on a student project and got a 'big' issue :

i have a local s7-1500 i'm working with and a gateway with node-red container installed inside docker.

reading out the data with S7in Node is no problem, but when i'm using the example code (from the readme) and put in my adress (just an array of 8 integers for testing) , node-red crashes after ~120s. First it works fine, i'm receiving the data as expected, but after this time i'm loosing connection to node-red. The problem is reconstructable.. any ideas? best regards

plcpeople commented 5 years ago

Can you please post some sort of stack trace, log or other information so that we know where in the code it's crashing? It may not even be crashing in NodeS7.

pabaxx commented 5 years ago

unfortunately, i dont have access to the host-system where nodered shows the logs.. i just setup a new container https://hub.docker.com/r/hilschernetpi/netpi-nodered-fieldbus/ and the only thing i've installed in it was an ssh-server & nodeS7, but it crashed again after about 2minutes when i read out data..

plcpeople commented 5 years ago

Are you able to get a stack trace or log from that new container?

pabaxx commented 5 years ago

i'm very new to this all, but i installed stacktrace-js and got this output, no idea wether its helpful or not..

Function()@node:eeea8b0d.93ffa8:13:12 Function()@node:eeea8b0d.93ffa8:17:3 ContextifyScript.Script.runInContext()@vm.js:59:29 FunctionNode.()@/usr/lib/node_modules/node-red/nodes/core/core/80-function.js:224:33 emitOne()@events.js:116:13 FunctionNode.emit()@events.js:211:7 FunctionNode.Node.receive()@/usr/lib/node_modules/node-red/red/runtime/nodes/Node.js:215:14 InjectNode.Node.send()@/usr/lib/node_modules/node-red/red/runtime/nodes/Node.js:202:14

dont think so because the message dont change when the container crashes

plcpeople commented 5 years ago

By stack trace I mean the console output when the node process crashes, if it's actually crashing rather than just stopping communicating with the PLC. Can you access the console output through the container somehow? Docker logs maybe?

pabaxx commented 5 years ago

unfortunately, i cannot access the docker logs because the host system is secured and i only have access to the docker UI. The communication doesnt stop instantly, first i get the same outputs several times and then the connection to node-red gets lost..

Lichtjaeger commented 5 years ago

Can't you run your program locally instead of the container for debugging purposes?

pabaxx commented 5 years ago

I just saw that docker gives me an error, maybe you can tell me something about it..

DPM status changed 0xFF (OK => 0x11)! Error SPIReadChunk: DPM Addr=0x200 / Len=0x4

but this only appears when starting the container..

plcpeople commented 5 years ago

That is not the information we're after.

Please let us know if you can duplicate the issue locally. Do you have local access to a PLC? If so, install Node-RED and everything locally, in a Docker container or just on its own, and see if you can duplicate the problem that way.

pabaxx commented 5 years ago

Yes I installed Node-Red in Windows and get the same issue..

[1576,703541400 192.168.222.5 S1] Attempting to connect to host... [1576,706120599 192.168.222.5 S1] TCP Connection Established to 192.168.222.5 on port 102 [1576,707020700 192.168.222.5 S1] Will attempt ISO-on-TCP connection [1576,707752300 192.168.222.5 S1] Using rack [0] and slot [1] [1576,710439100 192.168.222.5 S1] ISO-on-TCP Connection Confirm Packet Received 16 Oct 09:05:13 - [red] Uncaught Exception: 16 Oct 09:05:13 - Error: write ECONNRESET at _errnoException (util.js:992:11) at Socket._writeGeneric (net.js:764:25) at Socket._write (net.js:783:8) at doWrite (_stream_writable.js:397:12) at writeOrBuffer (_stream_writable.js:383:5) at Socket.Writable.write (_stream_writable.js:290:11) at Socket.write (net.js:707:40) at NodeS7.onISOConnectReply (C:\Users\Administrator.node-red\node_modules\nodes7\nodeS7.js:315:17) at Socket. (C:\Users\Administrator.node-red\node_modules\nodes7\nodeS7.js:271:26) at emitOne (events.js:116:13)

pabaxx commented 5 years ago
var nodes7 = global.get('nodes7');  // This is the package name, if the repository is cloned you may need to require 'nodeS7' with uppercase S
var conn = new nodes7();
var doneReading = false;
var doneWriting = false;

var variables = { TEST1: 'DB3,INT2.8'       // Integer Array of 8 in DB3 at Offset 2
//        TEST2: 'M32.2',       // Bit at M32.2
//        TEST3: 'M20.0',       // Bit at M20.0
//        TEST4: 'DB1,REAL0.20',    // Array of 20 values in DB1
//        TEST5: 'DB1,REAL4',       // Single real value
//        TEST6: 'DB1,REAL8',       // Another single real value
//        TEST7: 'DB1,INT12.2'      // Two integer value array
};

conn.initiateConnection({port: 102, host: '192.168.222.5', rack: 0, slot: 1}, connected); // slot 2 for 300/400, slot 1 for 1200/1500
//conn.initiateConnection({port: 102, host: '192.168.0.2', localTSAP: 0x0100, remoteTSAP: 0x0200, timeout: 8000}, connected); // local and remote TSAP can also be directly specified instead.  The timeout option specifies the TCP timeout.

function connected(err) {
    if (typeof(err) !== "undefined") {
        // We have an error.  Maybe the PLC is not reachable.
        console.log(err);
        process.exit();
    }
    conn.setTranslationCB(function(tag) {return variables[tag];});  // This sets the "translation" to allow us to work with object names
    conn.addItems(['TEST1']);
//  conn.addItems('TEST6');
//  conn.removeItems(['TEST2', 'TEST3']);  // We could do this.
//  conn.writeItems(['TEST5', 'TEST6'], [ 867.5309, 9 ], valuesWritten);  // You can write an array of items as well.
//  conn.writeItems('TEST7', [ 666, 777 ], valuesWritten);  // You can write a single array item too.
    conn.readAllItems(valuesReady);
}

function valuesReady(anythingBad, values) {
    if (anythingBad) { console.log("SOMETHING WENT WRONG READING VALUES!!!!"); }
//  node.error(values.TEST1);
    flow.set("values",values.TEST1);
    doneReading = true;
    if (doneWriting) { process.exit(); }
}

function valuesWritten(anythingBad) {
    if (anythingBad) { console.log("SOMETHING WENT WRONG WRITING VALUES!!!!"); }
    console.log("Done writing.");
    doneWriting = true;
    if (doneReading) { process.exit(); }
}
msg.payload = flow.get("values");
return msg;
gfcittolin commented 5 years ago

Are you putting this code inside a function node on Node-RED? Please note that the whole code is executed on every incoming message. This means you're creating a new connection on every message, without cleaning up the old one. So you end up using all the connection resources of the PLC and it won't accept new connections, that's why you're getting the ECONNRESET.

Why don't you use the node-red-contrib-s7 node? It uses this library and handles all the details for you.

pabaxx commented 5 years ago

Okey thank you, then thats the problem.. I wont use contrib-s7 because my DB addresses are variable and read out from another document.. I know i can upload an csv file but that should be automated so I'm using the code in a function for easy handling

could i simply add dropConnection() to the end of my function?

gfcittolin commented 5 years ago

Adding dropConnection() may do it there. But take care not run

Another (maybe cleaner) solution in your case would be to create a separate executable, where you can pass the variables over command line arguments or stdin, and then call it using the "exec" node, so you don't have this giant function in Node-RED.