Exemple #1
0
 def validate_connection(self):
     try:
         subprocess.call([BIN, '--version'])
     except:
         LOG.info("Failed to find mimic at: " + BIN)
         raise Exception(
             'Mimic was not found. Run install-mimic.sh to install it.')
Exemple #2
0
    def __init__(self, cache=None):
        super(RemoteConf, self).__init__(None)

        cache = cache or '/opt/mycroft/web_config_cache.json'

        try:
            # Here to avoid cyclic import
            from mycroft.api import DeviceApi
            api = DeviceApi()
            setting = api.get_settings()
            location = api.get_location()
            if location:
                setting["location"] = location
            # Remove server specific entries
            config = {}
            translate_remote(config, setting)
            for key in config:
                self.__setitem__(key, config[key])
            self.store(cache)

        except HTTPError as e:
            LOG.error("HTTPError fetching remote configuration: %s" %
                      e.response.status_code)
            self.load_local(cache)

        except Exception as e:
            LOG.error("Failed to fetch remote configuration: %s" % repr(e),
                      exc_info=True)
            self.load_local(cache)
def _read_data():
    """ Writes the dictionary of state data from the IPC directory.
    Returns:
        dict: loaded state information
    """
    managerIPCDir = os.path.join(get_ipc_directory(), "managers")

    path = os.path.join(managerIPCDir, "disp_info")
    permission = "r" if os.path.isfile(path) else "w+"

    if permission == "w+" and os.path.isdir(managerIPCDir) is False:
        os.makedirs(managerIPCDir)

    data = {}
    try:
        with open(path, permission) as dispFile:

            if os.stat(str(dispFile.name)).st_size != 0:
                data = json.load(dispFile)

    except Exception as e:
        LOG.error(e)
        os.remove(path)
        _read_data()

    return data
 def _load():
     LOG.debug('Loading identity')
     try:
         with FileSystemAccess('identity').open('identity2.json', 'r') as f:
             IdentityManager.__identity = DeviceIdentity(**json.load(f))
     except Exception:
         IdentityManager.__identity = DeviceIdentity()
Exemple #5
0
def main():
    global ws
    global loop
    global config
    lock = PIDLock("voice")
    ws = WebsocketClient()
    config = Configuration.get()
    Configuration.init(ws)
    loop = RecognizerLoop()
    loop.on('recognizer_loop:utterance', handle_utterance)
    loop.on('speak', handle_speak)
    loop.on('recognizer_loop:record_begin', handle_record_begin)
    loop.on('recognizer_loop:wakeword', handle_wakeword)
    loop.on('recognizer_loop:record_end', handle_record_end)
    loop.on('recognizer_loop:no_internet', handle_no_internet)
    ws.on('open', handle_open)
    ws.on('complete_intent_failure', handle_complete_intent_failure)
    ws.on('recognizer_loop:sleep', handle_sleep)
    ws.on('recognizer_loop:wake_up', handle_wake_up)
    ws.on('mycroft.mic.mute', handle_mic_mute)
    ws.on('mycroft.mic.unmute', handle_mic_unmute)
    ws.on("mycroft.paired", handle_paired)
    ws.on('recognizer_loop:audio_output_start', handle_audio_start)
    ws.on('recognizer_loop:audio_output_end', handle_audio_end)
    ws.on('mycroft.stop', handle_stop)
    event_thread = Thread(target=connect)
    event_thread.setDaemon(True)
    event_thread.start()

    try:
        loop.run()
    except KeyboardInterrupt, e:
        LOG.exception(e)
        sys.exit()
