Closed karmicthreat closed 7 years ago
Richard;
Thanks for the report. Yes, the Tag parsing code in Cpppo is presently pretty simplistic. Asking for elements of arrays of structs is pretty sketchy, at this point. In the first example, you are successfully asking for the data, but the response parser probably isn't capable of parsing the data response. In the second example, the simplistic Tag parser is erroneously handling the two indices.
I would recommend trying the first approach, and increasing the verbosity (add -vvv to the CLI command-line). Then, send me the logging output. I should be able to diagnose why the response is not being parsed.
I'll work on the Tag parsing code, to properly parse multi-level tags with multiple indices. In the mean time, you can hand-assemble arbitrarily complex EPATHs (instead of using the Tag parser):
python -m cpppo.server.enip.client --print -vvv '@{"symbolic":"JugARecipeName"}/{"element":0}/{"symbolic":"DATA"}'
Unfortunately, the element count supplied to the Read Tag [Fragmented] request in these cases is always == 1, so our options are limited to asking for a single element of whatever EPATH you provide...
The EPATH segments that you can ask for (each in a separate JSON dict) are:
symbolic
element
class
instance
connection
attribute
port, link
Example below, directly defining the EPATH does work for me: python3 -m cpppo.server.enip.client -a 192.168.2.210 --print '@{"symbolic":"JugARecipeName"}/{"element":5}/{"symbolic":"DATA"}/{"element":1}' JugARecipeName.DATA[1][ 1-1 ]+ 0 == [80]: 'OK'
Verbose example from previous:
python3 -m cpppo.server.enip.client -a 192.168.2.210 --print -vvv 'JugARecipeName[1].DATA[1]'
03-03 14:18:39.361 MainThread enip.cli DETAIL init Connect: TCP/IP to ('192.168.2.210', 44818)
03-03 14:18:39.391 MainThread enip.cli DETAIL cip_send Client CIP Send: {
"enip.options": 0,
"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.status": 0,
"enip.session_handle": 0
}
03-03 14:18:39.391 MainThread enip.cli INFO cip_send EtherNet/IP: 24 + CIP: 4 == 28 bytes total
03-03 14:18:39.391 MainThread enip.cli INFO send EtherNet/IP--> 192.168.2.210: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'
03-03 14:18:39.392 MainThread enip.cli INFO next EtherNet/IP--> 192.168.2.210:44818 rcvd 0: None
03-03 14:18:39.398 MainThread enip.cli INFO next EtherNet/IP--> 192.168.2.210:44818 rcvd 28: b'e\x00\x04\x00\x01\x00\x0b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00'
03-03 14:18:39.402 MainThread cpppo INFO terminate ( header.( command.((byte)) : => enip.command = 101 (format b'<H' over array('B', [101, 0]))
03-03 14:18:39.403 MainThread cpppo INFO terminate ( header.( command.((byte)) : => enip.length = 4 (format b'<H' over array('B', [4, 0]))
03-03 14:18:39.403 MainThread cpppo INFO terminate ( header.( command.((byte)) : => enip.session_handle = 720897 (format b'<I' over array('B', [1, 0, 11, 0]))
03-03 14:18:39.403 MainThread cpppo INFO terminate ( header.( command.((byte)) : => enip.status = 0 (format b'<I' over array('B', [0, 0, 0, 0]))
03-03 14:18:39.404 MainThread cpppo INFO terminate ( header.( command.((byte)) : => enip.options = 0 (format b'<I' over array('B', [0, 0, 0, 0]))
03-03 14:18:39.404 MainThread enip.cli INFO next EtherNet/IP 192.168.2.210:44818 done: ((enip.((payload.((byte))) -> ((payload.; next byte 28: None : {'enip': {'options': 0, 'command': 101, 'status': 0, 'session_handle': 720897, 'input': array('B', [1, 0, 0, 0]), 'length': 4, 'sender_context': {'input': array('B', [0, 0, 0, 0, 0, 0, 0, 0])}}, 'peer': ('192.168.2.210', 44818)}
03-03 14:18:39.406 MainThread cpppo INFO run ( register.( protocol_version.((byte)) -- limit='enip.CIP.register...length' == 4; ending at symbol 4 vs. None
03-03 14:18:39.406 MainThread cpppo INFO terminate ( register.( protocol_version.((byte)) : => enip.CIP.register.protocol_version = 1 (format b'<H' over array('B', [1, 0]))
03-03 14:18:39.406 MainThread cpppo INFO terminate ( register.( protocol_version.((byte)) : => enip.CIP.register.options = 0 (format b'<H' over array('B', [0, 0]))
03-03 14:18:39.406 MainThread enip.cli INFO next Returning result: {'enip': {'options': 0, 'command': 101, 'status': 0, 'session_handle': 720897, 'input': array('B', [1, 0, 0, 0]), 'CIP': {'register': {'options': 0, 'protocol_version': 1}}, 'length': 4, 'sender_context': {'input': array('B', [0, 0, 0, 0, 0, 0, 0, 0])}}, 'peer': ('192.168.2.210', 44818)}
03-03 14:18:39.415 MainThread enip.cli NORMAL init Connect: Success in 0.054s/ 5.000s
03-03 14:18:39.415 MainThread enip.cli DETAIL main Client Register Rcvd 0.055/ 5.000s
Traceback (most recent call last):
File "/usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/runpy.py", line 170, in _run_module_as_main
"main", mod_spec)
File "/usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/runpy.py", line 85, in _run_code
exec(code, run_globals)
File "/usr/local/lib/python3.5/site-packages/cpppo/server/enip/client.py", line 1609, in
If you clone https://github.com/pjkundert/cpppo.git, and 'git checkout feature-paths', I've now implemented (hopefully) more complete handling of more complex paths. If you 'python setup.py install' it, let me know if it handles your paths better...
-pjk
On Thu, Mar 3, 2016 at 12:33 PM, Richard Nienhuis notifications@github.com wrote:
Example below, directly defining the EPATH does work for me: python3 -m cpppo.server.enip.client -a 192.168.2.210 --print '@{"symbolic":"JugARecipeName"}/{"element":5}/{"symbolic":"DATA"}/{"element":1}' JugARecipeName.DATA[1][ 1-1 ]+ 0 == [80]: 'OK'
Verbose example from previous: python3 -m cpppo.server.enip.client -a 192.168.2.210 --print -vvv 'JugARecipeName[1].DATA[1]' 03-03 14:18:39.361 MainThread enip.cli DETAIL init Connect: TCP/IP to ('192.168.2.210', 44818) 03-03 14:18:39.391 MainThread enip.cli DETAIL cip_send Client CIP Send: { "enip.options": 0, "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.status": 0, "enip.session_handle": 0 } 03-03 14:18:39.391 MainThread enip.cli INFO cip_send EtherNet/IP: 24 + CIP: 4 == 28 bytes total 03-03 14:18:39.391 MainThread enip.cli INFO send EtherNet/IP--> 192.168.2.210: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' 03-03 14:18:39.392 MainThread enip.cli INFO next EtherNet/IP--> 192.168.2.210:44818 rcvd 0: None 03-03 14:18:39.398 MainThread enip.cli INFO next EtherNet/IP--> 192.168.2.210:44818 rcvd 28: b'e\x00\x04\x00\x01\x00\x0b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00' 03-03 14:18:39.402 MainThread cpppo INFO terminate ( header.( command.((byte)) : => enip.command = 101 (format b' 03-03 14:18:39.403 MainThread cpppo INFO terminate ( header.( command.((byte)) : => enip.length = 4 (format b' 03-03 14:18:39.403 MainThread cpppo INFO terminate ( header.( command.((byte)) : => enip.session_handle = 720897 (format b' 03-03 14:18:39.403 MainThread cpppo INFO terminate ( header.( command.((byte)) : => enip.status = 0 (format b' 03-03 14:18:39.404 MainThread cpppo INFO terminate ( header.( command.((byte)) : => enip.options = 0 (format b' 03-03 14:18:39.404 MainThread enip.cli INFO next EtherNet/IP 192.168.2.210:44818 done: ((enip.((payload.((byte))) -> ((payload.; next byte 28: None : {'enip': {'options': 0, 'command': 101, 'status': 0, 'session_handle': 720897, 'input': array('B', [1, 0, 0, 0]), 'length': 4, 'sender_context': {'input': array('B', [0, 0, 0, 0, 0, 0, 0, 0])}}, 'peer': ('192.168.2.210', 44818)} 03-03 14:18:39.406 MainThread cpppo INFO run ( register.( protocol_version.((byte)) -- limit='enip.CIP.register...length' == 4; ending at symbol 4 vs. None 03-03 14:18:39.406 MainThread cpppo INFO terminate ( register.( protocol_version.((byte)) : => enip.CIP.register.protocol_version = 1 (format b' 03-03 14:18:39.406 MainThread cpppo INFO terminate ( register.( protocol_version.((byte)) : => enip.CIP.register.options = 0 (format b' 03-03 14:18:39.406 MainThread enip.cli INFO next Returning result: {'enip': {'options': 0, 'command': 101, 'status': 0, 'session_handle': 720897, 'input': array('B', [1, 0, 0, 0]), 'CIP': {'register': {'options': 0, 'protocol_version': 1}}, 'length': 4, 'sender_context': {'input': array('B', [0, 0, 0, 0, 0, 0, 0, 0])}}, 'peer': ('192.168.2.210', 44818)} 03-03 14:18:39.415 MainThread enip.cli NORMAL init Connect: Success in 0.054s/ 5.000s 03-03 14:18:39.415 MainThread enip.cli DETAIL main Client Register Rcvd 0.055/ 5.000s Traceback (most recent call last): File "/usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/runpy.py", line 170, in _run_module_as_main "main", mod_spec) File "/usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/runpy.py", line 85, in _run_code exec(code, run_globals) File "/usr/local/lib/python3.5/site-packages/cpppo/server/enip/client.py", line 1609, in sys.exit( main() ) File "/usr/local/lib/python3.5/site-packages/cpppo/server/enip/client.py", line 1590, in main fragment=fragment, printing=printing, timeout=timeout ) File "/usr/local/lib/python3.5/site-packages/cpppo/server/enip/client.py", line 1366, in process transactions = list( self.results( operations=operations, *
_kwds )) File "/usr/local/lib/python3.5/site-packages/cpppo/server/enip/client.py", line 1358, in results for idx,dsc,req,rpy,sts,val in self.operate( operations, *_kwds ): File "/usr/local/lib/python3.5/site-packages/cpppo/server/enip/client.py", line 1353, in operate for idx,dsc,req,rpy,sts,val in harvested: File "/usr/local/lib/python3.5/site-packages/cpppo/server/enip/client.py", line 1243, in validate for index,descr,request,reply,status,val in harvested: File "/usr/local/lib/python3.5/site-packages/cpppo/server/enip/client.py", line 1208, in pipeline iss = next( issuer ) File "/usr/local/lib/python3.5/site-packages/cpppo/server/enip/client.py", line 932, in issue for op in operations: File "/usr/local/lib/python3.5/site-packages/cpppo/server/enip/client.py", line 205, in parse_operations seg,elm,cnt = parse_path_elements( tag ) File "/usr/local/lib/python3.5/site-packages/cpppo/server/enip/device.py", line 314, in parse_pathelements elm, = elm.split( ']' ) ValueError: too many values to unpack (expected 2)
— Reply to this email directly or view it on GitHub https://github.com/pjkundert/cpppo/issues/14#issuecomment-191927460.
Seems to work. I will look closer at it later this week.
Great; it's a work in progress; I may make changes that don't pass all unit tests from time to time...
On Wednesday, March 9, 2016, Richard Nienhuis notifications@github.com wrote:
Seems to work. I will look closer at it later this week.
— Reply to this email directly or view it on GitHub https://github.com/pjkundert/cpppo/issues/14#issuecomment-194312367.
-pjk
Had some time. One other place that I am running into the issue:
python3 -m cpppo.server.enip.client -a 192.168.2.210 -vvv --print 'JugARptStepTime[2][2]'
03-24 14:55:20.278 MainThread enip.cli DETAIL init Connect: TCP/IP to ('192.168.2.210', 44818)
03-24 14:55:20.309 MainThread enip.cli DETAIL cip_send Client CIP Send: {
"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,
"enip.session_handle": 0
}
03-24 14:55:20.309 MainThread enip.cli INFO cip_send EtherNet/IP: 24 + CIP: 4 == 28 bytes total
03-24 14:55:20.309 MainThread enip.cli INFO send EtherNet/IP--> 192.168.2.210: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'
03-24 14:55:20.309 MainThread enip.cli INFO next EtherNet/IP--> 192.168.2.210:44818 rcvd 0: None
03-24 14:55:20.314 MainThread enip.cli INFO next EtherNet/IP--> 192.168.2.210:44818 rcvd 28: b'e\x00\x04\x00\x01\x00\x15\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00'
03-24 14:55:20.319 MainThread cpppo INFO terminate ( header.( command.((byte)) : => enip.command = 101 (format b'<H' over array('B', [101, 0]))
03-24 14:55:20.319 MainThread cpppo INFO terminate ( header.( command.((byte)) : => enip.length = 4 (format b'<H' over array('B', [4, 0]))
03-24 14:55:20.320 MainThread cpppo INFO terminate ( header.( command.((byte)) : => enip.session_handle = 1376257 (format b'<I' over array('B', [1, 0, 21, 0]))
03-24 14:55:20.320 MainThread cpppo INFO terminate ( header.( command.((byte)) : => enip.status = 0 (format b'<I' over array('B', [0, 0, 0, 0]))
03-24 14:55:20.321 MainThread cpppo INFO terminate ( header.( command.((byte)) : => enip.options = 0 (format b'<I' over array('B', [0, 0, 0, 0]))
03-24 14:55:20.321 MainThread enip.cli INFO next EtherNet/IP 192.168.2.210:44818 done: ((enip.((payload.((byte))) -> ((payload.; next byte 28: None : {'peer': ('192.168.2.210', 44818), 'enip': {'length': 4, 'input': array('B', [1, 0, 0, 0]), 'command': 101, 'options': 0, 'status': 0, 'session_handle': 1376257, 'sender_context': {'input': array('B', [0, 0, 0, 0, 0, 0, 0, 0])}}}
03-24 14:55:20.323 MainThread cpppo INFO run ( register.( protocol_version.((byte)) -- limit='enip.CIP.register...length' == 4; ending at symbol 4 vs. None
03-24 14:55:20.323 MainThread cpppo INFO terminate ( register.( protocol_version.((byte)) : => enip.CIP.register.protocol_version = 1 (format b'<H' over array('B', [1, 0]))
03-24 14:55:20.323 MainThread cpppo INFO terminate ( register.( protocol_version.((byte)) : => enip.CIP.register.options = 0 (format b'<H' over array('B', [0, 0]))
03-24 14:55:20.324 MainThread enip.cli INFO next Returning result: {'peer': ('192.168.2.210', 44818), 'enip': {'length': 4, 'input': array('B', [1, 0, 0, 0]), 'CIP': {'register': {'protocol_version': 1, 'options': 0}}, 'command': 101, 'options': 0, 'status': 0, 'session_handle': 1376257, 'sender_context': {'input': array('B', [0, 0, 0, 0, 0, 0, 0, 0])}}}
03-24 14:55:20.333 MainThread enip.cli NORMAL init Connect: Success in 0.055s/ 5.000s
03-24 14:55:20.333 MainThread enip.cli DETAIL main Client Register Rcvd 0.055/ 5.000s
Traceback (most recent call last):
File "/usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/runpy.py", line 170, in _run_module_as_main
"main", mod_spec)
File "/usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/runpy.py", line 85, in _run_code
exec(code, run_globals)
File "/usr/local/lib/python3.5/site-packages/cpppo-3.9.3-py3.5.egg/cpppo/server/enip/client.py", line 1609, in
I can get it to work with: python -m cpppo.server.enip.client --print -a 192.168.2.210 -vvv '@{"symbolic":"JugARptStep"}/{"element":2}/{"element":2}' 03-24 14:58:11.934 MainThread enip.cli DETAIL init Connect: TCP/IP to ('192.168.2.210', 44818) 03-24 14:58:11.965 MainThread enip.cli DETAIL cip_send Client CIP Send: { "enip.status": 0, "enip.sender_context.input": "bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00')", "enip.session_handle": 0, "enip.CIP.register.protocol_version": 1, "enip.CIP.register.options": 0, "enip.options": 0 } 03-24 14:58:11.965 MainThread enip.cli INFO cip_send EtherNet/IP: 24 + CIP: 4 == 28 bytes total 03-24 14:58:11.965 MainThread enip.cli INFO send EtherNet/IP--> 192.168.2.210:44818 send 28: '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' 03-24 14:58:11.965 MainThread enip.cli INFO next EtherNet/IP--> 192.168.2.210:44818 rcvd 0: None 03-24 14:58:11.973 MainThread enip.cli INFO next EtherNet/IP--> 192.168.2.210:44818 rcvd 28: 'e\x00\x04\x00\x01\x00\x16\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00' 03-24 14:58:11.975 MainThread cpppo INFO terminate ( header.( command.((byte)) : => enip.command = 101 (format '<H' over array('c', 'e\x00')) 03-24 14:58:11.975 MainThread cpppo INFO terminate ( header.( command.((byte)) : => enip.length = 4 (format '<H' over array('c', '\x04\x00')) 03-24 14:58:11.976 MainThread cpppo INFO terminate ( header.( command.((byte)) : => enip.session_handle = 1441793 (format '<I' over array('c', '\x01\x00\x16\x00')) 03-24 14:58:11.976 MainThread cpppo INFO terminate ( header.( command.((byte)) : => enip.status = 0 (format '<I' over array('c', '\x00\x00\x00\x00')) 03-24 14:58:11.976 MainThread cpppo INFO terminate ( header.( command.((byte)) : => enip.options = 0 (format '<I' over array('c', '\x00\x00\x00\x00')) 03-24 14:58:11.977 MainThread enip.cli INFO next EtherNet/IP 192.168.2.210:44818 done: ((enip.((payload.((byte))) -> ((payload.; next byte 28: None : {'peer': ('192.168.2.210', 44818), 'enip': {'status': 0, 'sender_context': {'input': array('c', '\x00\x00\x00\x00\x00\x00\x00\x00')}, 'session_handle': 1441793, 'length': 4, 'command': 101, 'input': array('c', '\x01\x00\x00\x00'), 'options': 0}} 03-24 14:58:11.979 MainThread cpppo INFO run ( register.( protocol_version.((byte)) -- limit='enip.CIP.register...length' == 4; ending at symbol 4 vs. None 03-24 14:58:11.979 MainThread cpppo INFO terminate ( register.( protocol_version.((byte)) : => enip.CIP.register.protocol_version = 1 (format '<H' over array('c', '\x01\x00')) 03-24 14:58:11.979 MainThread cpppo INFO terminate ( register.( protocol_version.((byte)) : => enip.CIP.register.options = 0 (format '<H' over array('c', '\x00\x00')) 03-24 14:58:11.989 MainThread enip.cli INFO next Returning result: {'peer': ('192.168.2.210', 44818), 'enip': {'status': 0, 'sender_context': {'input': array('c', '\x00\x00\x00\x00\x00\x00\x00\x00')}, 'session_handle': 1441793, 'length': 4, 'CIP': {'register': {'protocol_version': 1, 'options': 0}}, 'command': 101, 'input': array('c', '\x01\x00\x00\x00'), 'options': 0}} 03-24 14:58:11.989 MainThread enip.cli NORMAL init Connect: Success in 0.055s/ 5.000s 03-24 14:58:11.989 MainThread enip.cli DETAIL main Client Register Rcvd 0.055/ 5.000s 03-24 14:58:11.990 MainThread enip.cli DETAIL parse_oper Tag: '@{"symbolic":"JugARptStep"}/{"element":2}/{"element":2}' yields Operation: {'path': [{u'symbolic': u'JugARptStep'}, {u'element': 2}, {u'element': 2}]}.update({'route_path': None, 'send_path': None}) 03-24 14:58:11.990 MainThread enip.cli DETAIL cip_send Client CIP Send: { "enip.status": 0, "enip.sender_context.input": "bytearray(b'0\x00\x00\x00\x00\x00\x00\x00')", "enip.session_handle": 1441793, "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.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.service": 82, "enip.CIP.send_data.CPF.item[1].unconnected_send.timeout_ticks": 157, "enip.CIP.send_data.CPF.item[1].unconnected_send.request.path.segment[0].symbolic": "JugARptStep", "enip.CIP.send_data.CPF.item[1].unconnected_send.request.path.segment[1].element": 2, "enip.CIP.send_data.CPF.item[1].unconnected_send.request.path.segment[2].element": 2, "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\t\x91\x0bJugARptStep\x00(\x02(\x02\x01\x00')", "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].type_id": 178, "enip.CIP.send_data.timeout": 0, "enip.options": 0 } 03-24 14:58:11.991 MainThread enip.cli INFO cip_send EtherNet/IP: 24 + CIP: 52 == 76 bytes total 03-24 14:58:11.991 MainThread enip.cli INFO send EtherNet/IP--> 192.168.2.210:44818 send 76: 'o\x004\x00\x01\x00\x16\x00\x00\x00\x00\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$\x00R\x02 \x06$\x01\x05\x9d\x16\x00L\t\x91\x0bJugARptStep\x00(\x02(\x02\x01\x00\x01\x00\x01\x00' 03-24 14:58:11.991 MainThread enip.cli DETAIL format_pat Formatted JugARptStep[2] from: [{u'symbolic': u'JugARptStep'}, {u'element': 2}, {u'element': 2}] 03-24 14:58:11.991 MainThread enip.cli DETAIL issue Sent 0.001/ 5.000s: Single Read Tag JugARptStep[2] { "path.segment[0].symbolic": "JugARptStep", "path.segment[1].element": 2, "path.segment[2].element": 2, "read_tag.elements": 1, "service": 76, "input": "bytearray(b'L\t\x91\x0bJugARptStep\x00(\x02(\x02\x01\x00')" } 03-24 14:58:11.991 MainThread enip.cli DETAIL issue Sending 1 (Context '0') 03-24 14:58:11.991 MainThread enip.cli DETAIL pipeline Issuing 0/ 1; curr: 0 - last: -1 == 1 depth 03-24 14:58:11.991 MainThread enip.cli INFO next EtherNet/IP--> 192.168.2.210:44818 rcvd 0: None 03-24 14:58:11.996 MainThread enip.cli INFO next EtherNet/IP--> 192.168.2.210:44818 rcvd 48: 'o\x00\x18\x00\x01\x00\x16\x00\x00\x00\x00\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\x08\x00\xcc\x00\x00\x00\xc3\x00\x02\x00' 03-24 14:58:11.997 MainThread cpppo INFO terminate ( header.( command.((byte)) : => enip.command = 111 (format '<H' over array('c', 'o\x00')) 03-24 14:58:11.998 MainThread cpppo INFO terminate ( header.( command.((byte)) : => enip.length = 24 (format '<H' over array('c', '\x18\x00')) 03-24 14:58:11.999 MainThread cpppo INFO terminate ( header.( command.((byte)) : => enip.session_handle = 1441793 (format '<I' over array('c', '\x01\x00\x16\x00')) 03-24 14:58:12.000 MainThread cpppo INFO terminate ( header.( command.((byte)) : => enip.status = 0 (format '<I' over array('c', '\x00\x00\x00\x00')) 03-24 14:58:12.001 MainThread cpppo INFO terminate ( header.( command.((byte)) : => enip.options = 0 (format '<I' over array('c', '\x00\x00\x00\x00')) 03-24 14:58:12.002 MainThread enip.cli INFO next EtherNet/IP 192.168.2.210:44818 done: ((enip.((payload.((byte))) -> ((payload.; next byte 76: None : {'peer': ('192.168.2.210', 44818), 'enip': {'status': 0, 'sender_context': {'input': array('c', '0\x00\x00\x00\x00\x00\x00\x00')}, 'session_handle': 1441793, 'length': 24, 'command': 111, 'input': array('c', '\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\xb2\x00\x08\x00\xcc\x00\x00\x00\xc3\x00\x02\x00'), 'options': 0}} 03-24 14:58:12.002 MainThread cpppo INFO run ( send_data.( interface.((byte)) -- limit='enip.CIP.send_data...length' == 24; ending at symbol 24 vs. None 03-24 14:58:12.002 MainThread cpppo INFO terminate ( send_data.( interface.((byte)) : => enip.CIP.send_data.interface = 0 (format '<I' over array('c', '\x00\x00\x00\x00')) 03-24 14:58:12.003 MainThread cpppo INFO terminate ( send_data.( interface.((byte)) : => enip.CIP.send_data.timeout = 0 (format '<H' over array('c', '\x00\x00')) 03-24 14:58:12.003 MainThread cpppo INFO terminate ( CPF.( count.((byte)) : => enip.CIP.send_data.CPF.count = 2 (format '<H' over array('c', '\x02\x00')) 03-24 14:58:12.003 MainThread cpppo INFO terminate ( each.( type_id.((byte)) : => enip.CIP.send_data.CPF.item.type_id = 0 (format '<H' over array('c', '\x00\x00')) 03-24 14:58:12.004 MainThread cpppo INFO terminate ( each.( type_id.((byte)) : => enip.CIP.send_data.CPF.item.length = 0 (format '<H' over array('c', '\x00\x00')) 03-24 14:58:12.004 MainThread cpppo INFO terminate ( each.( type_id.((byte)) : => enip.CIP.send_data.CPF.item.type_id = 178 (format '<H' over array('c', '\xb2\x00')) 03-24 14:58:12.004 MainThread cpppo INFO terminate ( each.( type_id.((byte)) : => enip.CIP.send_data.CPF.item.length = 8 (format '<H' over array('c', '\x08\x00')) 03-24 14:58:12.004 MainThread cpppo INFO run ( unconnected_send.( select.((noop)) -- limit='enip.CIP.send_data.CPF.item__.unconnected_send..length' == 8; ending at symbol 24 vs. 24 03-24 14:58:12.005 MainThread cpppo INFO terminate ( read_tag.( service.((byte)) : => service = 204 (format 'B' over array('c', '\xcc')) 03-24 14:58:12.006 MainThread cpppo INFO terminate ( status.( status.((byte)) : => status = 0 (format 'B' over array('c', '\x00')) 03-24 14:58:12.006 MainThread cpppo INFO terminate ( status.( status.((byte)) : => status_ext.size = 0 (format 'B' over array('c', '\x00')) 03-24 14:58:12.006 MainThread cpppo INFO terminate ( read_tag.( service.((byte)) : => read_tag.type = 195 (format '<H' over array('c', '\xc3\x00')) 03-24 14:58:12.007 MainThread cpppo INFO terminate ( data.( INT.((byte)) : => read_tag.INT = 2 (format '<h' over array('c', '\x02\x00')) 03-24 14:58:12.007 MainThread enip.cli INFO next Returning result: {'peer': ('192.168.2.210', 44818), 'enip': {'status': 0, 'sender_context': {'input': array('c', '0\x00\x00\x00\x00\x00\x00\x00')}, 'session_handle': 1441793, 'length': 24, 'CIP': {'send_data': {'interface': 0, 'CPF': {'count': 2, 'item': [{'length': 0, 'type_id': 0}, {'length': 8, 'unconnected_send': {'request': {'status': 0, 'input': array('c', '\xcc\x00\x00\x00\xc3\x00\x02\x00'), 'status_ext': {'size': 0}, 'read_tag': {'data': [2], 'type': 195}, 'service': 204}}, 'type_id': 178}]}, 'timeout': 0}}, 'command': 111, 'input': array('c', '\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\xb2\x00\x08\x00\xcc\x00\x00\x00\xc3\x00\x02\x00'), 'options': 0}} 03-24 14:58:12.007 MainThread enip.cli DETAIL collect Rcvd 0.016/ 5.000s { "peer": [ "192.168.2.210", 44818 ], "enip.status": 0, "enip.sender_context.input": "array('c', '0\x00\x00\x00\x00\x00\x00\x00')", "enip.session_handle": 1441793, "enip.length": 24, "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": 8, "enip.CIP.send_data.CPF.item[1].unconnected_send.request.status": 0, "enip.CIP.send_data.CPF.item[1].unconnected_send.request.input": "array('c', '\xcc\x00\x00\x00\xc3\x00\x02\x00')", "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.data": [ 2 ], "enip.CIP.send_data.CPF.item[1].unconnected_send.request.read_tag.type": 195, "enip.CIP.send_data.CPF.item[1].unconnected_send.request.service": 204, "enip.CIP.send_data.CPF.item[1].type_id": 178, "enip.CIP.send_data.timeout": 0, "enip.command": 111, "enip.input": "array('c', '\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\xb2\x00\x08\x00\xcc\x00\x00\x00\xc3\x00\x02\x00')", "enip.options": 0 } 03-24 14:58:12.008 MainThread enip.cli DETAIL collect Receive 1 (Context '0') 03-24 14:58:12.008 MainThread enip.cli DETAIL pipeline Completed 1/ 1; curr: 0 - last: 0 == 0 depth 03-24 14:58:12.008 MainThread enip.cli DETAIL validate Client Single Read Tag JugARptStep[2] Request: { "path.segment[0].symbolic": "JugARptStep", "path.segment[1].element": 2, "path.segment[2].element": 2, "read_tag.elements": 1, "service": 76, "input": "bytearray(b'L\t\x91\x0bJugARptStep\x00(\x02(\x02\x01\x00')" } 03-24 14:58:12.008 MainThread enip.cli DETAIL validate Yields Reply: { "status": 0, "input": "array('c', '\xcc\x00\x00\x00\xc3\x00\x02\x00')", "status_ext.size": 0, "read_tag.data": [ 2 ], "read_tag.type": 195, "service": 204 } 03-24 14:58:12.008 MainThread enip.cli DETAIL format_pat Formatted JugARptStep[2] from: [{u'symbolic': u'JugARptStep'}, {u'element': 2}, {u'element': 2}] 03-24 14:58:12.008 MainThread enip.cli NORMAL validate JugARptStep[2][ 2-2 ]+ 0 == [2]: 'OK' JugARptStep[2][ 2-2 ]+ 0 == [2]: 'OK' 03-24 14:58:12.009 MainThread enip.cli DETAIL pipeline Pipelined 1/ 1; curr: 0 - last: 0 == 0 depth 03-24 14:58:12.009 MainThread enip.cli NORMAL main Client Tag I/O Average 51.499 TPS ( 0.019s ea).
CIP STRING type is now supported.
So I am trying to read a string that is part of an array of strings out of a AB CompactLogix L18ER. With the structure JugARecipeName STRING[32] and the DATA tag inside is SINT[82] so 32 strings with a length of 82. I get a ValueError: too many values to unpack (expected 2) if I try to read one element. But I can't seem to read JugARepcipeName[1] or JugARecipeName[1].DATA as I just get 'cpppo.automata.NonTerminal: ( data.( select.((noop)) ) ) sub-machine terminated in a non-terminal state' am I doing something wrong to read this?
Examples below:
python3 -m cpppo.server.enip.client -a 192.168.2.210 -l cpppo.txt --print 'JugARecipeName[1].DATA' Traceback (most recent call last): File "/usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/runpy.py", line 170, in _run_module_as_main "main", mod_spec) File "/usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/runpy.py", line 85, in _run_code exec(code, run_globals) File "/usr/local/lib/python3.5/site-packages/cpppo/server/enip/client.py", line 1609, in
sys.exit( main() )
File "/usr/local/lib/python3.5/site-packages/cpppo/server/enip/client.py", line 1590, in main
fragment=fragment, printing=printing, timeout=timeout )
File "/usr/local/lib/python3.5/site-packages/cpppo/server/enip/client.py", line 1366, in process
transactions = list( self.results( operations=operations, _kwds ))
File "/usr/local/lib/python3.5/site-packages/cpppo/server/enip/client.py", line 1358, in results
for idx,dsc,req,rpy,sts,val in self.operate( operations, _kwds ):
File "/usr/local/lib/python3.5/site-packages/cpppo/server/enip/client.py", line 1353, in operate
for idx,dsc,req,rpy,sts,val in harvested:
File "/usr/local/lib/python3.5/site-packages/cpppo/server/enip/client.py", line 1243, in validate
for index,descr,request,reply,status,val in harvested:
File "/usr/local/lib/python3.5/site-packages/cpppo/server/enip/client.py", line 1218, in pipeline
col = next( harvester )
File "/usr/local/lib/python3.5/site-packages/cpppo/server/enip/client.py", line 1150, in harvest
issued, self.collect( timeout=timeout )): # must be "lazy" zip!
File "/usr/local/lib/python3.5/site-packages/cpppo/server/enip/client.py", line 1075, in collect
response,elapsed = await( self, timeout=timeout )
File "/usr/local/lib/python3.5/site-packages/cpppo/server/enip/client.py", line 832, in await
for response in cli: # if StopIteration raised immediately, defaults to {} signalling completion
File "/usr/local/lib/python3.5/site-packages/cpppo/server/enip/client.py", line 509, in next
for mch,sta in engine:
File "/usr/local/lib/python3.5/site-packages/cpppo/automata.py", line 645, in run
source=source, machine=machine, path=path, data=data, ending=ending ):
File "/usr/local/lib/python3.5/site-packages/cpppo/automata.py", line 1226, in delegate
for which,target in submach: # 75% of runtime is spent inside 'run'
File "/usr/local/lib/python3.5/site-packages/cpppo/automata.py", line 645, in run
source=source, machine=machine, path=path, data=data, ending=ending ):
File "/usr/local/lib/python3.5/site-packages/cpppo/automata.py", line 1226, in delegate
for which,target in submach: # 75% of runtime is spent inside 'run'
File "/usr/local/lib/python3.5/site-packages/cpppo/automata.py", line 645, in run
source=source, machine=machine, path=path, data=data, ending=ending ):
File "/usr/local/lib/python3.5/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
python3 -m cpppo.server.enip.client -a 192.168.2.210 -l cpppo.txt --print 'JugARecipeName[1].DATA[0]'
Traceback (most recent call last): File "/usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/runpy.py", line 170, in _run_module_as_main "main", mod_spec) File "/usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/runpy.py", line 85, in _run_code exec(code, run_globals) File "/usr/local/lib/python3.5/site-packages/cpppo/server/enip/client.py", line 1609, in
sys.exit( main() )
File "/usr/local/lib/python3.5/site-packages/cpppo/server/enip/client.py", line 1590, in main
fragment=fragment, printing=printing, timeout=timeout )
File "/usr/local/lib/python3.5/site-packages/cpppo/server/enip/client.py", line 1366, in process
transactions = list( self.results( operations=operations, _kwds ))
File "/usr/local/lib/python3.5/site-packages/cpppo/server/enip/client.py", line 1358, in results
for idx,dsc,req,rpy,sts,val in self.operate( operations, _kwds ):
File "/usr/local/lib/python3.5/site-packages/cpppo/server/enip/client.py", line 1353, in operate
for idx,dsc,req,rpy,sts,val in harvested:
File "/usr/local/lib/python3.5/site-packages/cpppo/server/enip/client.py", line 1243, in validate
for index,descr,request,reply,status,val in harvested:
File "/usr/local/lib/python3.5/site-packages/cpppo/server/enip/client.py", line 1208, in pipeline
iss = next( issuer )
File "/usr/local/lib/python3.5/site-packages/cpppo/server/enip/client.py", line 932, in issue
for op in operations:
File "/usr/local/lib/python3.5/site-packages/cpppo/server/enip/client.py", line 205, in parse_operations
seg,elm,cnt = parse_path_elements( tag )
File "/usr/local/lib/python3.5/site-packages/cpppo/server/enip/device.py", line 314, in parse_pathelements
elm, = elm.split( ']' )
ValueError: too many values to unpack (expected 2)