Esempio n. 1
0
    def enable_intent(self, intent_name):
        """
        (Re)Enable a registered intent if it belongs to this skill

        Args:
                intent_name: name of the intent to be enabled

        Returns:
                bool: True if enabled, False if it wasn't registered
        """
        names = [intent[0] for intent in self.registered_intents]
        intents = [intent[1] for intent in self.registered_intents]
        if intent_name in names:
            intent = intents[names.index(intent_name)]
            self.registered_intents.remove((intent_name, intent))
            if ".intent" in intent_name:
                self.register_intent_file(intent_name, None)
            else:
                intent.name = intent_name
                self.register_intent(intent, None)
            LOG.debug('Enabling intent ' + intent_name)
            return True

        LOG.error('Could not enable ' + intent_name + ', it hasn\'t been '
                  'registered.')
        return False
Esempio n. 2
0
def mute_and_speak(utterance, ident):
    """
        Mute mic and start speaking the utterance using selected tts backend.

        Args:
            utterance:  The sentence to be spoken
            ident:      Ident tying the utterance to the source query
    """
    global tts_hash

    # update TTS object if configuration has changed
    if tts_hash != hash(str(config.get('tts', ''))):
        global tts
        # Stop tts playback thread
        tts.playback.stop()
        tts.playback.join()
        # Create new tts instance
        tts = TTSFactory.create()
        tts.init(bus)
        tts_hash = hash(str(config.get('tts', '')))

    LOG.info("Speak: " + utterance)
    try:
        tts.execute(utterance, ident)
    except Exception as e:
        LOG.error('TTS execution failed ({})'.format(repr(e)))
Esempio n. 3
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
Esempio n. 4
0
    def default_shutdown(self):
        """Parent function called internally to shut down everything.

        Shuts down known entities and calls skill specific shutdown method.
        """
        try:
            self.shutdown()
        except Exception as e:
            LOG.error('Skill specific shutdown function encountered '
                      'an error: {}'.format(repr(e)))
        # Store settings
        if exists(self._dir):
            self.settings.store()
            self.settings.stop_polling()
        # removing events
        self.cancel_all_repeating_events()
        for e, f in self.events:
            self.bus.remove(e, f)
        self.events = []  # Remove reference to wrappers

        self.bus.emit(
            Message("detach_skill", {"skill_id": str(self.skill_id) + ":"}))
        try:
            self.stop()
        except:
            LOG.error("Failed to stop skill: {}".format(self.name),
                      exc_info=True)
Esempio n. 5
0
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
Esempio n. 6
0
def get_services(services_folder):
    """
        Load and initialize services from all subfolders.

        Args:
            services_folder: base folder to look for services in.

        Returns:
            Sorted list of audio services.
    """
    LOG.info("Loading services from " + services_folder)
    services = []
    possible_services = listdir(services_folder)
    for i in possible_services:
        location = join(services_folder, i)
        if (isdir(location) and not MAINMODULE + ".py" in listdir(location)):
            for j in listdir(location):
                name = join(location, j)
                if (not isdir(name)
                        or not MAINMODULE + ".py" in listdir(name)):
                    continue
                try:
                    services.append(create_service_descriptor(name))
                except Exception:
                    LOG.error('Failed to create service from ' + name,
                              exc_info=True)
        if (not isdir(location)
                or not MAINMODULE + ".py" in listdir(location)):
            continue
        try:
            services.append(create_service_descriptor(location))
        except Exception:
            LOG.error('Failed to create service from ' + location,
                      exc_info=True)
    return sorted(services, key=lambda p: p.get('name'))
Esempio n. 7
0
    def __init__(self, bus, service):
        FallbackSkill.__init__(self)
        if not PadatiousService.instance:
            PadatiousService.instance = self

        self.config = Configuration.get()['padatious']
        self.service = service
        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

        self.container = IntentContainer(intent_cache)

        self.bus = bus
        self.bus.on('padatious:register_intent', self.register_intent)
        self.bus.on('padatious:register_entity', self.register_entity)
        self.bus.on('detach_intent', self.handle_detach_intent)
        self.bus.on('owo.skills.initialized', self.train)
        self.register_fallback(self.handle_fallback, 5)
        self.finished_training_event = Event()
        self.finished_initial_train = False

        self.train_delay = self.config['train_delay']
        self.train_time = get_time() + self.train_delay
