Incorrect behavior when writing to struct containing array of structs
carl2009 opened this issue · comments
I have an issue when I'm writing to a struct symbol containing array of structs, where variables in the inner structs are not assigned properly (looks like an offset issue). I have only seen the issue when writing to the whole symbol at once from a single JavaScript object.
I'm using ads-client 1.13.2 and TwinCat v3.1.4024.12
How to recreate the issue
I have two structs
TYPE Temp :
STRUCT
foo : BOOL;
bar : ARRAY [0..1] OF Temp2;
END_STRUCT
END_TYPE
TYPE Temp2 :
STRUCT
baz : BOOL;
END_STRUCT
END_TYPE
And a GVL GVL_symbols
{attribute 'qualified_only'}
VAR_GLOBAL
temp: Temp;
END_VAR
When I write to the whole symbol GVL_symbols.temp
in the following way I get incorrect behavior:
const adsClient = new ads.Client({
targetAmsNetId: ...,
targetAdsPort: ...,
timeoutDelay: 2000,
});
await adsClient.connect();
await adsClient.writeSymbol('GVL_symbols.temp',
{
"foo": false,
"bar": [
{
"baz": true
},
{
"baz": true
}
]
},
false);
await adsClient.readSymbol('GVL_symbols.temp');
// Results in the following:
/*
{
"foo": false,
"bar": [
{
"baz": true
},
{
"baz": false
}
]
}
*/
Notice that baz
is still false
. This appears to be a bug.
Additionally, if I add more variables in the Temp2
struct than the BOOL, then the wrong variables get assigned values when I write to the symbol. E.g. the second variable gets assigned a value when I write to the first variable.
Workaround
I have found a workaround where I write directly to GVL_symbols.temp.bar
instead.
This workaround fixes the issue and sets baz
to true
, but it would be nice to resolve this bug anyway.
Thank you for this library, it has proven very useful for my project.
Thanks for reporting! I will check this in few days :)
Hi @carl2009
Sorry I have been too busy to check this out. But will do it when I have time.
I started working on this. Quite complicated bug to inspect, something wrong with the ads data type offsets. However thanks very much for reporting!
I completely understand, thanks anyway for looking into this! The workaround I noted in my original message has worked well enough for me. In my case it also helped normalizing the data in the symbols so that symbols only contain arrays of simple data types, such as INT and LREAL (not STRUCT). And like with a database I use INT IDs to refer structs to eachother, but instead they are located in arrays mapped to different symbols.
Feel free to close this issue!
Good that you got the system working even with this bug.
I think I found the reason, just need to do some more testing until I'm sure everything works OK!
If you want to try meanwhile, you can change the
buffer = Buffer.alloc(dataType.offset + dataType.size)
to
buffer = Buffer.alloc(dataType.size)
at ads-client.js line 5233
https://github.com/jisotalo/ads-client/blob/master/src/ads-client.js#L5233
But not 100% sure yet.
This should be fixed in version 1.14.0 :)
I also finally created a test system to make sure everything works after update. At least everything that is being tested now works as before.
Please let me know if you have any issues, I'm closing this for now.