def deactivate_named_layer(self, name): if name in self.named_layers: i = self.named_layers[name] LOG.info("deactivating layer named: " + name) self.deactivate_layer(i) else: LOG.error("no layer named: " + name)
def get_regex_manifest(self): start = time.time() self._response = None self.waiting = True self.bus.emit( Message("intent.service.adapt.vocab.manifest.get", context={ "destination": "intent_service", "source": "intent_api" })) while self.waiting and time.time() - start <= self.timeout: time.sleep(0.3) if time.time() - start > self.timeout: LOG.error("Intent Service timed out!") return None vocab = {} for voc in self._response["vocab"]: if not voc.get("regex"): continue name = voc["regex"].split("(?P<")[-1].split(">")[0] if name not in vocab: vocab[name] = {"samples": []} vocab[name]["samples"].append(voc["regex"]) return [{ "name": voc, "regexes": vocab[voc]["samples"] } for voc in vocab]
def get_entities_manifest(self): start = time.time() self._response = None self.waiting = True self.bus.emit( Message("intent.service.padatious.entities.manifest.get", context={ "destination": "intent_service", "source": "intent_api" })) while self.waiting and time.time() - start <= self.timeout: time.sleep(0.3) if time.time() - start > self.timeout: LOG.error("Intent Service timed out!") return None entities = [] # read files for ent in self._response["entities"]: if isfile(ent["file_name"]): with open(ent["file_name"]) as f: lines = f.read().replace("(", "").replace(")", "").split("\n") samples = [] for l in lines: samples += [a.strip() for a in l.split("|") if a.strip()] entities.append({"name": ent["name"], "samples": samples}) return entities
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
def read(self): try: audio = self.queue.get(timeout=0.5) except Empty: return if audio is None: return tag, data = audio if tag == AUDIO_DATA: if data is not None: if self.state.sleeping: self.wake_up(data) else: self.process(data) elif tag == STREAM_START: self.stt.stream_start() elif tag == STREAM_DATA: self.stt.stream_data(data) elif tag == STREAM_STOP: self.stt.stream_stop() else: LOG.error("Unknown audio queue type %r" % audio)
def on_gui_message(self, payload): try: msg = json.loads(payload) if self.debug: LOG.debug("Msg: " + str(payload)) msg_type = msg.get("type") if msg_type == "mycroft.session.set": skill = msg.get("namespace") self.skill = self.skill or skill data = msg.get("data") if skill not in self.vars: self.vars[skill] = {} for d in data: self.vars[skill][d] = data[d] self.on_new_gui_data(data) elif msg_type == "mycroft.session.list.insert": # Insert new namespace self.skill = msg['data'][0]['skill_id'] self.loaded.insert(0, [self.skill, []]) elif msg_type == "mycroft.gui.list.insert": # Insert a page in an existing namespace self.page = msg['data'][0]['url'] pos = msg.get('position') # TODO sometimes throws IndexError: list index out of range # not invalid json, seems like either pos is out of range or # "mycroft.session.list.insert" message was missed # NOTE: only happened once with wiki skill, cant replicate self.loaded[0][1].insert(pos, self.page) #self.skill = self.loaded[0][0] elif msg_type == "mycroft.session.list.move": # Move the namespace at "pos" to the top of the stack pos = msg.get('from') self.loaded.insert(0, self.loaded.pop(pos)) elif msg_type == "mycroft.session.list.remove": pos = msg.get('position') skill = msg.get("namespace") if self.skill == skill: self.skill = None self.loaded.pop(pos) elif msg_type == "mycroft.events.triggered": # Switch selected page of namespace skill = msg['namespace'] self.skill = self.skill or skill pos = msg['data']['number'] for n in self.loaded: if n[0] == skill: # TODO sometimes pos throws # IndexError: list index out of range # ocasionally happens with weather skill # LOGS: # 05:38:29.363 - __main__:on_gui_message:56 - DEBUG - Msg: {"type": "mycroft.events.triggered", "namespace": "mycroft-weather.mycroftai", "event_name": "page_gained_focus", "data": {"number": 1}} # 05:38:29.364 - __main__:on_gui_message:90 - ERROR - list index out of range self.page = n[1][pos] self._draw_buffer() self.on_message(msg) except Exception as e: if self.debug: LOG.exception(e) LOG.error("Invalid JSON: " + str(payload))
def replace_named_layer(self, name, intent_list=None): if name in self.named_layers: i = self.named_layers[name] LOG.info("replacing layer named: " + name) self.replace_layer(i, intent_list) else: LOG.error("no layer named: " + name)
def remove_named_layer(self, name): if name in self.named_layers: i = self.named_layers[name] LOG.info("removing layer named: " + name) self.remove_layer(i) else: LOG.error("no layer named: " + name)
def previous(self): LOG.info("Going to previous Intent Layer") self.current_layer -= 1 if self.current_layer < 0: self.current_layer = 0 LOG.error("Already in layer 0") else: self.activate_layer(self.current_layer)
def handle_incoming_mycroft(self, message): assert isinstance(message, Message) if message.msg_type == "speak": utterance = message.data["utterance"] self.speak(utterance) elif message.msg_type == "hive.complete_intent_failure": LOG.error("complete intent failure") self.speak('I don\'t know how to answer that')
def step(callback=callback): try: if not self.finished: self.animate() if callback: callback(self) except Exception as e: LOG.error(e)
def validate_connection(self): try: if not self.tts.voice: raise Exception("Polly TTS Voice not configured") output = self.tts.describe_voices() except NoCredentialsError: LOG.error('PollyTTS credentials not set') raise
def deactivate_layer(self, layer_num): # error check if layer_num < 0 or layer_num > len(self.layers): LOG.error("invalid layer number") return False LOG.info("Deactivating Layer " + str(layer_num)) for intent_name in self.layers[layer_num]: self.disable_intent(intent_name) return True
def __play(self, req): resp = req.result() filename = join(self.cache_dir, "tts.wav") if resp.status_code == 200: self.__save(resp.content) play_wav(filename).communicate() else: LOG.error('%s Http Error: %s for url: %s' % (resp.status_code, resp.reason, resp.url))
def _respond(self, message): """ gather data and emit to bus """ try: if self.callback: self.callback(message) except Exception as e: LOG.error(e) self.service.respond(message)
def encrypt(key, text, nonce=None): if AES is None: LOG.error("run pip install pycryptodome") raise ImportError if not isinstance(text, bytes): text = bytes(text, encoding="utf-8") if not isinstance(key, bytes): key = bytes(key, encoding="utf-8") cipher = AES.new(key, AES.MODE_GCM, nonce=nonce) ciphertext, tag = cipher.encrypt_and_digest(text) return ciphertext, tag, cipher.nonce
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
def execute(self, sentence, ident=None, listen=False): 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()
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))
def handle_incoming_mycroft(self, message): assert isinstance(message, Message) channel_id = message.context.get("channel") user_data = message.context.get("user") if channel_id and user_data: if message.msg_type == "speak": utterance = message.data["utterance"] self.speak(utterance, channel_id, user_data) elif message.msg_type == "hive.complete_intent_failure": LOG.error("complete intent failure") utterance = 'I don\'t know how to answer that' self.speak(utterance, channel_id, user_data)
def decrypt(key, ciphertext, tag, nonce): if AES is None: LOG.error("run pip install pycryptodome") raise ImportError if not isinstance(key, bytes): key = bytes(key, encoding="utf-8") cipher = AES.new(key, AES.MODE_GCM, nonce) try: data = cipher.decrypt_and_verify(ciphertext, tag) text = data.decode(encoding="utf-8") return text except Exception as e: LOG.error("decryption failed, invalid key?") raise
def play_ogg(uri, play_cmd="ogg123 -q %1"): """ Play a ogg-file. Returns: subprocess.Popen object """ play_ogg_cmd = str(play_cmd).split(" ") for index, cmd in enumerate(play_ogg_cmd): if cmd == "%1": play_ogg_cmd[index] = uri try: return subprocess.Popen(play_ogg_cmd) except Exception as e: LOG.error("Failed to launch OGG: {}".format(play_ogg_cmd)) LOG.debug("Error: {}".format(repr(e)), exc_info=True) return None
def sendMessage(self, type, data, context=None): if self.client is None: logger.error("Client is none") return if context is None: context = {} msg = self.client.serialize_message(Message(type, data, context)) self.client.sendMessage(msg, isBinary=False) self.bus.emit( Message("hive.mind.message.sent", { "type": type, "data": data, "context": context, "raw": msg }))
def load_phonemes(self, key): """ Load phonemes from cache file. Args: Key: Key identifying phoneme cache """ pho_file = os.path.join(get_cache_directory("tts"), key + ".pho") if os.path.exists(pho_file): try: with open(pho_file, "r") as cachefile: phonemes = json.load(cachefile) return phonemes except Exception as e: LOG.error("Failed to read .PHO from cache ({})".format(e)) return None
def get_skills(self): start = time.time() self._response = None self.waiting = True self.bus.emit( Message("intent.service.skills.get", context={ "destination": "intent_service", "source": "intent_api" })) while self.waiting and time.time() - start <= self.timeout: time.sleep(0.3) if time.time() - start > self.timeout: LOG.error("Intent Service timed out!") return None return self._response["skills"]
def get_intent(self, utterance): """ get best intent for utterance """ start = time.time() self._response = None self.waiting = True self.bus.emit( Message("intent.service.intent.get", {"utterance": utterance}, context={ "destination": "intent_service", "source": "intent_api" })) while self.waiting and time.time() - start <= self.timeout: time.sleep(0.3) if time.time() - start > self.timeout: LOG.error("Intent Service timed out!") return None return self._response["intent"]
def update_precise(self, precise_config): """Continously try to download precise until successful""" precise_exe = None while not precise_exe: try: precise_exe = self.install_exe(precise_config['dist_url']) except TriggerReload: raise except Exception as e: LOG.error( 'Precise could not be downloaded({})'.format(repr(e))) if exists(self.install_destination): precise_exe = self.install_destination else: # Wait one minute before retrying sleep(60) return precise_exe
def transcribe(self, audio): def send_unknown_intent(): """ Send message that nothing was transcribed. """ self.emitter.emit('recognizer_loop:speech.recognition.unknown') try: # Invoke the STT engine on the audio clip text = self.stt.execute(audio) if text is not None: text = text.lower().strip() LOG.debug("STT: " + text) else: send_unknown_intent() LOG.info('no words were transcribed') if self.save_utterances: mtd = self._compile_metadata(text) filename = os.path.join(self.saved_utterances_dir, mtd["name"]) with open(filename, 'wb') as f: f.write(audio.get_wav_data()) filename = os.path.join(self.saved_utterances_dir, mtd["name"].replace(".wav", ".json")) with open(filename, 'w') as f: json.dump(mtd, f, indent=4) return text except sr.RequestError as e: LOG.error("Could not request Speech Recognition {0}".format(e)) except ConnectionError as e: LOG.error("Connection Error: {0}".format(e)) self.emitter.emit("recognizer_loop:no_internet") except RequestException as e: LOG.error(e.__class__.__name__ + ': ' + str(e)) except Exception as e: send_unknown_intent() LOG.error(e) LOG.error("Speech Recognition could not understand audio") return None dialog_name = 'not connected to the internet' self.emitter.emit('speak', {'utterance': dialog_name})
def handle_send(self, message): # send message to client msg = message.data.get("payload") is_file = message.data.get("isBinary") peer = message.data.get("peer") if is_file: # TODO send file pass elif peer in self.clients: # send message to client client = self.clients[peer] payload = Message.serialize(msg) client.sendMessage(payload, False) else: LOG.error("That client is not connected") self.mycroft_send("hive.client.send.error", { "error": "That client is not connected", "peer": peer }, message.context)
def create_self_signed_cert(cert_dir, name="jarbas"): """ If name.crt and name.key don't exist in cert_dir, create a new self-signed cert and key pair and write them into that directory. """ if crypto is None: LOG.error("run pip install pyopenssl") raise ImportError CERT_FILE = name + ".crt" KEY_FILE = name + ".key" cert_path = join(cert_dir, CERT_FILE) key_path = join(cert_dir, KEY_FILE) if not exists(join(cert_dir, CERT_FILE)) \ or not exists(join(cert_dir, KEY_FILE)): # create a key pair k = crypto.PKey() k.generate_key(crypto.TYPE_RSA, 1024) # create a self-signed cert cert = crypto.X509() cert.get_subject().C = "PT" cert.get_subject().ST = "Europe" cert.get_subject().L = "Mountains" cert.get_subject().O = "Jarbas AI" cert.get_subject().OU = "Powered by Mycroft-Core" cert.get_subject().CN = gethostname() cert.set_serial_number(random.randint(0, 2000)) cert.gmtime_adj_notBefore(0) cert.gmtime_adj_notAfter(10 * 365 * 24 * 60 * 60) cert.set_issuer(cert.get_subject()) cert.set_pubkey(k) # TODO don't use sha1 cert.sign(k, 'sha1') if not exists(cert_dir): makedirs(cert_dir) open(cert_path, "wt").write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert)) open(join(cert_dir, KEY_FILE), "wt").write(crypto.dump_privatekey(crypto.FILETYPE_PEM, k)) return cert_path, key_path