-
Notifications
You must be signed in to change notification settings - Fork 184
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
exception with plc_read using pylogix 1.0.5 #257
Comments
Thanks, I'll check this out as soon as I can |
@ChristopheLaurent, I have a solution for this that is almost complete. |
@ChristopheLaurent, if you can try the branch bugfix/large-list-read, that would be helpful. |
Hello,
I fetched this branch, copy and paste the pylogix folder in my code and removed pylogix requirements.
Unfortunately I still have the same problem:
groot-svc | Exception reading 405 tags from 192.168.22.10: unpack_from requires a buffer of at least 49 bytes for unpacking 1 bytes at offset 48 (actual buffer size is 24)
groot-svc | File "/opt/everest/dev-ts-groot/groot_lib.py", line 159, in plc_read
groot-svc | results = comm.Read(batch)
groot-svc | File "/opt/everest/dev-ts-groot/pylogix/eip.py", line 126, in Read
groot-svc | return self._batch_read(tag)
groot-svc | File "/opt/everest/dev-ts-groot/pylogix/eip.py", line 393, in _batch_read
groot-svc | responses += [Response(tag, value, status) for tag, value, status in self._multi_read(current_requests)]
groot-svc | File "/opt/everest/dev-ts-groot/pylogix/eip.py", line 428, in _multi_read
groot-svc | status, ret_data = self.conn.send(request)
groot-svc | File "/opt/everest/dev-ts-groot/pylogix/lgx_comm.py", line 69, in send
groot-svc | return self._get_bytes(eip_header, connected)
groot-svc | File "/opt/everest/dev-ts-groot/pylogix/lgx_comm.py", line 177, in _get_bytes
groot-svc | status = unpack_from('<B', ret_data, 48)[0]
However, the call stack is not exactly the same as before.
Thanks a lot for your help, please let me know if you want me to check something else.
Best regards,
Christophe
|
Could I convince you to capture it with wireshark and email the capture to me? |
I'm experiencing the same issue. Grabbing 5 tags sequentially, my program outputs:
But trying to grab them all in a batch using I subclassed class DebugPLC(PLC):
def _parse_multi_read(self, data, tags):
"""
Extract the values from the multi-service message reply
"""
print("Entering _parse_multi_read")
print(f"Raw data received: {data!r}") # Print raw data for inspection
data = data[46:]
print(f"Data after removing header (46 bytes): {data!r}")
try:
service = unpack_from("<H", data, 0)[0]
print(f"Service code: {service}")
status, ext_status = unpack_from("<BB", data, 2)
print(f"Status: {status}, Extended Status: {ext_status}")
service_count = unpack_from("<H", data, 4)[0]
print(f"Service count: {service_count}")
offsets = [
unpack_from("<H", data, i * 2 + 6)[0] for i in range(service_count)
]
print(f"Offsets: {offsets}")
# Adjust offsets to be relative to data start (after header)
data_start = (
4 + service_count * 2 + 2
) # 4 (header) + service_count * 2 (offsets) + 2 (service count)
offsets = [offset - data_start for offset in offsets]
print(f"Adjusted offsets (relative to data start): {offsets}")
data = data[data_start:]
print(f"Data after offset adjustment: {data!r}")
reply = []
current_offset = 0
for idx, tag_info in enumerate(tags):
print(f"\nProcessing tag: {tag_info[0]}")
tag_name, base_tag, index = parse_tag_name(tag_info[0])
element_count = tag_info[1]
# Determine segment end based on next offset or end of data
if idx + 1 < len(offsets):
segment_end = offsets[idx + 1]
else:
segment_end = len(data)
segment = data[current_offset:segment_end]
print(f"Segment for tag: {segment!r}")
current_offset = segment_end
segment_service = unpack_from("<H", segment, 0)[0]
print(f"Segment service: {segment_service}")
segment_status = unpack_from("<B", segment, 2)[0]
print(f"Segment status: {segment_status}")
if segment_status == 6:
print("Segment status is 6 (partial), attempting to read more data")
segment_data_type = unpack_from("<B", segment, 4)[0]
ioi = self._build_ioi(tag_name, segment_data_type)
self.Offset = len(segment) - 8
request = self._add_partial_read_service(ioi, element_count)
segment_status, ret_data = self.conn.send(request)
print(f"Partial read status: {segment_status}, data: {ret_data!r}")
segment += ret_data[54:]
if segment_status == 0:
print("Segment status is 0 (success)")
segment_data_type = unpack_from("<B", segment, 4)[0]
print(f"Segment data type: {segment_data_type}")
self.KnownTags[base_tag] = (segment_data_type, 0)
if segment_data_type == 0xA0: # String
print("Parsing string value")
value = self._parse_string_value(segment)
elif segment_data_type == 0xC4: # DINT (for counters)
print("Parsing DINT value")
value = self._parse_dint_values(segment)
elif segment_data_type == 0xD3 or bit_of_word(
tag_name
): # BOOL Array or Bit of Word
print("Parsing BOOL array or bit of word")
values = self._parse_bool_values(segment, segment_data_type)
value = self._words_to_bits(tag_name, values, element_count)
else:
print("Parsing other value type")
value = self._parse_other_values(segment, segment_data_type)
else:
print(
f"Segment status is not 0, setting value to None. Status: {segment_status}"
)
value = None
# value shouldn't be a list if there is only one
if isinstance(value, list) and len(value) == 1:
value = value[0]
response = [tag_name, value, segment_status]
reply.append(response)
print("\nExiting _parse_multi_read")
return reply
except Exception as e:
print(f"ERROR in _parse_multi_read: {e}")
raise And here's its output:
Thanks for working on this! And let me know if I can help you with any more information on diagnosing the problem. |
Hmm, I can see this being an issue when including types that are not the basic data types (STRUCTs). @ChristopheLaurent, do you also have tags that are structures/UDT's? I'll need to do some more testing... |
I could email you my WireShark capture, if that would be helpful. Where should I send it to? |
My user name at gmail |
I think that the root cause of my issue is not _parse_multi_read but _multi_read. I modified _multi_read as follow:
The resulting trace shows that the first call to multi_read works fine:
Then the second call looks completely different with the 1st service that generate a huge request :
Eventually I get the same exception as before. How the service #0 can have 400 tags in the second call to _multi_read, instead of 20 in the 1st call to _multi_read ? Possibly @ammonwk had a related but different issue ? |
I'm working on a fix. The issue has to do with not taking into account the size of structs when trying to unpack the multi-message request. Apologies for the issue, I'll have it fixed as soon as I can. |
No worries, this is not an emergency for us, we can stay on version 0.8 for the time being. Furthermore I won't be able to test your fix before the 18th of December. Thanks a lot for your support ! |
@ammonwk, are you able to run the lates changes on the bugfix branch? |
Thanks for your work on this! It sort of works for me now, I'll give you
the details:
A little testing/proof of concept script:
Individual Reading (not batched)
Attempting to connect to PLC at 10.1.18.132...
Successfully connected to PLC!
PLC Time: 2024-12-16 20:19:52.154345
Reading tag structure...
=== Available Tags ===
Found 2951 tags
Attempting to read the tag Program:Preinspection.PreInspect
Result: Program:Preinspection.PreInspect
b'\x01\x00\x00\x00"\xe3\x01\x00\xe8\x03\x00\x00\x00\x00\x00\x00\xef\xdf\x01\x00\xe8\x03\x00\x00\x00\x00\x00\x00\xc7\x00\x00\x00\x01\x00\x00\x00\x1a\x00\x00\x00\x01\x00\x00\x00%\xa3\x01\x00\xe8\x03\x00\x00\x00\x00\x00\x00%\xa3\x01\x00\xe8\x03\x00\x00\x00\x00\x00\x00\x87\x00\x00\x00\x01\x00\x00\x00"\x00\x00\x00\x00\x00\x000\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00V2Z\x00\x00\x00\x00\x00\x00\x00\x00\x00\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe5,\x10\xc0`\xea\x00\x00\xc1)\x00\x00\x00\x00\x00\x00\xc0\xf1\xff\x7f\x00\x00\x00\x00/\xb7\x0b\x00\xc0\xf1\xff\x7f\xdf\xfa"\x00\xe5,\x10\xa0\xc0\xf1\xff\x7f\xc0\xf1\xff\x7f\xe5,\x10\xa0\x90\x01\x00\x00\x90\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00T\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1f\x00\x00\x00Wt\xff\xff\x1a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xb2*\x10\x00\xfa\x00\x00\x00\x00\x00\x00\x00!\xb4\x0f\x00k\x03\x00\x00\x00\x00\x00\x00\xb3*\x10\x00\xa4\x06\x00\x00\x00\x00\x00\x00\xf6\xba\x0f\x00A\n\x00\x00\x00\x00\x00\x00\xe5,\x10\xc0,\x01\x00\x00\x9c\x00\x00\x00U*\x10\x00\xf4\x01\x00\x00\x00\x00\x00\x00c\xc2\x0f\x00\xf4\x01\x00\x00\x00\x00\x00\x00\xe7*\x10\x002\x00\x00\x00\x00\x00\x00\x00I,\x10\x00\x88\x13\x00\x00\x00\x00\x00\x00\xa1)\x10\x00\xc8\x00\x00\x00\x00\x00\x00\x00\xe5,\x10\xc0\x98:\x00\x001\x02\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x98:\x00\x00\x81\x00\x04\x13'
Success
Attempting to read the tag
Program:Preinspection.Preinspect_Fail_Full_Light_Off
Result: Program:Preinspection.Preinspect_Fail_Full_Light_Off
b'\x96[)\x00\xfa\x00\x00\x00\x00\x00\x00\x00' Success
Attempting to read the tag
Program:Preinspection.Preinspect_Fail_Full_Light_On
Result: Program:Preinspection.Preinspect_Fail_Full_Light_On
b'd\xc2\x0f\x00\xfa\x00\x00\x00\x00\x00\x00\x00' Success
Attempting to read the tag Program:Preinspection.PreinspectGoodPartsCounter
Result: Program:Preinspection.PreinspectGoodPartsCounter
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' Success
Batched Reading (same tags)
Attempting to connect to PLC at 10.1.18.132...
Successfully connected to PLC!
PLC Time: 2024-12-16 20:20:17.429085
Reading tag structure...
=== Available Tags ===
Found 2951 tags
Attempting to read the tags ['Program:Preinspection.PreInspect',
'Program:Preinspection.Preinspect_Fail_Full_Light_Off',
'Program:Preinspection.Preinspect_Fail_Full_Light_On',
'Program:Preinspection.PreinspectGoodPartsCounter'] in a batch
comm.Read(['Program:Preinspection.PreInspect',
'Program:Preinspection.Preinspect_Fail_Full_Light_Off',
'Program:Preinspection.Preinspect_Fail_Full_Light_On',
'Program:Preinspection.PreinspectGoodPartsCounter'])
Result: [Response(TagName=Program:Preinspection.PreInspect,
Value=b'"\xe3\x01\x00\xe8\x03\x00\x00\x00\x00\x00\x00\xef\xdf\x01\x00\xe8\x03\x00\x00\x00\x00\x00\x00\xc7\x01\x00\x00\x01\x00\x00\x00&\x00\x00\x00\x01\x00\x00\x00%\xa3\x01\x00\xe8\x03\x00\x00\x00\x00\x00\x00%\xa3\x01\x00\xe8\x03\x00\x00\x00\x00\x00\x00\x87\x01\x00\x00\x01\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x000\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h2Z\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x9a\x8f\x10\xc0`\xea\x00\x00v\x8c\x00\x00\x00\x00\x00\x00\xc0\xf1\xff\x7f\x00\x00\x00\x00/\xb7\x0b\x00\xc0\xf1\xff\x7f\xdf\xfa"\x00`\x8c\x10
\xc0\xf1\xff\x7f\xc0\xf1\xff\x7f`\x8c\x10\x00\x90\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00T\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1f\x00\x00\x00Wt\xff\xff\x1a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xae\x89\x10\x00\xfa\x00\x00\x00\x00\x00\x00\x00!\xb4\x0f\x00k\x03\x00\x00\x00\x00\x00\x00\xaf\x89\x10\x00\xa4\x06\x00\x00\x00\x00\x00\x00\xf6\xba\x0f\x00A\n\x00\x00\x00\x00\x00\x00\x9a\x8f\x10\xa0,\x01\x00\x00,\x01\x00\x00\xf5\x7f\x10\x00\xf4\x01\x00\x00\x00\x00\x00\x00c\xc2\x0f\x00\xf4\x01\x00\x00\x00\x00\x00\x00\xe3\x89\x10\x002\x00\x00\x00\x00\x00\x00\x005\x8b\x10\x00\x88\x13\x00\x00\x00\x00\x00\x00\x9a\x8f\x10\xa0\xc8\x00\x00\x00\xc8\x00\x00\x00\x9a\x8f\x10\xc0\x98:\x00\x00\xea\x05\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x98:\x00\x00\xc1\x00\x04\x13',
Status=Success),
Response(TagName=Program:Preinspection.Preinspect_Fail_Full_Light_Off,
Value=b'\xfa\x00\x00\x00\x00\x00\x00\x00', Status=Success),
Response(TagName=Program:Preinspection.Preinspect_Fail_Full_Light_On,
Value=b'\xfa\x00\x00\x00\x00\x00\x00\x00', Status=Success),
Response(TagName=Program:Preinspection.PreinspectGoodPartsCounter,
Value=b'\x00\x00\x00\x00\x00\x00\x00\x00', Status=Success)]
Where the library might need better error handling:
If I iterate through all the tags.TagName to fetch them all, some result in
(None, Privilege violation), because they don't have a value to read:
Individual Reading ( Privilege violation )
Attempting to connect to PLC at 10.1.18.132...
Successfully connected to PLC!
PLC Time: 2024-12-16 20:19:38.582386
Reading tag structure...
=== Available Tags ===
Found 2951 tags
Attempting to read the tag Program:Preinspection
Result: Program:Preinspection None Privilege violation
Attempting to read the tag Program:Preinspection.PreInspect
Result: Program:Preinspection.PreInspect
b'\x01\x00\x00\x00"\xe3\x01\x00\xe8\x03\x00\x00\x00\x00\x00\x00\xef\xdf\x01\x00\xe8\...etc.
Success
Batched Reading ( Privilege violation )
Attempting to connect to PLC at 10.1.18.132...
Successfully connected to PLC!
PLC Time: 2024-12-16 20:18:30.836586
Reading tag structure...
=== Available Tags ===
Found 2951 tags
Attempting to read the tags ['Program:Preinspection',
'Program:Preinspection.PreInspect'] in a batch
comm.Read(['Program:Preinspection', 'Program:Preinspection.PreInspect'])
Traceback (most recent call last):
File "c:\Users\KAmmon\OneDrive - Ultradent Products
Inc\Documents\Scripts\data_analytics\tags_from_rockwell_batched.py", line
84, in <module>
connect_and_browse_plc(PLC_IP, PLC_SLOT)
~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^
File "c:\Users\KAmmon\OneDrive - Ultradent Products
Inc\Documents\Scripts\data_analytics\tags_from_rockwell_batched.py", line
52, in connect_and_browse_plc
batch_read_results = comm.Read(tag_names_to_read)
File
"C:\Users\KAmmon\AppData\Local\Programs\Python\Python313\Lib\site-packages\pylogix\eip.py",
line 126, in Read
return self._batch_read(tag)
~~~~~~~~~~~~~~~~^^^^^
File
"C:\Users\KAmmon\AppData\Local\Programs\Python\Python313\Lib\site-packages\pylogix\eip.py",
line 376, in _batch_read
self._get_unknown_types(tags)
~~~~~~~~~~~~~~~~~~~~~~~^^^^^^
File
"C:\Users\KAmmon\AppData\Local\Programs\Python\Python313\Lib\site-packages\pylogix\eip.py",
line 1394, in _get_unknown_types
self._multi_read(unk_tags)
~~~~~~~~~~~~~~~~^^^^^^^^^^
File
"C:\Users\KAmmon\AppData\Local\Programs\Python\Python313\Lib\site-packages\pylogix\eip.py",
line 434, in _multi_read
response.extend(self._parse_multi_read_response(ret_data, new_tags[i]))
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^
File
"C:\Users\KAmmon\AppData\Local\Programs\Python\Python313\Lib\site-packages\pylogix\eip.py",
line 1495, in _parse_multi_read_response
data_type = unpack_from("<B", segment, 4)[0]
~~~~~~~~~~~^^^^^^^^^^^^^^^^^^
struct.error: unpack_from requires a buffer of at least 5 bytes for
unpacking 1 bytes at offset 4 (actual buffer size is 4)
…-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
This might have been my error all along. If Batched Read could account for
those errors and return N/A, None, or "" values there, that would be
amazing.
Even if not, it should definitely have a more descriptive error than a
buffer error.
Thanks again, and let me know if I can get you any more information on this!
On Mon, Dec 16, 2024 at 6:18 PM dmroeder ***@***.***> wrote:
@ammonwk <https://github.com/ammonwk>, are you able to run the lates
changes on the bugfix branch?
—
Reply to this email directly, view it on GitHub
<#257 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ASE56OBKVJRLOCKPQQ6LA2T2F53VLAVCNFSM6AAAAABSU4ZHJCVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDKNBXGI4TMMRTGQ>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
Thanks for testing. How many bytes are the larger data types? |
I downloaded the branch |
I believe both issues are resolved in the branch. @ammonwk are you able to try it? |
Type of issue
Description of issue
I get an exception reading 583 tags in batch
This error occurs with latest 1.0.5 version. Going back to my previous version 0.8.13, it works perfectly well.
Stacktrace
groot-svc | Exception reading 192.168.22.10: unpack_from requires a buffer of at least 49 bytes for unpacking 1 bytes at offset 48 (actual buffer size is 24)
groot-svc | File "/opt/everest/dev-ts-groot/groot_lib.py", line 194, in plc_read
groot-svc | results = comm.Read(batch)
groot-svc | File "/usr/local/lib/python3.10/site-packages/pylogix/eip.py", line 126, in Read
groot-svc | return self._batch_read(tag)
groot-svc | File "/usr/local/lib/python3.10/site-packages/pylogix/eip.py", line 376, in _batch_read
groot-svc | self._get_unknown_types(tags)
groot-svc | File "/usr/local/lib/python3.10/site-packages/pylogix/eip.py", line 1392, in _get_unknown_types
groot-svc | self._multi_read(unk_tags)
groot-svc | File "/usr/local/lib/python3.10/site-packages/pylogix/eip.py", line 428, in _multi_read
groot-svc | status, ret_data = self.conn.send(request)
groot-svc | File "/usr/local/lib/python3.10/site-packages/pylogix/lgx_comm.py", line 69, in send
groot-svc | return self._get_bytes(eip_header, connected)
groot-svc | File "/usr/local/lib/python3.10/site-packages/pylogix/lgx_comm.py", line 177, in _get_bytes
groot-svc | status = unpack_from('<B', ret_data, 48)[0]
Versions
The text was updated successfully, but these errors were encountered: