Hi Jody,
Unfortunately, #2 is going to be non-trivial unless I really make application code or wrappers work for it. To get UDTs there are actually two calls you need to do for each UDT (AB just could not make things easy!). The first one gets information/metadata about the number of entries (fields) and their sizes. The next one gets that data. Note that interpreting the fields is also... interesting. You need to ignore fields that start with "ZZZZZZZZZZ" for instance. AB did not use special flags or types or anything that could be easily checked programmatically. You have to interpret the field names. That is all going to be on the application code. Then you have things like overlapping offsets and knowing the types of fields (from the metadata in the first call) to tell how to handle bit/bool fields.
For example, if you have two bit fields in your UDT they are packed into a dummy SINT field at the beginning of the UDT. The offsets of both fields are in bytes and will be the same, zero (0). The dummy field will have a type of SINT and a name that starts with "ZZZZZZZ..." You have to look at the type metadata of the fields to see that the type is 0xC1 for bit/bool, and the remaining byte (types are two bytes) contains the bit offset in the lower three bits. So to figure out which bit is that field, you need to look in multiple places.
For now what I will do for these is probably (subject to change as I try to implement it):
1. For this one, take tags with a special name or format. For instance 'name=@tagID:3af56.myField[42].anotherField'. The leading '@tagID:3af56' would be the top level tag symbol ID. You would list the tags out and get the mapping from your tag, e.g. 'myTag' to the ID '3af56'. I will update list_tags.c to show how to do that. The data is there already.
2.This, I am still not sure. Maybe a special tag like '@udt:820af2'. It will need to get the metadata about the UDT and then the data about the UDT. I can batch that up into one tag, but that is starting to be a lot of extra code in just the ControlLogix path.
3. This is going to need a special tag as well. Not sure about what that would be maybe '@tagVersion' or something. From what I understand, you can just treat the result as a byte string and look for changes. There are certain errors that need to be handled appropriately and very differently from other calls.
After some consideration, I will not have raw CIP support. Why? The security implications are horrible. Any time you have a tag name exposed to user input, a maliciously crafted name can destroy the PLC program or the PLC run mode, nearly anything. I had thought to use this as a way to quickly prototype, but the more I thought about the security problems, the less I liked the idea. It would make things easier to prototype, but, wow, would the the black hats have fun with that!
Because of depth of the code changes, I am going to do some refactoring first to split out how the tags work for AB. The Modbus code ended up drastically simpler in overall structure and does zero allocation during normal operation. I want to get that for AB as well. It will help keep all these special tag operations separate from the main code for reading and writing tags.
I will go as fast as I can, but right now my priority is getting libplctag4j into good enough shape that I can get it up on JCenter (the equivalent of Nuget) for both plain Java and Android use. With work taking 12-16 hours a day right now, that only leaves some weekend time. And I need most of that to spend with my family as they are peeved already at my lack of time. What I am trying to say is that this is probably not going to go very quickly. Sorry about that!
Best,
Kyle