plcpeople / nodes7 Goto Github PK
View Code? Open in Web Editor NEWNode.JS library for communication to Siemens S7 PLCs
License: MIT License
Node.JS library for communication to Siemens S7 PLCs
License: MIT License
'DB17,S304.20.10' does not work.
We're having an issue, where nodeS7 is treating a packet that is apparently correct as invalid.
...
[997,136871469 172.25.24.210 S2] SendReadPacket called
[997,137073486 172.25.24.210 S2] Sending Read Packet
[997,137322621 172.25.24.210 S2] Sending Read Packet
[997,138683123] INVALID READ RESPONSE - DISCONNECTING
[997,138820445] TPKT Length From Header is 231 and RCV buffer length is 468 and COTP length is 2 and data[6] is 128
[997,138856085] <Buffer 03 00 00 e7 02 f0 80 32 03 00 00 00 02 00 02 00 d2 00 00 04 0b ff 04 00 70 00 00 00 00 00 09 00 00 00 00 00 00 00 00 ff 04 00 70 00 00 00 00 00 00 00 ... >
[997,139296666] ConnectionReset is happening
I've analyzed it a bit and, for the case we have here, it looks like that onResponse
is being called with two packages in the buffer (maybe the system was a bit slow at the moment) - this explains the TPKT length being 231 and the buffer length being 468 for the example above.
The code even treat this special case here, but it looks like the code isn't reaching this anymore because of the fastACK check being mate by checkRFCData
:
//...
}else if((LastDataUnit >> 7) == 1 && TPKT_Length === data.length){
//...
}else{
ret='error';
}
this causes ret
being assigned 'error'
instead of the buffer. Maybe the if-else comparison should be changed to:
//...
}else if((LastDataUnit >> 7) == 1 && TPKT_Length <= data.length){
//...
}else{
ret='error';
}
thus allowing the check previous mentioned check to be executed and succeed.
I have no experience with this fastACK functionality, therefore I don't know if this could break something. But if you agree on that I can create a PR for the modification above
Hello,
i try to fix an error in case you pull out the cable off the PLC. At some point during the Error process the ISO CS is 0 and the stack tries to reconnect to the PLC again. Perfect, so far. The an (TCP) timeout occures and nothing happens again. Not good.
In my opinion the stack always has to reconnect.
There are two options:
1: Try to reconnect from outside
2: The stack handles the TCP-reconnection. I think it should happen in the function/method connectError
@plcpeople : Do you plan to extend the functionality?
If not...@ all: any idea to implement No.1?
I tried to check the connection via isoConnectionState but i thik it would be way easier to change the lib.
Hi,
I want to extend the functionality to read/write the remaining basic Datatypes (S5TIME,TIME,CHAR,DATE,TOD). In which places of the src-code do i have to do changes?
Need some hints!!
Thanks
Here is how I am writing my setInterval call:
var myTimer;
myTimer = setInterval(conn.readAllItems, 2000, function(err, values){
if(!err){
callback(null, values);
}
else{
console.log(err);
callback(err);
}
})
The callback I reference is in the wrapper function where I am setting the interval. I tried passing it by placing "callback," after the 2000, and before the function(err, values)... but that didn't seem to change anything.
Here is what I get when I try to run it:
[27462038,628543252] Unable to read when not connected. Return bad values.
/home/ssi/nodemonitor/node_modules/nodes7/nodeS7.js:504
if (self.isWaiting()) {
^
TypeError: Object [object Object] has no method 'isWaiting'
If there is a better way to constantly monitor tags I'm all ears.
hey,
I'm still a beginner in programming but have become accustomed to it
I would like to use nodes7 to connect a website with a plc.
If someone has a better Idea I am happy about every suggestion.
what I've done so far:
Installation of node, browserify and the modules
create a file with browserify and integrate it into my website
We have an error. Maybe the PLC is not reachable.Cannot open TCP connection [404]: <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL /api/vm/net/connect was not found on this server.</p>
<hr>
<address>Apache/2.4.18 (Ubuntu) Server at 192.168.2.124 Port 80</address>
</body></html>
Maybe someone can help or give me a hint
Hi all,
A problem has been reported on netsmarttech/node-red-contrib-s7, where node eventually throws with the following stack trace:
30 Oct 11:42:37 - [red] Uncaught Exception:
30 Oct 11:42:37 - Error: write after end
at writeAfterEnd (_stream_writable.js:193:12)
at Socket.Writable.write (_stream_writable.js:244:5)
at Socket.write (net.js:658:40)
at NodeS7.onISOConnectReply (/home/pi/.node-red/node_modules/nodes7/nodeS7.js:306:17)
at Socket.<anonymous> (/home/pi/.node-red/node_modules/nodes7/nodeS7.js:262:26)
at emitOne (events.js:96:13)
at Socket.emit (events.js:188:7)
at readableAddChunk (_stream_readable.js:176:18)
at Socket.Readable.push (_stream_readable.js:134:10)
at TCP.onread (net.js:548:20)
I haven't done a full analysis/reproduction yet, but from the stack trace we can already guess the onISOConnectReply
is trying to write on a socket that has been already closed (isoclient.end()
has been called)
One of the possibilities I've thought about is, if dropConnection()
is called, isoclient.end()
is also called and the PLC may eventually send some data. If that would be the state where we're waiting for the ISO connect reply, this might happen.
Have you ever seen this?
When we receive multiple response packets from the PLC very fast, we must split them accordingly. Even though the function seems to be working correctly, the log output is producing a weird "NaN.":
...
[2633,113671889 172.168.31.60 S1] SendReadPacket called
[2633,212312295 172.168.31.60 S1] Sending Read Packet
[2633,218683916] NaN.
[2633,239537615] We assume this is because two packets were sent at nearly the same time by the PLC.
[2633,241705139] We are slicing the buffer and scheduling the second half for further processing next loop.
[2633,244438727 172.168.31.60 S1] Received 220 bytes of S7-data from PLC. Sequence number is 37
...
It looks like there's a simple fix for this, just a formatting issue. It's a small issue, but it's kind of annoying when analyzing bigger problems. I'll submit a PR for this.
Hi again,
now I have a problem on writing an Array of Boolean. In reality I need 16bit but for testcase I used 2.
Adress is "DB1,X2.0.2". Write command: plc.writeItems(['boolean'], [[false, true]], ...
Log:
[10622,237878058 192.168.36.94 S1] Preparing to WRITE boolean to value false,true
[10622,292730964] Received write error of 7 on DB1,X2.0.2
Hi,
found an Error. I declared an Array of Boolean ("DB1,X2.0.16") now I write the values (
[true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false]
) to the PLC. But the result within the PLC is
[true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false].
The first 8bit are copied to both bytes.
I tried two other sets:
this:
[true, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false]
results in:
[true, false, true, false, false, false, false, false, true, false, true, false, false, false, false, false]
and this:
[true, false, true, false, false, false, false, false, false, true, false, false, false, false, false, false]
results in:
[true, false, true, false, false, false, false, false, true, true, true, false, false, false, false, false]
Hardware ist still the same. #5
Version is 0.1.8.
Hello,
I've got the following log:
[18193,176543379] Initiate Called - Connecting to PLC with address and parameters:
[18193,182467207] { host: '192.168.36.94', port: 102, slot: 1, rack: 0 }
[18193,209406185] Connection cleanup is happening
[18193,216527877 192.168.36.94 S1] Attempting to connect to host...
[18193,224857695 192.168.36.94 S1] TCP Connection Established to 192.168.36.94 on port 102
[18193,227583800 192.168.36.94 S1] Will attempt ISO-on-TCP connection
[18193,235965423 192.168.36.94 S1] ISO-on-TCP Connection Confirm Packet Received
[18193,242886738 192.168.36.94 S1] Received PDU Response - Proceeding with PDU 240 and 3 max parallel connections.
[18193,247310183] Translation OK
[18193,249174666 192.168.36.94 S1] Preparing to WRITE g0,x0,v0,g1,x1,v1,g2,x2,v2,g3,x3,v3,g4,x4,v4,g5,x5,v5,g6,x6,v6,g7,x7,v7,g8,x8,v8,g9,x9,v9,g10,x10,v10,g11,x11,v11,g12,x12,v12 to value 50,3000,33,21,10000,100,10,30000,100,5,1000,0,20,-22000,75,10,30000,75,20,-22000,75,10,30000,75,20,-22000,75,10,30000,75,10,10000,25,11,0,10,0,0,0
[18193,286220953] PDU type (byte 8) was returned as 2 where the response PDU of 3 was expected.
[18193,288932884] Maybe you are requesting more than 240 bytes of data in a packet?
[18193,292037751] <Buffer 03 00 00 13 02 f0 80 32 02 00 00 00 02 00 00 00 00 85 00>
[18193,294749193] ConnectionReset is happening
[18193,297145409] We Caught a read/write error ECONNRESET - will DISCONNECT and attempt to reconnect.
[18193,300186252] ConnectionReset is happening
[18194,791888445 192.168.36.94 S1] WRITE TIMEOUT on sequence number 2
[18194,798587879] We must have timed Out - we have no response to process
[18194,804174488] Stopping Processing Write Response Packet due to unrecoverable packet error
[18194,814658604 192.168.36.94 S1] WRITE TIMEOUT on sequence number 3
[18194,819903105] We must have timed Out - we have no response to process
[18194,823505981] Stopping Processing Write Response Packet due to unrecoverable packet error
true
[18194,831520084] ResetNOW is happening
[18194,833264341] Clearing an earlier scheduled reset
I want to write to an Array of Struct in DB2. One Struct (line) conatins g: USINT; x: DINT and v: INT. The addresses are map the following way:
let map = {}
;[{g:1,x:2,v:3},...,{g:6,x:7,v:8}].forEach((line, index) => {
map['g' + index] = [`DB2,BYTE${index * 8}`, line.g]
map['x' + index] = [`DB2,DINT${index * 8 + 2}`, line.x]
map['v' + index] = [`DB2,INT${index * 8 + 6}`, line.v]
})
I can write exactly four lines at a time. One byte more and I get the error.
There is something about 240 byte in the log but 4 * 8 byte = 32 byte is much lower then 240 byte.
I am using a S7 1214 v2.2 CPU.
Hi, any intention to port this to TypeScript?
We could benefit from Async/Await and other ES2015 features while mantaining compatibility with ES3 and the actual API of nodeS7.
Also, if interested I can work on this.
It would be good to have example codes.
Hi, just a few questions from me 😃
I'm planning on including this in a restful API to avoid the need of a SCADA/OPC type 3rd party system and a database to pass information back and forth to a PLC. It's working up to now (Where by I have a basic api with express returning values from my datablock and posting any changes i make from a web front end)
Currently there are lots of outputs from the module, is there a way to turn these off 'in general' not error stuff just the normal information messages or will I have to do this myself? It's just so I don't fill up my logs with unnecessary information or will I have to go through one by one?
Also, instead of process.exit(); that is used in the example I call conn.dropConnection(); I'm concerned the connection is left open once a query has been made. Is this the intended use of this? I get connectionReset logs. If I don't drop the connection I can only make one get request and the ones after just hang, if I call dropConnection I can makes lots of requests in quick succession.
Any help appreciated!
Rogan.
Thank for you beatiful software.
I'm trying to simulate a pushbutton sending two consecutive request to write 1 and then 0 but there is a error message that I can't write if the previous activity is not completed. Evens using setTimeout with 3000 there is the same message. There is a way to solve?
Thanks
Walter
Is there any experience with S7-400H (it is the high availability version with two IP-Addresses)?
I get the "Error connecting to PLC: Error: read ECONNRESET" error.
I'm using it via node-red 0.17.5, node-red-contrib-s7 1.4.0 and nodes7 0.2.5.
Hello,
I have tested this node with node-red with my raspberrypi and Siemens S7200 smart PLC
It supports variable like. Input (I0.0) , Output (Q0.0), Memory Variables MW, MB. and working well.
But not able to read & write Variable Memory VB, VW , Vbit, and timer e.g T100 , counters.
Please help to how to get control this variable with nodeS7.
Not able to connect to S7-200 over the IP. Am using a USR IOT device over lan.....
[561172,811872480] Initiate Called - Connecting to PLC with address and parameters:
[561172,813506328] { port: 8899, host: '192.168.100.200', rack: 0, slot: 2 }
[561172,815174310] Connection cleanup is happening
[561172,817187607 192.168.100.200 S2] Attempting to connect to host...
[561172,832953789 192.168.100.200 S2] TCP Connection Established to 192.168.100.200 on port 8899
[561172,833238234 192.168.100.200 S2] Will attempt ISO-on-TCP connection
[561172,834068242 192.168.100.200 S2] Using rack [0] and slot [2]
[561174,338090001 192.168.100.200 S2] TIMED OUT connecting to the PLC - Disconnecting
[561174,338766979 192.168.100.200 S2] Wait for 2 seconds then try again.
[561174,339950267] ConnectionReset is happening
[561174,340925343 192.168.100.200 S2] Scheduling a reconnect from packetTimeout, connect type
[561175,842110622] ResetNOW is happening
[561175,843107315] Clearing an earlier scheduled reset
[561175,874652764 192.168.100.200 S2] ISO-on-TCP connection DISCONNECTED.
Error - TCP connected, ISO didn't
Hellooo,
Question: How can i track if the tcp Connection is ended in case of closing it?
I want to reconnect my connection after the RST packet of the plc arrived. At the moment the reconnection is 1,5 sec before the RST packet. (see Wireshark trace.) because of the Timeout function in NodeS7.prototype.connectionReset = function() { ... };
How can i track the reset? Maybe with self.resetPending?
Thanks
I just ran this test against an local s7 we have. The only thing I changed from the example code was the IP. I'm not familiar with ISO-on-TCP. Am I missing something on the configuration?
[97849,313122985] Initiate Called - Connecting to PLC with address and parameters:
[97849,313985846] { port: 102, host: '10.2.202.145', rack: 0, slot: 1 }
[97849,315746540] Connection cleanup is happening
[97849,329727559 10.2.202.145 S1] Attempting to connect to host...
[97849,334747742 10.2.202.145 S1] TCP Connection Established to 10.2.202.145 on port 102
[97849,334815782 10.2.202.145 S1] Will attempt ISO-on-TCP connection
[97849,341580313 10.2.202.145 S1] ISO-on-TCP connection DISCONNECTED.
Error - TCP connected, ISO didn't
Found a bug in line 1929:
//theItem.writeBuffer.writeUInt8(String.toCharCode(theItem.writeValue), thePointer);//buggy
theItem.writeBuffer.writeUInt8(theItem.writeValue.charCodeAt(theItem.writeValue), thePointer);
Scenario to reproduce: Write char
conn.writeItems('DB111,CHAR4', 'f', valuesWritten);
Can anyone confirm?
self.connectReq = new Buffer([0x03, 0x00, 0x00, 0x16, 0x11, 0xe0, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc0, 0x01, 0x0a, 0xc1, 0x02, 0x01, 0x00, 0xc2, 0x02, 0x01, 0x02]);
self.negotiatePDU = new Buffer([0x03, 0x00, 0x00, 0x19, 0x02, 0xf0, 0x80, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x08, 0x00, 0x08, 0x03, 0xc0]);
self.readReqHeader = new Buffer([0x03, 0x00, 0x00, 0x1f, 0x02, 0xf0, 0x80, 0x32, 0x01, 0x00, 0x00, 0x08, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x04, 0x01]);
self.readReq = new Buffer(1500);
self.writeReqHeader = new Buffer([0x03, 0x00, 0x00, 0x1f, 0x02, 0xf0, 0x80, 0x32, 0x01, 0x00, 0x00, 0x08, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x05, 0x01]);
self.writeReq = new Buffer(1500);
Is there a datasheet or it just the profinet protocal?
Hello,
at first of all - nodes7 is great !
The only problem i have is to write a bit.
Conntection is OK and read items works fine - REAL, BITS, INT.
Write INT, REAL works also fine.
The only Problem is to write Bits
TEST:'M20.0',
TEST1: 'DB10,X4.0',
For example i use
conn.writeItems('TEST', [true], valuesWritten);
The function valuesWritten bring me a "Done Writing" Message.
Do have a syntax mistake at my variables or at my code?
Description:
I tested the connection management of nodes7 under Windows as well as under Linux. For the test I use keepalive. (Note: Under Linux I use the modul net-keepalive).
Environment:
Tests (Under Linux as well as under Windows.) :
Test case 1:
Test case 2:
Steps to Reproduce:
const NodeS7 = require('nodes7');
let NetKeepAlive = null;
try {
NetKeepAlive = require('net-keepalive'); // net-keepalive depends on the OS
} catch (er) {
console.log('Installation of Module net-keepalive failed. (OS=' + process.platform + ')');
NetKeepAlive = null;
}
const plc = new NodeS7({ debug: 1, silent: false });
const param = { port: 102, host: '192.168.0.111', rack: 0, slot: 2 };
const intervalReading = false; // Set Flag to true/false
plc.initiateConnection(param, (err) => {
if (typeof (err) !== 'undefined') {
console.log(err);
process.exit();
}
// Enable KeepAlive.
plc.isoclient.setKeepAlive(true, 3000);
if (NetKeepAlive) {
console.log('Set keepalive parameter for linux.');
NetKeepAlive.setKeepAliveInterval(plc.isoclient, 3000);
NetKeepAlive.setKeepAliveProbes(plc.isoclient, 5);
}
if (intervalReading) {
plc.addItems('MB0');
setInterval(() => {
console.log('Status: ' + plc.isoConnectionState);
plc.readAllItems((anythingBad, values) => {
if (anythingBad) {
console.log('SOMETHING WENT WRONG READING VALUES!!!!');
} else {
console.log(values);
}
});
}, 1000);
}
});
Expected Behavior:
Test case 1:
Test case 2:
Actual Behavior:
Overview:
Testcase | 1 | 2 |
---|---|---|
Windows | OK | OK |
Linux | OK | Not OK |
Detailed:
To Testcase 1 (windows): NodeS7 resets Program due to ECONNRESET
To Testcase 2 (windows): NodeS7 resets Program due to ECONNRESET, restarts communication again.
To Testcase 1 (linux): NodeS7 resets Program due to ETIMEDOUT
To Testcase 2 (linux): No reset of nodes7, state always at 4 due to missing ETIMEDOUT, but nodes7 restarts communication again.
I think the state should also go to 0 here.
Hi,
currently i have a problem that due to the lovely Fast Acknowledge a timeout occurs.
See:
org.txt
Until the “onResponse” function, the communication is alright.
I would we should somehow cancel the timer or re-trigger it here:
Line 1088 in 3f70a74
I tried it out with “clearReadPacketTimeouts” but then further communication was not possible anymore. How can I restart the timer?
Hallo everyone,
i have a problem that I want to discuss.
The NodeS7-module uses the net-module to create a socket for the whole communication.
I'm reading cyclic values from the plc. To simulate a connection error I pulled off the Ethernet cable. I tested the reaction of my software on three OS. Windows, Ubuntu VM and the destination system an embedded Linux OS. Each of them behave different. The Windows-OS and Ubuntu VM are stopping the communication which is good. In the emb. Linux nothing happens. I debugged the net module to see what's happening in it.
The following picture shows the log-files of each OS.
left shell=Windows: after a Timeout of the nodeS7-library the net-module detects an ECONNRESET
middle shell=Ubuntu: after a Timeout of the nodeS7-library the net-module detects an EOF
right shell=embedded Linux: nothing is getting detected
When you have a look on the src-code of the net-module you can see that the debug-log onread is getting created within the onread-function. The on-read function is always called whenever the handle gets a buffer, or when there's an error reading.
Well, I have a reading error. What I am doing wrong???
Any ideas?
We need to add tests in order not to break anything while adding new features/fixing bugs.
This bug was created by myself. Sorry. I am now creating a pull request to fix it.
I have a problem to drop a connection instance when a previous initiateConnection() has returned an error.
Use Case:
That behaviour only applies to ECONNRESET, not ETIMEDOUT
Any thoughts?
Hello, everyone,
I've discovered a bug that shouldn't exist.
The variable requestMaxParallel and maxparallel are used to define the number of parallel jobs in the network. These connection parameters are negotiated with the PLC in the function onPDUReply. That's working as far as I can tell. (see)
This error means that I have set the values from 8 to 1 and still two orders are sent.
The error occurred with a WinAC. Because of "Fast Acknowledge" I have set the values from 8 to 1.
On the following picture you can see a Wireshark section:
Packets 236,237 and 238 show a successful data exchange (including Fast Acknoledge).
Packet 240 shows a transmission request. Packet 242 another one, although maxparallel is set to 1 (!).
The error behavior is that with the received stream data (usually 460 bytes) are not complete.
e. g.:
[2482,147791652 172.20.15.70 S2] Address DB11134, BYTE0.6456 has value
0,..., 0,0,0,0,0,8..., 3,3,32, and quality BAD 255,..., BAD 255, OK, OK, OK, OK, OK, OK, OK, OK, OK, OK, OK, OK, OK, OK
Hi plcpeople
I tried read data from PLC S7 1200. But I can't read data with data type float from PLC.
DB155.DBD332,FLOAT0
DB155.DBD332,FLOAT0.0
with no success.
could you tell me what the type of float is?
Add ability for a custom timeout when connecting to a PLC.
This is the result of the analysis of the following issue: st-one-io/node-red-contrib-s7#10
The issue there says that, although all variables seem to be setup correctly, the read process return "Bad values". With the variable list provided and the logs, I could reproduce the issue locally (with Snap7 acting as the PLC).
With the help of Wireshark, we can take a look at the packets exchanged and I found that, even though the negotiated PDU size was 240 bytes...
... nodes7
was requesting a packet bigger than that (in this case, 276 bytes - can be seen in the status bar):
Checking on how the packets are created, I saw that care is taken so that the reply is not bigger than the PDU size, but not the request. This usually not the case, but can occur under the following circumstance:
data_length + 4
), andI propose to fix this by computing the resulting request packet size, not only the reply one. Then we can split it when the response or when the request would be bigger than the negotiated PDU size. I've implemented this locally and it seems to solve the problem. A PR will follow with this suggestion.
Dear Sir,
I there any provision for PLC Password Authentication ?
Hi,
I using context sensible translationCB's.
Now if I add items and don't read, then change context, remove old and add the new items and change translationCB, I get an error on the next read. Because the old items in the addRemoveArray
are not covered by the latest translationCB.
I solved this by removing all unnessesary addItems
but I am sure the is a better solution.
Hi @plcpeople and all users of nodeS7,
We all love nodeS7 the project and all the possibilities it opens. The code has been maturing along the last weeks and months, but I see some improvement room to codebase, and therefore I'd like to propose and discuss a roadmap to the version 1.0.0
of this awesome project.
In my personal opinion, in this first milestone I'd like to see (and of course contribute to) a major refactor of the code, separating the logic, creating classes, and organizing the code, without introducing any new feature. This would make it much easier to understand and to maintain, also making it easier to introduce many new features. We could then have more guarantees for the future of the project.
I think we could create a Wiki page or a Project to summarize all the ideas and discuss them, what do you think?
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
Hi,
I evaluated some writing constellations and saw that some are not working:
`conn.writeItems('M0.0', [false], valuesWritten); //OK
conn.writeItems(['MB0.0'], [false], valuesWritten); //**Not Working**
conn.writeItems(['M0.0','M0.1','M0.2','M0.3'], [true,true,false,false], valuesWritten);//OK
conn.writeItems('MB0', [7], valuesWritten); //OK
conn.writeItems(['MB0'], [6], valuesWritten); //OK
conn.writeItems('MB0.3', [ 1,2,3 ], valuesWritten); //OK
conn.writeItems(['MB0.3'], [ 2,3,4 ], valuesWritten); //**Not Working**`
Is this on purpose??
We're having a pretty hard to solve issue on st-one-io/node-red-contrib-s7#3. Some users of this Node-RED node are reporting that an uncaught exception related to the TCP connection is bringing the whole process down. I've already spent quite some hours trying to simulate it and I could not reproduce it. However, analyzing nodes7's code, I could find one special case where such a thing could happen.
In my previous experiences dealing with net.Socket
, I found out it's only safe to remove all listeners from a socket after calling its destroy()
method or after the close
event, making sure that no more i/o operations will happen on it, according to the docs.
On nodes7, however, all listeners are removed by calling connectionCleanup()
, but destroy()
is not called there. destroy()
is only called on the timeout of dropConnection()
, but connectionCleanup()
is called from other places too, specially by connectNow()
. Therefore, in some special cases, like packet timeouts, connectNow()
may be called (and by consequence connectionCleanup()
) without the previous connection being completely closed. This could lead to these strange exceptions being thrown.
Finally, I would like to suggest a modification: move the destroy()
call to the connectionCleanup()
, so we'd make sure we wouldn't left anything open before removing the listeners for errors. I hope this fixes or at least amends the problems there :)
Thanks!
I've found an odd condition, where nodeS7 keeps trying to reconnect forever, and there's no way to stop it.
I've simulated the following with an S7-1200:
If you create a connection with a wrong parameter (e.g. wrong slot), we'll open the TCP socket, onTCPConnect()
ist called, but then the connection is rejected after the ISO-on-TCP connection because of the wrong parameter. error
and close
events are emitted, and they both correctly triggers the cleanup process by calling connectionReset()
and resetNow()
.
The main problem happens with the connectTimeout
from onTCPConnect()
: There, the packetTimeout()
gets called with he "connect"
parameter, and this calls connectNow()
again after some time. But as the parameters are wrong, the same error will happen again, and this will keep happening forever. There's no way to stop it but to kill the process.
I see two possible solutions here:
dropConnection()
to stop the loop: dropConnection()
is the way we currently have to close the communication, so we could either:
dropConnection()
signalizing we're dead, so 'connectNow()' would just skip it, ordropConnection()
clean the timer from packetTimeout()
, preventing the connection reset to happen againconnectTimeout
timer from onTCPConnect()
if we get an error
event (on the connectError()
).The second solution seems more correct in my point of view, as it should stop doing anything if the connection callback is called with an error.
What do you think about it? I can create then a PR with the fix for this using the solution chosen.
P.S.: This seems to be the cause of the issues st-one-io/node-red-contrib-s7#26 and st-one-io/node-red-contrib-s7#29
Hello, after being about 10 minutes reading, it gives this error and I can not control it to continue the execution. (S7-1500 )
Does anyone know why this might happen?
Thank you.
[6802,958350399] Connection cleanup is happening
[6802,958702800 192.168.0.2 S1] Attempting to connect to host...
[6802,959635499 192.168.0.2 S1] TCP Connection Established to 192.168.0.2 on port 102
[6802,959848699 192.168.0.2 S1] Will attempt ISO-on-TCP connection
[6802,960114000 192.168.0.2 S1] Using rack [0] and slot [1]
[6802,961254600 192.168.0.2 S1] ISO-on-TCP Connection Confirm Packet Received
[6802,962537699] We Caught a read/write error ECONNRESET - will DISCONNECT and attempt to reconnect.
[6802,962793700] ConnectionReset is happening
[6802,963064500] ConnectionReset is happening
[6804,461757300] TIMED OUT waiting for PDU reply packet from PLC - Disconnecting
[6804,462975099 192.168.0.2 S1] Wait for 2 seconds then try again.
[6804,463273599] ConnectionReset is happening
[6804,463524400 192.168.0.2 S1] Scheduling a reconnect from packetTimeout, connect type
[6804,464642200] ResetNOW is happening
[6804,464870400] Clearing an earlier scheduled reset
[6806,463175399 192.168.0.2 S1] The scheduled reconnect from packetTimeout, PDU type, is happening now
[6806,464447400] Connection cleanup is happening
[6806,464894500 192.168.0.2 S1] Attempting to connect to host...
[6806,466437600 192.168.0.2 S1] TCP Connection Established to 192.168.0.2 on port 102
[6806,466659799 192.168.0.2 S1] Will attempt ISO-on-TCP connection
[6806,466880999 192.168.0.2 S1] Using rack [0] and slot [1]
[6806,468413500 192.168.0.2 S1] We Caught a connect error ECONNRESET
{ Error: read ECONNRESET
at _errnoException (util.js:992:11)
at TCP.onread (net.js:618:25) code: 'ECONNRESET', errno: 'ECONNRESET', syscall: 'read' }
Support to be added in the future. For now, "V" memory in S7-200 is accessed by specifying DB1.
Hy,
I had to change :
require('nodeS7');
into
require('nodes7');
to make the test run.
Thanks, great jobs, it runs almost out of the box with S7-1200.
Hi,
I can not connect to the S7-1200 PLC. However, I can connect to the same PLC using this library: https://github.com/killnine/s7netplus
What causes this problem?
Hi, while trying to read BOOL located in a DB, I cannot access to it,
I tried
DB1,BOOL0
DB1,BOOL0.0
with no success.
Is this a lack from your implementation, or shall I investigate on PLC/firmware/TIAportal side ?
Hello everyone,
i am not 100% shure if this is a bug. I have following issue:
Within my PLC (S7-300) i have a Datablock DB111. Address 0 is parameterized as STRING[12] with the content "SIMATIC--PLC".
When i read out following variables:
var variable = [ 'DB111,CHAR0.14', 'DB111,STRING0.11', 'DB111,STRING1.12', ];
i'll get:
{ 'DB111,CHAR0.14': '\u0000\u0000SIMATIC--PLC', 'DB111,STRING0.11': '', 'DB111,STRING1.12': 'IMATIC--PLC\u0000' }
.
Interpretation:
'DB111,CHAR0.14', =>should be alright, two bytes infront of the actual string.
'DB111,STRING0.11', => Wrong
'DB111,STRING1.12',=> For testing purpose
Hey,
can somebody tell me if it work with a Logo 8?
I testet already but i can't change or read values.
They sad the Logo is online but nothing more.
Thx
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.