Exemplo n.º 1
0
def handle_paired(event):
    """Update identity information with pairing data.

    This is done here to make sure it's only done in a single place.
    TODO: Is there a reason this isn't done directly in the pairing skill?
    """
    IdentityManager.update(event.data)
Exemplo n.º 2
0
    def refresh_token(self):
        LOG.debug('Refreshing token')
        if identity_lock.acquire(blocking=False):
            try:
                data = self.send({
                    "path": "auth/token",
                    "headers": {
                        "Authorization": "Bearer " + self.identity.refresh,
                        "Device": self.identity.uuid
                    }
                })
                IdentityManager.save(data, lock=False)
                LOG.debug('Saved credentials')
            except HTTPError as e:
                if e.response.status_code == 401:
                    LOG.error('Could not refresh token, invalid refresh code.')
                else:
                    raise

            finally:
                identity_lock.release()
        else:  # Someone is updating the identity wait for release
            with identity_lock:
                LOG.debug('Refresh is already in progress, waiting until done')
                time.sleep(1.2)
                os.sync()
                self.identity = IdentityManager.load(lock=False)
                LOG.debug('new credentials loaded')
Exemplo n.º 3
0
    def refresh_token(self):
        LOG.debug('Refreshing token')
        if identity_lock.acquire(blocking=False):
            try:
                data = self.send({
                    "path": "auth/token",
                    "headers": {
                        "Authorization": "Bearer " + self.identity.refresh
                    }
                })
                IdentityManager.save(data, lock=False)
                LOG.debug('Saved credentials')
            except HTTPError as e:
                if e.response.status_code == 401:
                    LOG.error('Could not refresh token, invalid refresh code.')
                else:
                    raise

            finally:
                identity_lock.release()
        else:  # Someone is updating the identity wait for release
            with identity_lock:
                LOG.debug('Refresh is already in progress, waiting until done')
                time.sleep(1.2)
                os.sync()
                self.identity = IdentityManager.load(lock=False)
                LOG.debug('new credentials loaded')
 def refresh_token(self):
     data = self.send({
         "path": "auth/token",
         "headers": {
             "Authorization": "Bearer " + self.identity.refresh
         }
     })
     IdentityManager.save(data)
Exemplo n.º 5
0
 def refresh_token(self):
     data = self.send({
         "path": "auth/token",
         "headers": {
             "Authorization": "Bearer " + self.identity.refresh
         }
     })
     IdentityManager.save(data)
Exemplo n.º 6
0
 def __init__(self, config=_config, pairing_code=None):
     self.config = config
     self.ws_client = WebsocketClient(host=config.get("host"),
                                      port=config.get("port"),
                                      path=config.get("route"),
                                      ssl=str2bool(config.get("ssl")))
     self.identity_manager = IdentityManager()
     self.identity = self.identity_manager.identity
     self.pairing_code = pairing_code if pairing_code else generate_pairing_code()
Exemplo n.º 7
0
 def check_token(self):
     # If the identity hasn't been loaded, load it
     if not self.identity.has_refresh():
         self.identity = IdentityManager.load()
     # If refresh is needed perform a refresh
     if self.identity.refresh and self.identity.is_expired():
         self.identity = IdentityManager.load()
         # if no one else has updated the token refresh it
         if self.identity.is_expired():
             self.refresh_token()
Exemplo n.º 8
0
 def check_token(self):
     # If the identity hasn't been loaded, load it
     if not self.identity.has_refresh():
         self.identity = IdentityManager.load()
     # If refresh is needed perform a refresh
     if self.identity.refresh and self.identity.is_expired():
         self.identity = IdentityManager.load()
         # if no one else has updated the token refresh it
         if self.identity.is_expired():
             self.refresh_token()
Exemplo n.º 9
0
 def check_token(self):
     if self.identity.refresh and self.identity.is_expired():
         self.identity = IdentityManager.load()
         if self.identity.is_expired():
             data = self.send({
                 "path": "auth/token",
                 "headers": {
                     "Authorization": "Bearer " + self.identity.refresh
                 }
             })
             IdentityManager.save(data)