Exemple #6
0
        def handler(message):
            # indicate fallback handling start
            ws.emit(Message("mycroft.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)
                            ws.emit(Message(
                                'mycroft.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
                    ws.emit(Message('complete_intent_failure'))
                    warning = "No fallback could handle intent."
                    LOG.warning(warning)
                    #  indicate completion with exception
                    ws.emit(Message('mycroft.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})
Exemple #7
0
def handle_utterance(event):
    LOG.info("Utterance: " + str(event['utterances']))
    context = {'client_name': 'mycroft_listener'}
    if 'ident' in event:
        ident = event.pop('ident')
        context['ident'] = ident
    bus.emit(Message('recognizer_loop:utterance', event, context))
 def during_download(self, first_run=False):
     LOG.info('Still downloading executable...')
     if first_run:  # TODO: Localize
         self._snd_msg('mouth.text=Updating listener...')
     if not self.download_complete:
         self.show_download_progress = Timer(30, self.during_download)
         self.show_download_progress.start()
    def load_module(module, hotword, config, lang, loop):
        LOG.info('Loading "{}" wake word via {}'.format(hotword, module))
        instance = None
        complete = Event()

        def initialize():
            nonlocal instance, complete
            try:
                clazz = HotWordFactory.CLASSES[module]
                instance = clazz(hotword, config, lang=lang)
            except TriggerReload:
                complete.set()
                sleep(0.5)
                loop.reload()
            except NoModelAvailable:
                LOG.warning('Could not found find model for {} on {}.'.format(
                    hotword, module
                ))
                instance = None
            except Exception:
                LOG.exception(
                    'Could not create hotword. Falling back to default.')
                instance = None
            complete.set()

        Thread(target=initialize, daemon=True).start()
        if not complete.wait(INIT_TIMEOUT):
            LOG.info('{} is taking too long to load'.format(module))
            complete.set()
        return instance
Exemple #10
0
    def __init__(self):
        super(GoVivaceSTT, self).__init__()
        self.default_uri = "https://services.govivace.com:49149/telephony"

        if not self.lang.startswith("en") and not self.lang.startswith("es"):
            LOG.error("GoVivace STT only supports english and spanish")
            raise NotImplementedError
Exemple #11
0
    def shutdown(self):
        for s in self.service:
            try:
                LOG.info('shutting down ' + s.name)
                s.shutdown()
            except Exception as e:
                LOG.error('shutdown of ' + s.name + ' failed: ' + repr(e))

        # remove listeners
        self.bus.remove('mycroft.audio.service.play', self._play)
        self.bus.remove('mycroft.audio.service.queue', self._queue)
        self.bus.remove('mycroft.audio.service.pause', self._pause)
        self.bus.remove('mycroft.audio.service.resume', self._resume)
        self.bus.remove('mycroft.audio.service.stop', self._stop)
        self.bus.remove('mycroft.audio.service.next', self._next)
        self.bus.remove('mycroft.audio.service.prev', self._prev)
        self.bus.remove('mycroft.audio.service.track_info', self._track_info)
        self.bus.remove('mycroft.audio.service.seek_forward',
                        self._seek_forward)
        self.bus.remove('mycroft.audio.service.seek_backward',
                        self._seek_backward)
        self.bus.remove('recognizer_loop:audio_output_start',
                        self._lower_volume)
        self.bus.remove('recognizer_loop:record_begin', self._lower_volume)
        self.bus.remove('recognizer_loop:audio_output_end',
                        self._restore_volume)
        self.bus.remove('recognizer_loop:record_end', self._restore_volume)
        self.bus.remove('mycroft.stop', self._stop)
Exemple #12
0
def main():
    global ws
    global config
    ws = WebsocketClient()
    Configuration.init(ws)
    config = Configuration.get()
    speech.init(ws)

    # Setup control of pulse audio
    setup_pulseaudio_handlers(config.get('Audio').get('pulseaudio'))

    def echo(message):
        try:
            _message = json.loads(message)
            if 'mycroft.audio.service' not in _message.get('type'):
                return
            message = json.dumps(_message)
        except:
            pass
        LOG.debug(message)

    LOG.info("Staring Audio Services")
    ws.on('message', echo)
    ws.once('open', load_services_callback)
    try:
        ws.run_forever()
    except KeyboardInterrupt, e:
        LOG.exception(e)
        speech.shutdown()
        sys.exit()
Exemple #13
0
    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 get(phrase, lang=None, context=None):
    """
    Looks up a resource file for the given phrase.  If no file
    is found, the requested phrase is returned as the string.
    This will use the default language for translations.

    Args:
        phrase (str): resource phrase to retrieve/translate
        lang (str): the language to use
        context (dict): values to be inserted into the string

    Returns:
        str: a randomized and/or translated version of the phrase
    """

    if not lang:
        from mycroft.configuration import Configuration
        lang = Configuration.get().get("lang")

    filename = "text/" + lang.lower() + "/" + phrase + ".dialog"
    template = resolve_resource_file(filename)
    if not template:
        LOG.debug("Resource file not found: " + filename)
        return phrase

    stache = MustacheDialogRenderer()
    stache.load_template_file("template", template)
    if not context:
        context = {}
    return stache.render("template", context)
Exemple #15
0
    def _poll_skill_settings(self):
        """ If identifier exists for this skill poll to backend to
            request settings and store it if it changes
            TODO: implement as websocket

            Args:
                hashed_meta (int): the hashed identifier
        """
        try:
            if not self._complete_intialization:
                self.initialize_remote_settings()
                if not self._complete_intialization:
                    return  # unable to do remote sync
            else:
                original = hash(str(self))
                self.update_remote()
                # Call callback for updated settings
                if self.changed_callback and hash(str(self)) != original:
                    self.changed_callback()

        except Exception as e:
            LOG.error(e)
            LOG.exception("")

        # this is used in core so do not delete!
        if self.is_alive:
            # continues to poll settings every 60 seconds
            t = Timer(60, self._poll_skill_settings)
            t.daemon = True
            t.start()
    def __init__(self, emitter):
        FallbackSkill.__init__(self)
        self.config = ConfigurationManager.get()['padatious']
        intent_cache = expanduser(self.config['intent_cache'])

        try:
            from padatious import IntentContainer
        except ImportError:
            LOG.error('Padatious not installed. Please re-run dev_setup.sh')
            try:
                call(['notify-send', 'Padatious not installed',
                      'Please run build_host_setup and dev_setup again'])
            except OSError:
                pass
            return
        ver = get_distribution('padatious').version
        if ver != PADATIOUS_VERSION:
            LOG.warning('Using Padatious v' + ver + '. Please re-run ' +
                        'dev_setup.sh to install ' + PADATIOUS_VERSION)

        self.container = IntentContainer(intent_cache)

        self.emitter = emitter
        self.emitter.on('padatious:register_intent', self.register_intent)
        self.emitter.on('padatious:register_entity', self.register_entity)
        self.register_fallback(self.handle_fallback, 5)
        self.finished_training_event = Event()

        self.train_delay = self.config['train_delay']
        self.train_time = get_time() + self.train_delay
        self.wait_and_train()
Exemple #17
0
    def _do_net_check(self):
        # TODO: This should live in the derived Enclosure, e.g. Enclosure_Mark1
        LOG.info("Checking internet connection")
        if not connected():  # and self.conn_monitor is None:
            if has_been_paired():
                # TODO: Enclosure/localization
                self.speak("This unit is not connected to the Internet. "
                           "Either plug in a network cable or hold the "
                           "button on top for two seconds, then select "
                           "wifi from the menu")
            else:
                # Begin the unit startup process, this is the first time it
                # is being run with factory defaults.

                # TODO: This logic should be in Enclosure_Mark1
                # TODO: Enclosure/localization

                # Don't listen to mic during this out-of-box experience
                self.ws.emit(Message("mycroft.mic.mute"))
                # Setup handler to unmute mic at the end of on boarding
                # i.e. after pairing is complete
                self.ws.once('mycroft.paired', self._handle_pairing_complete)

                self.speak(mycroft.dialog.get('mycroft.intro'))
                wait_while_speaking()
                time.sleep(2)  # a pause sounds better than just jumping in

                # Kick off wifi-setup automatically
                data = {'allow_timeout': False, 'lang': self.lang}
                self.ws.emit(Message('system.wifi.setup', data))
Exemple #18
0
    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__})
Exemple #19
0
    def _load_config(self):
        """
            Load configuration parameters from configuration
        """
        config = Configuration.get()
        self.config_core = config
        self._config_hash = hash(str(config))
        self.lang = config.get('lang')
        self.config = config.get('listener')
        rate = self.config.get('sample_rate')

        device_index = self.config.get('device_index')
        device_name = self.config.get('device_name')
        if not device_index and device_name:
            device_index = find_input_device(device_name)

        LOG.debug('Using microphone (None = default): '+str(device_index))

        self.microphone = MutableMicrophone(device_index, rate,
                                            mute=self.mute_calls > 0)
        # TODO:19.02 - channels are not been used, remove from mycroft.conf
        #              and from code.
        self.microphone.CHANNELS = self.config.get('channels')
        self.wakeword_recognizer = self.create_wake_word_recognizer()
        # TODO - localization
        self.wakeup_recognizer = self.create_wakeup_recognizer()
        self.responsive_recognizer = ResponsiveRecognizer(
            self.wakeword_recognizer)
        self.state = RecognizerLoopState()
Exemple #20
0
    def initialize(self):
        """
        Initialization function to be implemented by all Skills.

        Usually used to create intents rules and register them.
        """
        LOG.debug("No initialize function implemented")
Exemple #21
0
    def _poll_skill_settings(self):
        """ If identifier exists for this skill poll to backend to
            request settings and store it if it changes
            TODO: implement as websocket
        """
        original = hash(str(self))
        try:
            if not is_paired():
                pass
            elif not self._complete_intialization:
                self.initialize_remote_settings()
            else:
                self.update_remote()

        except Exception as e:
            LOG.exception('Failed to fetch skill settings: {}'.format(repr(e)))
        finally:
            # Call callback for updated settings
            if self._complete_intialization:
                if self.changed_callback and hash(str(self)) != original:
                    self.changed_callback()

        if self._poll_timer:
            self._poll_timer.cancel()

        if not self._is_alive:
            return

        # continues to poll settings every minute
        self._poll_timer = Timer(1 * 60, self._poll_skill_settings)
        self._poll_timer.daemon = True
        self._poll_timer.start()
Exemple #22
0
    def handle_converse_request(self, message):
        """ Check if the targeted skill id can handle conversation

        If supported, the conversation is invoked.
        """

        skill_id = int(message.data["skill_id"])
        utterances = message.data["utterances"]
        lang = message.data["lang"]

        # loop trough skills list and call converse for skill with skill_id
        for skill in self.loaded_skills:
            if self.loaded_skills[skill]["id"] == skill_id:
                try:
                    instance = self.loaded_skills[skill]["instance"]
                except BaseException:
                    LOG.error("converse requested but skill not loaded")
                    self.ws.emit(Message("skill.converse.response", {
                        "skill_id": 0, "result": False}))
                    return
                try:
                    result = instance.converse(utterances, lang)
                    self.ws.emit(Message("skill.converse.response", {
                        "skill_id": skill_id, "result": result}))
                    return
                except BaseException:
                    LOG.error(
                        "Converse method malformed for skill " + str(skill_id))
        self.ws.emit(Message("skill.converse.response",
                             {"skill_id": 0, "result": False}))
Exemple #23
0
 def on_gui_show_page(self, message):
     try:
         page, namespace, index = _get_page_data(message)
         # Pass the request to the GUI(s) to pull up a page template
         self.show(namespace, page, index)
     except Exception as e:
         LOG.exception(repr(e))
Exemple #24
0
 def on_gui_delete_page(self, message):
     """ Bus handler for removing pages. """
     page, namespace, _ = _get_page_data(message)
     try:
         self.remove_pages(namespace, page)
     except Exception as e:
         LOG.exception(repr(e))
Exemple #25
0
 def on_gui_delete_namespace(self, message):
     """ Bus handler for removing namespace. """
     try:
         namespace = message.data['__from']
         self.remove_namespace(namespace)
     except Exception as e:
         LOG.exception(repr(e))
def simple_cli():
    global bus
    global bSimple
    bSimple = True
    bus = WebsocketClient()  # Mycroft messagebus connection
    event_thread = Thread(target=connect)
    event_thread.setDaemon(True)
    event_thread.start()
    bus.on('speak', handle_speak)
    try:
        while True:
            # Sleep for a while so all the output that results
            # from the previous command finishes before we print.
            time.sleep(1.5)
            print("Input (Ctrl+C to quit):")
            line = sys.stdin.readline()
            bus.emit(Message("recognizer_loop:utterance",
                             {'utterances': [line.strip()]}))
    except KeyboardInterrupt as e:
        # User hit Ctrl+C to quit
        print("")
    except KeyboardInterrupt as e:
        LOG.exception(e)
        event_thread.exit()
        sys.exit()
Exemple #27
0
 def send(self, *args, **kwargs):
     """ Send to all registered GUIs. """
     for gui in self.GUIs.values():
         if gui.socket:
             gui.socket.send(*args, **kwargs)
         else:
             LOG.error('GUI connection {} has no socket!'.format(gui))
Exemple #28
0
    def __insert_new_namespace(self, namespace, pages):
        """ Insert new namespace and pages.

        This first sends a message adding a new namespace at the
        highest priority (position 0 in the namespace stack)

        Args:
            namespace (str):  The skill namespace to create
            pages (str):      Pages to insert (name matches QML)
        """
        LOG.debug("Inserting new namespace")
        self.send({"type": "mycroft.session.list.insert",
                   "namespace": "mycroft.system.active_skills",
                   "position": 0,
                   "data": [{"skill_id": namespace}]
                   })

        # Load any already stored Data
        data = self.datastore.get(namespace, {})
        for key in data:
            msg = {"type": "mycroft.session.set",
                   "namespace": namespace,
                   "data": {key: data[key]}}
            self.send(msg)

        LOG.debug("Inserting new page")
        self.send({"type": "mycroft.gui.list.insert",
                   "namespace": namespace,
                   "position": 0,
                   "data": [{"url": p} for p in pages]
                   })
        # Make sure the local copy is updated
        self.loaded.insert(0, Namespace(namespace, pages))
Exemple #29
0
 def supported_uris(self):
     """ Return supported uris of chromecast. """
     LOG.info("Chromecasts found: " + str(self.cast))
     if self.cast:
         return ['http', 'https']
     else:
         return []
Exemple #30
0
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)

    # Expand and normalize the path
    directory = os.path.normpath(directory)
    directory = os.path.expanduser(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
Exemple #31
0
    def _get_sentence_from_cache(self, sentence_hash):
        cached_sentence = self.cache.cached_sentences[sentence_hash]
        audio_file, phoneme_file = cached_sentence
        LOG.info("Found {} in TTS cache".format(audio_file.name))

        return audio_file, phoneme_file
Exemple #32
0
def handle_wakeword(event):
    LOG.info("Wakeword Detected: " + event['utterance'])
    bus.emit(Message('recognizer_loop:wakeword', event))
Exemple #33
0
def handle_awoken():
    """Forward mycroft.awoken to the messagebus."""
    LOG.info("Listener is now Awake: ")
    context = {'client_name': 'mycroft_listener', 'source': 'audio'}
    bus.emit(Message('mycroft.awoken', context=context))
Exemple #34
0
def handle_no_internet():
    LOG.debug("Notifying enclosure of no internet connection")
    context = {'client_name': 'mycroft_listener', 'source': 'audio'}
    bus.emit(Message('enclosure.notify.no_internet', context=context))
Exemple #35
0
def handle_record_end():
    """Forward internal bus message to external bus."""
    LOG.info("End Recording...")
    context = {'client_name': 'mycroft_listener', 'source': 'audio'}
    bus.emit(Message('recognizer_loop:record_end', context=context))
Exemple #36
0
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:              Mycroft messagebus connection
        skill_id:         id number for skill

    Returns:
        MycroftSkill: 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("__mycroft_skill_firstrun", True)
            if first_run:
                LOG.info("First run of " + name)
                skill.settings["__mycroft_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
Exemple #37
0
 def on_close(ws):
     LOG.info("### socket closed ###")
Exemple #38
0
 def on_message(self, mqttc, obj,
                msg):  # called when a new MQTT message is received
     # Sample Payload {"source":"basement", "message":"is dinner ready yet"}
     LOG.info('message received for location id: ' + str(self.location_id))
     LOG.info("This device location is: " +
              DeviceApi().get()["description"])
     try:
         mqtt_message = msg.payload.decode('utf-8')
         LOG.info(msg.topic + " " + str(msg.qos) + ", " + mqtt_message)
         new_message = json.loads(mqtt_message)
         if "command" in new_message:
             # example: {"source":"kitchen", "command":"what time is it"}
             LOG.info('Command Received! - ' + new_message["command"] +
                      ', From: ' + new_message["source"])
             self.response_location = new_message["source"]
             self.send_message(new_message["command"])
         elif "message" in new_message:
             # example: {"source":"kitchen", "message":"is dinner ready yet"}
             self.response_location = ''
             LOG.info('Message Received! - ' + new_message["message"] +
                      ', From: ' + new_message["source"])
             self.speak_dialog('location',
                               data={"result": new_message["source"]},
                               expect_response=False)
             wait_while_speaking()
             self.speak_dialog('message',
                               data={"result": new_message["message"]},
                               expect_response=False)
         else:
             LOG.info('Unable to decode the MQTT Message')
     except Exception as e:
         LOG.error('Error: {0}'.format(e))
Exemple #39
0
 def get_mac_address(
         self):  #used to create a unique UUID for this device that
     node = uuid.getnode()
     mac = uuid.UUID(int=node).hex[-12:]
     LOG.info("MQTT using UUID: " + mac)
     return mac
Exemple #40
0
    def run(self):
        global ws, loaded_skills, last_modified_skill

        # Load priority skills first by order
        load_skill_list(PRIORITY_SKILLS)
        self._loaded_priority.set()

        # Scan the file folder that contains Skills.  If a Skill is updated,
        # unload the existing version from memory and reload from the disk.
        while not self._stop_event.is_set():
            if exists(SKILLS_DIR):
                # checking skills dir and getting all skills there
                list = filter(
                    lambda x: os.path.isdir(os.path.join(SKILLS_DIR, x)),
                    os.listdir(SKILLS_DIR))

                for skill_folder in list:
                    if skill_folder not in loaded_skills:
                        loaded_skills[skill_folder] = {
                            "id": hash(os.path.join(SKILLS_DIR, skill_folder))
                        }
                    skill = loaded_skills.get(skill_folder)
                    skill["path"] = os.path.join(SKILLS_DIR, skill_folder)
                    # checking if is a skill
                    if not MainModule + ".py" in os.listdir(skill["path"]):
                        continue
                    # getting the newest modified date of skill
                    last_mod = _get_last_modified_date(skill["path"])
                    skill["last_modified"] = last_mod
                    modified = skill.get("last_modified", 0)
                    # checking if skill is loaded and wasn't modified
                    if skill.get("loaded") and modified <= last_modified_skill:
                        continue
                    # checking if skill was modified
                    elif (skill.get("instance")
                          and modified > last_modified_skill):
                        # checking if skill should be reloaded
                        if not skill["instance"].reload_skill:
                            continue
                        LOG.debug("Reloading Skill: " + skill_folder)
                        # removing listeners and stopping threads
                        skill["instance"].shutdown()

                        # -2 since two local references that are known
                        refs = sys.getrefcount(skill["instance"]) - 2
                        if refs > 0:
                            LOG.warning("After shutdown of {} there are still "
                                        "{} references remaining. The skill "
                                        "won't be cleaned from memory.".format(
                                            skill['instance'].name, refs))
                        del skill["instance"]
                    skill["loaded"] = True
                    skill["instance"] = load_skill(
                        create_skill_descriptor(skill["path"]), ws,
                        skill["id"], BLACKLISTED_SKILLS)
            # get the last modified skill
            modified_dates = map(lambda x: x.get("last_modified"),
                                 loaded_skills.values())
            if len(modified_dates) > 0:
                last_modified_skill = max(modified_dates)

            if not self._loaded_once.is_set():
                self._loaded_once.set()
            # Pause briefly before beginning next scan
            time.sleep(2)
Exemple #41
0
def scan_wifi(interface="wlan0", sudo=False):
    class _LineMatcher(object):
        def __init__(self, regexp, handler):
            self.regexp = re.compile(regexp)
            self.handler = handler

    def _handle_new_network(line, result, networks):
        # group(1) is the mac address
        networks.append({})
        networks[-1]['Address'] = result.group(1)

    def _handle_essid(line, result, networks):
        # group(1) is the essid name
        networks[-1]['ESSID'] = result.group(1)

    def _handle_quality(line, result, networks):
        # group(1) is the quality value
        # group(2) is probably always 100
        networks[-1]['Quality'] = result.group(1) + '/' + result.group(2)

    def _handle_unknown(line, result, networks):
        # group(1) is the key, group(2) is the rest of the line
        networks[-1][result.group(1)] = result.group(2)

    # if you are not using sudo you will only find your own wifi
    if sudo:
        args = ['sudo', '/sbin/iwlist', interface, 'scanning']
    else:
        args = ['/sbin/iwlist', interface, 'scanning']
    proc = subprocess.Popen(args, stdout=subprocess.PIPE)
    stdout, stderr = proc.communicate()

    lines = str(stdout)[2:-2].replace("\\n", "\n").split("\n")[1:-1]
    networks = []
    matchers = []

    # catch the line 'Cell ## - Address: XX:YY:ZZ:AA:BB:CC'
    matchers.append(
        _LineMatcher(r'\s+Cell \d+ - Address: (\S+)', _handle_new_network))

    # catch the line 'ESSID:"network name"
    matchers.append(_LineMatcher(r'\s+ESSID:"([^"]+)"', _handle_essid))

    # catch the line 'Quality:X/Y Signal level:X dBm Noise level:Y dBm'
    matchers.append(_LineMatcher(r'\s+Quality:(\d+)/(\d+)', _handle_quality))

    # catch any other line that looks like this:
    # Key:value
    matchers.append(_LineMatcher(r'\s+([^:]+):(.+)', _handle_unknown))

    # read each line of output, testing against the matches above
    # in that order (so that the key:value matcher will be tried last)
    for line in lines:
        # hack for signal strenght TODO use a matcher
        if line.rstrip().lstrip().startswith("Quality="):
            index = line.find("Signal level=") + len("Signal level=")
            line = line[index:].strip()
            networks[-1]["strength"] = line
            continue

        for m in matchers:
            result = m.regexp.match(line)
            if result:
                m.handler(line, result, networks)
                break
    LOG.info("scanned networks: " + str(networks))
    return networks
Exemple #42
0
 def on_disconnect(self, mqttc, obj, flags, rc):
     self._is_setup = False
     LOG.info("MQTT has Dis-Connected")
Exemple #43
0
def play(tracks, prefered_service):
    """
        play starts playing the audio on the prefered service if it supports
        the uri. If not the next best backend is found.

        Args:
            tracks: list of tracks to play.
            prefered_service: indecates the service the user prefer to play
                              the tracks.
    """
    global current
    global service
    LOG.info('play')
    _stop()
    uri_type = tracks[0].split(':')[0]
    LOG.info('uri_type: ' + uri_type)
    # check if user requested a particular service
    if prefered_service and uri_type in prefered_service.supported_uris():
        selected_service = prefered_service
    # check if default supports the uri
    elif default and uri_type in default.supported_uris():
        LOG.info("Using default backend")
        LOG.info(default.name)
        selected_service = default
    else:  # Check if any other service can play the media
        LOG.info("Searching the services")
        for s in service:
            LOG.info(str(s))
            if uri_type in s.supported_uris():
                LOG.info("Service " + str(s) + " supports URI " + uri_type)
                selected_service = s
                break
        else:
            LOG.info('No service found for uri_type: ' + uri_type)
            return
    LOG.info('Clear list')
    selected_service.clear_list()
    LOG.info('Add tracks' + str(tracks))
    selected_service.add_list(tracks)
    LOG.info('Playing')
    selected_service.play()
    current = selected_service
Exemple #44
0
import random
import json
import paho.mqtt.client as mqtt
import paho.mqtt.publish as publish
import re

__author__ = 'PCWii'

# Logger: used for debug lines, like "LOGGER.debug(xyz)". These
# statements will show up in the command line when running Mycroft.
LOGGER = getLogger(__name__)

# clear any previously connected mqtt clients on first load
try:
    mqttc
    LOG.info('Client exist')
    mqttc.loop_stop()
    mqttc.disconnect()
    LOG.info('Stopped old client loop')
except NameError:
    mqttc = mqtt.Client()
    LOG.info('Client created')


# The logic of each skill is contained within its own class, which inherits
# base methods from the MycroftSkill class with the syntax you can see below:
# "class ____Skill(MycroftSkill)"
class MeshSkill(MycroftSkill):

    # The constructor of the skill, which calls Mycroft Skill's constructor
    def __init__(self):
Exemple #45
0
 def make_executable(dest):
     """Call back function to make the downloaded file executable."""
     LOG.info('Make executable new voice binary executable')
     # make executable
     file_stat = os.stat(dest)
     os.chmod(dest, file_stat.st_mode | stat.S_IEXEC)
Exemple #46
0
 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)
Exemple #47
0
 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)
Exemple #48
0
def load_services_callback():
    """
        Main callback function for loading services. Sets up the globals
        service and default and registers the event handlers for the subsystem.
    """
    global ws
    global default
    global service

    config = Configuration.get().get("Audio")
    service = load_services(config, ws)
    LOG.info(service)
    default_name = config.get('default-backend', '')
    LOG.info('Finding default backend...')
    for s in service:
        LOG.info('checking ' + s.name)
        if s.name == default_name:
            default = s
            LOG.info('Found ' + default.name)
            break
    else:
        default = None
        LOG.info('no default found')
    LOG.info('Default:' + str(default))

    ws.on('mycroft.audio.service.play', _play)
    ws.on('mycroft.audio.service.pause', _pause)
    ws.on('mycroft.audio.service.resume', _resume)
    ws.on('mycroft.audio.service.stop', _stop)
    ws.on('mycroft.audio.service.next', _next)
    ws.on('mycroft.audio.service.prev', _prev)
    ws.on('mycroft.audio.service.track_info', _track_info)
    ws.on('recognizer_loop:audio_output_start', _lower_volume)
    ws.on('recognizer_loop:record_begin', _lower_volume)
    ws.on('recognizer_loop:audio_output_end', _restore_volume)
    ws.on('recognizer_loop:record_end', _restore_volume)
    ws.on('mycroft.stop', _stop)
Exemple #49
0
    def download_skills(self, speak=False):
        """ Invoke MSM to install default skills and/or update installed skills

            Args:
                speak (bool, optional): Speak the result? Defaults to False
        """
        if not connected():
            LOG.error('msm failed, network connection not available')
            if speak:
                self.bus.emit(
                    Message("speak", {
                        'utterance':
                        dialog.get("not connected to the internet")
                    }))
            self.next_download = time.time() + 5 * MINUTES
            return False

        installed_skills = self.load_installed_skills()
        msm = SkillManager.create_msm()
        with msm.lock, self.thread_lock:
            default_groups = dict(msm.repo.get_default_skill_names())
            if msm.platform in default_groups:
                platform_groups = default_groups[msm.platform]
            else:
                LOG.info('Platform defaults not found, using DEFAULT '
                         'skills only')
                platform_groups = []
            default_names = set(
                chain(default_groups['default'], platform_groups))
            default_skill_errored = False

            def get_skill_data(skill_name):
                """ Get skill data structure from name. """
                for e in msm.skills_data.get('skills', []):
                    if e.get('name') == skill_name:
                        return e
                # if skill isn't in the list return empty structure
                return {}

            def install_or_update(skill):
                """Install missing defaults and update existing skills"""
                if get_skill_data(skill.name).get('beta'):
                    skill.sha = None  # Will update to latest head
                if skill.is_local:
                    skill.update()
                    if skill.name not in installed_skills:
                        skill.update_deps()
                elif skill.name in default_names:
                    try:
                        msm.install(skill, origin='default')
                    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)

            try:
                msm.apply(install_or_update, msm.list())
                if SkillManager.manifest_upload_allowed and is_paired():
                    try:
                        DeviceApi().upload_skills_data(msm.skills_data)
                    except Exception:
                        LOG.exception('Could not upload skill manifest')

            except MsmException as e:
                LOG.error('Failed to update skills: {}'.format(repr(e)))

        self.save_installed_skills(installed_skills)

        if speak:
            data = {'utterance': dialog.get("skills updated")}
            self.bus.emit(Message("speak", data))

        # Schedule retry in 5 minutes on failure, after 10 shorter periods
        # Go back to 60 minutes wait
        if default_skill_errored and self.num_install_retries < 10:
            self.num_install_retries += 1
            self.next_download = time.time() + 5 * MINUTES
            return False
        self.num_install_retries = 0

        # Update timestamp on .msm file to be used when system is restarted
        with open(self.dot_msm, 'a'):
            os.utime(self.dot_msm, None)
        self.next_download = time.time() + self.update_interval

        return True
Exemple #50
0
def pronounce_number_en(num, places=2, short_scale=True, scientific=False):
    """
    Convert a number to its spoken equivalent

    For example, '5.2' would return 'five point two'

    Args:
        num(float or int): the number to pronounce (under 100)
        places(int): maximum decimal places to speak
        short_scale (bool) : use short (True) or long scale (False)
            https://en.wikipedia.org/wiki/Names_of_large_numbers
        scientific (bool): pronounce in scientific notation
    Returns:
        (str): The pronounced number
    """
    if scientific:
        number = '%E' % num
        n, power = number.replace("+", "").split("E")
        power = int(power)
        if power != 0:
            # This handles negatives of powers separately from the normal
            # handling since each call disables the scientific flag
            return '{}{} times ten to the power of {}{}'.format(
                'negative ' if float(n) < 0 else '',
                pronounce_number_en(abs(float(n)), places, short_scale, False),
                'negative ' if power < 0 else '',
                pronounce_number_en(abs(power), places, short_scale, False))
    if short_scale:
        number_names = _NUM_STRING_EN.copy()
        number_names.update(_SHORT_SCALE_EN)
    else:
        number_names = _NUM_STRING_EN.copy()
        number_names.update(_LONG_SCALE_EN)

    digits = [number_names[n] for n in range(0, 20)]

    tens = [number_names[n] for n in range(10, 100, 10)]

    if short_scale:
        hundreds = [_SHORT_SCALE_EN[n] for n in _SHORT_SCALE_EN.keys()]
    else:
        hundreds = [_LONG_SCALE_EN[n] for n in _LONG_SCALE_EN.keys()]

    # deal with negatives
    result = ""
    if num < 0:
        result = "negative " if scientific else "minus "
    num = abs(num)

    try:
        # deal with 4 digits
        # usually if it's a 4 digit num it should be said like a date
        # i.e. 1972 => nineteen seventy two
        if len(str(num)) == 4 and isinstance(num, int):
            _num = str(num)
            # deal with 1000, 2000, 2001, 2100, 3123, etc
            # is skipped as the rest of the
            # functin deals with this already
            if _num[1:4] == '000' or _num[1:3] == '00' or int(_num[0:2]) >= 20:
                pass
            # deal with 1900, 1300, etc
            # i.e. 1900 => nineteen hundred
            elif _num[2:4] == '00':
                first = number_names[int(_num[0:2])]
                last = number_names[100]
                return first + " " + last
            # deal with 1960, 1961, etc
            # i.e. 1960 => nineteen sixty
            #      1961 => nineteen sixty one
            else:
                first = number_names[int(_num[0:2])]
                if _num[3:4] == '0':
                    last = number_names[int(_num[2:4])]
                else:
                    second = number_names[int(_num[2:3])*10]
                    last = second + " " + number_names[int(_num[3:4])]
                return first + " " + last
    # exception used to catch any unforseen edge cases
    # will default back to normal subroutine
    except Exception as e:
        LOG.error('Exception in pronounce_number_en: {}' + repr(e))

    # check for a direct match
    if num in number_names:
        if num > 90:
            result += "one "
        result += number_names[num]
    else:
        def _sub_thousand(n):
            assert 0 <= n <= 999
            if n <= 19:
                return digits[n]
            elif n <= 99:
                q, r = divmod(n, 10)
                return tens[q - 1] + (" " + _sub_thousand(r) if r else "")
            else:
                q, r = divmod(n, 100)
                return digits[q] + " hundred" + (
                    " and " + _sub_thousand(r) if r else "")

        def _short_scale(n):
            if n >= max(_SHORT_SCALE_EN.keys()):
                return "infinity"
            n = int(n)
            assert 0 <= n
            res = []
            for i, z in enumerate(_split_by(n, 1000)):
                if not z:
                    continue
                number = _sub_thousand(z)
                if i:
                    number += " "
                    number += hundreds[i]
                res.append(number)

            return ", ".join(reversed(res))

        def _split_by(n, split=1000):
            assert 0 <= n
            res = []
            while n:
                n, r = divmod(n, split)
                res.append(r)
            return res

        def _long_scale(n):
            if n >= max(_LONG_SCALE_EN.keys()):
                return "infinity"
            n = int(n)
            assert 0 <= n
            res = []
            for i, z in enumerate(_split_by(n, 1000000)):
                if not z:
                    continue
                number = pronounce_number_en(z, places, True, scientific)
                # strip off the comma after the thousand
                if i:
                    # plus one as we skip 'thousand'
                    # (and 'hundred', but this is excluded by index value)
                    number = number.replace(',', '')
                    number += " " + hundreds[i+1]
                res.append(number)
            return ", ".join(reversed(res))

        if short_scale:
            result += _short_scale(num)
        else:
            result += _long_scale(num)

    # Deal with fractional part
    if not num == int(num) and places > 0:
        result += " point"
        place = 10
        while int(num * place) % 10 > 0 and places > 0:
            result += " " + number_names[int(num * place) % 10]
            place *= 10
            places -= 1
    return result
def handle_complete_intent_failure(event):
    """Extreme backup for answering completely unhandled intent requests."""
    LOG.info("Failed to find intent.")
    data = {'utterance': dialog.get('not.loaded')}
    bus.emit(Message('speak', data))
Exemple #52
0
    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("mycroft.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(
                    'mycroft.skills.loaded', {
                        'path': skill_path,
                        'id': skill['id'],
                        'name': skill['instance'].name,
                        'modified': modified
                    }))
            return True
        else:
            self.bus.emit(
                Message('mycroft.skills.loading_failure', {
                    'path': skill_path,
                    'id': skill['id']
                }))
        return False
def handle_no_internet():
    LOG.debug("Notifying enclosure of no internet connection")
    bus.emit(Message('enclosure.notify.no_internet'))
Exemple #54
0
def gui_main(stdscr):
    global scr
    global ws
    global line
    global log_line_lr_scroll
    global longest_visible_line
    global find_str
    global last_key

    scr = stdscr
    init_screen()

    ws = WebsocketClient()
    ws.on('speak', handle_speak)
    ws.on('message', handle_message)
    event_thread = Thread(target=connect)
    event_thread.setDaemon(True)
    event_thread.start()

    history = []
    hist_idx = -1  # index, from the bottom
    try:
        input = ""
        while True:
            draw_screen()

            c = scr.getch()

            # Convert VT100 ESC codes generated by some terminals
            if c == 27:
                c1 = scr.getch()
                c2 = scr.getch()
                if c1 == 79 and c2 == 120:
                    c = curses.KEY_UP
                elif c1 == 79 and c2 == 116:
                    c = curses.KEY_LEFT
                elif c1 == 79 and c2 == 114:
                    c = curses.KEY_DOWN
                elif c1 == 79 and c2 == 118:
                    c = curses.KEY_RIGHT
                elif c1 == 79 and c2 == 121:
                    c = curses.KEY_PPAGE  # aka PgUp
                elif c1 == 79 and c2 == 115:
                    c = curses.KEY_NPAGE  # aka PgDn
                elif c1 == 79 and c2 == 119:
                    c = curses.KEY_HOME
                elif c1 == 79 and c2 == 113:
                    c = curses.KEY_END
                else:
                    c = c2
                last_key = str(c) + ",ESC+" + str(c1) + "+" + str(c2)
            else:
                last_key = str(c)

            if c == curses.KEY_ENTER or c == 10 or c == 13:
                # ENTER sends the typed line to be processed by Mycroft
                if line == "":
                    continue

                if line[:1] == ":":
                    # Lines typed like ":help" are 'commands'
                    if handle_cmd(line[1:]) == 1:
                        break
                else:
                    # Treat this as an utterance
                    history.append(line)
                    chat.append(line)
                    ws.emit(
                        Message("recognizer_loop:utterance", {
                            'utterances': [line.strip()],
                            'lang': 'en-us'
                        }))
                hist_idx = -1
                line = ""
            elif c == 16 or c == 545:  # Ctrl+P or Ctrl+Left (Previous)
                # Move up the history stack
                hist_idx = clamp(hist_idx + 1, -1, len(history) - 1)
                if hist_idx >= 0:
                    line = history[len(history) - hist_idx - 1]
                else:
                    line = ""
            elif c == 14 or c == 560:  # Ctrl+N or Ctrl+Right (Next)
                # Move down the history stack
                hist_idx = clamp(hist_idx - 1, -1, len(history) - 1)
                if hist_idx >= 0:
                    line = history[len(history) - hist_idx - 1]
                else:
                    line = ""
            elif c == curses.KEY_LEFT:
                # scroll long log lines left
                log_line_lr_scroll += curses.COLS // 4
            elif c == curses.KEY_RIGHT:
                # scroll long log lines right
                log_line_lr_scroll -= curses.COLS // 4
                if log_line_lr_scroll < 0:
                    log_line_lr_scroll = 0
            elif c == curses.KEY_HOME:
                # HOME scrolls log lines all the way to the start
                log_line_lr_scroll = longest_visible_line
            elif c == curses.KEY_END:
                # END scrolls log lines all the way to the end
                log_line_lr_scroll = 0
            elif c == curses.KEY_UP:
                scroll_log(False, 1)
            elif c == curses.KEY_DOWN:
                scroll_log(True, 1)
            elif c == curses.KEY_NPAGE:  # aka PgDn
                # PgDn to go down a page in the logs
                scroll_log(True)
            elif c == curses.KEY_PPAGE:  # aka PgUp
                # PgUp to go up a page in the logs
                scroll_log(False)
            elif c == 2 or c == 550:  # Ctrl+B or Ctrl+PgDn
                scroll_log(True, max_log_lines)
            elif c == 20 or c == 555:  # Ctrl+T or Ctrl+PgUp
                scroll_log(False, max_log_lines)
            elif c == curses.KEY_RESIZE:
                # Generated by Curses when window/screen has been resized
                y, x = scr.getmaxyx()
                curses.resizeterm(y, x)

                # resizeterm() causes another curses.KEY_RESIZE, so
                # we need to capture that to prevent a loop of resizes
                c = scr.getch()
            elif c == curses.KEY_BACKSPACE or c == 127:
                # Backspace to erase a character in the utterance
                line = line[:-1]
            elif c == 6:  # Ctrl+F (Find)
                line = ":find "
            elif c == 18:  # Ctrl+R (Redraw)
                scr.erase()
                scr.refresh()
            elif c == 24:  # Ctrl+X (Exit)
                if find_str:
                    # End the find session
                    find_str = None
                    rebuild_filtered_log()
            elif curses.ascii.isascii(c):
                # Accept typed character in the utterance
                line += chr(c)

            # DEBUG: Uncomment the following code to see what key codes
            #        are generated when an unknown key is pressed.
            # else:
            #    line += str(c)

    except KeyboardInterrupt as e:
        # User hit Ctrl+C to quit
        pass
    except KeyboardInterrupt as e:
        LOG.exception(e)
    finally:
        scr.erase()
        scr.refresh()
        scr = None
        pass
def handle_record_begin():
    """Forward internal bus message to external bus."""
    LOG.info("Begin Recording...")
    bus.emit(Message('recognizer_loop:record_begin'))
def handle_awoken():
    """Forward mycroft.awoken to the messagebus."""
    LOG.info("Listener is now Awake: ")
    bus.emit(Message('mycroft.awoken'))
 def store(self, force=False):
     LOG.warning('DEPRECATED - use mycroft.skills.settings.save_settings()')
     save_settings(self._skill.root_dir, self._settings)
def handle_record_end():
    """Forward internal bus message to external bus."""
    LOG.info("End Recording...")
    bus.emit(Message('recognizer_loop:record_end'))
Exemple #59
0
    def _load_or_reload_skill(self, skill_folder):
        """
            Check if unloaded skill or changed skill needs reloading
            and perform loading if necessary.
        """
        if skill_folder not in self.loaded_skills:
            self.loaded_skills[skill_folder] = {
                "id": hash(os.path.join(SKILLS_DIR, skill_folder))
            }
        skill = self.loaded_skills.get(skill_folder)
        skill["path"] = os.path.join(SKILLS_DIR, skill_folder)

        # check if folder is a skill (must have __init__.py)
        if not MainModule + ".py" in os.listdir(skill["path"]):
            return

        # 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  # 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:
                return

            LOG.debug("Reloading Skill: " + skill_folder)
            # removing listeners and stopping threads
            skill["instance"].shutdown()

            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:
                    LOG.warning("After shutdown of {} there are still "
                                "{} references remaining. The skill "
                                "won't be cleaned from memory.".format(
                                    skill['instance'].name, refs))
            del skill["instance"]
            self.ws.emit(
                Message("mycroft.skills.shutdown", {
                    "folder": skill_folder,
                    "id": skill["id"]
                }))

        # (Re)load the skill from disk
        with self.__msm_lock:  # Make sure msm isn't running
            skill["loaded"] = True
            desc = create_skill_descriptor(skill["path"])
            skill["instance"] = load_skill(desc, self.ws, skill["id"],
                                           BLACKLISTED_SKILLS)
            skill["last_modified"] = modified
            if skill['instance'] is not None:
                self.ws.emit(
                    Message(
                        'mycroft.skills.loaded', {
                            'folder': skill_folder,
                            'id': skill['id'],
                            'name': skill['instance'].name,
                            'modified': modified
                        }))
            else:
                self.ws.emit(
                    Message('mycroft.skills.loading_failure', {
                        'folder': skill_folder,
                        'id': skill['id']
                    }))
 def set_changed_callback(self, callback):
     LOG.warning('DEPRECATED - set the settings_change_callback attribute')
     self._skill.settings_change_callback = callback