pjkundert / cpppo

Communications Protocol Python Parser and Originator -- EtherNet/IP CIP
https://hardconsulting.com/products/6-cpppo-enip-api
Other
332 stars 109 forks source link

Writing a CIP attribute or a TAG #18

Closed piertoni closed 7 years ago

piertoni commented 8 years ago

Hi, First of all thanks for your library! Really a good Job! I am using it to connect to an Omron PLC I got success reading CIP values, but not writing. python -m cpppo.server.enip.get_attribute -a 192.168.0.50 "@4/100/3" "@4/102/3" "@4/103/3" "@4/104/3" "@4/105/3"=(DINT)77 "@4/106/3"=(DINT)44 "@4/105/3" "@4/106/3" I got the answer True from the two writing variables and values from reading ones. Is the form of the writing requests correct? If the form is correct is there anything I can try or it should depend on PLC's settings? Can I use other request methods (I tryed proxy(ip).write but is not yet implemented LOL) ? Thanks in advance

pjkundert commented 8 years ago

If it returned True for the writes, this means that Cpppo thinks that the CIP response indicated success.

Using cpppo.server.get_attribute, you are always dealing in raw SINT buffers; there are no CIP data types in the CIP Get/Set Attribute Single or Get Attributes All requests. Therefore, when you specify "@4/106/3=(DINT)44", the API is converting that 32-bit integer value 44 into 4 8-bit values, in "little-endian" format: 44,0,0,0 (lowest order byte first). It then transmits the Set Attribute Single request, and the response status indicated success, and we return a True. If the status would have indicated failure, we would have returned a None.

If it didn't actually change the values in the Omron, then something strange is happening. I would recommend increasing the verbosity (by adding -vvv to the call), and take a look at the status codes.

piertoni commented 8 years ago