Exemplo n.º 10
0
    def activate(self):
        try:
            token = self.data.get("token")
            login = self.api.activate(self.state, token)
            self.enclosure.activate_mouth_events()
            self.speak_dialog("pairing.paired")
            IdentityManager.save(login)
            self.emitter.emit(Message("mycroft.paired", login))
        except:
            self.data["expiration"] -= self.delay

            if self.data.get("expiration") <= 0:
                self.data = None
                self.handle_pairing()
            else:
                self.__create_activator()
Exemplo n.º 11
0
 def handle_update_intent(self, message):
     identity = IdentityManager().get()
     if not identity.owner:
         self.speak_dialog("not.paired")
     else:
         ConfigurationManager.load_remote()
         self.speak_dialog("config.updated")
Exemplo n.º 12
0
 def __init__(self, path):
     self.path = path
     config = ConfigurationManager().get()
     config_server = config.get("server")
     self.url = config_server.get("url")
     self.version = config_server.get("version")
     self.identity = IdentityManager.get()
Exemplo n.º 13
0
 def __init__(self, path):
     self.path = path
     config = ConfigurationManager.get()
     config_server = config.get("server")
     self.url = config_server.get("url")
     self.version = config_server.get("version")
     self.identity = IdentityManager.get()
Exemplo n.º 14
0
 def handle_update_request(self, message):
     identity = IdentityManager().get()
     if not identity.owner:
         self.speak_dialog("not.paired")
     else:
         rc = RemoteConfiguration()
         rc.update()
         self.speak_dialog("config.updated")
Exemplo n.º 15
0
 def __init__(self, path):
     self.path = path
     config = Configuration.get(
         [DEFAULT_CONFIG, SYSTEM_CONFIG, USER_CONFIG], cache=False)
     config_server = config.get("server")
     self.url = config_server.get("url")
     self.version = config_server.get("version")
     self.identity = IdentityManager.get()
Exemplo n.º 16
0
 def select_stt(self, message):
     selection = message.data["engine"]
     self.send_stop_signal("pairing.stt.menu.stop")
     if selection == "google":
         self.change_to_chromium()
     elif selection == "kaldi":
         self.change_to_kaldi()
     if not self.using_mock:
         self.enable_mock()
         # create pairing file with dummy data
         login = {"uuid": self.state,
                  "access":
                      "OVOSdbF1wJ4jA5lN6x6qmVk_QvJPqBQZTUJQm7fYzkDyY_Y=",
                  "refresh":
                      "OVOS66c5SpAiSpXbpHlq9HNGl1vsw_srX49t5tCv88JkhuE=",
                  "expires_at": time.time() + 999999}
         IdentityManager.save(login)
     self.handle_tts_menu()
Exemplo n.º 17
0
    def transcribe(self,
                   audio,
                   language="en-US",
                   show_all=False,
                   metrics=None):
        timer = Stopwatch()
        timer.start()
        identity = IdentityManager().get()
        headers = {}
        if identity.token:
            headers['Authorization'] = 'Bearer %s:%s' % (identity.device_id,
                                                         identity.token)

        response = requests.post(config.get("proxy_host") +
                                 "/stt/google_v2?language=%s&version=%s" %
                                 (language, self.version),
                                 audio.get_flac_data(),
                                 headers=headers)

        if metrics:
            t = timer.stop()
            metrics.timer("mycroft.cerberus.proxy.client.time_s", t)
            metrics.timer("mycroft.stt.remote.time_s", t)

        if response.status_code == 401:
            raise CerberusAccessDenied()

        try:
            actual_result = response.json()
        except:
            raise UnknownValueError()

        log.info("STT JSON: " + json.dumps(actual_result))
        if show_all:
            return actual_result

        # return the best guess
        if "alternative" not in actual_result:
            raise UnknownValueError()
        alternatives = actual_result["alternative"]
        if len([alt for alt in alternatives if alt.get('confidence')]) > 0:
            # if there is at least one element with confidence, force it to
            # the front
            alternatives.sort(key=lambda e: e.get('confidence', 0.0),
                              reverse=True)

        for entry in alternatives:
            if "transcript" in entry:
                return entry["transcript"]

        if len(alternatives) > 0:
            log.error("Found %d entries, but none with a transcript." %
                      len(alternatives))

        # no transcriptions available
        raise UnknownValueError()
