ornl-epics / etherip

Java lib. for Ethernet/IP (AllenBradley ControlLogix, Compact Logix PLCs)
Eclipse Public License 1.0
111 stars 69 forks source link

Error writing more than 7 tags in a batch #27

Closed DanArf closed 2 years ago

DanArf commented 5 years ago

Hello,

I am seeing an exception when attempting to Write batches of tags when the batch size exceeds 7 tags.

For all tags attempted, the tag data is all of type BOOL. Writing to the tags individually works and in batch groups of 2-7 the transactions is successful. Attempting to write a batch of 8 or more tags throws an exception with the following stack:

java.nio.BufferOverflowException at java.base/java.nio.Buffer.nextPutIndex(Unknown Source) at java.base/java.nio.DirectByteBuffer.put(Unknown Source) at etherip.types.CNSymbolPath$PathElement.encodeElementName(CNSymbolPath.java:114) at etherip.types.CNSymbolPath$PathElement.encode(CNSymbolPath.java:92) at etherip.types.CNSymbolPath.encode(CNSymbolPath.java:209) at etherip.protocol.MessageRouterProtocol.encode(MessageRouterProtocol.java:70) at etherip.protocol.CIPMultiRequestProtocol.encode(CIPMultiRequestProtocol.java:82) at etherip.protocol.MessageRouterProtocol.encode(MessageRouterProtocol.java:79) at etherip.protocol.UnconnectedSendProtocol.encode(UnconnectedSendProtocol.java:79) at etherip.protocol.SendRRDataProtocol.encode(SendRRDataProtocol.java:72) at etherip.protocol.Encapsulation.encode(Encapsulation.java:129) at etherip.protocol.TcpConnection.write(TcpConnection.java:62) at etherip.protocol.Connection.execute(Connection.java:120) at etherip.EtherNetIP.writeTags(EtherNetIP.java:589) ... Error in Writing tags: java.nio.BufferOverflowException

The line throwing the error in CNSymbolPath is: buf.put((byte) path.length());

Are there any intended limits to writing batches larger than 7 tags?

Thank you for your help and for developing this library!

edit: added code block styling

kasemir commented 5 years ago

The PLC has a buffer limit somewhere around 500 bytes. So when you try to write something where the complete write request exceeds 500 bytes, or read something where the complete response exceeds 500 bytes, you'll get an error from the PLC.

The Connection uses an internal BUFFER_SIZE of 600, i.e. larger than the PLC buffer size, but still that's what I think you're hitting.

To test, make the Connection.BUFFER_SIZE larger. That way the code should not give you the error you see, but you might instead get an error from the PLC.

DanArf commented 5 years ago

Thank you Kay, that helps explain why I'm seeing this.

When reading tags, it seems to limit the batch size to 100 by default: public CIPData[] readTags(final String... tags) throws Exception { return readTags(100, tags); }

Reading a large number (100+) of tags is completing successfully.

If I can Read 100 BOOL Tags without an issue, is the Writing limited to 7 BOOL Tags because the execution data includes the CIPData? Should the Read and Write execution requests be limited to the same sizes?

kasemir commented 5 years ago

Those methods with 'batch sizes' where from an outside pull request that I merged. Maybe should not have accepted that part because splitting simply based on the number of tags makes no sense.

For performance, you want to pack as many reads and writes into one network request. The limit is ~500 bytes for each the request and the response. If you have long tag names, that limits the number you can put into the request. If one tag is an array of UINT[400], than just that one tag(!) will get you close to the 500 byte limit for the response.