stlehmann / pyads

Python wrapper for TwinCAT ADS
MIT License
253 stars 94 forks source link

Add support for reading and writing structures of multiple types #82

Closed chrisbeardy closed 4 years ago

chrisbeardy commented 5 years ago

I believe it would be beneficial to be able to read and write to structures made up of multiple types, as I understand this is not possible and it can only be done of structures made of multiples of a single type.

The way I imagine this would be a call looking something like:

plc.read_by_name('MAIN.TestStruct', [pyads.PLCTYPE_LREAL,
                                     pyads.PLCTYPE_BOOL,
                                     pyads.PLCTYPE_INT])

This would return a list of [1.2, TRUE, 3] for example.

Alternatively new functions specifically for reading/writing STRUCT types.

Am happy to look into to this but was not sure the best way to proceed,looking at my example this would require changes all the way down to adsSyncReadReqEx2 etc to change the data_type parameter to type LIST, then would require some manipulation to get al the returns. Not sure you would want to change the input type just to add this feature.

Can anyone think of a better way to implement this why maintaining compatibility?

I think this is benefical as it allows just a single read to read all variables , as it would be quicker on the python code and less intensive on the ADS router. For example the PLC at the end of the cycle copies all required variables into one "super" STRUCT which can then be read more frequently. I have used the VB.NET examples from Beckhoff in the past to read such a structure.

Doing this also to callback notifications would then also be very useful!

stlehmann commented 4 years ago

@chrisbeardy Thanks for sharing your thoughts and elaborating it in PR #88. I need to look over the implementation but I really like the idea. The feature of reading/writing structs with elements of multiple datatypes was missing so far. I would like to add this feature to the code base. Of course we will also need testing for it. So if you have already done some testing maybe you would like to add the test-code to the PR.

chrisbeardy commented 4 years ago

@stlehmann no formal testing yet, I'll work on that shortly and add it in, just wanted to get a draft in to get your thoughts on the implementation.

chrisbeardy commented 4 years ago

new draft pull request #92

stlehmann commented 4 years ago

OK, I just gave it a try. I used a structure definition like so:

mystruct = (
    ("b", pyads.PLCTYPE_BOOL, 1),
    ("i", pyads.PLCTYPE_INT, 1),
)

Turns out that the bool takes two bytes of memory. So the value of the int ends up wrong. ;)

chrisbeardy commented 4 years ago

Did you define your structure in twincat with the 1 byte alignment pack mode?

https://infosys.beckhoff.com/content/1033/tc3_plc_intro/2529746059.html?id=3686945105176987925

stlehmann commented 4 years ago

Ah with pack_mode := 1 it works perfectly. Now I see you added a hint in the documentation for this. Should have read the docs first ;) I also added the hint to the Quickstart guide.

stlehmann commented 4 years ago

All looks fine so far. Thanks for the great work. I just releases version 3.1.2. I like the solution with the separate read_structure_by_name function. It is more explicit then if we would have put this in read_by_name.

chrisbeardy commented 4 years ago

Great, always read the docs haha

chrisbeardy commented 4 years ago

Thanks, I hope people find it useful, I think I will. I've really enjoyed working on pyads the last couple of weeks so thanks again for maintaining this.

chrisbeardy commented 4 years ago

Closed: This has been implemented in PR #92 and released version 3.1.2.