def ensure_directory_exists(directory, domain=None): """ Create a directory and give access rights to all Args: domain (str): The IPC domain. Basically a subdirectory to prevent overlapping signal filenames. Returns: str: a path to the directory """ if domain: directory = os.path.join(directory, domain) directory = os.path.normpath(directory) if not os.path.isdir(directory): try: save = os.umask(0) os.makedirs(directory, 0o777) # give everyone rights to r/w here except OSError: LOG.warning("Failed to create: " + directory) pass finally: os.umask(save) return directory
def read(self, size, of_exc=False): """ Read data from stream. Arguments: size (int): Number of bytes to read of_exc (bool): flag determining if the audio producer thread should throw IOError at overflows. Returns: Data read from device """ frames = collections.deque() remaining = size while remaining > 0: to_read = min(self.wrapped_stream.get_read_available(), remaining) if to_read == 0: sleep(.01) continue result = self.wrapped_stream.read(to_read, exception_on_overflow=of_exc) frames.append(result) remaining -= to_read if self.muted: return self.muted_buffer input_latency = self.wrapped_stream.get_input_latency() if input_latency > 0.2: LOG.warning("High input latency: %f" % input_latency) audio = b"".join(list(frames)) return audio
def process(self, audio): SessionManager.touch() payload = { 'utterance': self.wakeword_recognizer.key_phrase, 'session': SessionManager.get().session_id, } self.emitter.emit("recognizer_loop:wakeword", payload) if self._audio_length(audio) < self.MIN_AUDIO_SIZE: LOG.warning("Audio too short to be processed") else: stopwatch = Stopwatch() with stopwatch: transcription = self.transcribe(audio) if transcription: ident = str(stopwatch.timestamp) + str(hash(transcription)) # STT succeeded, send the transcribed speech on for processing payload = { 'utterances': [transcription], 'lang': self.stt.lang, 'session': SessionManager.get().session_id, 'ident': ident } self.emitter.emit("recognizer_loop:utterance", payload) self.metrics.attr('utterances', [transcription]) else: ident = str(stopwatch.timestamp) # Report timing metrics report_timing(ident, 'stt', stopwatch, { 'transcription': transcription, 'stt': self.stt.__class__.__name__ })
def transcribe(self, audio): try: # Invoke the STT engine on the audio clip text = self.stt.execute(audio).lower().strip() LOG.debug("STT: " + text) return text except sr.RequestError as e: LOG.error("Could not request Speech Recognition {0}".format(e)) except ConnectionError as e: LOG.error("Connection Error: {0}".format(e)) self.emitter.emit("recognizer_loop:no_internet") except HTTPError as e: if e.response.status_code == 401: LOG.warning("Access Denied at owo.ai") return "pair my device" # phrase to start the pairing process else: LOG.error(e.__class__.__name__ + ': ' + str(e)) except RequestException as e: LOG.error(e.__class__.__name__ + ': ' + str(e)) except Exception as e: self.emitter.emit('recognizer_loop:speech.recognition.unknown') if isinstance(e, IndexError): LOG.info('no words were transcribed') else: LOG.error(e) LOG.error("Speech Recognition could not understand audio") return None if connected(): dialog_name = 'backend.down' else: dialog_name = 'not connected to the internet' self.emitter.emit('speak', {'utterance': dialog.get(dialog_name)})
def load_skill(skill_descriptor, bus, skill_id, BLACKLISTED_SKILLS=None): """ Load skill from skill descriptor. Args: skill_descriptor: descriptor of skill to load bus: OwO messagebus connection skill_id: id number for skill Returns: OwOSkill: the loaded skill or None on failure """ BLACKLISTED_SKILLS = BLACKLISTED_SKILLS or [] path = skill_descriptor["path"] name = basename(path) LOG.info("ATTEMPTING TO LOAD SKILL: {} with ID {}".format(name, skill_id)) if name in BLACKLISTED_SKILLS: LOG.info("SKILL IS BLACKLISTED " + name) return None main_file = join(path, MainModule + '.py') try: with open(main_file, 'rb') as fp: skill_module = imp.load_module(name.replace('.', '_'), fp, main_file, ('.py', 'rb', imp.PY_SOURCE)) if (hasattr(skill_module, 'create_skill') and callable(skill_module.create_skill)): # v2 skills framework skill = skill_module.create_skill() skill.settings.allow_overwrite = True skill.settings.load_skill_settings_from_file() skill.bind(bus) try: skill.skill_id = skill_id skill.load_data_files(path) # Set up intent handlers skill._register_decorated() skill.initialize() except Exception as e: # If an exception occurs, make sure to clean up the skill skill.default_shutdown() raise e LOG.info("Loaded " + name) # The very first time a skill is run, speak the intro first_run = skill.settings.get("__OwO_skill_firstrun", True) if first_run: LOG.info("First run of " + name) skill.settings["__OwO_skill_firstrun"] = False skill.settings.store() intro = skill.get_intro_message() if intro: skill.speak(intro) return skill else: LOG.warning("Module {} does not appear to be skill".format(name)) except Exception: LOG.exception("Failed to load skill: " + name) return None
def remove_fallback(cls, handler_to_del): """ Remove a fallback handler Args: handler_to_del: reference to handler """ for priority, handler in cls.fallback_handlers.items(): if handler == handler_to_del: del cls.fallback_handlers[priority] return LOG.warning('Could not remove fallback!')
def _register_object(self, message, object_name, register_func): file_name = message.data['file_name'] name = message.data['name'] LOG.debug('Registering Padatious ' + object_name + ': ' + name) if not isfile(file_name): LOG.warning('Could not find file ' + file_name) return register_func(name, file_name) self.train_time = get_time() + self.train_delay self.wait_and_train()
def read(self): while self.alive: try: data = self.serial.readline()[:-2] if data: try: data_str = data.decode() except UnicodeError as e: data_str = data.decode('utf-8', errors='replace') LOG.warning('Invalid characters in response from ' ' enclosure: {}'.format(repr(e))) self.process(data_str) except Exception as e: LOG.error("Reading error: {0}".format(e))
def emit(self, message): if not self.connected_event.wait(10): if not self.started_running: raise ValueError('You must execute run_forever() ' 'before emitting messages') self.connected_event.wait() try: if hasattr(message, 'serialize'): self.client.send(message.serialize()) else: self.client.send(json.dumps(message.__dict__)) except WebSocketConnectionClosedException: LOG.warning('Could not send {} message because connection ' 'has been closed'.format(message.type))
def install_or_update(skill): """Install missing defaults and update existing skills""" if skills_data.get(skill.name, {}).get('beta'): skill.sha = 'HEAD' if skill.is_local: skill.update() if skill.name not in installed_skills: skill.update_deps() elif skill.name in default_names: try: skill.install() except Exception: if skill.name in default_names: LOG.warning('Failed to install default skill: ' + skill.name) nonlocal default_skill_errored default_skill_errored = True raise installed_skills.add(skill.name)
def __init__(self, key_phrase="hey OwO", config=None, lang="en-us"): super(SnowboyHotWord, self).__init__(key_phrase, config, lang) # Hotword module imports from snowboydecoder import HotwordDetector # Hotword module config module = self.config.get("module") if module != "snowboy": LOG.warning(module + " module does not match with Hotword class " "snowboy") # Hotword params models = self.config.get("models", {}) paths = [] for key in models: paths.append(models[key]) sensitivity = self.config.get("sensitivity", 0.5) self.snowboy = HotwordDetector(paths, sensitivity=[sensitivity] * len(paths)) self.lang = str(lang).lower() self.key_phrase = str(key_phrase).lower()
def handler(message): # indicate fallback handling start bus.emit( message.reply("owo.skill.handler.start", data={'handler': "fallback"})) stopwatch = Stopwatch() handler_name = None with stopwatch: for _, handler in sorted(cls.fallback_handlers.items(), key=operator.itemgetter(0)): try: if handler(message): # indicate completion handler_name = get_handler_name(handler) bus.emit( message.reply('owo.skill.handler.complete', data={ 'handler': "fallback", "fallback_handler": handler_name })) break except Exception: LOG.exception('Exception in fallback.') else: # No fallback could handle the utterance bus.emit(message.reply('complete_intent_failure')) warning = "No fallback could handle intent." LOG.warning(warning) # indicate completion with exception bus.emit( message.reply('owo.skill.handler.complete', data={ 'handler': "fallback", 'exception': warning })) # Send timing metric if message.context and message.context['ident']: ident = message.context['ident'] report_timing(ident, 'fallback_handler', stopwatch, {'handler': handler_name})
def load(self, dialog_dir): """ Load all dialog files within the specified directory. Args: dialog_dir (str): directory that contains dialog files Returns: a loaded instance of a dialog renderer """ directory = Path(dialog_dir) if not directory.exists() or not directory.is_dir(): LOG.warning("No dialog files found: " + dialog_dir) return self.__renderer for path, _, files in os.walk(str(directory)): for f in files: if f.endswith(".dialog"): self.__renderer.load_template_file( f.replace('.dialog', ''), join(path, f)) return self.__renderer
def on_error(self, ws, error): """ On error start trying to reconnect to the websocket. """ if isinstance(error, WebSocketConnectionClosedException): LOG.warning('Could not send message because connection has closed') else: LOG.exception('=== ' + repr(error) + ' ===') try: self.emitter.emit('error', error) if self.client.keep_running: self.client.close() except Exception as e: LOG.error('Exception closing websocket: ' + repr(e)) LOG.warning("WS Client will reconnect in %d seconds." % self.retry) time.sleep(self.retry) self.retry = min(self.retry * 2, 60) try: self.client = self.create_client() self.run_forever() except WebSocketException: pass
def execute(self, audio, language=None): LOG.warning("WITSTT language should be configured at wit.ai settings.") return self.recognizer.recognize_wit(audio, self.token)
def remove_git_locks(self): """If git gets killed from an abrupt shutdown it leaves lock files""" for i in glob(join(self.msm.skills_dir, '*/.git/index.lock')): LOG.warning('Found and removed git lock file: ' + i) os.remove(i)
def _load_or_reload_skill(self, skill_path): """ Check if unloaded skill or changed skill needs reloading and perform loading if necessary. Returns True if the skill was loaded/reloaded """ skill_path = skill_path.rstrip('/') skill = self.loaded_skills.setdefault(skill_path, {}) skill.update({"id": basename(skill_path), "path": skill_path}) # check if folder is a skill (must have __init__.py) if not MainModule + ".py" in os.listdir(skill_path): return False # getting the newest modified date of skill modified = _get_last_modified_date(skill_path) last_mod = skill.get("last_modified", 0) # checking if skill is loaded and hasn't been modified on disk if skill.get("loaded") and modified <= last_mod: return False # Nothing to do! # check if skill was modified elif skill.get("instance") and modified > last_mod: # check if skill has been blocked from reloading if (not skill["instance"].reload_skill or not skill.get('active', True)): return False LOG.debug("Reloading Skill: " + basename(skill_path)) # removing listeners and stopping threads try: skill["instance"].default_shutdown() except Exception: LOG.exception("An error occured while shutting down {}".format( skill["instance"].name)) if DEBUG: gc.collect() # Collect garbage to remove false references # Remove two local references that are known refs = sys.getrefcount(skill["instance"]) - 2 if refs > 0: msg = ("After shutdown of {} there are still " "{} references remaining. The skill " "won't be cleaned from memory.") LOG.warning(msg.format(skill['instance'].name, refs)) del skill["instance"] self.bus.emit( Message("owo.skills.shutdown", { "path": skill_path, "id": skill["id"] })) skill["loaded"] = True desc = create_skill_descriptor(skill_path) skill["instance"] = load_skill(desc, self.bus, skill["id"], BLACKLISTED_SKILLS) skill["last_modified"] = modified if skill['instance'] is not None: self.bus.emit( Message( 'owo.skills.loaded', { 'path': skill_path, 'id': skill['id'], 'name': skill['instance'].name, 'modified': modified })) return True else: self.bus.emit( Message('owo.skills.loading_failure', { 'path': skill_path, 'id': skill['id'] })) return False
def test_logging(): LOG.debug('testing debug') LOG.info('testing info') LOG.warning('testing warning') LOG.error('testing error') LOG('testing custom').debug('test')
def remove(self, event_name, func): try: if event_name in self.emitter._events: LOG.debug("Removing found '" + str(event_name) + "'") else: LOG.debug("Not able to find '" + str(event_name) + "'") self.emitter.remove_listener(event_name, func) except ValueError as e: LOG.warning('Failed to remove event {}: {}'.format( event_name, str(func))) for line in traceback.format_stack(): LOG.warning(line.strip()) if event_name in self.emitter._events: LOG.debug("Removing found '" + str(event_name) + "'") else: LOG.debug("Not able to find '" + str(event_name) + "'") LOG.warning("Existing events: " + str(self.emitter._events)) for evt in self.emitter._events: LOG.warning(" " + str(evt)) LOG.warning(" " + str(self.emitter._events[evt])) if event_name in self.emitter._events: LOG.debug("Removing found '" + str(event_name) + "'") else: LOG.debug("Not able to find '" + str(event_name) + "'") LOG.warning('----- End dump -----')