Exemplo n.º 18
0
 def __init__(self, path):
     self.path = path
     config = Configuration.get([LocalConf(DEFAULT_CONFIG),
                                 LocalConf(SYSTEM_CONFIG),
                                 LocalConf(USER_CONFIG)],
                                cache=False)
     config_server = config.get("server")
     self.url = config_server.get("url")
     self.version = config_server.get("version")
     self.identity = IdentityManager.get()
Exemplo n.º 19
0
class DevicePairingClient(object):
    def __init__(self, config=_config, pairing_code=None):
        self.config = config
        self.paired = False
        self.ws_client = WebsocketClient(host=config.get("host"),
                                         port=config.get("port"),
                                         path=config.get("route"),
                                         ssl=str2bool(config.get("ssl")))
        self.identity_manager = IdentityManager()
        self.identity = self.identity_manager.identity
        self.pairing_code = (pairing_code
                             if pairing_code else generate_pairing_code())

    def on_registration(self, message):
        # TODO: actually accept the configuration message and store it in
        # identity
        identity = self.identity_manager.get()
        register_payload = message.metadata
        if register_payload.get("device_id") == identity.device_id:
            identity.token = register_payload.get('token')
            identity.owner = register_payload.get('user')
            self.identity_manager.update(identity)
            self.ws_client.close()
            self.paired = True

    def send_device_info(self):
        msg = Message("device_info",
                      metadata={
                          "pairing_code": self.pairing_code,
                          "device_id": self.identity.device_id
                      })

        self.ws_client.emit(msg)

    @staticmethod
    def print_error(message):
        print(repr(message))

    def run(self):
        self.ws_client.on('registration', self.on_registration)
        self.ws_client.on('open', self.send_device_info)
        self.ws_client.on('error', self.print_error)
        self.ws_client.run_forever()
Exemplo n.º 20
0
def has_been_paired():
    """ Determine if this device has ever been paired with a web backend

    Returns:
        bool: True if ever paired with backend (not factory reset)
    """
    # This forces a load from the identity file in case the pairing state
    # has recently changed
    id = IdentityManager.load()
    return id.uuid is not None and id.uuid != ""
Exemplo n.º 21
0
def has_been_paired():
    """ Determine if this device has ever been paired with a web backend

    Returns:
        bool: True if ever paired with backend (not factory reset)
    """
    # This forces a load from the identity file in case the pairing state
    # has recently changed
    id = IdentityManager.load()
    return id.uuid is not None and id.uuid != ""
Exemplo n.º 22
0
    def __init__(self, path):
        self.path = path

        # Load the config, skipping the remote config since we are
        # getting the info needed to get to it!
        config = Configuration.get(cache=False, remote=False)
        config_server = config.get("server")
        self.url = config_server.get("url")
        self.version = config_server.get("version")
        self.identity = IdentityManager.get()
Exemplo n.º 23
0
class DevicePairingClient(object):
    def __init__(self, config=_config, pairing_code=None):
        self.config = config
        self.paired = False
        self.ws_client = WebsocketClient(host=config.get("host"),
                                         port=config.get("port"),
                                         path=config.get("route"),
                                         ssl=str2bool(config.get("ssl")))
        self.identity_manager = IdentityManager()
        self.identity = self.identity_manager.identity
        self.pairing_code = (
            pairing_code if pairing_code else generate_pairing_code())

    def on_registration(self, message):
        # TODO: actually accept the configuration message and store it in
        # identity
        identity = self.identity_manager.get()
        register_payload = message.metadata
        if register_payload.get("device_id") == identity.device_id:
            identity.token = register_payload.get('token')
            identity.owner = register_payload.get('user')
            self.identity_manager.update(identity)
            self.ws_client.close()
            self.paired = True

    def send_device_info(self):
        msg = Message("device_info",
                      metadata={
                          "pairing_code": self.pairing_code,
                          "device_id": self.identity.device_id
                      })

        self.ws_client.emit(msg)

    @staticmethod
    def print_error(message):
        print(repr(message))

    def run(self):
        self.ws_client.on('registration', self.on_registration)
        self.ws_client.on('open', self.send_device_info)
        self.ws_client.on('error', self.print_error)
        self.ws_client.run_forever()
