1212from canopen .sdo .constants import *
1313from canopen .sdo .exceptions import *
1414from canopen .utils import pretty_index
15+ from canopen .async_guard import ensure_not_async
1516
1617
1718logger = logging .getLogger (__name__ )
@@ -49,9 +50,11 @@ def __init__(self, rx_cobid, tx_cobid, od):
4950 def on_response (self , can_id , data , timestamp ):
5051 self .responses .put_nowait (bytes (data ))
5152
53+ @ensure_not_async # NOTE: Safeguard for accidental async use
5254 def send_request (self , request ):
5355 retries_left = self .MAX_RETRIES
5456 if self .PAUSE_BEFORE_SEND :
57+ # NOTE: Blocking
5558 time .sleep (self .PAUSE_BEFORE_SEND )
5659 while True :
5760 try :
@@ -63,6 +66,7 @@ def send_request(self, request):
6366 raise
6467 logger .info (str (e ))
6568 if self .RETRY_DELAY :
69+ # NOTE: Blocking
6670 time .sleep (self .RETRY_DELAY )
6771 else :
6872 break
@@ -108,6 +112,7 @@ def abort(self, abort_code=0x08000000):
108112 self .send_request (request )
109113 logger .error ("Transfer aborted by client with code 0x%08X" , abort_code )
110114
115+ @ensure_not_async # NOTE: Safeguard for accidental async use
111116 def upload (self , index : int , subindex : int ) -> bytes :
112117 """May be called to make a read operation without an Object Dictionary.
113118
@@ -126,7 +131,9 @@ def upload(self, index: int, subindex: int) -> bytes:
126131 with self .open (index , subindex , buffering = 0 ) as fp :
127132 response_size = fp .size
128133 data = fp .read ()
134+ return self .truncate_data (index , subindex , data , response_size )
129135
136+ def truncate_data (self , index : int , subindex : int , data : bytes , size : int ) -> bytes :
130137 # If size is available through variable in OD, then use the smaller of the two sizes.
131138 # Some devices send U32/I32 even if variable is smaller in OD
132139 var = self .od .get_variable (index , subindex )
@@ -137,7 +144,7 @@ def upload(self, index: int, subindex: int) -> bytes:
137144 if var .data_type not in objectdictionary .DATA_TYPES :
138145 # Get the size in bytes for this variable
139146 var_size = len (var ) // 8
140- if response_size is None or var_size < response_size :
147+ if size is None or var_size < size :
141148 # Truncate the data to specified size
142149 data = data [0 :var_size ]
143150 return data
@@ -152,8 +159,16 @@ async def aupload(self, index: int, subindex: int) -> bytes:
152159 # upload -> open -> ReadableStream -> request_reponse -> send_request -> network.send_message
153160 # recv -> on_reponse -> queue.put
154161 # request_reponse -> read_response -> queue.get
155- return await asyncio .to_thread (self .upload , index , subindex )
162+ def _upload ():
163+ with self ._open (index , subindex , buffering = 0 ) as fp :
164+ response_size = fp .size
165+ data = fp .read ()
166+ return data , response_size
156167
168+ data , response_size = await asyncio .to_thread (_upload )
169+ return self .truncate_data (index , subindex , data , response_size )
170+
171+ @ensure_not_async # NOTE: Safeguard for accidental async use
157172 def download (
158173 self ,
159174 index : int ,
@@ -193,10 +208,22 @@ async def adownload(
193208 """
194209 async with self .lock : # Ensure only one active SDO request per channel
195210 # Deferring to thread because there are sleeps in the call chain
196- return await asyncio .to_thread (self .download , index , subindex , data , force_segment )
197211
212+ def _download ():
213+ with self ._open (index , subindex , "wb" , buffering = 7 , size = len (data ),
214+ force_segment = force_segment ) as fp :
215+ fp .write (data )
216+
217+ return await asyncio .to_thread (_download )
218+
219+ @ensure_not_async # NOTE: Safeguard for accidental async use
198220 def open (self , index , subindex = 0 , mode = "rb" , encoding = "ascii" ,
199221 buffering = 1024 , size = None , block_transfer = False , force_segment = False , request_crc_support = True ):
222+ return self ._open (index , subindex , mode , encoding , buffering ,
223+ size , block_transfer , force_segment , request_crc_support )
224+
225+ def _open (self , index , subindex = 0 , mode = "rb" , encoding = "ascii" ,
226+ buffering = 1024 , size = None , block_transfer = False , force_segment = False , request_crc_support = True ):
200227 """Open the data stream as a file like object.
201228
202229 :param int index:
0 commit comments