Esempio n. 8
0
 def flush(self):
     while self.alive:
         try:
             cmd = self.commands.get() + '\n'
             self.serial.write(cmd.encode())
             self.commands.task_done()
         except Exception as e:
             LOG.error("Writing error: {0}".format(e))
Esempio n. 9
0
 def __play(self, req):
     resp = req.result()
     if resp.status_code == 200:
         self.__save(resp.content)
         play_wav(self.filename).communicate()
     else:
         LOG.error('%s Http Error: %s for url: %s' %
                   (resp.status_code, resp.reason, resp.url))
Esempio n. 10
0
 def deactivate_skill(self, message):
     """ Deactivate a skill. """
     try:
         skill = message.data['skill']
         if skill in [basename(s) for s in self.loaded_skills]:
             self.__deactivate_skill(skill)
     except Exception as e:
         LOG.error('Couldn\'t deactivate skill, {}'.format(repr(e)))
Esempio n. 11
0
 def get():
     data_dir = expanduser(Configuration.get()['data_dir'])
     version_file = join(data_dir, 'version.json')
     if exists(version_file) and isfile(version_file):
         try:
             with open(version_file) as f:
                 return json.load(f)
         except Exception:
             LOG.error("Failed to load version from '%s'" % version_file)
     return {"coreVersion": None, "enclosureVersion": None}
Esempio n. 12
0
 def __deactivate_skill(self, skill):
     """ Deactivate a skill. """
     for s in self.loaded_skills:
         if skill in s:
             skill = s
             break
     try:
         self.loaded_skills[skill]['active'] = False
         self.loaded_skills[skill]['instance'].default_shutdown()
     except Exception as e:
         LOG.error('Couldn\'t deactivate skill, {}'.format(repr(e)))
Esempio n. 13
0
def handle_speak(event):
    """
        Handle "speak" message
    """
    config = Configuration.get()
    Configuration.init(bus)
    global _last_stop_signal

    # Get conversation ID
    if event.context and 'ident' in event.context:
        ident = event.context['ident']
    else:
        ident = 'unknown'

    with lock:
        stopwatch = Stopwatch()
        stopwatch.start()
        utterance = event.data['utterance']
        if event.data.get('expect_response', False):
            # When expect_response is requested, the listener will be restarted
            # at the end of the next bit of spoken audio.
            bus.once('recognizer_loop:audio_output_end', _start_listener)

        # This is a bit of a hack for Picroft.  The analog audio on a Pi blocks
        # for 30 seconds fairly often, so we don't want to break on periods
        # (decreasing the chance of encountering the block).  But we will
        # keep the split for non-Picroft installs since it give user feedback
        # faster on longer phrases.
        #
        # TODO: Remove or make an option?  This is really a hack, anyway,
        # so we likely will want to get rid of this when not running on Mimic
        if (config.get('enclosure', {}).get('platform') != "picroft"
                and len(re.findall('<[^>]*>', utterance)) == 0):
            start = time.time()
            chunks = re.split(r'(?<!\w\.\w.)(?<![A-Z][a-z]\.)(?<=\.|\?)\s',
                              utterance)
            for chunk in chunks:
                try:
                    mute_and_speak(chunk, ident)
                except KeyboardInterrupt:
                    raise
                except Exception:
                    LOG.error('Error in mute_and_speak', exc_info=True)
                if (_last_stop_signal > start
                        or check_for_signal('buttonPress')):
                    break
        else:
            mute_and_speak(utterance, ident)

        stopwatch.stop()
    report_timing(ident, 'speech', stopwatch, {
        'utterance': utterance,
        'tts': tts.__class__.__name__
    })
Esempio n. 14
0
 def __init_serial(self):
     try:
         self.port = self.config.get("port")
         self.rate = self.config.get("rate")
         self.timeout = self.config.get("timeout")
         self.serial = serial.serial_for_url(
             url=self.port, baudrate=self.rate, timeout=self.timeout)
         LOG.info("Connected to: %s rate: %s timeout: %s" %
                  (self.port, self.rate, self.timeout))
     except:
         LOG.error("Impossible to connect to serial port: "+str(self.port))
         raise