Exemplo n.º 24
0
    def on_activate(self):
        try:
            # wait for a signal from the backend that pairing is complete
            token = self.data.get("token")
            login = self.api.activate(self.state, token)

            # shut down thread that repeats the code to the user
            if self.repeater:
                self.repeater.cancel()
                self.repeater = None

            # is_speaking() and stop_speaking() support is mycroft-core 0.8.16+
            try:
                if mycroft.util.is_speaking():
                    # Assume speaking is the pairing code.  Stop TTS
                    mycroft.util.stop_speaking()
            except:
                pass

            self.enclosure.activate_mouth_events()  # clears the display
            self.speak_dialog("pairing.paired")
            
            # wait_while_speaking() support is mycroft-core 0.8.16+
            try:
                mycroft.util.wait_while_speaking()
            except:
                pass

            IdentityManager.save(login)
            self.emitter.emit(Message("mycroft.paired", login))

            # Un-mute.  Would have been muted during onboarding for a new
            # unit, and not dangerous to do if pairing was started
            # independently.
            self.emitter.emit(Message("mycroft.mic.unmute", None))

        except:
            if self.last_request < time.time():
                self.data = None
                self.handle_pairing()
            else:
                self.__create_activator()
Exemplo n.º 25
0
    def __init__(self, path):
        self.path = path

        # Load the config, skipping the REMOTE_CONFIG since we are
        # getting the info needed to get to it!
        config = Configuration.get(
            [DEFAULT_CONFIG, SYSTEM_CONFIG, USER_CONFIG], cache=False)
        config_server = config.get("server")
        self.url = config_server.get("url")
        self.version = config_server.get("version")
        self.identity = IdentityManager.get()
Exemplo n.º 26
0
 def refresh_token(self):
     LOG.debug('Refreshing token')
     if identity_lock.acquire(blocking=False):
         try:
             data = self.send({
                 "path": "auth/token",
                 "headers": {
                     "Authorization": "Bearer " + self.identity.refresh
                 }
             })
             IdentityManager.save(data, lock=False)
             LOG.debug('Saved credentials')
         finally:
             identity_lock.release()
     else:  # Someone is updating the identity wait for release
         with identity_lock:
             LOG.debug('Refresh is already in progress, waiting until done')
             time.sleep(1.2)
             os.sync()
             self.identity = IdentityManager.load(lock=False)
             LOG.debug('new credentials loaded')
Exemplo n.º 27
0
 def refresh_token(self):
     LOG.debug('Refreshing token')
     if identity_lock.acquire(blocking=False):
         try:
             data = self.send({
                 "path": "auth/token",
                 "headers": {
                     "Authorization": "Bearer " + self.identity.refresh
                 }
             })
             IdentityManager.save(data, lock=False)
             LOG.debug('Saved credentials')
         finally:
             identity_lock.release()
     else:  # Someone is updating the identity wait for release
         with identity_lock:
             LOG.debug('Refresh is already in progress, waiting until done')
             time.sleep(1.2)
             os.sync()
             self.identity = IdentityManager.load(lock=False)
             LOG.debug('new credentials loaded')
Exemplo n.º 28
0
    def __init__(self, path):
        self.path = path

        # Load the config, skipping the REMOTE_CONFIG since we are
        # getting the info needed to get to it!
        config = Configuration.get([DEFAULT_CONFIG,
                                    SYSTEM_CONFIG,
                                    USER_CONFIG],
                                   cache=False)
        config_server = config.get("server")
        self.url = config_server.get("url")
        self.version = config_server.get("version")
        self.identity = IdentityManager.get()
Exemplo n.º 29
0
 def query(self, query):
     """
     Query Wolfram|Alpha with query using the v2.0 API
     """
     identity = IdentityManager().get()
     bearer_token = 'Bearer %s:%s' % (identity.device_id, identity.token)
     query = urllib.parse.urlencode(dict(input=query))
     url = 'https://cerberus.mycroft.ai/wolframalpha/v2/query?' + query
     headers = {'Authorization': bearer_token}
     response = requests.get(url, headers=headers)
     if response.status_code == 401:
         raise CerberusAccessDenied()
     return wolframalpha.Result(StringIO(response.content))