(EthernetIP) C:\Users\ppancino\Dropbox\EthernetIP\cpppo>python -m cpppo.server.enip.get_attribute -a 192.168.0.50 "@4/106/3"=44 -vvv
06-10 09:23:32.398 MainThread enip.cli DETAIL   __init__   Connect:  TCP/IP to ('192.168.0.50', 44818)
06-10 09:23:32.443 MainThread enip.cli DETAIL   cip_send   Client CIP Send: {
    "enip.options": 0,
    "enip.session_handle": 0,
    "enip.sender_context.input": "bytearray(b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')",
    "enip.status": 0,
    "enip.CIP.register.options": 0,
    "enip.CIP.register.protocol_version": 1
}
06-10 09:23:32.444 MainThread enip.cli INFO     cip_send   EtherNet/IP:  24 + CIP:   4 ==  28 bytes total
06-10 09:23:32.445 MainThread enip.cli INFO     send       EtherNet/IP-->    192.168.0.50:44818 send    28: b'e\x00\x04\x00\x00\x00\x00\x00\x00\x00\x0
0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00'
06-10 09:23:32.445 MainThread enip.cli INFO     __next__   EtherNet/IP-->    192.168.0.50:44818 rcvd     0: None
06-10 09:23:32.447 MainThread enip.cli INFO     __next__   EtherNet/IP-->    192.168.0.50:44818 rcvd    28: b'e\x00\x04\x00\x84\x01\x9d\x00\x00\x00\x0
0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00'
06-10 09:23:32.448 MainThread cpppo    INFO     terminate                        ( header.( command.((byte))  :             =>         enip.command
  = 101 (format b'<H' over array('B', [101, 0]))
06-10 09:23:32.448 MainThread cpppo    INFO     terminate                        ( header.( command.((byte))  :             =>          enip.length
  = 4 (format b'<H' over array('B', [4, 0]))
06-10 09:23:32.449 MainThread cpppo    INFO     terminate                        ( header.( command.((byte))  :             =>  enip.session_handle
  = 10289540 (format b'<I' over array('B', [132, 1, 157, 0]))
06-10 09:23:32.449 MainThread cpppo    INFO     terminate                        ( header.( command.((byte))  :             =>          enip.status
  = 0 (format b'<I' over array('B', [0, 0, 0, 0]))
06-10 09:23:32.450 MainThread cpppo    INFO     terminate                        ( header.( command.((byte))  :             =>         enip.options
  = 0 (format b'<I' over array('B', [0, 0, 0, 0]))
06-10 09:23:32.451 MainThread enip.cli INFO     __next__   EtherNet/IP       192.168.0.50:44818 done:                         ((enip.((payload.((byte)
)) -> ((payload.; next byte  28: None      : {'enip': {'options': 0, 'sender_context': {'input': array('B', [0, 0, 0, 0, 0, 0, 0, 0])}, 'status': 0, '
session_handle': 10289540, 'command': 101, 'length': 4, 'input': array('B', [1, 0, 0, 0])}, 'peer': ('192.168.0.50', 44818)}
06-10 09:23:32.451 MainThread cpppo    INFO     run                   ( register.( protocol_version.((byte))  -- limit='enip.CIP.register...length' ==
 4; ending at symbol 4 vs. None
06-10 09:23:32.452 MainThread cpppo    INFO     terminate             ( register.( protocol_version.((byte))  :             => enip.CIP.register.proto
col_version     = 1 (format b'<H' over array('B', [1, 0]))
06-10 09:23:32.452 MainThread cpppo    INFO     terminate             ( register.( protocol_version.((byte))  :             => enip.CIP.register.optio
ns     = 0 (format b'<H' over array('B', [0, 0]))
06-10 09:23:32.453 MainThread enip.cli INFO     __next__   Returning result: {'enip': {'options': 0, 'sender_context': {'input': array('B', [0, 0, 0,
0, 0, 0, 0, 0])}, 'status': 0, 'CIP': {'register': {'options': 0, 'protocol_version': 1}}, 'session_handle': 10289540, 'command': 101, 'length': 4, 'i
nput': array('B', [1, 0, 0, 0])}, 'peer': ('192.168.0.50', 44818)}
06-10 09:23:32.453 MainThread enip.cli NORMAL   __init__   Connect:  Success in   0.055s/  5.000s
06-10 09:23:32.454 MainThread enip.cli DETAIL   parse_oper Tag: '@4/106/3' yields Operation: {'data': [44], 'method': 'write', 'tag_type': 194, 'path'
: [{'class': 4}, {'instance': 106}, {'attribute': 3}], 'elements': 1}.update({'send_path': None, 'route_path': None})
06-10 09:23:32.454 MainThread enip.cli DETAIL   cip_send   Client CIP Send: {
    "enip.options": 0,
    "enip.session_handle": 10289540,
    "enip.sender_context.input": "bytearray(b'0\\x00\\x00\\x00\\x00\\x00\\x00\\x00')",
    "enip.status": 0,
    "enip.CIP.send_data.interface": 0,
    "enip.CIP.send_data.timeout": 0,
    "enip.CIP.send_data.CPF.item[0].type_id": 0,
    "enip.CIP.send_data.CPF.item[1].unconnected_send.status": 0,
    "enip.CIP.send_data.CPF.item[1].unconnected_send.route_path.segment[0].link": 0,
    "enip.CIP.send_data.CPF.item[1].unconnected_send.route_path.segment[0].port": 1,
    "enip.CIP.send_data.CPF.item[1].unconnected_send.timeout_ticks": 157,
    "enip.CIP.send_data.CPF.item[1].unconnected_send.path.segment[0].class": 6,
    "enip.CIP.send_data.CPF.item[1].unconnected_send.path.segment[1].instance": 1,
    "enip.CIP.send_data.CPF.item[1].unconnected_send.priority": 5,
    "enip.CIP.send_data.CPF.item[1].unconnected_send.service": 82,
    "enip.CIP.send_data.CPF.item[1].unconnected_send.request.path.segment[0].class": 4,
    "enip.CIP.send_data.CPF.item[1].unconnected_send.request.path.segment[1].instance": 106,
    "enip.CIP.send_data.CPF.item[1].unconnected_send.request.path.segment[2].attribute": 3,
    "enip.CIP.send_data.CPF.item[1].unconnected_send.request.set_attribute_single.data": [
        44
    ],
    "enip.CIP.send_data.CPF.item[1].unconnected_send.request.set_attribute_single.elements": 1,
    "enip.CIP.send_data.CPF.item[1].unconnected_send.request.input": "bytearray(b'\\x10\\x03 \\x04$j0\\x03,')",
    "enip.CIP.send_data.CPF.item[1].unconnected_send.request.service": 16,
    "enip.CIP.send_data.CPF.item[1].type_id": 178
}
06-10 09:23:32.458 MainThread enip.cli INFO     cip_send   EtherNet/IP:  24 + CIP:  40 ==  64 bytes total
06-10 09:23:32.463 MainThread enip.cli INFO     send       EtherNet/IP-->    192.168.0.50:44818 send    64: b'o\x00(\x00\x84\x01\x9d\x00\x00\x00\x00\x
000\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\xb2\x00\x18\x00R\x02 \x06$\x01\x05\x9d\t\x00\x10\x03 \
x04$j0\x03,\x00\x01\x00\x01\x00'
06-10 09:23:32.466 MainThread enip.cli DETAIL   format_pat Formatted                    @0x0004/106/3 from: [{'class': 4}, {'instance': 106}, {'attrib
ute': 3}]
06-10 09:23:32.467 MainThread enip.cli DETAIL   issue      Sent   0.012/  5.000s: Single S_A_S      @0x0004/106/3 {
    "path.segment[0].class": 4,
    "path.segment[1].instance": 106,
    "path.segment[2].attribute": 3,
    "set_attribute_single.data": [
        44
    ],
    "set_attribute_single.elements": 1,
    "input": "bytearray(b'\\x10\\x03 \\x04$j0\\x03,')",
    "service": 16
}
06-10 09:23:32.469 MainThread enip.cli DETAIL   issue      Sending  1 (Context       b'0')
06-10 09:23:32.472 MainThread enip.cli DETAIL   pipeline   Issuing     0/  1; curr:   0 - last:  -1 ==   1 depth
06-10 09:23:32.473 MainThread enip.cli INFO     __next__   EtherNet/IP-->    192.168.0.50:44818 rcvd    44: b'o\x00\x14\x00\x84\x01\x9d\x00\x00\x00\x0
0\x000\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\xb2\x00\x04\x00\x90\x00\x13\x00'
06-10 09:23:32.475 MainThread cpppo    INFO     terminate                        ( header.( command.((byte))  :             =>         enip.command
  = 111 (format b'<H' over array('B', [111, 0]))
06-10 09:23:32.476 MainThread cpppo    INFO     terminate                        ( header.( command.((byte))  :             =>          enip.length
  = 20 (format b'<H' over array('B', [20, 0]))
06-10 09:23:32.477 MainThread cpppo    INFO     terminate                        ( header.( command.((byte))  :             =>  enip.session_handle
  = 10289540 (format b'<I' over array('B', [132, 1, 157, 0]))
06-10 09:23:32.478 MainThread cpppo    INFO     terminate                        ( header.( command.((byte))  :             =>          enip.status
  = 0 (format b'<I' over array('B', [0, 0, 0, 0]))
06-10 09:23:32.481 MainThread cpppo    INFO     terminate                        ( header.( command.((byte))  :             =>         enip.options
  = 0 (format b'<I' over array('B', [0, 0, 0, 0]))
06-10 09:23:32.482 MainThread enip.cli INFO     __next__   EtherNet/IP       192.168.0.50:44818 done:                         ((enip.((payload.((byte)
)) -> ((payload.; next byte  72: None      : {'enip': {'options': 0, 'sender_context': {'input': array('B', [48, 0, 0, 0, 0, 0, 0, 0])}, 'status': 0,
'session_handle': 10289540, 'command': 111, 'length': 20, 'input': array('B', [0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 178, 0, 4, 0, 144, 0, 19, 0])}, 'pe
er': ('192.168.0.50', 44818)}
06-10 09:23:32.483 MainThread cpppo    INFO     run                         ( send_data.( interface.((byte))  -- limit='enip.CIP.send_data...length' =
= 20; ending at symbol 20 vs. None
06-10 09:23:32.484 MainThread cpppo    INFO     terminate                   ( send_data.( interface.((byte))  :             => enip.CIP.send_data.inte
rface     = 0 (format b'<I' over array('B', [0, 0, 0, 0]))
06-10 09:23:32.485 MainThread cpppo    INFO     terminate                   ( send_data.( interface.((byte))  :             => enip.CIP.send_data.time
out     = 0 (format b'<H' over array('B', [0, 0]))
06-10 09:23:32.487 MainThread cpppo    INFO     terminate                             ( CPF.( count.((byte))  :             => enip.CIP.send_data.CPF.
count     = 2 (format b'<H' over array('B', [2, 0]))
06-10 09:23:32.488 MainThread cpppo    INFO     terminate                          ( each.( type_id.((byte))  :             => enip.CIP.send_data.CPF.
item__.type_id     = 0 (format b'<H' over array('B', [0, 0]))
06-10 09:23:32.489 MainThread cpppo    INFO     terminate                          ( each.( type_id.((byte))  :             => enip.CIP.send_data.CPF.
item__.length     = 0 (format b'<H' over array('B', [0, 0]))
06-10 09:23:32.490 MainThread cpppo    INFO     terminate                          ( each.( type_id.((byte))  :             => enip.CIP.send_data.CPF.
item__.type_id     = 178 (format b'<H' over array('B', [178, 0]))
06-10 09:23:32.491 MainThread cpppo    INFO     terminate                          ( each.( type_id.((byte))  :             => enip.CIP.send_data.CPF.
item__.length     = 4 (format b'<H' over array('B', [4, 0]))
06-10 09:23:32.492 MainThread cpppo    INFO     run                     ( unconnected_send.( select.((noop))  -- limit='enip.CIP.send_data.CPF.item__.
unconnected_send..length' == 4; ending at symbol 20 vs. 20
06-10 09:23:32.494 MainThread cpppo    INFO     terminate          ( set_attribute_single.( service.((byte))  :             =>              service
  = 144 (format b'B' over array('B', [144]))
06-10 09:23:32.495 MainThread cpppo    INFO     terminate                         ( status.( status.((byte))  :             =>               status
  = 19 (format b'B' over array('B', [19]))
06-10 09:23:32.497 MainThread cpppo    INFO     terminate                         ( status.( status.((byte))  :             =>      status_ext.size
  = 0 (format b'B' over array('B', [0]))
06-10 09:23:32.498 MainThread enip.cli INFO     __next__   Returning result: {'enip': {'options': 0, 'sender_context': {'input': array('B', [48, 0, 0,
 0, 0, 0, 0, 0])}, 'status': 0, 'CIP': {'send_data': {'interface': 0, 'timeout': 0, 'CPF': {'count': 2, 'item': [{'length': 0, 'type_id': 0}, {'unconn
ected_send': {'request': {'status_ext': {'size': 0}, 'status': 19, 'set_attribute_single': True, 'service': 144, 'input': array('B', [144, 0, 19, 0])}
}, 'length': 4, 'type_id': 178}]}}}, 'session_handle': 10289540, 'command': 111, 'length': 20, 'input': array('B', [0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0
, 178, 0, 4, 0, 144, 0, 19, 0])}, 'peer': ('192.168.0.50', 44818)}
06-10 09:23:32.500 MainThread enip.cli DETAIL   collect    Rcvd   0.026/  5.000s {
    "enip.options": 0,
    "enip.sender_context.input": "array('B', [48, 0, 0, 0, 0, 0, 0, 0])",
    "enip.status": 0,
    "enip.CIP.send_data.interface": 0,
    "enip.CIP.send_data.timeout": 0,
    "enip.CIP.send_data.CPF.count": 2,
    "enip.CIP.send_data.CPF.item[0].length": 0,
    "enip.CIP.send_data.CPF.item[0].type_id": 0,
    "enip.CIP.send_data.CPF.item[1].unconnected_send.request.status_ext.size": 0,
    "enip.CIP.send_data.CPF.item[1].unconnected_send.request.status": 19,
    "enip.CIP.send_data.CPF.item[1].unconnected_send.request.set_attribute_single": true,
    "enip.CIP.send_data.CPF.item[1].unconnected_send.request.service": 144,
    "enip.CIP.send_data.CPF.item[1].unconnected_send.request.input": "array('B', [144, 0, 19, 0])",
    "enip.CIP.send_data.CPF.item[1].length": 4,
    "enip.CIP.send_data.CPF.item[1].type_id": 178,
    "enip.session_handle": 10289540,
    "enip.command": 111,
    "enip.length": 20,
    "enip.input": "array('B', [0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 178, 0, 4, 0, 144, 0, 19, 0])",
    "peer": [
        "192.168.0.50",
        44818
    ]
}
06-10 09:23:32.503 MainThread enip.cli DETAIL   collect    Receive  1 (Context       b'0')
06-10 09:23:32.507 MainThread enip.cli DETAIL   pipeline   Completed   1/  1; curr:   0 - last:   0 ==   0 depth
Fri Jun 10 09:23:32 2016:   0: Single S_A_S      @0x0004/106/3 == None
06-10 09:23:32.509 MainThread enip.cli DETAIL   pipeline   Pipelined   1/  1; curr:   0 - last:   0 ==   0 depth
06-10 09:23:32.510 MainThread enip.get NORMAL   main         1 requests in   0.056s at pipeline depth  0;  17.747 TPS

(EthernetIP) C:\Users\ppancino\Dropbox\EthernetIP\cpppo>

Can you give me any advice? Thanks

pjkundert commented 8 years ago

It is returning a None, not a True -- indicating failure. A status code of 19 is being returned: CIP Status: 0x13 (Not enough data)

You are not specify the data type in your request (so it defaults to SINT):

... "@4/106/3"=44 ...

So, I would guess that, since you are using the CIP Set Attribute Single request, and since you must supply exactly the correct number of SINT (8-bit) data to fully specify the entire CIP Attribute, you probably aren't using the right data type for the Attribute, or it is an Array, meaning that you must supply a number of values greater than 1.

If its a single DINT, try:

... "@4/106/3=(DINT)44" ...

It its an array, supply data for all elements (say, for a 5-element DINT array):

... "@4/106/3=(DINT)44,55,66,77,88" ...

If it is indeed a DINT array, find out the size of the array, and supply that number of elements.

pjkundert commented 8 years ago

The Command-Line Interfaces work great and are reliable, but they are very limited in the amount of data they return. Using the Python API calls returns vast amounts of data about the response, including status and extended status codes...

piertoni commented 8 years ago

Damn! I posted the wrong request...

(EthernetIP) C:\Users\ppancino\Dropbox\EthernetIP\cpppo>python -m cpppo.server.enip.get_attribute -a 192.168.0.50 "@4/100/3"=(SINT)44,1,1,1 "@4/100/3"

Fri Jun 10 18:35:31 2016:   0: Single S_A_S      @0x0004/100/3 == True
Fri Jun 10 18:35:31 2016:   1: Single G_A_S      @0x0004/100/3 == [0, 0, 0, 0]

As you can see this returns True, so it is supposed to be ok, but doesn't changes the value And the following is the verbose version:

(EthernetIP) C:\Users\ppancino.SBP\Dropbox\EthernetIP\cpppo>python -m cpppo.server.enip.get_attribute -a 192.168.0.50 "@4/100/3"=(SINT)44,1,1,1 -vvv
06-10 18:37:10.180 MainThread enip.cli DETAIL   __init__   Connect:  TCP/IP to ('192.168.0.50', 44818)
06-10 18:37:10.227 MainThread enip.cli DETAIL   cip_send   Client CIP Send: {
    "enip.CIP.register.options": 0,
    "enip.CIP.register.protocol_version": 1,
    "enip.sender_context.input": "bytearray(b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')",
    "enip.options": 0,
    "enip.session_handle": 0,
    "enip.status": 0
}
06-10 18:37:10.227 MainThread enip.cli INFO     cip_send   EtherNet/IP:  24 + CIP:   4 ==  28 bytes total
06-10 18:37:10.243 MainThread enip.cli INFO     send       EtherNet/IP-->    192.168.0.50:44818 send    28: b'e\x00\x04\x00\x00\x00\x00\x00\x00\x00\x0
0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00'
06-10 18:37:10.243 MainThread enip.cli INFO     __next__   EtherNet/IP-->    192.168.0.50:44818 rcvd     0: None
06-10 18:37:10.243 MainThread enip.cli INFO     __next__   EtherNet/IP-->    192.168.0.50:44818 rcvd    28: b'e\x00\x04\x00\x87\x01\x14\x00\x00\x00\x0
0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00'
06-10 18:37:10.243 MainThread cpppo    INFO     terminate                        ( header.( command.((byte))  :             =>         enip.command
  = 101 (format b'<H' over array('B', [101, 0]))
06-10 18:37:10.243 MainThread cpppo    INFO     terminate                        ( header.( command.((byte))  :             =>          enip.length
  = 4 (format b'<H' over array('B', [4, 0]))
06-10 18:37:10.243 MainThread cpppo    INFO     terminate                        ( header.( command.((byte))  :             =>  enip.session_handle
  = 1311111 (format b'<I' over array('B', [135, 1, 20, 0]))
06-10 18:37:10.243 MainThread cpppo    INFO     terminate                        ( header.( command.((byte))  :             =>          enip.status
  = 0 (format b'<I' over array('B', [0, 0, 0, 0]))
06-10 18:37:10.243 MainThread cpppo    INFO     terminate                        ( header.( command.((byte))  :             =>         enip.options
  = 0 (format b'<I' over array('B', [0, 0, 0, 0]))
06-10 18:37:10.243 MainThread enip.cli INFO     __next__   EtherNet/IP       192.168.0.50:44818 done:                         ((enip.((payload.((byte)
)) -> ((payload.; next byte  28: None      : {'enip': {'length': 4, 'sender_context': {'input': array('B', [0, 0, 0, 0, 0, 0, 0, 0])}, 'status': 0, 'c
ommand': 101, 'options': 0, 'session_handle': 1311111, 'input': array('B', [1, 0, 0, 0])}, 'peer': ('192.168.0.50', 44818)}
06-10 18:37:10.243 MainThread cpppo    INFO     run                   ( register.( protocol_version.((byte))  -- limit='enip.CIP.register...length' ==
 4; ending at symbol 4 vs. None
06-10 18:37:10.243 MainThread cpppo    INFO     terminate             ( register.( protocol_version.((byte))  :             => enip.CIP.register.proto
col_version     = 1 (format b'<H' over array('B', [1, 0]))
06-10 18:37:10.243 MainThread cpppo    INFO     terminate             ( register.( protocol_version.((byte))  :             => enip.CIP.register.optio
ns     = 0 (format b'<H' over array('B', [0, 0]))
06-10 18:37:10.243 MainThread enip.cli INFO     __next__   Returning result: {'enip': {'CIP': {'register': {'options': 0, 'protocol_version': 1}}, 'le
ngth': 4, 'sender_context': {'input': array('B', [0, 0, 0, 0, 0, 0, 0, 0])}, 'status': 0, 'command': 101, 'options': 0, 'session_handle': 1311111, 'in
put': array('B', [1, 0, 0, 0])}, 'peer': ('192.168.0.50', 44818)}
06-10 18:37:10.243 MainThread enip.cli NORMAL   __init__   Connect:  Success in   0.056s/  5.000s
06-10 18:37:10.243 MainThread enip.cli DETAIL   parse_oper Tag: '@4/100/3' yields Operation: {'tag_type': 194, 'elements': 4, 'path': [{'class': 4}, {
'instance': 100}, {'attribute': 3}], 'method': 'write', 'data': [44, 1, 1, 1]}.update({'route_path': None, 'send_path': None})
06-10 18:37:10.243 MainThread enip.cli DETAIL   cip_send   Client CIP Send: {
    "enip.CIP.send_data.interface": 0,
    "enip.CIP.send_data.CPF.item[0].type_id": 0,
    "enip.CIP.send_data.CPF.item[1].unconnected_send.route_path.segment[0].link": 0,
    "enip.CIP.send_data.CPF.item[1].unconnected_send.route_path.segment[0].port": 1,
    "enip.CIP.send_data.CPF.item[1].unconnected_send.service": 82,
    "enip.CIP.send_data.CPF.item[1].unconnected_send.status": 0,
    "enip.CIP.send_data.CPF.item[1].unconnected_send.request.set_attribute_single.data": [
        44,
        1,
        1,
        1
    ],
    "enip.CIP.send_data.CPF.item[1].unconnected_send.request.set_attribute_single.elements": 4,
    "enip.CIP.send_data.CPF.item[1].unconnected_send.request.service": 16,
    "enip.CIP.send_data.CPF.item[1].unconnected_send.request.path.segment[0].class": 4,
    "enip.CIP.send_data.CPF.item[1].unconnected_send.request.path.segment[1].instance": 100,
    "enip.CIP.send_data.CPF.item[1].unconnected_send.request.path.segment[2].attribute": 3,
    "enip.CIP.send_data.CPF.item[1].unconnected_send.request.input": "bytearray(b'\\x10\\x03 \\x04$d0\\x03,\\x01\\x01\\x01')",
    "enip.CIP.send_data.CPF.item[1].unconnected_send.priority": 5,
    "enip.CIP.send_data.CPF.item[1].unconnected_send.path.segment[0].class": 6,
    "enip.CIP.send_data.CPF.item[1].unconnected_send.path.segment[1].instance": 1,
    "enip.CIP.send_data.CPF.item[1].unconnected_send.timeout_ticks": 157,
    "enip.CIP.send_data.CPF.item[1].type_id": 178,
    "enip.CIP.send_data.timeout": 0,
    "enip.sender_context.input": "bytearray(b'0\\x00\\x00\\x00\\x00\\x00\\x00\\x00')",
    "enip.options": 0,
    "enip.session_handle": 1311111,
    "enip.status": 0
}
06-10 18:37:10.243 MainThread enip.cli INFO     cip_send   EtherNet/IP:  24 + CIP:  42 ==  66 bytes total
06-10 18:37:10.258 MainThread enip.cli INFO     send       EtherNet/IP-->    192.168.0.50:44818 send    66: b'o\x00*\x00\x87\x01\x14\x00\x00\x00\x00\x
000\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\xb2\x00\x1a\x00R\x02 \x06$\x01\x05\x9d\x0c\x00\x10\x03
 \x04$d0\x03,\x01\x01\x01\x01\x00\x01\x00'
06-10 18:37:10.258 MainThread enip.cli DETAIL   format_pat Formatted                    @0x0004/100/3 from: [{'class': 4}, {'instance': 100}, {'attrib
ute': 3}]
06-10 18:37:10.258 MainThread enip.cli DETAIL   issue      Sent   0.011/  5.000s: Single S_A_S      @0x0004/100/3 {
    "set_attribute_single.data": [
        44,
        1,
        1,
        1
    ],
    "set_attribute_single.elements": 4,
    "service": 16,
    "path.segment[0].class": 4,
    "path.segment[1].instance": 100,
    "path.segment[2].attribute": 3,
    "input": "bytearray(b'\\x10\\x03 \\x04$d0\\x03,\\x01\\x01\\x01')"
}
06-10 18:37:10.258 MainThread enip.cli DETAIL   issue      Sending  1 (Context       b'0')
06-10 18:37:10.258 MainThread enip.cli DETAIL   pipeline   Issuing     0/  1; curr:   0 - last:  -1 ==   1 depth
06-10 18:37:10.258 MainThread enip.cli INFO     __next__   EtherNet/IP-->    192.168.0.50:44818 rcvd    44: b'o\x00\x14\x00\x87\x01\x14\x00\x00\x00\x0
0\x000\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\xb2\x00\x04\x00\x90\x00\x00\x00'
06-10 18:37:10.258 MainThread cpppo    INFO     terminate                        ( header.( command.((byte))  :             =>         enip.command
  = 111 (format b'<H' over array('B', [111, 0]))
06-10 18:37:10.274 MainThread cpppo    INFO     terminate                        ( header.( command.((byte))  :             =>          enip.length
  = 20 (format b'<H' over array('B', [20, 0]))
06-10 18:37:10.274 MainThread cpppo    INFO     terminate                        ( header.( command.((byte))  :             =>  enip.session_handle
  = 1311111 (format b'<I' over array('B', [135, 1, 20, 0]))
06-10 18:37:10.274 MainThread cpppo    INFO     terminate                        ( header.( command.((byte))  :             =>          enip.status
  = 0 (format b'<I' over array('B', [0, 0, 0, 0]))
06-10 18:37:10.274 MainThread cpppo    INFO     terminate                        ( header.( command.((byte))  :             =>         enip.options
  = 0 (format b'<I' over array('B', [0, 0, 0, 0]))
06-10 18:37:10.274 MainThread enip.cli INFO     __next__   EtherNet/IP       192.168.0.50:44818 done:                         ((enip.((payload.((byte)
)) -> ((payload.; next byte  72: None      : {'enip': {'length': 20, 'sender_context': {'input': array('B', [48, 0, 0, 0, 0, 0, 0, 0])}, 'status': 0,
'command': 111, 'options': 0, 'session_handle': 1311111, 'input': array('B', [0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 178, 0, 4, 0, 144, 0, 0, 0])}, 'peer
': ('192.168.0.50', 44818)}
06-10 18:37:10.274 MainThread cpppo    INFO     run                         ( send_data.( interface.((byte))  -- limit='enip.CIP.send_data...length' =
= 20; ending at symbol 20 vs. None
06-10 18:37:10.274 MainThread cpppo    INFO     terminate                   ( send_data.( interface.((byte))  :             => enip.CIP.send_data.inte
rface     = 0 (format b'<I' over array('B', [0, 0, 0, 0]))
06-10 18:37:10.274 MainThread cpppo    INFO     terminate                   ( send_data.( interface.((byte))  :             => enip.CIP.send_data.time
out     = 0 (format b'<H' over array('B', [0, 0]))
06-10 18:37:10.274 MainThread cpppo    INFO     terminate                             ( CPF.( count.((byte))  :             => enip.CIP.send_data.CPF.
count     = 2 (format b'<H' over array('B', [2, 0]))
06-10 18:37:10.274 MainThread cpppo    INFO     terminate                          ( each.( type_id.((byte))  :             => enip.CIP.send_data.CPF.
item__.type_id     = 0 (format b'<H' over array('B', [0, 0]))
06-10 18:37:10.274 MainThread cpppo    INFO     terminate                          ( each.( type_id.((byte))  :             => enip.CIP.send_data.CPF.
item__.length     = 0 (format b'<H' over array('B', [0, 0]))
06-10 18:37:10.274 MainThread cpppo    INFO     terminate                          ( each.( type_id.((byte))  :             => enip.CIP.send_data.CPF.
item__.type_id     = 178 (format b'<H' over array('B', [178, 0]))
06-10 18:37:10.290 MainThread cpppo    INFO     terminate                          ( each.( type_id.((byte))  :             => enip.CIP.send_data.CPF.
item__.length     = 4 (format b'<H' over array('B', [4, 0]))
06-10 18:37:10.290 MainThread cpppo    INFO     run                     ( unconnected_send.( select.((noop))  -- limit='enip.CIP.send_data.CPF.item__.
unconnected_send..length' == 4; ending at symbol 20 vs. 20
06-10 18:37:10.290 MainThread cpppo    INFO     terminate          ( set_attribute_single.( service.((byte))  :             =>              service
  = 144 (format b'B' over array('B', [144]))
06-10 18:37:10.290 MainThread cpppo    INFO     terminate                         ( status.( status.((byte))  :             =>               status
  = 0 (format b'B' over array('B', [0]))
06-10 18:37:10.290 MainThread cpppo    INFO     terminate                         ( status.( status.((byte))  :             =>      status_ext.size
  = 0 (format b'B' over array('B', [0]))
06-10 18:37:10.290 MainThread enip.cli INFO     __next__   Returning result: {'enip': {'CIP': {'send_data': {'interface': 0, 'CPF': {'count': 2, 'item
': [{'length': 0, 'type_id': 0}, {'length': 4, 'unconnected_send': {'request': {'status_ext': {'size': 0}, 'set_attribute_single': True, 'service': 14
4, 'status': 0, 'input': array('B', [144, 0, 0, 0])}}, 'type_id': 178}]}, 'timeout': 0}}, 'length': 20, 'sender_context': {'input': array('B', [48, 0,
 0, 0, 0, 0, 0, 0])}, 'status': 0, 'command': 111, 'options': 0, 'session_handle': 1311111, 'input': array('B', [0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1
78, 0, 4, 0, 144, 0, 0, 0])}, 'peer': ('192.168.0.50', 44818)}
06-10 18:37:10.290 MainThread enip.cli DETAIL   collect    Rcvd   0.026/  5.000s {
    "enip.CIP.send_data.interface": 0,
    "enip.CIP.send_data.CPF.count": 2,
    "enip.CIP.send_data.CPF.item[0].length": 0,
    "enip.CIP.send_data.CPF.item[0].type_id": 0,
    "enip.CIP.send_data.CPF.item[1].length": 4,
    "enip.CIP.send_data.CPF.item[1].unconnected_send.request.status_ext.size": 0,
    "enip.CIP.send_data.CPF.item[1].unconnected_send.request.set_attribute_single": true,
    "enip.CIP.send_data.CPF.item[1].unconnected_send.request.service": 144,
    "enip.CIP.send_data.CPF.item[1].unconnected_send.request.status": 0,
    "enip.CIP.send_data.CPF.item[1].unconnected_send.request.input": "array('B', [144, 0, 0, 0])",
    "enip.CIP.send_data.CPF.item[1].type_id": 178,
    "enip.CIP.send_data.timeout": 0,
    "enip.length": 20,
    "enip.sender_context.input": "array('B', [48, 0, 0, 0, 0, 0, 0, 0])",
    "enip.status": 0,
    "enip.command": 111,
    "enip.options": 0,
    "enip.session_handle": 1311111,
    "enip.input": "array('B', [0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 178, 0, 4, 0, 144, 0, 0, 0])",
    "peer": [
        "192.168.0.50",
        44818
    ]
}
06-10 18:37:10.290 MainThread enip.cli DETAIL   collect    Receive  1 (Context       b'0')
06-10 18:37:10.305 MainThread enip.cli DETAIL   pipeline   Completed   1/  1; curr:   0 - last:   0 ==   0 depth
Fri Jun 10 18:37:10 2016:   0: Single S_A_S      @0x0004/100/3 == True
06-10 18:37:10.305 MainThread enip.cli DETAIL   pipeline   Pipelined   1/  1; curr:   0 - last:   0 ==   0 depth
06-10 18:37:10.305 MainThread enip.get NORMAL   main         1 requests in   0.058s at pipeline depth  0;  17.255 TPS

The Command-Line Interfaces work great and are reliable, but they are very limited in the amount of data they return. Using the Python API calls returns vast amounts of data about the response, including status and extended status codes...

Sure! I am just testing and learning, step by step. I will! Thanks for your time

pjkundert commented 8 years ago

Strange, indeed. Perhaps the Assembly (Class 0x04) is read-only? Perhaps try writing to a different attribute. Assemblies reference other Attributes in the device, and sometimes have such read/write restrictions...

jaytiwari commented 8 years ago

I want to read DR memory from Omron CJ2M CPU35 PLC. Could you please help me out to send the CIP commands to PLC.

service code, instance id, command code etc..

If possiblel, please let me know full telegram format.