Esempio n. 15
0
 def run(self):
     self.start_async()
     while self.state.running:
         try:
             time.sleep(1)
             if self._config_hash != hash(str(Configuration().get())):
                 LOG.debug('Config has changed, reloading...')
                 self.reload()
         except KeyboardInterrupt as e:
             LOG.error(e)
             self.stop()
             raise  # Re-raise KeyboardInterrupt
Esempio n. 16
0
    def _play(self, req):
        """play wav file after saving to tmp

        Args:
            req (object): requests object
        """
        if req.status_code == 200:
            self._save(req.content)
            play_wav(self.filename).communicate()
        else:
            LOG.error('%s Http Error: %s for url: %s' %
                      (req.status_code, req.reason, req.url))
Esempio n. 17
0
    def execute(self, sentence, ident=None):
        phrases = self.__get_phrases(sentence)

        if len(phrases) > 0:
            for req in self.__requests(phrases):
                try:
                    self.begin_audio()
                    self.__play(req)
                except Exception as e:
                    LOG.error(e.message)
                finally:
                    self.end_audio()
Esempio n. 18
0
 def create_config(self, dict_name, config):
     model_file = join(RECOGNIZER_DIR, 'model', self.lang, 'hmm')
     if not exists(model_file):
         LOG.error('PocketSphinx model not found at ' + str(model_file))
     config.set_string('-hmm', model_file)
     config.set_string('-dict', dict_name)
     config.set_string('-keyphrase', self.key_phrase)
     config.set_float('-kws_threshold', float(self.threshold))
     config.set_float('-samprate', self.sample_rate)
     config.set_int('-nfft', 2048)
     config.set_string('-logfn', '/dev/null')
     return config
Esempio n. 19
0
 def load_skill_settings_from_file(self):
     """ If settings.json exist, open and read stored values into self """
     if isfile(self._settings_path):
         with open(self._settings_path) as f:
             try:
                 json_data = json.load(f)
                 for key in json_data:
                     self[key] = json_data[key]
             except Exception as e:
                 # TODO: Show error on webUI.  Dev will have to fix
                 # metadata to be able to edit later.
                 LOG.error(e)
Esempio n. 20
0
 def deactivate_except(self, message):
     """ Deactivate all skills except the provided. """
     try:
         skill_to_keep = message.data['skill']
         LOG.info('DEACTIVATING ALL SKILLS EXCEPT {}'.format(skill_to_keep))
         if skill_to_keep in [basename(i) for i in self.loaded_skills]:
             for skill in self.loaded_skills:
                 if basename(skill) != skill_to_keep:
                     self.__deactivate_skill(skill)
         else:
             LOG.info('Couldn\'t find skill')
     except Exception as e:
         LOG.error('Error during skill removal, {}'.format(repr(e)))
Esempio n. 21
0
    def _play(self, message=None):
        """ Implementation specific async method to handle playback.
            This allows mpg123 service to use the "next method as well
            as basic play/stop.
        """
        LOG.info('SimpleAudioService._play')
        self._is_playing = True
        if isinstance(self.tracks[self.index], list):
            track = self.tracks[self.index][0]
            mime = self.tracks[self.index][1]
            mime = mime.split('/')
        else:  # Assume string
            track = self.tracks[self.index]
            mime = find_mime(track)
        # Indicate to audio service which track is being played
        if self._track_start_callback:
            self._track_start_callback(track)

        # Replace file:// uri's with normal paths
        track = track.replace('file://', '')
        try:
            if 'mpeg' in mime[1]:
                self.process = play_mp3(track)
            elif 'ogg' in mime[1]:
                self.process = play_ogg(track)
            elif 'wav' in mime[1]:
                self.process = play_wav(track)
            else:
                # If no mime info could be determined guess mp3
                self.process = play_mp3(track)
        except FileNotFoundError as e:
            LOG.error('Couldn\'t play audio, {}'.format(repr(e)))
            self.process = None

        # Wait for completion or stop request
        while (self.process and self.process.poll() is None
               and not self._stop_signal):
            sleep(0.25)

        if self._stop_signal:
            self.process.terminate()
            self.process = None
            self._is_playing = False
            return

        self.index += 1
        # if there are more tracks available play next
        if self.index < len(self.tracks):
            self.bus.emit(Message('SimpleAudioServicePlay'))
        else:
            self._is_playing = False
