From 741cc1c8dbb454b71df52cfb4961ab27cba45f4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=85ke=20Forslund?= Date: Sat, 26 Oct 2019 09:24:33 +0200 Subject: [PATCH 1/3] Fallback to default STT if loading fails If a STT backend fails to load log the exception and fallback to the MycroftSTT. --- mycroft/stt/__init__.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/mycroft/stt/__init__.py b/mycroft/stt/__init__.py index b1a7a5f806..9a6a93ea63 100644 --- a/mycroft/stt/__init__.py +++ b/mycroft/stt/__init__.py @@ -497,7 +497,17 @@ class STTFactory: @staticmethod def create(): - config = Configuration.get().get("stt", {}) - module = config.get("module", "mycroft") - clazz = STTFactory.CLASSES.get(module) - return clazz() + try: + config = Configuration.get().get("stt", {}) + module = config.get("module", "mycroft") + clazz = STTFactory.CLASSES.get(module) + return clazz() + except Exception as e: + # The STT backend failed to start. Report it and fall back to + # default. + LOG.exception('The selected STT backend could not be loaded, ' + 'falling back to default...') + if module != 'mycroft': + return MycroftSTT() + else: + raise From 8bdeddb9658fb92f41487b7702ca255724a7b5ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=85ke=20Forslund?= Date: Sat, 26 Oct 2019 09:30:45 +0200 Subject: [PATCH 2/3] Catch and log errors starting up the speech client --- mycroft/client/speech/listener.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/mycroft/client/speech/listener.py b/mycroft/client/speech/listener.py index 2d85ae05e4..7b8dfe9f27 100644 --- a/mycroft/client/speech/listener.py +++ b/mycroft/client/speech/listener.py @@ -402,7 +402,18 @@ class RecognizerLoop(EventEmitter): self.state.sleeping = False def run(self): - self.start_async() + """Start and reload mic and STT handling threads as needed. + + Wait for KeyboardInterrupt and shutdown cleanly. + """ + try: + self.start_async() + except Exception: + LOG.exception('Starting producer/consumer threads for listener ' + 'failed.') + return + + # Handle reload of consumer / producer if config changes while self.state.running: try: time.sleep(1) From 8d4413db9c842b4eaa788e8c7c46f328a1aa8a68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=85ke=20Forslund?= Date: Sat, 26 Oct 2019 09:35:03 +0200 Subject: [PATCH 3/3] Update account id fetching Account ID will now be refetched if invalid the first time. This also adds some general exception handling to avoid client crashing due to the servers invalid 204 response. --- mycroft/client/speech/mic.py | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/mycroft/client/speech/mic.py b/mycroft/client/speech/mic.py index d690093a40..db0e83f9d4 100644 --- a/mycroft/client/speech/mic.py +++ b/mycroft/client/speech/mic.py @@ -244,10 +244,25 @@ class ResponsiveRecognizer(speech_recognition.Recognizer): self.TEST_WW_SEC = num_phonemes * len_phoneme self.SAVED_WW_SEC = max(3, self.TEST_WW_SEC) - try: - self.account_id = DeviceApi().get()['user']['uuid'] - except (requests.RequestException, AttributeError): - self.account_id = '0' + self._account_id = None + + @property + def account_id(self): + """Fetch account from backend when needed. + + If an error occurs it's handled and a temporary value is returned. + When a value is received it will be cached until next start. + """ + if not self._account_id: + try: + self._account_id = DeviceApi().get()['user']['uuid'] + except (requests.RequestException, AttributeError): + pass # These are expected and won't be reported + except Exception as e: + LOG.debug('Unhandled exception while determining device_id, ' + 'Error: {}'.format(repr(e))) + + return self._account_id or '0' def record_sound_chunk(self, source): return source.stream.read(source.CHUNK, self.overflow_exc)