ornl-epics / etherip

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

Unable to write STRUCT value #7

Open uthaman opened 8 years ago

uthaman commented 8 years ago

Hi,

I am not able to write Message type data to PLC, When i read the value and check the Type , it says "STRUCT" and when I use the same to write it says "(CIP type does not match object type)"

final byte[] data = new byte[] { (byte)0xCE, (byte)0x0F, 7, 0, 0, 0, 'w', 'j', 'h', ' ', '1', '2', '4' }; CIPData value1 = new CIPData(Type.STRUCT, data); plc.writeTag("S1_ScreenId", value1);

Below is the finest logs.

Jun 21, 2016 4:32:07 PM etherip.protocol.Connection write FINER: Protocol Encoding Encapsulation Header UINT command : SendRRData (0x006F) UINT length : 64 UDINT session : 0x1002D600 UDINT status : 0x00000000 USINT context[8] : 'Funstuff' UDINT options : 0x00000000 Send RR Data UDINT interface handle : 0 UINT timeout : 0 UINT count (addr., data): 2 UINT address type : 0x0 (UCMM) UINT address length : 0x00 UINT data type : 0xB2 (Unconnected Message) UINT data length : 48 MR Request USINT service : CM_Unconnected_Send (0x52) USINT path : Path (2 el) Class(0x20) 0x6 (ConnectionManager), instance(0x24) 1 CM_Unconnected_Send USINT tick_time : 10 USINT ticks : -16 UINT message size : 33 \/\/\/ embedded message \/\/\/ (33 bytes) MR Request USINT service : CIP_WriteData (0x4D) USINT path : Path Symbol(0x91) 'S1_ScreenId', 0x00 USINT type, data : 'wjh 124' /\/\/\ embedded message /\/\/\ USINT pad : 0 (odd length message) USINT path size : 1 words USINT reserved : 0 USINT port 1, slot 0

Jun 21, 2016 4:32:07 PM etherip.protocol.Connection write FINEST: Data sent (88 bytes): 0000 - 6F 00 40 00 00 D6 02 10 00 00 00 00 46 75 6E 73 - o.@.........Funs 0010 - 74 75 66 66 00 00 00 00 00 00 00 00 00 00 02 00 - tuff............ 0020 - 00 00 00 00 B2 00 30 00 52 02 20 06 24 01 0A F0 - ......0.R. .$... 0030 - 21 00 4D 07 91 0B 53 31 5F 53 63 72 65 65 6E 49 - !.M...S1_ScreenI 0040 - 64 00 A0 02 01 00 CE 0F 07 00 00 00 77 6A 68 20 - d...........wjh 0050 - 31 32 34 00 01 00 01 00 - 124.....

Jun 21, 2016 4:32:07 PM etherip.protocol.Connection read FINEST: Data read (46 bytes): 0000 - 6F 00 16 00 00 D6 02 10 00 00 00 00 46 75 6E 73 - o...........Funs 0010 - 74 75 66 66 00 00 00 00 00 00 00 00 00 00 02 00 - tuff............ 0020 - 00 00 00 00 B2 00 06 00 CD 00 FF 01 07 21 - .............!

Jun 21, 2016 4:32:07 PM etherip.protocol.Connection read FINER: Protocol Decoding Encapsulation Header UINT command : SendRRData (0x006F) UINT length : 22 UDINT session : 0x1002D600 UDINT status : 0x00000000 (OK) USINT context[8] : 'Funstuff' UDINT options : 0x00000000 Received RR Data UDINT interface handle : 0 UINT timeout : 0 UINT count (addr., data): 2 UINT address type : 0x0 (UCMM) UINT address length : 0 UINT data type : 0xB2 (Unconnected Message) UINT data length : 6 MR Response USINT service : CIP_WriteData_Reply (0xCD) USINT reserved : 0x0 USINT status : 0xffffffff () USINT ext. stat. size : 0x1 USINT ext status : 0x2107 (CIP type does not match object type)

Jun 21, 2016 4:32:07 PM etherip.protocol.Connection write FINER: Protocol Encoding Encapsulation Header UINT command : UnRegisterSession (0x0066) UINT length : 0 UDINT session : 0x1002D600 UDINT status : 0x00000000 USINT context[8] : 'Funstuff' UDINT options : 0x00000000

