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

Problem reading/writing STRING data types from 1769-L30ER/A Logix5330ER PLC #44

Open davkuzmin opened 6 years ago

davkuzmin commented 6 years ago

I'm using the client to read/write DINT tags like so: python -m cpppo.server.enip.client -a myaddress "myDINTtag" python -m cpppo.server.enip.client -a myaddress "myDINTtag=(DINT)1234"

These work as expected.

However, when I attempt to read a string like so: python -m cpppo.server.enip.client -a myaddress "mySTRINGtag" I get this error output.

When I try to write a string value like so: python -m cpppo.server.enip.client -a myaddress "mySTRINGtag=(STRING)asdf" I get the following result, and the value is not written to the PLC: mySTRINGtag <= ['asdf']: 'Status 255 [8445]'

Am I doing anything obviously wrong? How can I proceed in debugging this issue?

pjkundert commented 6 years ago

It looks like the STRING data type is not being parsed properly on the first example:

python -m cpppo.server.enip.client -a myaddress "mySTRINGtag"

If you could add -vvv and make the request, and give me the logging output, it would tell me where the parser is failing.

Likewise, the device is rejecting an attempt to write a CIP "STRING" to the specified Tag. I am unsure what the extended status code 8445 means; as with almost everything EtherNet/IP CIP, there is little to no documentation available (correction: there is vast quantities of documentation available from the ODVA: but it is almost entirely useless).

smotero92 commented 5 years ago

I'm finding a similar issue when trying to read a STRING type tag. I use

python -m cpppo.server.enip.client -a "192.168.1.101" "PVString[0]

and get the output

Traceback (most recent call last):
  File "C:\PYTHON36\lib\runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "C:\PYTHON36\lib\runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "C:\Users\sotero\python\TPM_CMMS\venv\lib\site-packages\cpppo\server\enip\client.py", line 1649, in <module>
    sys.exit( main() )
  File "C:\Users\sotero\python\TPM_CMMS\venv\lib\site-packages\cpppo\server\enip\client.py", line 1630, in main
    fragment=fragment, printing=printing, timeout=timeout )
  File "C:\Users\sotero\python\TPM_CMMS\venv\lib\site-packages\cpppo\server\enip\client.py", line 1406, in process
    transactions                = list( self.results( operations=operations, **kwds ))
  File "C:\Users\sotero\python\TPM_CMMS\venv\lib\site-packages\cpppo\server\enip\client.py", line 1398, in results
    for idx,dsc,req,rpy,sts,val in self.operate( operations, **kwds ):
  File "C:\Users\sotero\python\TPM_CMMS\venv\lib\site-packages\cpppo\server\enip\client.py", line 1393, in operate
    for idx,dsc,req,rpy,sts,val in harvested:
  File "C:\Users\sotero\python\TPM_CMMS\venv\lib\site-packages\cpppo\server\enip\client.py", line 1283, in validate
    for index,descr,request,reply,status,val in harvested:
  File "C:\Users\sotero\python\TPM_CMMS\venv\lib\site-packages\cpppo\server\enip\client.py", line 1258, in pipeline
    col         = next( harvester )
  File "C:\Users\sotero\python\TPM_CMMS\venv\lib\site-packages\cpppo\server\enip\client.py", line 1190, in harvest
    issued, self.collect( timeout=timeout )): # must be "lazy" zip!
  File "C:\Users\sotero\python\TPM_CMMS\venv\lib\site-packages\cpppo\server\enip\client.py", line 1115, in collect
    response,elapsed    = await( self, timeout=timeout )
  File "C:\Users\sotero\python\TPM_CMMS\venv\lib\site-packages\cpppo\server\enip\client.py", line 872, in await
    for response in cli: # if StopIteration raised immediately, defaults to {} signalling completion
  File "C:\Users\sotero\python\TPM_CMMS\venv\lib\site-packages\cpppo\server\enip\client.py", line 546, in __next__
    for mch,sta in engine:
  File "C:\Users\sotero\python\TPM_CMMS\venv\lib\site-packages\cpppo\automata.py", line 645, in run
    source=source, machine=machine, path=path, data=data, ending=ending ):
  File "C:\Users\sotero\python\TPM_CMMS\venv\lib\site-packages\cpppo\automata.py", line 1226, in delegate
    for which,target in submach: # 75% of runtime is spent inside 'run'
  File "C:\Users\sotero\python\TPM_CMMS\venv\lib\site-packages\cpppo\automata.py", line 645, in run
    source=source, machine=machine, path=path, data=data, ending=ending ):
  File "C:\Users\sotero\python\TPM_CMMS\venv\lib\site-packages\cpppo\automata.py", line 1226, in delegate
    for which,target in submach: # 75% of runtime is spent inside 'run'
  File "C:\Users\sotero\python\TPM_CMMS\venv\lib\site-packages\cpppo\automata.py", line 645, in run
    source=source, machine=machine, path=path, data=data, ending=ending ):
  File "C:\Users\sotero\python\TPM_CMMS\venv\lib\site-packages\cpppo\automata.py", line 1291, in delegate
    raise NonTerminal( "%s sub-machine terminated in a non-terminal state" % ( self ))
