-
Notifications
You must be signed in to change notification settings - Fork 58
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
Sporadic transfer of random numbers to the S7 #96
Comments
Version 1.0.7 did not change the code of node-snap7. Just the build tools to prebuild the native cpp addon for the current node version. So I would say unlikely but never say never. A test case would be good.. |
This problem has existed since 2018, I didn't have it until I did a test in ioBroker because I didn't believe it. |
I wrote the current seconds into a DInt every second since the beginning of the day and after a while a negative value arrived in the PLC. The polling time was set to 200ms. I excluded the ioBroker adapter because I inserted a log before describing with node-snap7 in which the data was still correct.
|
Could you post a minimal example without any other dependencies, that fails for you? Then I can run this locally and see if I can reproduce this behaviour. Otherwise it is hard to help. |
I tried it like this (without copying the double word in the S7): Now, of course, the whole thing has run again in the ioBroker environment with a Javascript (Blockly). If anyone can give me a tip on how to run and log such a script on a Linux system without iobroker, I would be happy to try it. So: Linux is installed (in my case Ubuntu 22 Server), node-js, npm installed, node-snap7 is installed and configured and writes a double word with a number and this number is read back and logged if the number is outside the limits. |
I'll do some testing this week. If I can't reproduce I will share the test code so you can try to in your environment. |
In my current constellation the random numbers occur like 6 times in 24 hours in average over the last couple of days |
With this script I wrote random numbers into DB2.DBD12 at a rate of 100ms.
|
@Bettman66 is that a script you run independent from iobroker? Or do you run it in iobroker in Javascript just not in blockly? |
I run the script independently of ioBroker. |
Ah okay, and what is the conclusion? Does anything in iobroker screw something up, after all? |
I don't know what to say anymore. |
I do some more testing to narrow the behavior down further... |
@Bettman66 I took your Javascript from above and put it in iobroker as Javascript but a little modified as I couldn't get it to run (I installed system-sleep). I'm writing a Float in the S7 every 500ms but the comparison of written and read value didn't work in the iobroker environment (error was like "readInt32BE not defined" or so even when I tried to read Float).
So I'm reading the DB23.DBD620 now in blockly and check if the value is above 99 or below -99 and if so I write into the log file. Sure enough over the last two days I did not get any over- or under run bypassing the S7 Adapter (which the script does, I guess) while other values (written via blockly) do get the sporadic over- or under run. Does that help in any direction? Another thing I'm wondering about: I don't see where a poll delay/ cycle time is being set in the script while in the S7 Adapter I configured a poll delay of 200ms. Can that have something to do with our problem? Another interesting effect: Even if I stop the script in iobroker, it keeps running (writing data to DB23.DBD620) and stops only once I stop the Javascript instance. Any clue why that? |
I think I found the issue: When I use one/ the same "buf" only to write multiple values to multiple DB.DBDs, the sporadic transfer happens:
As soon as I use one buf per value to be written (buf1 - buf5), the transfer works perfectly without any sporadic random value:
The question for me now is: Is that behavior to be expected and is there a way to go with one "buf" only by making sure that only correct values will be stored in buf and transferred to the S7? How is the API supposed to be used? |
Clearing the buffer each cycle, not overwriting it seems to do the trick - maybe worthwhile to mention in the API? Anyways: node-snap7 does what it is expected to do. Sorry for the hassle and thanks for the great work! |
@fu-zhou This is expected behaviour.. The issue with your code is that you treat the async functions as synchronous.. So what happens is as you call DBWrite with the reference to ´buf´, node puts the call in the event loop but the actual Write to the PLC is on the next tick while the other allocations happen in the same tick, where ´buf´ refers already to the fourth different object at the end. Remeber javascript is pass by reference for objects. so the first three buffers are not referenced anymore and can be garbage collected or overwritten. Snap7 still has the reference to these "dead" objects that can now be random memory blocks and writes these to the PLC... Result
Your modified test code var snap7 = require('node-snap7');
let buf;
var s7client = new snap7.S7Client();
s7client.ConnectTo('172.27.160.1', 0, 1, function(err) {
if(err)
return console.log(' >> Connection failed. Code #' + err + ' - ' + s7client.ErrorText(err));
setInterval(anS7senden, 100);
});
function anS7senden() {
buf = Buffer.alloc(4);
console.log(`1 - Node - alloc ${buf.toString('hex')}`);
buf.writeFloatBE(1);
console.log(`2 - Node - writeFloatBE ${buf.toString('hex')}`);
s7client.DBWrite(1, 0, 4, buf, function(err, res) {
if(err)
return console.log(' >> DBWrite failed. Code #' + err + ' - ' + s7client.ErrorText(err));
});
console.log(`3 - Node - DBWrite ${buf.toString('hex')}`);
buf = Buffer.alloc(4);
console.log(`4 - Node - alloc ${buf.toString('hex')}`);
buf.writeFloatBE(2);
console.log(`5 - Node - writeFloatBE ${buf.toString('hex')}`);
s7client.DBWrite(1, 16, 4, buf, function(err, res) {
if(err)
return console.log(' >> DBWrite failed. Code #' + err + ' - ' + s7client.ErrorText(err));
});
console.log(`6 - Node - DBWrite ${buf.toString('hex')}`);
buf = Buffer.alloc(4);
console.log(`7 - Node - alloc ${buf.toString('hex')}`);
buf.writeFloatBE(3);
console.log(`8 - Node - writeFloatBE ${buf.toString('hex')}`);
s7client.DBWrite(1, 32, 4, buf, function(err, res) {
if(err)
return console.log(' >> DBWrite failed. Code #' + err + ' - ' + s7client.ErrorText(err));
});
console.log(`9 - Node - DBWrite ${buf.toString('hex')}`);
buf = Buffer.alloc(4);
console.log(`10 - Node - alloc ${buf.toString('hex')}`);
buf.writeFloatBE(4);
console.log(`11 - Node - writeFloatBE ${buf.toString('hex')}`);
s7client.DBWrite(1, 48, 4, buf, function(err, res) {
if(err)
return console.log(' >> DBWrite failed. Code #' + err + ' - ' + s7client.ErrorText(err));
});
console.log(`12 - Node - DBWrite ${buf.toString('hex')}`);
} Modified node-snap7 to see the actual write ...
case WRITEAREA:
printf("Snap7 - WriteArea (%02x%02x%02x%02x)\n"
, ((uint8_t*) pData)[0]
, ((uint8_t*) pData)[1]
, ((uint8_t*) pData)[2]
, ((uint8_t*) pData)[3]);
returnValue = s7client->snap7Client->WriteArea(int1, int2, int3, int4
, int5, pData);
break;
... |
@mathiask88 thanks for taking the effort to explain the situation. To be honest: I still have no clue what's going on, maybe a little ;-). However I hope @Bettman66 knows what you are referring to, the fix seemed pretty simple... |
@mathiask88 Maybe a reference to the buffer should be kept in snap7.S7Client.prototype.DBWrite until the callback is called to prevent it from being garbage collected. Or just a note on the docs that this could happen. I ran into this problem today. I could only replicate it consistently on a very slow connection while sending write requests continuously. If I don't keep a reference to the buffer, sometimes it ends up writing garbage to the PLC. let buf = Buffer.alloc(4);
buf.writeFloatBE(1234);
s7client.DBWrite(1, 0, 4, buf, function(err) {
buf; // Just to prevent been garbaged collected before is sent to the PLC
}); Thank you for this project! |
The following issue is being reported by several users of the iobroker S7-Adapter.
ioBroker/ioBroker.s7#13
Over the last two days one of the developers looked into the issue and "suspects" node-snap7.
https://forum.iobroker.net/post/1094196
It is just an idea, but can @mathiask88 you give me some clues how to test if node-snap7 causes the transfer of randomly high or low numbers to the S7?
Actually V1.0.7 is installed.
The text was updated successfully, but these errors were encountered: