def main(): parser = ArgumentParser() subparsers = parser.add_subparsers(dest='action') subparsers.add_parser('setup') args = parser.parse_args() if args.action == 'setup': import mycroft.util from mycroft.util.log import PrintLogger, Level mycroft.util.log = PrintLogger(Level.INFO) mycroft.util.log._get_prefix = lambda level, offset: '' from mycroft.util import log from mycroft.root import Root if args.action == 'setup': Root(None, blacklist=['skills']) return rt = Root() if rt.config['use_server'] and rt.device_info: rt.config.load_remote() rt.intent.context.compile() rt.interfaces.all.run(gp_daemon=True) try: rt.main_thread.wait() except KeyboardInterrupt: pass log.info('Quiting...') sleep(0.1) print()
def __init__(self, rt): ServicePlugin.__init__(self, rt) sys.path.append(self.rt.paths.skills) def inject_rt(cls): cls.rt = rt log.info('Loading skills...') GroupPlugin.__init__(self, gp_alter_class=inject_rt, gp_blacklist=self.config['blacklist'], gp_timeout=10.0, gp_daemon=True) for name, thread in self._init_threads.items(): if thread.is_alive(): log.warning('Skill init method taking too long for:', name) log.info('Finished loading skills.') # The watch manager stores the watches and provides operations on watches wm = pyinotify.WatchManager() mask = pyinotify.IN_MODIFY | pyinotify.IN_CREATE | pyinotify.IN_DELETE | pyinotify.IN_MOVED_TO skills_dir = self.rt.paths.skills handler = EventHandler(self, skills_dir) notifier = pyinotify.ThreadedNotifier(wm, handler) notifier.daemon = True wm.add_watch(skills_dir, mask, rec=True, auto_add=True) notifier.start() self.git_repo = self.create_git_repo()
def _run_prehandlers(self, matches: List[IntentMatch]) -> List[Package]: """Iterate through matches, executing prehandlers""" package_generators = [] for match in matches: def callback(match=match): data = self.intent_data[match.intent_id] prehandler = data.get('prehandler', self.default_prehandler) package = self.rt.package(match=match) package.skill = self.intent_to_skill[match.intent_id] return self._run_handler(prehandler, package) package_generators.append(callback) for package in run_parallel(package_generators, filter_none=True, label='prehandler'): match = package.match log.info(str(match.intent_id) + ':', str(match.confidence)) log.debug('\tConfidence:', package.confidence) if match.confidence is not None: package.confidence = sqrt(package.confidence * match.confidence) yield package
def reload(self, folder_name): log.debug('Reloading', folder_name + '...') skill_name = folder_name.replace(self._suffix_, '') if skill_name in self._plugins: safe_run(self._plugins[skill_name]._unload, label='Skill unload') del self._plugins[skill_name] if skill_name in self._classes: self.rt.intent.remove_skill(skill_name) del self._classes[skill_name] if not isfile(join(self.rt.paths.skills, folder_name, 'skill.py')): return cls = self.load_skill_class(folder_name) if not cls: return cls.rt = self.rt self._classes[skill_name] = cls def init(): self._plugins[skill_name] = cls() return True if safe_run( init, label='Reloading ' + skill_name, custom_exception=NotImplementedError, custom_handler=lambda e, l: log.info(l + ': Skipping disabled plugin') ): self.rt.intent.context.compile() log.info('Reloaded', folder_name)
def _get_transcription(self, recording): utterance = '' try: utterance = self.stt.transcribe(recording) except ValueError: log.info('Found no words in audio') except RequestException: log.exception('Speech Client') else: log.info('Utterance: ' + utterance) return utterance
def __init__(self, rt): # type: (Root) -> None self.rt = rt if self._package_struct: if 'package' not in self.rt: log.warning('Package struct for module loaded before package:', self._plugin_path) else: self.rt.package.add_struct(self._package_struct) if not self._plugin_path and self._config: print('PLUGIN_PATH:', self._plugin_path, self._attr_name, self._config, self) raise RuntimeError( 'Cannot set _config for non-dynamically loaded class {}'. format(self.__class__.__name__)) if 'config' in rt and self._plugin_path: if self._root_config: rt.config.inject(self._root_config) if self._config: rt.config.inject(self._config, self._plugin_path) self.config = {} rt.config.on_change(self._plugin_path, self.on_config_change) self.on_config_change(rt.config.get_path(self._plugin_path)) else: self.config = {} if 'config' in rt and self._required_attributes: for required_attribute in self._required_attributes: if required_attribute not in self.rt.config['platform'][ 'attributes']: raise NotImplementedError('Missing attribute: ' + required_attribute) if 'plugin_versions' in rt: old_version = rt.plugin_versions.get(self._plugin_path) if old_version != self.__version__: if self.setup.__func__ is not BasePlugin.setup: log.info( 'Running {}.setup() to upgrade from {} to {}'.format( self.__class__.__name__, old_version, self.__version__)) self.setup() rt.plugin_versions[self._plugin_path] = self.__version__
def _try_run_packages(self, packages: List[Package]) -> Union[Package, None]: """Iterates through packages, executing handlers until one succeeds""" while len(packages) > 0: package = max(packages, key=lambda x: x.confidence) intent_id = package.match.intent_id del packages[packages.index(package)] log.info('Selected intent', intent_id, package.confidence) try: handler = self.intent_data[intent_id].get( 'handler', self.default_handler) return self._run_handler(handler, package) except Exception: log.exception(intent_id, 'callback') return None
def __init__(self, rt): super().__init__(rt) sys.stdout = StreamHandler(lambda x: log.info(x, stack_offset=3)) sys.stderr = StreamHandler(lambda x: log.error(x, stack_offset=3)) self.response_event = Event() self.response_event.set() self.prompt = self.config['prompt']
def record_phrase(self) -> AudioData: """Records until a period of silence""" log.info('Recording...') raw_audio = b'\0' * self.sample_width self.integral = 0 self.noise_level = 0 total_sec = 0 while total_sec < self.recording_timeout: self._check_intercept() chunk = self.stream.read(self.chunk_size) raw_audio += chunk total_sec += self.chunk_sec energy = self._calc_energy(chunk) self.update_energy(energy) if self.integral > self.required_integral and self.noise_level == 0: break log.info('Done recording.') return AudioData(raw_audio, self.sample_rate, self.sample_width)
def calc_package(self, query: str) -> Package: """ Find the best intent and run the handler to find the result Args: query: input sentence Returns: package: object containing display data from skill """ log.info('Query:', query) query = query.strip().lower() matches = self.context.calc_intents(query) matches = [i for i in matches if i.confidence > 0.5] packages = self._run_prehandlers(matches) result_package = self._try_run_packages( [i for i in packages if i.confidence > 0.5]) if result_package: return result_package log.info('No intents matched. Falling back.') matches = [ IntentMatch(intent_id, confidence=None, query=query) for intent_id in self.fallback_intents ] packages = self._run_prehandlers(matches) result_package = self._try_run_packages(list(packages)) if result_package: return result_package log.info('All fallbacks failed.') return self.rt.package()
def _load_classes(self, package, suffix, blacklist): """ Looks in the skill folder and loads the CamelCase equivalent class of the snake case folder This class should be inside the skill.py file. Example: skills/ time_skill/ skill.py - class TimeSkill(MycroftSkill): weather_skill/ skill.py - class WeatherSkill(MycroftSkill): """ log.info('Loading classes...') self.setup() classes = {} folder_names, invalid_names = listdir(self.rt.paths.skills), [] for folder_name in folder_names: if not folder_name.endswith(suffix) or \ not isfile(join(self.rt.paths.skills, folder_name, 'skill.py')): invalid_names.append(folder_name) continue attr_name = folder_name[:-len(suffix)] if attr_name in blacklist: continue cls = self.load_skill_class(folder_name) if not cls: continue classes[attr_name] = cls log.info('Skipped folders:', ', '.join(invalid_names)) return classes
def func(*args, **kwargs): def create_plugin(*args, **kwargs): new_cls = (alter_class(cls) or cls) if alter_class else cls instance = new_cls(*args, **kwargs) self._plugins[self._make_name(new_cls)] = instance return instance plugin = safe_run(create_plugin, args=args, kwargs=kwargs, label='Loading ' + cls._attr_name + self._suffix_, custom_exception=NotImplementedError, custom_handler=lambda e, l: log.info( l + ': Skipping disabled plugin')) if not plugin: log.debug('Unloading partially loaded plugin:', cls._attr_name + self._suffix_) self._on_partial_load(cls._attr_name) return plugin
def on_activation(self): """Called by child classes""" log.info('Heard wake word!') self._has_activated = True
def compile(self): log.info('Training...') self.container.train() log.info('Training complete!')