Logix Tag Read Service

Hi all,

I’ve thoroughly covered the Logix Data Access manual and am deeply familiar with the CIP protocol. I’m working to improve a Logix utility I wrote that creates diagnostic tags for Ignition.

I know Symbol (0x6B) service 0x55 returns a list of instances, with each instance followed by a specified list of attributes.

Is there a way to specify that service 0x55 also filter the types of instances returned to specific ones? (ie only DINT tags, or only STRING tags)

Or…

Is this provided by another service that returns a list of instances of a specified type?

I appreciate your help!

Not that I'm aware of, but I only know about what's documented in the data access manual.

@pturmel might know more?

Yeah, no, there's no such filtering in the service or any other service of which I'm aware. You have to do it yourself.

This black box information model grates me.

I found Symbol services 0x52 and 0x53.

0x52 is similar to 0x55 in requiring some added payload, but eventually errors in the same way 0x53 does.

0x53 errors with or without payload.

I’ll continue seeing if these or others bear fruit.

(1) Until now, I was using service 0x03 to get the Symbol class max instance and instance count, then following up with the same service by brute iteration. Minimizes memory use but consumes far more time on processors with large tag counts. In addition, Symbol table instances aren’t contiguous, so the misses were adding up.

(2) I can make a big improvement in what I’m already doing by just caching a pass of 0x55 instance Ids of matching type attribute results, then making a pass to collect names using service 0x03.

(3) The other approach I’ve found but not “unlocked,” is to use the Memory object address read service 0x4C locally. Unlike many other objects, this one is privileged to even the PLC itself and seems to require an initial ForwardOpen/Close handshake, then a follow-up ForwardOpen. However, it still requires the work in method (2) to get the address attribute for Symbol objects of interest.

What is it you're ultimately trying to accomplish?

1 Like

Symbol names can be requested as one of the returned attributes for the GetInstanceAttributeList (0x55) service, you don't need a second pass to read symbol names.

1 Like

The Symbol instances of interest in this case are almost always small in number compared to the total count of controller tags, so while the direct approach would ultimately work, it would be pretty inefficient. I’d bet this holds when looking for tags of any one type, generally.

The three Symbol attributes needed for that approach would be:
(1) Name (up to 44 bytes)
(2) Type (2 bytes)
(3) Address (4 bytes), this the 1:1 “key” to match to another class instance attribute.

Instance Id prefixes all those in the response and adds another 4 bytes.

I can’t speak to the average length of a string, but the worst case is one of 40 chars. Maybe we can assume here a min length of 8 and a max length of 40. So the data returned per Symbol ranges from 22 to 54 bytes.

Service 0x55 can serve external requests in 500 - 4 bytes result code = 496 bytes payloads. It serves internal (Local) requests in 4000 - 4 bytes result code = 3996 bytes payloads.

So that nets 9 to 22 external symbols or 74 to 181 local symbols per request.

It’s simple and eventually works.

————

On the other hand, by initially omitting the strings themselves, one can get just Symbol attributes (2) and (3), cache the relevant results (those of Type), then use those 8 bytes (Instance + Address) to later get strings.

Service 0x55 requests done this way will net 49 instances externally or 399 instances locally, per request.

Those are the documented read and write fragmented tag data services. In the Data Access manual. :man_shrugging:

1 Like

You get the larger packet externally, too, if you open a 4000 byte messaging connection.

1 Like

You are correct - lack of sleep from moving caught up to me.

I want to profile it on a network to see how much of an impact it makes. The code I’ve written works both ways right now, I’m just cautious about effects elsewhere.

Locally, it seems to always be 4000 bytes no matter what I do. That’s fine and all, but I’m also curious what impact that has on processor performance.

You should use a connection in most cases anyways--more efficient on the PLC side, too. But beware: old PLCs don't support service 0x55 inside connections, only via UCMM.

1 Like

Thanks for the info, Phil. About what firmware version would this apply?

Not sure where it started supporting 0x55 on connected messages. I just do the browse with UCMM messages, as the universally supported method. Not a significant performance difference on a LAN.

1 Like

Does UCMM max at 500 bytes?

Yes.

Strictly speaking, it is 504 bytes, per the EtherNet/IP Spec, Volume 2, §3-2.1.

Connected messaging with older hardware is 500 bytes. (502 in the Forward Open, but 2 bytes per message are a 16-bit sequence number.)

1 Like

That’s what I was thinking. I also try to generalize where possible, but running into firmware or hardware differences in CIP objects got me into the habit of checking object revisions, firmware, hardware, or all of the above.