python-snap7 3.2.0__py3-none-any.whl → 3.2.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {python_snap7-3.2.0.dist-info → python_snap7-3.2.1.dist-info}/METADATA +5 -1
- {python_snap7-3.2.0.dist-info → python_snap7-3.2.1.dist-info}/RECORD +12 -12
- snap7/async_client.py +76 -66
- snap7/client.py +82 -89
- snap7/client_base.py +75 -2
- snap7/s7protocol.py +170 -134
- snap7/server/__init__.py +178 -220
- snap7/util/getters.py +5 -5
- {python_snap7-3.2.0.dist-info → python_snap7-3.2.1.dist-info}/WHEEL +0 -0
- {python_snap7-3.2.0.dist-info → python_snap7-3.2.1.dist-info}/entry_points.txt +0 -0
- {python_snap7-3.2.0.dist-info → python_snap7-3.2.1.dist-info}/licenses/LICENSE +0 -0
- {python_snap7-3.2.0.dist-info → python_snap7-3.2.1.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-snap7
|
|
3
|
-
Version: 3.2.
|
|
3
|
+
Version: 3.2.1
|
|
4
4
|
Summary: Pure Python S7 communication library for Siemens PLCs
|
|
5
5
|
Author-email: Gijs Molenaar <gijsmolenaar@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -24,6 +24,7 @@ License-File: LICENSE
|
|
|
24
24
|
Provides-Extra: test
|
|
25
25
|
Requires-Dist: pytest; extra == "test"
|
|
26
26
|
Requires-Dist: pytest-asyncio; extra == "test"
|
|
27
|
+
Requires-Dist: pytest-bdd<9,>=8.1; extra == "test"
|
|
27
28
|
Requires-Dist: pytest-cov; extra == "test"
|
|
28
29
|
Requires-Dist: pytest-html; extra == "test"
|
|
29
30
|
Requires-Dist: hypothesis; extra == "test"
|
|
@@ -101,3 +102,6 @@ Documentation
|
|
|
101
102
|
|
|
102
103
|
Read the full documentation at
|
|
103
104
|
`python-snap7.readthedocs.io <https://python-snap7.readthedocs.io/en/latest/>`_.
|
|
105
|
+
|
|
106
|
+
The safe volunteer hardware-test procedure is in
|
|
107
|
+
`Real-PLC acceptance testing <doc/real-plc-testing.rst>`_.
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
python_snap7-3.2.
|
|
1
|
+
python_snap7-3.2.1.dist-info/licenses/LICENSE,sha256=PIihE_yP-8gc-ff9ikvQQPOa0biOCZ6Bc-6h3G3xRUQ,1097
|
|
2
2
|
s7/__init__.py,sha256=q6E4rA1BDx36PPkJS55xv7XCxwlaQeEK6HNotFjLeYo,1096
|
|
3
3
|
snap7/__init__.py,sha256=2NAAE1oaSSd7DqPl0dx7jNXtsM2PRBWRm9X-bkmgC6U,1275
|
|
4
|
-
snap7/async_client.py,sha256=
|
|
4
|
+
snap7/async_client.py,sha256=yPyqzD4WH3544hKV4aDHt48r8LSWKsbFcVBZxtQOcYQ,52571
|
|
5
5
|
snap7/cli.py,sha256=L1B7NMAemDcl93JUSqJV3Ls_CN2ghlG75nTMD08JkMs,13787
|
|
6
|
-
snap7/client.py,sha256=
|
|
7
|
-
snap7/client_base.py,sha256=
|
|
6
|
+
snap7/client.py,sha256=MWnqsxjjdSSAloluSqAXtmfpokyJEKezJj77e_SqR6I,107985
|
|
7
|
+
snap7/client_base.py,sha256=tNZs_MA8FGit8pg9axNoljH1kFToDI1HIzXC8WQLYHs,11324
|
|
8
8
|
snap7/connection.py,sha256=Qjis-ICK6E74_YfoJuy2_lgDqfSYs4ULux1FShJVvtw,18834
|
|
9
9
|
snap7/datatypes.py,sha256=Gqu1XDuKkQI76n4TYrFrhm0RlPz4XNA5GKA-GJJXJDU,12042
|
|
10
10
|
snap7/demo.py,sha256=JWSKLj2QPIXeSFTZSXuADAJzWVKls712MUZnuqwNkNs,17376
|
|
@@ -17,18 +17,18 @@ snap7/partner.py,sha256=HxaTYfojsf5Z170R4cAYFzoMSwqCOF42qPCkOaxbUkU,37916
|
|
|
17
17
|
snap7/ppi.py,sha256=p0fVelfUQOT3QH5uuWOjpDxA5IyT3gx5FzCMaYYEuWQ,16070
|
|
18
18
|
snap7/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
19
19
|
snap7/rate_limiter.py,sha256=dnXCOJLWmszo8oskbFM0om0gPC4LHHCOr-Nt22tImeU,4151
|
|
20
|
-
snap7/s7protocol.py,sha256=
|
|
20
|
+
snap7/s7protocol.py,sha256=BLuI6h3Cfbr4R55-v20fYMlKCY6ASbtxdJOC5T0JyaI,69396
|
|
21
21
|
snap7/szl.py,sha256=a9NhH7Lyp8SXJ2_kvyyV-14srIxm3tXnAnclBy5alDk,7998
|
|
22
22
|
snap7/tags.py,sha256=TmbNRHNWZVe3Yl_1L5WXE3Qb0lxIEW-veoCRGt0giZQ,26987
|
|
23
23
|
snap7/type.py,sha256=EiXqU0ayYYxlM-5fUcPL7psgL1EGNNqAa7JXH4QlAnU,9752
|
|
24
|
-
snap7/server/__init__.py,sha256=
|
|
24
|
+
snap7/server/__init__.py,sha256=0XqMGlqblhVNmILT_Ddm-yxTw1r19bfFrr-VuPLEDnI,112468
|
|
25
25
|
snap7/server/__main__.py,sha256=OdOgyMmFThjSe2jSgvlbkquGYnZcBW6wubs2ldhNSOE,1206
|
|
26
26
|
snap7/util/__init__.py,sha256=d6n2oy7tNYke1ia0TUyWz_ni3l0XN1qvilM5sW0T-Es,1874
|
|
27
27
|
snap7/util/db.py,sha256=geesYS2oyOuTADOJa2me1p1rqJVzPuLTCfye6JIeav0,27120
|
|
28
|
-
snap7/util/getters.py,sha256=
|
|
28
|
+
snap7/util/getters.py,sha256=pMsiCz0soMV7Q-VDPBdFG5eHzcFESZtKPw6mxj4S5ko,25370
|
|
29
29
|
snap7/util/setters.py,sha256=BpFqVxxUbhqarV6Gzt4ZuxycHljtDYsONCr6e9G33Ms,27226
|
|
30
|
-
python_snap7-3.2.
|
|
31
|
-
python_snap7-3.2.
|
|
32
|
-
python_snap7-3.2.
|
|
33
|
-
python_snap7-3.2.
|
|
34
|
-
python_snap7-3.2.
|
|
30
|
+
python_snap7-3.2.1.dist-info/METADATA,sha256=-oAcJHaF7AZL-10-rfF1c73I5E-JElaLi-azSxq76zg,3662
|
|
31
|
+
python_snap7-3.2.1.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
32
|
+
python_snap7-3.2.1.dist-info/entry_points.txt,sha256=IPZyYr1lKyavXXpAc4xO505afTGwTY8GmNFuy5lsSiM,75
|
|
33
|
+
python_snap7-3.2.1.dist-info/top_level.txt,sha256=PTgDoDG45QNL2XIE9RM7S_ZCdWQjtMMuXNyrI2UdnbU,9
|
|
34
|
+
python_snap7-3.2.1.dist-info/RECORD,,
|
snap7/async_client.py
CHANGED
|
@@ -10,15 +10,17 @@ import asyncio
|
|
|
10
10
|
import logging
|
|
11
11
|
import struct
|
|
12
12
|
import time
|
|
13
|
+
from collections.abc import Callable
|
|
14
|
+
from contextvars import ContextVar
|
|
13
15
|
from typing import List, Any, Optional, Tuple, Type
|
|
14
16
|
from types import TracebackType
|
|
15
17
|
from datetime import datetime
|
|
16
18
|
|
|
17
19
|
from .connection import TPDUSize
|
|
18
|
-
from .s7protocol import S7Protocol, get_return_code_description
|
|
20
|
+
from .s7protocol import S7Protocol, S7UserDataGroup, S7UserDataSubfunction, get_return_code_description
|
|
19
21
|
from .datatypes import S7DataTypes, S7WordLen
|
|
20
22
|
from .error import S7Error, S7ConnectionError, S7ProtocolError, S7TimeoutError
|
|
21
|
-
from .client_base import ClientMixin
|
|
23
|
+
from .client_base import ClientMixin, _instrumented
|
|
22
24
|
from .szl import parse_cp_info_szl, parse_cpu_info_szl, parse_order_code_szl, parse_protection_szl
|
|
23
25
|
from .client import _parse_force_szl
|
|
24
26
|
from .rate_limiter import RateLimitAlgorithm, RateLimitBehavior, RequestRateLimiter
|
|
@@ -319,6 +321,7 @@ class AsyncClient(ClientMixin):
|
|
|
319
321
|
rate_limit_algorithm: RateLimitAlgorithm = "fixed",
|
|
320
322
|
rate_limit_behavior: RateLimitBehavior = "block",
|
|
321
323
|
rate_limit_burst: int | None = None,
|
|
324
|
+
on_operation: Optional[Callable[[str, float, bool], None]] = None,
|
|
322
325
|
) -> None:
|
|
323
326
|
self.connection: Optional[AsyncISOTCPConnection] = None
|
|
324
327
|
self.protocol = S7Protocol()
|
|
@@ -336,6 +339,8 @@ class AsyncClient(ClientMixin):
|
|
|
336
339
|
|
|
337
340
|
self._exec_time = 0
|
|
338
341
|
self._last_error = 0
|
|
342
|
+
self._on_operation = on_operation
|
|
343
|
+
self._operation_depth: ContextVar[int] = ContextVar("snap7_async_client_operation_depth", default=0)
|
|
339
344
|
|
|
340
345
|
self._lock = asyncio.Lock()
|
|
341
346
|
self._rate_limiter = RequestRateLimiter(
|
|
@@ -539,6 +544,7 @@ class AsyncClient(ClientMixin):
|
|
|
539
544
|
# Core read / write
|
|
540
545
|
# ---------------------------------------------------------------
|
|
541
546
|
|
|
547
|
+
@_instrumented("read_area")
|
|
542
548
|
async def read_area(self, area: Area, db_number: int, start: int, size: int) -> bytearray:
|
|
543
549
|
"""Read data from memory area.
|
|
544
550
|
|
|
@@ -585,6 +591,7 @@ class AsyncClient(ClientMixin):
|
|
|
585
591
|
self._exec_time = int((time.time() - start_time) * 1000)
|
|
586
592
|
return result
|
|
587
593
|
|
|
594
|
+
@_instrumented("write_area")
|
|
588
595
|
async def write_area(self, area: Area, db_number: int, start: int, data: bytearray) -> int:
|
|
589
596
|
"""Write data to memory area.
|
|
590
597
|
|
|
@@ -630,6 +637,7 @@ class AsyncClient(ClientMixin):
|
|
|
630
637
|
self._exec_time = int((time.time() - start_time) * 1000)
|
|
631
638
|
return 0
|
|
632
639
|
|
|
640
|
+
@_instrumented("read_multi_vars")
|
|
633
641
|
async def read_multi_vars(self, items: List[dict[str, Any]]) -> Tuple[int, list[bytearray]]:
|
|
634
642
|
"""Read multiple variables (sequentially, one read_area per item).
|
|
635
643
|
|
|
@@ -654,6 +662,7 @@ class AsyncClient(ClientMixin):
|
|
|
654
662
|
results.append(data)
|
|
655
663
|
return (0, results)
|
|
656
664
|
|
|
665
|
+
@_instrumented("write_multi_vars")
|
|
657
666
|
async def write_multi_vars(self, items: List[dict[str, Any]]) -> int:
|
|
658
667
|
"""Write multiple variables (sequentially, one write_area per item).
|
|
659
668
|
|
|
@@ -687,6 +696,7 @@ class AsyncClient(ClientMixin):
|
|
|
687
696
|
|
|
688
697
|
request = self.protocol.build_list_blocks_request()
|
|
689
698
|
response = await self._send_receive(request)
|
|
699
|
+
self.protocol.check_userdata_response(response, S7UserDataGroup.BLOCK_INFO, S7UserDataSubfunction.LIST_ALL)
|
|
690
700
|
|
|
691
701
|
data_info = response.get("data", {})
|
|
692
702
|
return_code = data_info.get("return_code", 0xFF) if isinstance(data_info, dict) else 0xFF
|
|
@@ -719,6 +729,7 @@ class AsyncClient(ClientMixin):
|
|
|
719
729
|
|
|
720
730
|
request = self.protocol.build_list_blocks_of_type_request(type_code)
|
|
721
731
|
response = await self._send_receive(request)
|
|
732
|
+
self.protocol.check_userdata_response(response, S7UserDataGroup.BLOCK_INFO, S7UserDataSubfunction.LIST_BLOCKS_OF_TYPE)
|
|
722
733
|
|
|
723
734
|
data_info = response.get("data", {})
|
|
724
735
|
return_code = data_info.get("return_code", 0xFF) if isinstance(data_info, dict) else 0xFF
|
|
@@ -744,6 +755,7 @@ class AsyncClient(ClientMixin):
|
|
|
744
755
|
response_data = await conn.receive_data()
|
|
745
756
|
|
|
746
757
|
response = self.protocol.parse_response(response_data)
|
|
758
|
+
self.protocol.check_userdata_response(response, S7UserDataGroup.BLOCK_INFO, S7UserDataSubfunction.LIST_BLOCKS_OF_TYPE)
|
|
747
759
|
|
|
748
760
|
data_info = response.get("data", {})
|
|
749
761
|
return_code = data_info.get("return_code", 0xFF) if isinstance(data_info, dict) else 0xFF
|
|
@@ -779,6 +791,7 @@ class AsyncClient(ClientMixin):
|
|
|
779
791
|
|
|
780
792
|
request = self.protocol.build_get_block_info_request(type_code, db_number)
|
|
781
793
|
response = await self._send_receive(request)
|
|
794
|
+
self.protocol.check_userdata_response(response, S7UserDataGroup.BLOCK_INFO, S7UserDataSubfunction.BLOCK_INFO)
|
|
782
795
|
|
|
783
796
|
data_info = response.get("data", {})
|
|
784
797
|
return_code = data_info.get("return_code", 0xFF) if isinstance(data_info, dict) else 0xFF
|
|
@@ -808,6 +821,7 @@ class AsyncClient(ClientMixin):
|
|
|
808
821
|
# Upload / Download / Delete
|
|
809
822
|
# ---------------------------------------------------------------
|
|
810
823
|
|
|
824
|
+
@_instrumented("upload")
|
|
811
825
|
async def upload(self, block_num: int) -> bytearray:
|
|
812
826
|
"""Upload block from PLC (3-step: START_UPLOAD, UPLOAD, END_UPLOAD)."""
|
|
813
827
|
if not self.get_connected():
|
|
@@ -819,19 +833,27 @@ class AsyncClient(ClientMixin):
|
|
|
819
833
|
response = await self._send_receive(request)
|
|
820
834
|
|
|
821
835
|
upload_info = self.protocol.parse_start_upload_response(response)
|
|
822
|
-
upload_id = upload_info
|
|
836
|
+
upload_id = upload_info["upload_id"]
|
|
823
837
|
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
838
|
+
block_data = bytearray()
|
|
839
|
+
for fragment_index in range(1000):
|
|
840
|
+
request = self.protocol.build_upload_request(upload_id)
|
|
841
|
+
response = await self._send_receive(request)
|
|
842
|
+
fragment, is_last = self.protocol.parse_upload_fragment(response, first_fragment=fragment_index == 0)
|
|
843
|
+
block_data.extend(fragment)
|
|
844
|
+
if is_last:
|
|
845
|
+
break
|
|
846
|
+
else:
|
|
847
|
+
raise S7ProtocolError("Upload response exceeded fragment limit")
|
|
828
848
|
|
|
829
849
|
request = self.protocol.build_end_upload_request(upload_id)
|
|
830
850
|
response = await self._send_receive(request)
|
|
851
|
+
self.protocol.check_end_upload_response(response)
|
|
831
852
|
|
|
832
853
|
logger.info(f"Uploaded {len(block_data)} bytes from block {block_num}")
|
|
833
|
-
return
|
|
854
|
+
return block_data
|
|
834
855
|
|
|
856
|
+
@_instrumented("download")
|
|
835
857
|
async def download(self, data: bytearray, block_num: int = -1) -> int:
|
|
836
858
|
"""Download block to PLC."""
|
|
837
859
|
if not self.get_connected():
|
|
@@ -846,44 +868,33 @@ class AsyncClient(ClientMixin):
|
|
|
846
868
|
else:
|
|
847
869
|
block_num = 1
|
|
848
870
|
|
|
849
|
-
# Step 1: Request download
|
|
850
871
|
request = self.protocol.build_download_request(block_type, block_num, bytes(data))
|
|
851
|
-
await self._send_receive(request)
|
|
852
|
-
|
|
853
|
-
# Step 2: Download block (send data)
|
|
854
|
-
param_data = struct.pack(">BBB", 0x1B, 0x01, 0x00)
|
|
855
|
-
data_section = struct.pack(">HH", len(data), 0x00FB) + bytes(data)
|
|
856
|
-
header = struct.pack(
|
|
857
|
-
">BBHHHH",
|
|
858
|
-
0x32,
|
|
859
|
-
0x01,
|
|
860
|
-
0x0000,
|
|
861
|
-
self.protocol._next_sequence(),
|
|
862
|
-
len(param_data),
|
|
863
|
-
len(data_section),
|
|
864
|
-
)
|
|
865
|
-
|
|
866
872
|
async with self._lock:
|
|
867
|
-
await self._send_data(conn,
|
|
873
|
+
await self._send_data(conn, request)
|
|
868
874
|
response_data = await conn.receive_data()
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
875
|
+
response = self.protocol.parse_response(response_data)
|
|
876
|
+
if response["sequence"] != int.from_bytes(request[4:6], "big") or response.get("raw_parameters") != bytes((0x1A,)):
|
|
877
|
+
raise S7ProtocolError("Invalid request-download acknowledgement")
|
|
878
|
+
|
|
879
|
+
offset = 0
|
|
880
|
+
max_slice = self.pdu_length - 18
|
|
881
|
+
if max_slice <= 0:
|
|
882
|
+
raise S7ProtocolError("Negotiated PDU is too small for download")
|
|
883
|
+
for _ in range(1000):
|
|
884
|
+
request_data = await conn.receive_data()
|
|
885
|
+
sequence = self.protocol.parse_download_service_request(request_data, 0x1B, block_num)
|
|
886
|
+
fragment = bytes(data[offset : offset + max_slice])
|
|
887
|
+
offset += len(fragment)
|
|
888
|
+
is_last = offset == len(data)
|
|
889
|
+
await self._send_data(conn, self.protocol.build_download_fragment_response(sequence, is_last, fragment))
|
|
890
|
+
if is_last:
|
|
891
|
+
break
|
|
892
|
+
else:
|
|
893
|
+
raise S7ProtocolError("Download exceeded fragment limit")
|
|
882
894
|
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
self.protocol.parse_response(response_data)
|
|
895
|
+
request_data = await conn.receive_data()
|
|
896
|
+
sequence = self.protocol.parse_download_service_request(request_data, 0x1C, block_num)
|
|
897
|
+
await self._send_data(conn, self.protocol.build_download_ended_response(sequence))
|
|
887
898
|
|
|
888
899
|
logger.info(f"Downloaded {len(data)} bytes to block {block_num}")
|
|
889
900
|
return 0
|
|
@@ -931,32 +942,27 @@ class AsyncClient(ClientMixin):
|
|
|
931
942
|
response = await self._send_receive(request)
|
|
932
943
|
|
|
933
944
|
upload_info = self.protocol.parse_start_upload_response(response)
|
|
934
|
-
upload_id = upload_info
|
|
945
|
+
upload_id = upload_info["upload_id"]
|
|
935
946
|
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
947
|
+
block_data = bytearray()
|
|
948
|
+
for fragment_index in range(1000):
|
|
949
|
+
request = self.protocol.build_upload_request(upload_id)
|
|
950
|
+
response = await self._send_receive(request)
|
|
951
|
+
fragment, is_last = self.protocol.parse_upload_fragment(
|
|
952
|
+
response, first_fragment=fragment_index == 0, include_block_header=True
|
|
953
|
+
)
|
|
954
|
+
block_data.extend(fragment)
|
|
955
|
+
if is_last:
|
|
956
|
+
break
|
|
957
|
+
else:
|
|
958
|
+
raise S7ProtocolError("Upload response exceeded fragment limit")
|
|
939
959
|
|
|
940
960
|
request = self.protocol.build_end_upload_request(upload_id)
|
|
941
961
|
response = await self._send_receive(request)
|
|
962
|
+
self.protocol.check_end_upload_response(response)
|
|
942
963
|
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
0x70,
|
|
946
|
-
block_type.value,
|
|
947
|
-
block_num,
|
|
948
|
-
0x00,
|
|
949
|
-
0x00,
|
|
950
|
-
0x00,
|
|
951
|
-
0x00,
|
|
952
|
-
len(block_data) + 14,
|
|
953
|
-
len(block_data),
|
|
954
|
-
)
|
|
955
|
-
block_footer = b"\x00" * 4
|
|
956
|
-
full_block = bytearray(block_header + block_data + block_footer)
|
|
957
|
-
|
|
958
|
-
logger.info(f"Full upload of block {block_type.name} {block_num}: {len(full_block)} bytes")
|
|
959
|
-
return full_block, len(full_block)
|
|
964
|
+
logger.info(f"Full upload of block {block_type.name} {block_num}: {len(block_data)} bytes")
|
|
965
|
+
return block_data, len(block_data)
|
|
960
966
|
|
|
961
967
|
# ---------------------------------------------------------------
|
|
962
968
|
# PLC control
|
|
@@ -994,6 +1000,7 @@ class AsyncClient(ClientMixin):
|
|
|
994
1000
|
|
|
995
1001
|
request = self.protocol.build_get_clock_request()
|
|
996
1002
|
response = await self._send_receive(request)
|
|
1003
|
+
self.protocol.check_userdata_response(response, S7UserDataGroup.TIME, S7UserDataSubfunction.GET_CLOCK)
|
|
997
1004
|
return self.protocol.parse_get_clock_response(response)
|
|
998
1005
|
|
|
999
1006
|
async def set_plc_datetime(self, dt: datetime) -> int:
|
|
@@ -1002,7 +1009,8 @@ class AsyncClient(ClientMixin):
|
|
|
1002
1009
|
raise S7ConnectionError("Not connected to PLC")
|
|
1003
1010
|
|
|
1004
1011
|
request = self.protocol.build_set_clock_request(dt)
|
|
1005
|
-
await self._send_receive(request)
|
|
1012
|
+
response = await self._send_receive(request)
|
|
1013
|
+
self.protocol.check_userdata_response(response, S7UserDataGroup.TIME, S7UserDataSubfunction.SET_CLOCK)
|
|
1006
1014
|
logger.info(f"Set PLC datetime to {dt}")
|
|
1007
1015
|
return 0
|
|
1008
1016
|
|
|
@@ -1032,6 +1040,7 @@ class AsyncClient(ClientMixin):
|
|
|
1032
1040
|
|
|
1033
1041
|
request = self.protocol.build_read_szl_request(ssl_id, index)
|
|
1034
1042
|
response = await self._send_receive(request)
|
|
1043
|
+
self.protocol.check_userdata_response(response, S7UserDataGroup.SZL, S7UserDataSubfunction.READ_SZL)
|
|
1035
1044
|
|
|
1036
1045
|
data_info = response.get("data", {})
|
|
1037
1046
|
return_code = data_info.get("return_code", 0xFF) if isinstance(data_info, dict) else 0xFF
|
|
@@ -1058,6 +1067,7 @@ class AsyncClient(ClientMixin):
|
|
|
1058
1067
|
response_data = await conn.receive_data()
|
|
1059
1068
|
|
|
1060
1069
|
response = self.protocol.parse_response(response_data)
|
|
1070
|
+
self.protocol.check_userdata_response(response, S7UserDataGroup.SZL, S7UserDataSubfunction.READ_SZL)
|
|
1061
1071
|
|
|
1062
1072
|
data_info = response.get("data", {})
|
|
1063
1073
|
return_code = data_info.get("return_code", 0xFF) if isinstance(data_info, dict) else 0xFF
|
|
@@ -1188,7 +1198,7 @@ class AsyncClient(ClientMixin):
|
|
|
1188
1198
|
encoded = self.protocol.encode_password(password)
|
|
1189
1199
|
request = self.protocol.build_set_session_password_request(encoded)
|
|
1190
1200
|
response = await self._send_receive(request)
|
|
1191
|
-
self.protocol.check_userdata_response(response)
|
|
1201
|
+
self.protocol.check_userdata_response(response, S7UserDataGroup.SECURITY, S7UserDataSubfunction.SET_SESSION_PASSWORD)
|
|
1192
1202
|
logger.info("Session password set successfully")
|
|
1193
1203
|
return 0
|
|
1194
1204
|
|
|
@@ -1209,7 +1219,7 @@ class AsyncClient(ClientMixin):
|
|
|
1209
1219
|
|
|
1210
1220
|
request = self.protocol.build_clear_session_password_request()
|
|
1211
1221
|
response = await self._send_receive(request)
|
|
1212
|
-
self.protocol.check_userdata_response(response)
|
|
1222
|
+
self.protocol.check_userdata_response(response, S7UserDataGroup.SECURITY, S7UserDataSubfunction.CLEAR_SESSION_PASSWORD)
|
|
1213
1223
|
logger.info("Session password cleared successfully")
|
|
1214
1224
|
return 0
|
|
1215
1225
|
|