@@ -473,18 +473,29 @@ def getSpectrumData(self):
473473 """
474474 raise NotImplementedError ('You must implemented getSpectrumData for your subclass.' )
475475
476- def getSpectrum (self , integrationTime = None ):
476+ def getSpectrum (self , integrationTime = None , maxRequests = 4 , maxWait = 2.0 ):
477477 """ Obtain a spectrum from the spectrometer. This implies:
478478 1- changing the integration time if needed.
479479 2- requesting a spectrum,
480- 3- waiting until ready, then
480+ 3- waiting until ready, then
481481 4- actually retrieving and returning the data.
482-
482+
483+ The wait is bounded: at most `maxRequests` requests are issued, each
484+ awaited up to `maxWait` seconds. Rather than looping forever when the
485+ 'spectrum ready' flag never rises (a transient USB glitch can leave it
486+ stuck), SpectrumRequestTimeoutError is raised in bounded time. Transient
487+ USB errors raised by requestSpectrum()/isSpectrumReady() are absorbed
488+ and retried instead of propagating on the first hiccup.
489+
483490 Parameters
484491 ----------
485- integrationTime: int, default None
492+ integrationTime: int, default None
486493 integration time in milliseconds if not the currently configured
487494 time.
495+ maxRequests: int, default 4
496+ maximum number of spectrum requests before giving up.
497+ maxWait: float, default 2.0
498+ seconds to wait for the 'spectrum ready' flag after each request.
488499
489500 Returns
490501 -------
@@ -496,15 +507,22 @@ def getSpectrum(self, integrationTime=None):
496507 if integrationTime is not None :
497508 self .setIntegrationTime (integrationTime )
498509
499- self .requestSpectrum ()
500- timeOut = time .time () + 1
501- while not self .isSpectrumReady ():
502- time .sleep (0.001 )
503- if time .time () > timeOut :
504- self .requestSpectrum () # makes no sense, let's request another one
505- timeOut = time .time () + 1
506-
507- return self .getSpectrumData ()
510+ lastError = None
511+ for _ in range (maxRequests ):
512+ try :
513+ self .requestSpectrum ()
514+ deadline = time .time () + maxWait
515+ while time .time () < deadline :
516+ if self .isSpectrumReady ():
517+ return self .getSpectrumData ()
518+ time .sleep (0.001 )
519+ except usb .core .USBError as err : # includes USBTimeoutError
520+ lastError = err
521+ time .sleep (0.02 )
522+
523+ raise SpectrumRequestTimeoutError (
524+ "Spectrum never became ready after {0} requests "
525+ "(last USB error: {1})" .format (maxRequests , lastError ))
508526
509527 def sendCommand (self , cmdBytes , payloadBytes = None ):
510528 """ Main entry point to write to the device in order to have
0 commit comments