Jun 21, 2016 4:32:07 PM etherip.protocol.Connection write FINEST: Data sent (24 bytes): 0000 - 66 00 00 00 00 D6 02 10 00 00 00 00 46 75 6E 73 - f...........Funs 0010 - 74 75 66 66 00 00 00 00 - tuff....

kasemir commented 8 years ago

The only struct related data type that the driver handles for now is strings, see comments on STRUCT_STRING in src/etherip/types/CIPData.java. You'll need to find documentation from Allen Bradley on the struct that you want to read & write. Good luck.

uthaman commented 8 years ago

Allen Bradley message type says I/O Message as the Tag Type. Is there any way to write on this tag type?

kasemir commented 8 years ago

No idea. I've developed the driver based on the generic EtherNet/IP specification available from http://www.odva.org which describes the basic CIP commands, and Allen Bradley document 1756-RM005A-EN-E.pdf, "Logix5000 Data Access", which describes the CIP service codes specific to the ControlLogix 5000 series for reading and writing tags. In those documents I found no detail on structures. 1756-RM005A-EN-E.pdf only mentions that they exist. It was pure luck that the string read/write worked out. You'll have to find somebody at Allen Bradley who can help you get details on this tag type that you want to handle.

uthaman commented 8 years ago

Hi Kasemir, I was able to get the details on this tag type from PLC, when I read the value the CIPData type is STRUCT. But I am not ablle to write using that. Tag name is S1_ScreenId, please let me know how to write values to this tag.

image

READ OutPut tag=S1_ScreenId, value='wjh 122', type=STRUCT, time in ms=6

kasemir commented 8 years ago

Again, no idea about the STRUCT, you'll have to figure that out on your own.

What might be easier, though, is reading/writing "S1_ScreenID.DATA" as an SINT array. With the C implementation of the driver, https://github.com/EPICSTools/ether_ip, one could simply use that as a tag name and read/write the array field of the struct that way. In principle, the Java version should also allow that, except there's a shortcoming in the API when it comes to arrays. See #6: There's just EtherNetIP.readTag(String tag) which always gets just the first array element. We'd need EtherNetIP.readTag(String tag, int elements) to read more elements. Maybe you can fix #6 and then you should be able to read your structure field-by-field.

uthaman commented 8 years ago

Hi, tried as per your suggestion above, NPE in decode.

CIPData value1 = plc.readTag("S1_ScreenId.DATA[0]",1);

java.lang.NullPointerException at etherip.protocol.CIPReadDataProtocol.decode(CIPReadDataProtocol.java:56) at etherip.protocol.MessageRouterProtocol.decode(MessageRouterProtocol.java:103) at etherip.protocol.UnconnectedSendProtocol.decode(UnconnectedSendProtocol.java:92) at etherip.protocol.SendRRDataProtocol.decode(SendRRDataProtocol.java:94) at etherip.protocol.Encapsulation.decode(Encapsulation.java:190) at etherip.protocol.Connection.read(Connection.java:142) at etherip.protocol.Connection.execute(Connection.java:158) at etherip.EtherNetIP.readTag(EtherNetIP.java:171) at etherip.EtherIPDemo.testEtherIP(EtherIPDemo.java:76)

kasemir commented 8 years ago

java.lang.NullPointerException at etherip.protocol.CIPReadDataProtocol.decode(CIPReadDataProtocol.java:56):

CIPReadDataProtocol has no code in line 56 that could throw an NPE, https://github.com/EPICSTools/etherip/blob/master/src/etherip/protocol/CIPReadDataProtocol.java

Look, I really can't help you with that. If you have improvements to the code and submit a pull request, I can consider it. But I cannot solve your struct access problem.

uthaman commented 8 years ago

Hey kasemir, I figured out the request error and corrected it. Now i am getting the below error, do you know why PLC would send this?

