stlehmann / pyads

Python wrapper for TwinCAT ADS
MIT License
264 stars 96 forks source link

Support for monitored properties #261

Open dgl-cw opened 3 years ago

dgl-cw commented 3 years ago

Hi

I was using read_by_name before and wanted to switch to get_symbol(...).read() because of the nicer syntax and not having to pass around the plc object. So I discovered, that the latter failed for monitored properties.

With monitored properties I mean properties that have the monitoring pragma.

I couldn't find any documentation on accessing monitored properties over ADS, neither here nor on TwinCAT, so I experimented a bit.

Windows 10 TwinCAT 3.4024.10

With read_by_name monitoring GVL Program Function Block
variable (✔️) (✔️) ❌1808
call ❌1808 ❌1808 ✔️

❌ is a ADSError: symbol not found (1808) Same for write_by_name however with {attribute 'monitoring' := 'variable'} writing has not effect.

With get_symbol(...).read() or .write(...) monitoring GVL Program Function Block
variable (✔️) (✔️) ❌1808
call ❌1808 ❌1808 1806

Mostly the same as above but function block with call fails with ADSError: objects do not match (1806) Again .write(...) has no effect.

I was mostly interested in the 1806 case so I looked deeper and found that for the affected case adsGetSymbolInfo returns an index_group of 0xF019 and an index_offset of 0x0. I could not find any documentation on the index group 0xF019. As a workaround I tried to get a handle with plc.get_handle(...) for the case that index_group was 0xF019 and use that instead. That worked.

I did not look deeper into the case of the 1808 error.

In summary

I think

stlehmann commented 3 years ago

If I get it right from the documentation monitoring is just an attribute that is used by the TwinCAT IDE and it should not influence the way a variable can be accessed via ADS.

dgl-cw commented 3 years ago

My experiments above indicate, that the pragma does influence the accessibility via ADS. My assumption is, that TwinCAT uses ADS internally to show the variable values on the IDE and watch list. That however does not explain how they do it in the cases where I get the 1808 error above.

The TwinCAT documentation is clearly incomplete here (like in many other places). So I guess the best we can do for now is to reverse engineer these parts.

stlehmann commented 3 years ago

I'm just wondering why read_by_name works. Did we already implement the workaround there? Most certainly not 🤔. OK, I had to look it up: for read_by_name we use a handle while for the symbols we aquire the indexGroup and indexOffset via adsGetSymbolInfo. So for me this indicates that adsGetSymbolInfo does not work the way it should for monitored values or it has some undocumented functionality as @dgl-cw suggests. In the first case it would not be a good choice to implement a workaround in pyads as the problem might get fixed in later versions.

stlehmann commented 3 years ago

I don't mind the reverse-engineering approach but I would like to know what index group 0xF019 does to avoid any side-effects. Sadly documenation misses this part out:

grafik