@@ -91,6 +91,33 @@ def decorator(self, *args, **kwargs):
9191 return decorator
9292
9393
94+ def i2c_lock (fn ):
95+ """Attempt to get a lock on the I2C bus used for Notecard comms."""
96+
97+ def decorator (self , * args , ** kwargs ):
98+ retries = 5
99+ while use_i2c_lock and retries != 0 :
100+ if self .i2c .try_lock ():
101+ break
102+
103+ retries -= 1
104+ # Try again after 100 ms.
105+ time .sleep (.1 )
106+
107+ if retries == 0 :
108+ raise Exception ('Failed to acquire I2C lock.' )
109+
110+ try :
111+ ret = fn (self , * args , ** kwargs )
112+ finally :
113+ if use_i2c_lock :
114+ self .i2c .unlock ()
115+
116+ return ret
117+
118+ return decorator
119+
120+
94121class Notecard :
95122 """Base Notecard class.
96123
@@ -330,79 +357,49 @@ def _receive(self, timeout_secs, chunk_delay_secs, wait_for_newline):
330357
331358 return read_data
332359
333- def Command (self , req ):
334- """Perform a Notecard command and exit with no response."""
360+ def _transmit (self , req ):
335361 req = self ._preprocess_req (req )
336- if 'cmd' not in req :
337- raise Exception ("Please use 'cmd' instead of 'req'" )
338-
339362 req_json = _prepare_request (req , self ._debug )
340363
341- while not self .lock ():
342- pass
343-
344364 try :
345365 transaction_timeout_secs = 30
346366 if self ._transaction_manager :
347367 self ._transaction_manager .start (transaction_timeout_secs )
348368
349369 self ._send_payload (req_json )
350370 finally :
351- self .unlock ()
352371 if self ._transaction_manager :
353372 self ._transaction_manager .stop ()
354373
355- def Transaction (self , req ):
356- """Perform a Notecard transaction and return the result."""
357- req = self ._preprocess_req (req )
358-
359- req_json = _prepare_request (req , self ._debug )
360- rsp_json = ""
361-
362- while not self .lock ():
363- pass
374+ @i2c_lock
375+ def Command (self , req ):
376+ """Perform a Notecard command and exit with no response."""
377+ if 'cmd' not in req :
378+ raise Exception ("Please use 'cmd' instead of 'req'" )
364379
365- try :
366- transaction_timeout_secs = 30
367- if self ._transaction_manager :
368- self ._transaction_manager .start (transaction_timeout_secs )
380+ self ._transmit (req )
369381
370- self ._send_payload (req_json )
382+ @i2c_lock
383+ def Transaction (self , req ):
384+ """Perform a Notecard transaction and return the result."""
385+ self ._transmit (req )
371386
372- read_data = self ._receive (transaction_timeout_secs , 0.05 , True )
373- rsp_json = "" .join (map (chr , read_data ))
374- finally :
375- self .unlock ()
376- if self ._transaction_manager :
377- self ._transaction_manager .stop ()
387+ read_data = self ._receive (transaction_timeout_secs , 0.05 , True )
388+ rsp_json = "" .join (map (chr , read_data ))
378389
379390 if self ._debug :
380391 print (rsp_json .rstrip ())
381392
382393 return json .loads (rsp_json )
383394
395+
396+ @i2c_lock
384397 def Reset (self ):
385398 """Reset the Notecard."""
386- while not self .lock ():
387- pass
388399
389- try :
390- # Read from the Notecard until there's nothing left to read.
391- self ._receive (0 , .001 , False )
392- finally :
393- self .unlock ()
394-
395- def lock (self ):
396- """Lock the I2C port so the host can interact with the Notecard."""
397- if use_i2c_lock :
398- return self .i2c .try_lock ()
399- return True
400-
401- def unlock (self ):
402- """Unlock the I2C port."""
403- if use_i2c_lock :
404- return self .i2c .unlock ()
405- return True
400+ # Read from the Notecard until there's nothing left to read.
401+ self ._receive (0 , .001 , False )
402+
406403
407404 def __init__ (self , i2c , address , max_transfer , debug = False ):
408405 """Initialize the Notecard before a reset."""
0 commit comments