cpppo.automata.NonTerminal: ( data.( select.((noop)) ) ) sub-machine terminated in a non-terminal state

then i use

python -m cpppo.server.enip.client -vvv "192.168.1.101" "PVString[0]"

as you request from OP and get

02-13 11:35:33.151 MainThread enip.cli DETAIL   __init__   Connect:  TCP/IP to ('localhost', 44818)
02-13 11:35:34.197 MainThread enip.cli DETAIL   cip_send   Client CIP Send: {
    "enip.session_handle": 0,
    "enip.options": 0,
    "enip.status": 0,
    "enip.sender_context.input": "bytearray(b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')",
    "enip.CIP.register.options": 0,
    "enip.CIP.register.protocol_version": 1
}
02-13 11:35:34.198 MainThread enip.cli INFO     cip_send   EtherNet/IP:  24 + CIP:   4 ==  28 bytes total
02-13 11:35:34.199 MainThread enip.cli INFO     send       EtherNet/IP-->       localhost:44818 send    28: b'e\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
x00\x01\x00\x00\x00'
02-13 11:35:34.200 MainThread enip.cli INFO     __next__   EtherNet/IP-->       localhost:44818 rcvd    28: b'e\x00\x04\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
x00\x01\x00\x00\x00'
02-13 11:35:34.200 MainThread cpppo    INFO     terminate                        ( header.( command.((byte))  :             =>         enip.command     = 101 (format b'<H' over array('B', [101, 0]))
02-13 11:35:34.201 MainThread cpppo    INFO     terminate                        ( header.( command.((byte))  :             =>          enip.length     = 4 (format b'<H' over array('B', [4, 0]))
02-13 11:35:34.202 MainThread cpppo    INFO     terminate                        ( header.( command.((byte))  :             =>  enip.session_handle     = 4 (format b'<I' over array('B', [4, 0, 0, 0]))

02-13 11:35:34.202 MainThread cpppo    INFO     terminate                        ( header.( command.((byte))  :             =>          enip.status     = 0 (format b'<I' over array('B', [0, 0, 0, 0]))

02-13 11:35:34.203 MainThread cpppo    INFO     terminate                        ( header.( command.((byte))  :             =>         enip.options     = 0 (format b'<I' over array('B', [0, 0, 0, 0]))

02-13 11:35:34.203 MainThread enip.cli INFO     __next__   EtherNet/IP          localhost:44818 done:                         ((enip.((payload.((byte))) -> ((payload.; next byte  28: None      : {'pee
r': ('localhost', 44818), 'enip': {'command': 101, 'length': 4, 'session_handle': 4, 'status': 0, 'sender_context': {'input': array('B', [0, 0, 0, 0, 0, 0, 0, 0])}, 'options': 0, 'input': array('B', [
1, 0, 0, 0])}}
02-13 11:35:34.204 MainThread cpppo    INFO     run                   ( register.( protocol_version.((byte))  -- limit='enip.CIP.register...length' == 4; ending at symbol 4 vs. None
02-13 11:35:34.204 MainThread cpppo    INFO     terminate             ( register.( protocol_version.((byte))  :             => enip.CIP.register.protocol_version     = 1 (format b'<H' over array('B',
[1, 0]))
02-13 11:35:34.205 MainThread cpppo    INFO     terminate             ( register.( protocol_version.((byte))  :             => enip.CIP.register.options     = 0 (format b'<H' over array('B', [0, 0]))
02-13 11:35:34.205 MainThread enip.cli INFO     __next__   Returning result: {'peer': ('localhost', 44818), 'enip': {'command': 101, 'length': 4, 'session_handle': 4, 'status': 0, 'sender_context': {'
input': array('B', [0, 0, 0, 0, 0, 0, 0, 0])}, 'options': 0, 'input': array('B', [1, 0, 0, 0]), 'CIP': {'register': {'protocol_version': 1, 'options': 0}}}}
02-13 11:35:34.206 MainThread enip.cli NORMAL   __init__   Connect:  Success in   1.055s/  5.000s
02-13 11:35:34.206 MainThread enip.cli DETAIL   main       Client Register Rcvd   1.055/  5.000s
02-13 11:35:34.206 MainThread enip.cli DETAIL   parse_oper Tag: '192.168.1.101' yields Operation: {'path': [{'symbolic': '192'}, {'symbolic': '168'}, {'symbolic': '1'}, {'symbolic': '101'}]}.update({'
route_path': None, 'send_path': None})
02-13 11:35:34.207 MainThread enip.cli DETAIL   cip_send   Client CIP Send: {
    "enip.session_handle": 4,
    "enip.options": 0,
    "enip.status": 0,
    "enip.sender_context.input": "bytearray(b'0\\x00\\x00\\x00\\x00\\x00\\x00\\x00')",
    "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].type_id": 178,
    "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.priority": 5,
    "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.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.request.path.segment[0].symbolic": "192",
    "enip.CIP.send_data.CPF.item[1].unconnected_send.request.path.segment[1].symbolic": "168",
    "enip.CIP.send_data.CPF.item[1].unconnected_send.request.path.segment[2].symbolic": "1",
    "enip.CIP.send_data.CPF.item[1].unconnected_send.request.path.segment[3].symbolic": "101",
    "enip.CIP.send_data.CPF.item[1].unconnected_send.request.read_tag.elements": 1,
    "enip.CIP.send_data.CPF.item[1].unconnected_send.request.service": 76,
    "enip.CIP.send_data.CPF.item[1].unconnected_send.request.input": "bytearray(b'L\\x0b\\x91\\x03192\\x00\\x91\\x03168\\x00\\x91\\x011\\x00\\x91\\x03101\\x00\\x01\\x00')"
}
02-13 11:35:34.208 MainThread enip.cli INFO     cip_send   EtherNet/IP:  24 + CIP:  56 ==  80 bytes total
02-13 11:35:34.208 MainThread enip.cli INFO     send       EtherNet/IP-->       localhost:44818 send    80: b'o\x008\x00\x04\x00\x00\x00\x00\x00\x00\x000\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0
0\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\xb2\x00(\x00R\x02 \x06$\x01\x05\x9d\x1a\x00L\x0b\x91\x03192\x00\x91\x03168\x00\x91\x011\x00\x91\x03101\x00\x01\x00\x01\x00\x01\x00'
02-13 11:35:34.208 MainThread enip.cli DETAIL   format_pat Formatted                    192.168.1.101 from: [{'symbolic': '192'}, {'symbolic': '168'}, {'symbolic': '1'}, {'symbolic': '101'}]
02-13 11:35:34.209 MainThread enip.cli DETAIL   issue      Sent   0.002/  5.000s: Single Read  Tag  192.168.1.101 {
    "path.segment[0].symbolic": "192",
    "path.segment[1].symbolic": "168",
    "path.segment[2].symbolic": "1",
    "path.segment[3].symbolic": "101",
    "read_tag.elements": 1,
    "service": 76,
    "input": "bytearray(b'L\\x0b\\x91\\x03192\\x00\\x91\\x03168\\x00\\x91\\x011\\x00\\x91\\x03101\\x00\\x01\\x00')"
}
02-13 11:35:34.210 MainThread enip.cli DETAIL   issue      Sending  1 (Context       b'0')
02-13 11:35:34.210 MainThread enip.cli DETAIL   pipeline   Issuing     0/  1; curr:   0 - last:  -1 ==   1 depth
02-13 11:35:34.210 MainThread enip.cli DETAIL   parse_oper Tag: 'PVString[0]' yields Operation: {'path': [{'symbolic': 'PVString'}, {'element': 0}]}.update({'route_path': None, 'send_path': None})
02-13 11:35:34.211 MainThread enip.cli DETAIL   cip_send   Client CIP Send: {
    "enip.session_handle": 4,
    "enip.options": 0,
    "enip.status": 0,
    "enip.sender_context.input": "bytearray(b'1\\x00\\x00\\x00\\x00\\x00\\x00\\x00')",
    "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].type_id": 178,
    "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.priority": 5,
    "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.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.request.path.segment[0].symbolic": "PVString",
    "enip.CIP.send_data.CPF.item[1].unconnected_send.request.path.segment[1].element": 0,
    "enip.CIP.send_data.CPF.item[1].unconnected_send.request.read_tag.elements": 1,
    "enip.CIP.send_data.CPF.item[1].unconnected_send.request.service": 76,
    "enip.CIP.send_data.CPF.item[1].unconnected_send.request.input": "bytearray(b'L\\x06\\x91\\x08PVString(\\x00\\x01\\x00')"
}
02-13 11:35:34.212 MainThread enip.cli INFO     cip_send   EtherNet/IP:  24 + CIP:  46 ==  70 bytes total
02-13 11:35:34.212 MainThread enip.cli INFO     send       EtherNet/IP-->       localhost:44818 send    70: b'o\x00.\x00\x04\x00\x00\x00\x00\x00\x00\x001\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0
0\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\xb2\x00\x1e\x00R\x02 \x06$\x01\x05\x9d\x10\x00L\x06\x91\x08PVString(\x00\x01\x00\x01\x00\x01\x00'
02-13 11:35:34.213 MainThread enip.cli DETAIL   format_pat Formatted                      PVString[0] from: [{'symbolic': 'PVString'}, {'element': 0}]
02-13 11:35:34.213 MainThread enip.cli DETAIL   issue      Sent   0.002/  5.000s: Single Read  Tag  PVString[0] {
    "path.segment[0].symbolic": "PVString",
    "path.segment[1].element": 0,
    "read_tag.elements": 1,
    "service": 76,
    "input": "bytearray(b'L\\x06\\x91\\x08PVString(\\x00\\x01\\x00')"
}
02-13 11:35:34.213 MainThread enip.cli DETAIL   issue      Sending  1 (Context       b'1')
02-13 11:35:34.213 MainThread enip.cli DETAIL   pipeline   Issuing     0/  2; curr:   1 - last:  -1 ==   2 depth
02-13 11:35:34.214 MainThread enip.cli INFO     __next__   EtherNet/IP-->       localhost:44818 rcvd    88: b'o\x00\x14\x00\x04\x00\x00\x00\x00\x00\x00\x000\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
\x00\x00\x00\x00\x1e\x00\x02\x00\x00\x00\x00\x00\xb2\x00\x04\x00\xcc\x00\x08\x00o\x00\x14\x00\x04\x00\x00\x00\x00\x00\x00\x001\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1e\x00\x02\x
00\x00\x00\x00\x00\xb2\x00\x04\x00\xcc\x00\x08\x00'
02-13 11:35:34.214 MainThread cpppo    INFO     terminate                        ( header.( command.((byte))  :             =>         enip.command     = 111 (format b'<H' over array('B', [111, 0]))
02-13 11:35:34.215 MainThread cpppo    INFO     terminate                        ( header.( command.((byte))  :             =>          enip.length     = 20 (format b'<H' over array('B', [20, 0]))
02-13 11:35:34.215 MainThread cpppo    INFO     terminate                        ( header.( command.((byte))  :             =>  enip.session_handle     = 4 (format b'<I' over array('B', [4, 0, 0, 0]))

02-13 11:35:34.216 MainThread cpppo    INFO     terminate                        ( header.( command.((byte))  :             =>          enip.status     = 0 (format b'<I' over array('B', [0, 0, 0, 0]))

02-13 11:35:34.216 MainThread cpppo    INFO     terminate                        ( header.( command.((byte))  :             =>         enip.options     = 0 (format b'<I' over array('B', [0, 0, 0, 0]))

02-13 11:35:34.217 MainThread enip.cli INFO     __next__   EtherNet/IP          localhost:44818 done:                         ((enip.((payload.((byte))) -> ((payload.; next byte  72: 111       : {'pee
r': ('localhost', 44818), 'enip': {'command': 111, 'length': 20, 'session_handle': 4, 'status': 0, 'sender_context': {'input': array('B', [48, 0, 0, 0, 0, 0, 0, 0])}, 'options': 0, 'input': array('B',
 [0, 0, 0, 0, 30, 0, 2, 0, 0, 0, 0, 0, 178, 0, 4, 0, 204, 0, 8, 0])}}
02-13 11:35:34.218 MainThread cpppo    INFO     run                         ( send_data.( interface.((byte))  -- limit='enip.CIP.send_data...length' == 20; ending at symbol 20 vs. None
02-13 11:35:34.218 MainThread cpppo    INFO     terminate                   ( send_data.( interface.((byte))  :             => enip.CIP.send_data.interface     = 0 (format b'<I' over array('B', [0, 0,
 0, 0]))
02-13 11:35:34.219 MainThread cpppo    INFO     terminate                   ( send_data.( interface.((byte))  :             => enip.CIP.send_data.timeout     = 30 (format b'<H' over array('B', [30, 0]
))
02-13 11:35:34.220 MainThread cpppo    INFO     terminate                             ( CPF.( count.((byte))  :             => enip.CIP.send_data.CPF.count     = 2 (format b'<H' over array('B', [2, 0]
))
02-13 11:35:34.220 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]))
02-13 11:35:34.220 MainThread cpppo    INFO     terminate                          ( each.( type_id.((byte))  :             => enip.CIP.send_data.CPF.item__.length     = 0 (format b'<H' over array('B'
, [0, 0]))
02-13 11:35:34.221 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]))
02-13 11:35:34.221 MainThread cpppo    INFO     terminate                          ( each.( type_id.((byte))  :             => enip.CIP.send_data.CPF.item__.length     = 4 (format b'<H' over array('B'
, [4, 0]))
02-13 11:35:34.222 MainThread cpppo    INFO     run                     ( unconnected_send.( select.((noop))  -- limit='enip.CIP.send_data.CPF.item__.unconnected_send..length' == 4; ending at symbol 2
0 vs. 20
02-13 11:35:34.223 MainThread cpppo    INFO     terminate                      ( read_tag.( service.((byte))  :             =>              service     = 204 (format b'B' over array('B', [204]))
02-13 11:35:34.223 MainThread cpppo    INFO     terminate                         ( status.( status.((byte))  :             =>               status     = 8 (format b'B' over array('B', [8]))
02-13 11:35:34.223 MainThread cpppo    INFO     terminate                         ( status.( status.((byte))  :             =>      status_ext.size     = 0 (format b'B' over array('B', [0]))
02-13 11:35:34.224 MainThread enip.cli INFO     __next__   Returning result: {'peer': ('localhost', 44818), 'enip': {'command': 111, 'length': 20, 'session_handle': 4, 'status': 0, 'sender_context': {
'input': array('B', [48, 0, 0, 0, 0, 0, 0, 0])}, 'options': 0, 'input': array('B', [0, 0, 0, 0, 30, 0, 2, 0, 0, 0, 0, 0, 178, 0, 4, 0, 204, 0, 8, 0]), 'CIP': {'send_data': {'interface': 0, 'timeout':
30, 'CPF': {'count': 2, 'item': [{'type_id': 0, 'length': 0}, {'type_id': 178, 'length': 4, 'unconnected_send': {'request': {'input': array('B', [204, 0, 8, 0]), 'service': 204, 'status': 8, 'status_e
xt': {'size': 0}, 'read_tag': True}}}]}}}}}
02-13 11:35:34.224 MainThread enip.cli DETAIL   collect    Rcvd   0.010/  5.000s {
    "peer": [
        "localhost",
        44818
    ],
    "enip.command": 111,
    "enip.length": 20,
    "enip.session_handle": 4,
    "enip.status": 0,
    "enip.sender_context.input": "array('B', [48, 0, 0, 0, 0, 0, 0, 0])",
    "enip.options": 0,
    "enip.input": "array('B', [0, 0, 0, 0, 30, 0, 2, 0, 0, 0, 0, 0, 178, 0, 4, 0, 204, 0, 8, 0])",
    "enip.CIP.send_data.interface": 0,
    "enip.CIP.send_data.timeout": 30,
    "enip.CIP.send_data.CPF.count": 2,
    "enip.CIP.send_data.CPF.item[0].type_id": 0,
    "enip.CIP.send_data.CPF.item[0].length": 0,
    "enip.CIP.send_data.CPF.item[1].type_id": 178,
    "enip.CIP.send_data.CPF.item[1].length": 4,
    "enip.CIP.send_data.CPF.item[1].unconnected_send.request.input": "array('B', [204, 0, 8, 0])",
    "enip.CIP.send_data.CPF.item[1].unconnected_send.request.service": 204,
    "enip.CIP.send_data.CPF.item[1].unconnected_send.request.status": 8,
    "enip.CIP.send_data.CPF.item[1].unconnected_send.request.status_ext.size": 0,
    "enip.CIP.send_data.CPF.item[1].unconnected_send.request.read_tag": true
}
02-13 11:35:34.225 MainThread enip.cli DETAIL   collect    Receive  1 (Context       b'0')
02-13 11:35:34.225 MainThread enip.cli DETAIL   pipeline   Completed   1/  2; curr:   1 - last:   0 ==   1 depth
02-13 11:35:34.226 MainThread enip.cli DETAIL   validate   Client Single Read  Tag  192.168.1.101 Request: {
    "path.segment[0].symbolic": "192",
    "path.segment[1].symbolic": "168",
    "path.segment[2].symbolic": "1",
    "path.segment[3].symbolic": "101",
    "read_tag.elements": 1,
    "service": 76,
    "input": "bytearray(b'L\\x0b\\x91\\x03192\\x00\\x91\\x03168\\x00\\x91\\x011\\x00\\x91\\x03101\\x00\\x01\\x00')"
}
02-13 11:35:34.226 MainThread enip.cli DETAIL   validate     Yields Reply: {
    "input": "array('B', [204, 0, 8, 0])",
    "service": 204,
    "status": 8,
    "status_ext.size": 0,
    "read_tag": true
}
02-13 11:35:34.227 MainThread enip.cli DETAIL   format_pat Formatted                    192.168.1.101 from: [{'symbolic': '192'}, {'symbolic': '168'}, {'symbolic': '1'}, {'symbolic': '101'}]
02-13 11:35:34.227 MainThread enip.cli WARNING  validate   Client Single Read  Tag  192.168.1.101 returned non-zero status: Status 8
02-13 11:35:34.227 MainThread enip.cli NORMAL   validate          192.168.1.101              == None: 'Status 8 '
       192.168.1.101              == None: 'Status 8 '
02-13 11:35:34.228 MainThread cpppo    INFO     terminate                        ( header.( command.((byte))  :             =>         enip.command     = 111 (format b'<H' over array('B', [111, 0]))
02-13 11:35:34.228 MainThread cpppo    INFO     terminate                        ( header.( command.((byte))  :             =>          enip.length     = 20 (format b'<H' over array('B', [20, 0]))
02-13 11:35:34.228 MainThread cpppo    INFO     terminate                        ( header.( command.((byte))  :             =>  enip.session_handle     = 4 (format b'<I' over array('B', [4, 0, 0, 0]))

02-13 11:35:34.229 MainThread cpppo    INFO     terminate                        ( header.( command.((byte))  :             =>          enip.status     = 0 (format b'<I' over array('B', [0, 0, 0, 0]))

02-13 11:35:34.229 MainThread cpppo    INFO     terminate                        ( header.( command.((byte))  :             =>         enip.options     = 0 (format b'<I' over array('B', [0, 0, 0, 0]))

02-13 11:35:34.230 MainThread enip.cli INFO     __next__   EtherNet/IP          localhost:44818 done:                         ((enip.((payload.((byte))) -> ((payload.; next byte 116: None      : {'pee
r': ('localhost', 44818), 'enip': {'command': 111, 'length': 20, 'session_handle': 4, 'status': 0, 'sender_context': {'input': array('B', [49, 0, 0, 0, 0, 0, 0, 0])}, 'options': 0, 'input': array('B',
 [0, 0, 0, 0, 30, 0, 2, 0, 0, 0, 0, 0, 178, 0, 4, 0, 204, 0, 8, 0])}}
02-13 11:35:34.231 MainThread cpppo    INFO     run                         ( send_data.( interface.((byte))  -- limit='enip.CIP.send_data...length' == 20; ending at symbol 20 vs. None
02-13 11:35:34.231 MainThread cpppo    INFO     terminate                   ( send_data.( interface.((byte))  :             => enip.CIP.send_data.interface     = 0 (format b'<I' over array('B', [0, 0,
 0, 0]))
02-13 11:35:34.232 MainThread cpppo    INFO     terminate                   ( send_data.( interface.((byte))  :             => enip.CIP.send_data.timeout     = 30 (format b'<H' over array('B', [30, 0]
))
02-13 11:35:34.232 MainThread cpppo    INFO     terminate                             ( CPF.( count.((byte))  :             => enip.CIP.send_data.CPF.count     = 2 (format b'<H' over array('B', [2, 0]
))
02-13 11:35:34.233 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]))
02-13 11:35:34.234 MainThread cpppo    INFO     terminate                          ( each.( type_id.((byte))  :             => enip.CIP.send_data.CPF.item__.length     = 0 (format b'<H' over array('B'
, [0, 0]))
02-13 11:35:34.234 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]))
02-13 11:35:34.235 MainThread cpppo    INFO     terminate                          ( each.( type_id.((byte))  :             => enip.CIP.send_data.CPF.item__.length     = 4 (format b'<H' over array('B'
, [4, 0]))
02-13 11:35:34.235 MainThread cpppo    INFO     run                     ( unconnected_send.( select.((noop))  -- limit='enip.CIP.send_data.CPF.item__.unconnected_send..length' == 4; ending at symbol 2
0 vs. 20
02-13 11:35:34.238 MainThread cpppo    INFO     terminate                      ( read_tag.( service.((byte))  :             =>              service     = 204 (format b'B' over array('B', [204]))
02-13 11:35:34.239 MainThread cpppo    INFO     terminate                         ( status.( status.((byte))  :             =>               status     = 8 (format b'B' over array('B', [8]))
02-13 11:35:34.239 MainThread cpppo    INFO     terminate                         ( status.( status.((byte))  :             =>      status_ext.size     = 0 (format b'B' over array('B', [0]))
02-13 11:35:34.247 MainThread enip.cli INFO     __next__   Returning result: {'peer': ('localhost', 44818), 'enip': {'command': 111, 'length': 20, 'session_handle': 4, 'status': 0, 'sender_context': {
'input': array('B', [49, 0, 0, 0, 0, 0, 0, 0])}, 'options': 0, 'input': array('B', [0, 0, 0, 0, 30, 0, 2, 0, 0, 0, 0, 0, 178, 0, 4, 0, 204, 0, 8, 0]), 'CIP': {'send_data': {'interface': 0, 'timeout':
30, 'CPF': {'count': 2, 'item': [{'type_id': 0, 'length': 0}, {'type_id': 178, 'length': 4, 'unconnected_send': {'request': {'input': array('B', [204, 0, 8, 0]), 'service': 204, 'status': 8, 'status_e
xt': {'size': 0}, 'read_tag': True}}}]}}}}}
02-13 11:35:34.252 MainThread enip.cli DETAIL   collect    Rcvd   0.024/  5.000s {
    "peer": [
        "localhost",
        44818
    ],
    "enip.command": 111,
    "enip.length": 20,
    "enip.session_handle": 4,
    "enip.status": 0,
    "enip.sender_context.input": "array('B', [49, 0, 0, 0, 0, 0, 0, 0])",
    "enip.options": 0,
    "enip.input": "array('B', [0, 0, 0, 0, 30, 0, 2, 0, 0, 0, 0, 0, 178, 0, 4, 0, 204, 0, 8, 0])",
    "enip.CIP.send_data.interface": 0,
    "enip.CIP.send_data.timeout": 30,
    "enip.CIP.send_data.CPF.count": 2,
    "enip.CIP.send_data.CPF.item[0].type_id": 0,
    "enip.CIP.send_data.CPF.item[0].length": 0,
    "enip.CIP.send_data.CPF.item[1].type_id": 178,
    "enip.CIP.send_data.CPF.item[1].length": 4,
    "enip.CIP.send_data.CPF.item[1].unconnected_send.request.input": "array('B', [204, 0, 8, 0])",
    "enip.CIP.send_data.CPF.item[1].unconnected_send.request.service": 204,
    "enip.CIP.send_data.CPF.item[1].unconnected_send.request.status": 8,
    "enip.CIP.send_data.CPF.item[1].unconnected_send.request.status_ext.size": 0,
    "enip.CIP.send_data.CPF.item[1].unconnected_send.request.read_tag": true
}
02-13 11:35:34.253 MainThread enip.cli DETAIL   collect    Receive  1 (Context       b'1')
02-13 11:35:34.254 MainThread enip.cli DETAIL   pipeline   Completed   2/  2; curr:   1 - last:   1 ==   0 depth
02-13 11:35:34.255 MainThread enip.cli DETAIL   validate   Client Single Read  Tag  PVString[0] Request: {
    "path.segment[0].symbolic": "PVString",
    "path.segment[1].element": 0,
    "read_tag.elements": 1,
    "service": 76,
    "input": "bytearray(b'L\\x06\\x91\\x08PVString(\\x00\\x01\\x00')"
}
02-13 11:35:34.256 MainThread enip.cli DETAIL   validate     Yields Reply: {
    "input": "array('B', [204, 0, 8, 0])",
    "service": 204,
    "status": 8,
    "status_ext.size": 0,
    "read_tag": true
}
02-13 11:35:34.256 MainThread enip.cli DETAIL   format_pat Formatted                      PVString[0] from: [{'symbolic': 'PVString'}, {'element': 0}]
02-13 11:35:34.257 MainThread enip.cli WARNING  validate   Client Single Read  Tag  PVString[0] returned non-zero status: Status 8
02-13 11:35:34.258 MainThread enip.cli NORMAL   validate            PVString[0][  0-0  ]+  0 == None: 'Status 8 '
         PVString[0][  0-0  ]+  0 == None: 'Status 8 '
02-13 11:35:34.259 MainThread enip.cli DETAIL   pipeline   Pipelined   2/  2; curr:   1 - last:   1 ==   0 depth
02-13 11:35:34.259 MainThread enip.cli NORMAL   main       Client Tag I/O  Average  37.762 TPS (  0.026s ea).

Any Ideas? I've gotten the same results trying this

host = "192.168.1.101"
tags = ["PVString[0]"]
        with client.connector(host=host) as conn:
            for index, descr, op, reply, status, value in conn.pipeline(
                    operations=client.parse_operations(tags), depth=3):
                print("%20s: %s" % (descr, value))