Exemplo n.º 30
0
    def load(config=None):
        RemoteConfiguration.validate_config(config)

        identity = IdentityManager().get()
        config_remote = config.get("remote_configuration", {})
        enabled = str2bool(config_remote.get("enabled", "False"))

        if enabled and identity.token:
            url = config_remote.get("url")
            auth_header = "Bearer %s:%s" % (identity.device_id, identity.token)
            try:
                response = requests.get(url,
                                        headers={"Authorization": auth_header})
                user = response.json()
                RemoteConfiguration.__load_attributes(config, user)
            except Exception as e:
                logger.error("Failed to fetch remote configuration: %s" %
                             repr(e))
        else:
            logger.debug(
                "Device not paired, cannot retrieve remote configuration.")
        return config
Exemplo n.º 31
0
 def get_code(self, state):
     IdentityManager.update()
     return self.request({
         "path": "/code?state=" + state
     })
Exemplo n.º 32
0
 def check_token(self):
     if self.identity.refresh and self.identity.is_expired():
         self.identity = IdentityManager.load()
         if self.identity.is_expired():
             self.refresh_token()
Exemplo n.º 33
0
    def _wait_until_wake_word(self, source, sec_per_buffer):
        """Listen continuously on source until a wake word is spoken

        Args:
            source (AudioSource):  Source producing the audio chunks
            sec_per_buffer (float):  Fractional number of seconds in each chunk
        """
        num_silent_bytes = int(self.SILENCE_SEC * source.SAMPLE_RATE *
                               source.SAMPLE_WIDTH)

        silence = '\0' * num_silent_bytes

        # bytearray to store audio in
        byte_data = silence

        buffers_per_check = self.SEC_BETWEEN_WW_CHECKS / sec_per_buffer
        buffers_since_check = 0.0

        # Max bytes for byte_data before audio is removed from the front
        max_size = self.sec_to_bytes(self.SAVED_WW_SEC, source)
        test_size = self.sec_to_bytes(self.TEST_WW_SEC, source)

        said_wake_word = False

        # Rolling buffer to track the audio energy (loudness) heard on
        # the source recently.  An average audio energy is maintained
        # based on these levels.
        energies = []
        idx_energy = 0
        avg_energy = 0.0
        energy_avg_samples = int(5 / sec_per_buffer)  # avg over last 5 secs

        counter = 0

        while not said_wake_word and not self._stop_signaled:
            if self._skip_wake_word():
                break
            chunk = self.record_sound_chunk(source)

            energy = self.calc_energy(chunk, source.SAMPLE_WIDTH)
            if energy < self.energy_threshold * self.multiplier:
                self._adjust_threshold(energy, sec_per_buffer)

            if len(energies) < energy_avg_samples:
                # build the average
                energies.append(energy)
                avg_energy += float(energy) / energy_avg_samples
            else:
                # maintain the running average and rolling buffer
                avg_energy -= float(energies[idx_energy]) / energy_avg_samples
                avg_energy += float(energy) / energy_avg_samples
                energies[idx_energy] = energy
                idx_energy = (idx_energy + 1) % energy_avg_samples

                # maintain the threshold using average
                if energy < avg_energy * 1.5:
                    if energy > self.energy_threshold:
                        # bump the threshold to just above this value
                        self.energy_threshold = energy * 1.2

            # Periodically output energy level stats.  This can be used to
            # visualize the microphone input, e.g. a needle on a meter.
            if counter % 3:
                with open(self.mic_level_file, 'w') as f:
                    f.write("Energy:  cur=" + str(energy) + " thresh=" +
                            str(self.energy_threshold))
                f.close()
            counter += 1

            # At first, the buffer is empty and must fill up.  After that
            # just drop the first chunk bytes to keep it the same size.
            needs_to_grow = len(byte_data) < max_size
            if needs_to_grow:
                byte_data += chunk
            else:  # Remove beginning of audio and add new chunk to end
                byte_data = byte_data[len(chunk):] + chunk

            buffers_since_check += 1.0
            self.wake_word_recognizer.update(chunk)
            if buffers_since_check > buffers_per_check:
                buffers_since_check -= buffers_per_check
                chopped = byte_data[-test_size:] \
                    if test_size < len(byte_data) else byte_data
                audio_data = chopped + silence
                said_wake_word = \
                    self.wake_word_recognizer.found_wake_word(audio_data)
                # if a wake word is success full then record audio in temp
                # file.
                if self.save_wake_words and said_wake_word:
                    audio = self._create_audio_data(byte_data, source)

                    if not isdir(self.save_wake_words_dir):
                        mkdir(self.save_wake_words_dir)
                    dr = self.save_wake_words_dir

                    ww_module = self.wake_word_recognizer.__class__.__name__

                    ww = self.wake_word_name.replace(' ', '-')
                    md = str(abs(hash(ww_module)))
                    stamp = str(int(1000 * get_time()))
                    sid = SessionManager.get().session_id
                    uid = IdentityManager.get().uuid

                    fn = join(dr, '.'.join([ww, md, stamp, sid, uid]) + '.wav')
                    with open(fn, 'wb') as f:
                        f.write(audio.get_wav_data())

                    if self.upload_config['enable'] or self.config['opt_in']:
                        t = Thread(target=self._upload_file, args=(fn, ))
                        t.daemon = True
                        t.start()