Jun 27, 2016 11:03:49 AM etherip.protocol.Connection write FINEST: Data sent (84 bytes): 0000 - 6F 00 3A 00 02 4E 02 10 00 00 00 00 46 75 6E 73 - o.:..N......Funs 0010 - 74 75 66 66 00 00 00 00 00 00 00 00 00 00 02 00 - tuff............ 0020 - 00 00 00 00 B2 00 2A 00 52 02 20 06 24 01 0A F0 - ......*.R. .$... 0030 - 1B 00 4D 07 91 0B 53 31 5F 53 63 72 65 65 6E 49 - ..M...S1_ScreenI 0040 - 64 00 A0 02 CE 0F 07 00 77 6A 68 20 31 32 34 00 - d.......wjh 124. 0050 - 01 00 01 00 - ....

Jun 27, 2016 11:03:49 AM etherip.protocol.Connection read FINEST: Data read (48 bytes): 0000 - 6F 00 18 00 02 4E 02 10 00 00 00 00 46 75 6E 73 - o....N......Funs 0010 - 74 75 66 66 00 00 00 00 00 00 00 00 00 00 02 00 - tuff............ 0020 - 00 00 00 00 B2 00 08 00 D2 00 01 01 05 02 34 00 - ..............4.

java.lang.Exception: Expected CIP_WriteData_Reply (0xCD), got CM_Unconnected_Send_Reply (0xD2)

kasemir commented 8 years ago

I figured out the request error and corrected it

If you found an error in the code or have a suggested addition, please consider a pull request.

Expected CIP_WriteData_Reply (0xCD), got CM_Unconnected_Send_Reply (0xD2)

I would hope that when you dump the complete protocol at a higher log level there's been an error code in there that helps to understand why the PLC didn't send a WriteDataReply to a WriteDataRequest.

csobsidian commented 8 years ago

@uthaman This driver was not created for handling UDT structures. It could certainly be modified to do so using Logix5000 Data Access which outlines how to use the GetInstance Attribute List Service (0x55) and the Read Template Service (0x4c) to get a list of tags and the definitions for UDTs in the processor. There are many examples on then accessing the data in these UDTs.

kasemir commented 7 years ago

Not sure about writing, but for reading, #11 fixed the tag parsing, so "some_struct.element" as a tag name should now allow accessing an element of a structure, and as long as that element is a plain REAL, DINT, ... it should read and maybe also write it.

andresilveira89 commented 6 years ago

Hi, I don't have experience with java, but i know to do communication with Omron PLC using FINS Protocol.

Today, anybody has already comunication with Omron PLC using Java Ethernet/IP ?

TheFern2 commented 5 years ago

Hi Kasemir, I was able to get the details on this tag type from PLC, when I read the value the CIPData type is STRUCT. But I am not ablle to write using that. Tag name is S1_ScreenId, please let me know how to write values to this tag.

image

READ OutPut tag=S1_ScreenId, value='wjh 122', type=STRUCT, time in ms=6

Just wanted to add this for future user reference. The easiest thing to do here is, count the length of the string you want to write. Your screenshot appears to be 8, so then convert characters to ascii code, and foorloop to write one at a time. If the datatype is String then you can read without doing all this, but if is a custom string UDT you might need to read as below. Example below:

Read example:

    String stringID_LenTag = "S1_ScreenID.LEN"; // Tag for length
    CIPData tagData= plc.readTag(stringID_LenTag);  
    int tagDataIDLength = tagData.getNumber(0).intValue();  // string length

    StringBuilder stringSb = new StringBuilder();  

    for(int i = 0; i < tagDataIDLength; i++)  
    {  
      CIPData tempData = plc.readTag(String.format("S1_ScreenID.DATA[%d]", i));  
      stringSb.append(Character.toString ((char) tempData.getNumber(0).intValue()));  
    }

Write example:

    // convert your string to ascii somewhere here
    int[] stringAsciiValues = new int[]{ 72,101,108,108,111 };  

    // Set length of string in case is shorter or longer  
    stringID_LenData.set(0, stringAsciiValues.length);  
    plc.writeTag(stringID_LenTag, stringID_LenData);  

    for(int i = 0; i < stringAsciiValues.length; i++)  
    {  
      CIPData tempData = plc.readTag(String.format("S1_ScreenID.DATA[%d]", i));  
      tempData.set(0, stringAsciiValues[i]);  
      plc.writeTag(String.format("S1_ScreenID.DATA[%d]", i), tempData);  
    } 

Note that my tag name is different. image

Hope this helps someone in the future. : )