Esempio n. 22
0
 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))
Esempio n. 23
0
 def _load_settings_meta(self):
     """ Loads settings metadata from skills path. """
     if isfile(self._meta_path):
         try:
             with open(self._meta_path) as f:
                 data = json.load(f)
             return data
         except Exception as e:
             LOG.error("Failed to load setting file: " + self._meta_path)
             LOG.error(repr(e))
             return None
     else:
         LOG.debug("settingemeta.json does not exist")
         return None
Esempio n. 24
0
    def _send_settings_meta(self, settings_meta):
        """ Send settingsmeta.json to the server.

            Args:
                settings_meta (dict): dictionary of the current settings meta

            Returns:
                dict: uuid, a unique id for the setting meta data
        """
        try:
            uuid = self._put_metadata(settings_meta)
            return uuid
        except Exception as e:
            LOG.error(e)
            return None
Esempio n. 25
0
def report_metric(name, data):
    """
    Report a general metric to the OwO servers

    Args:
        name (str): Name of metric. Must use only letters and hyphens
        data (dict): JSON dictionary to report. Must be valid JSON
    """
    try:
        if is_paired() and Configuration().get()['opt_in']:
            DeviceApi().report_metric(name, data)
    except requests.RequestException as e:
        LOG.error(
            'Metric couldn\'t be uploaded, due to a network error ({})'.format(
                e))
Esempio n. 26
0
 def activate_skill(self, message):
     """ Activate a deactivated skill. """
     try:
         skill = message.data['skill']
         if skill == 'all':
             for s in self.loaded_skills:
                 self.__activate_skill(s)
         else:
             for s in self.loaded_skills:
                 if skill in s:
                     skill = s
                     break
             self.__activate_skill(skill)
     except Exception as e:
         LOG.error('Couldn\'t activate skill, {}'.format(repr(e)))
Esempio n. 27
0
    def _delete_metadata(self, uuid):
        """ Deletes the current skill metadata

            Args:
                uuid (str): unique id of the skill
        """
        try:
            LOG.debug("deleting metadata")
            self.api.request({
                "method": "DELETE",
                "path": self._api_path + "/{}".format(uuid)
            })
        except Exception as e:
            LOG.error(e)
            LOG.error("cannot delete metadata because this"
                      "device is not original uploader of skill")
Esempio n. 28
0
    def _lower_volume(self, message=None):
        """
            Is triggered when OwO starts to speak and reduces the volume.

            Args:
                message: message bus message, not used but required
        """
        if self.current:
            LOG.debug('lowering volume')
            self.current.lower_volume()
            self.volume_is_low = True
        try:
            if self.pulse_quiet:
                self.pulse_quiet()
        except Exception as exc:
            LOG.error(exc)
Esempio n. 29
0
 def _connect(self, message):
     LOG.info('Trying to connect to chromecast')
     casts = pychromecast.get_chromecasts()
     if self.config is None or 'identifier' not in self.config:
         LOG.error("Chromecast identifier not found!")
         return  # Can't connect since no id is specified
     else:
         identifier = self.config['identifier']
     for c in casts:
         if c.name == identifier:
             self.cast = c
             break
     else:
         LOG.info('Couldn\'t find chromecast ' + identifier)
         self.connection_attempts += 1
         time.sleep(10)
         self.bus.emit(Message('ChromecastServiceConnect'))
         return
Esempio n. 30
0
    def disable_intent(self, intent_name):
        """
        Disable a registered intent if it belongs to this skill

        Args:
            intent_name (string): name of the intent to be disabled

        Returns:
                bool: True if disabled, False if it wasn't registered
        """
        names = [intent_tuple[0] for intent_tuple in self.registered_intents]
        if intent_name in names:
            LOG.debug('Disabling intent ' + intent_name)
            name = str(self.skill_id) + ':' + intent_name
            self.bus.emit(Message("detach_intent", {"intent_name": name}))
            return True

        LOG.error('Could not disable ' + intent_name +
                  ', it hasn\'t been registered.')
        return False