Exemplo n.º 34
0
 def get_code(self, state):
     IdentityManager.update()
     return self.request({
         "path": "/code?state=" + state
     })
Exemplo n.º 35
0
def handle_paired(event):
    IdentityManager.update(event.data)
Exemplo n.º 36
0
 def __init__(self, identity=None):
     self.identity = identity or IdentityManager().get()
     self.config_manager = ConfigurationManager()
Exemplo n.º 37
0
 def check_token(self):
     if self.identity.refresh and self.identity.is_expired():
         self.identity = IdentityManager.load()
         if self.identity.is_expired():
             self.refresh_token()
Exemplo n.º 38
0
 def owm(self):
     return OWM(API_key=self.config.get('api_key', ''), identity=IdentityManager().get())
Exemplo n.º 39
0
def handle_paired(event):
    IdentityManager.update(event.data)
Exemplo n.º 40
0
    def check_for_activate(self):
        """Method is called every 10 seconds by Timer. Checks if user has
        activated the device yet on home.mycroft.ai and if not repeats
        the pairing code every 60 seconds.
        """
        try:
            # Attempt to activate.  If the user has completed pairing on the,
            # backend, this will succeed.  Otherwise it throws and HTTPError()

            token = self.data.get("token")
            login = self.api.activate(self.state, token)  # HTTPError() thrown

            # When we get here, the pairing code has been entered on the
            # backend and pairing can now be saved.
            # The following is kinda ugly, but it is really critical that we
            # get this saved successfully or we need to let the user know that
            # they have to perform pairing all over again at the website.
            try:
                IdentityManager.save(login)
            except Exception as e:
                self.log.debug("First save attempt failed: " + repr(e))
                time.sleep(2)
                try:
                    IdentityManager.save(login)
                except Exception as e2:
                    # Something must be seriously wrong
                    self.log.debug("Second save attempt failed: " + repr(e2))
                    self.abort_and_restart()

            if mycroft.audio.is_speaking():
                # Assume speaking is the pairing code.  Stop TTS of that.
                mycroft.audio.stop_speaking()

            self.enclosure.activate_mouth_events()  # clears the display

            # Notify the system it is paired
            self.gui.show_page("pairing_done.qml", override_idle=False)
            self.bus.emit(Message("mycroft.paired", login))

            self.pairing_performed = True
            with self.pair_dialog_lock:
                if self.mycroft_ready:
                    # Tell user they are now paired
                    self.speak_dialog(self.paired_dialog)
                    mycroft.audio.wait_while_speaking()
                else:
                    self.speak_dialog("wait.for.startup")
                    mycroft.audio.wait_while_speaking()

            # Un-mute.  Would have been muted during onboarding for a new
            # unit, and not dangerous to do if pairing was started
            # independently.
            self.bus.emit(Message("mycroft.mic.unmute", None))

            # Send signal to update configuration
            self.bus.emit(Message("configuration.updated"))

            # Allow this skill to auto-update again
            self.reload_skill = True
        except HTTPError:
            # speak pairing code every 60th second
            with self.counter_lock:
                if self.count == 0:
                    self.speak_code()
                self.count = (self.count + 1) % 6

            if time.monotonic() > self.time_code_expires:
                # After 20 hours the token times out.  Restart
                # the pairing process.
                with self.counter_lock:
                    self.count = -1
                self.data = None
                self.handle_pairing()
            else:
                # trigger another check in 10 seconds
                self.__create_activator()
        except Exception as e:
            self.log.debug("Unexpected error: " + repr(e))
            self.abort_and_restart()