async def handle_detection(
        self, matching_indexes: typing.List[int], raven: Raven
    ) -> typing.AsyncIterable[typing.Union[typing.Tuple[
            HotwordDetected, TopicArgs], HotwordError]]:
        """Handle a successful hotword detection"""
        try:
            template = raven.templates[matching_indexes[0]]

            wakeword_id = raven.keyword_name or template.name
            if not wakeword_id:
                wakeword_id = "default"

            yield (
                HotwordDetected(
                    site_id=self.last_audio_site_id,
                    model_id=template.name,
                    current_sensitivity=raven.probability_threshold,
                    model_version="",
                    model_type="personal",
                    lang=self.lang,
                ),
                {
                    "wakeword_id": wakeword_id
                },
            )
        except Exception as e:
            _LOGGER.exception("handle_detection")
            yield HotwordError(
                error=str(e),
                context=f"{raven.keyword_name}: {template.name}",
                site_id=self.last_audio_site_id,
            )
Example #2
0
 async def handle_detection(
     self,
     wakeword_id: str,
     site_id: str = "default"
 ) -> typing.AsyncIterable[typing.Union[typing.Tuple[
         HotwordDetected, TopicArgs], HotwordError]]:
     """Handle a successful hotword detection"""
     try:
         yield (
             HotwordDetected(
                 site_id=site_id,
                 model_id=self.keyphrase,
                 current_sensitivity=self.keyphrase_threshold,
                 model_version="",
                 model_type="personal",
             ),
             {
                 "wakeword_id": wakeword_id
             },
         )
     except Exception as e:
         _LOGGER.exception("handle_detection")
         yield HotwordError(error=str(e),
                            context=self.keyphrase,
                            site_id=site_id)
    async def handle_detection(
        self,
        keyword_index: int,
        wakeword_id: str,
        site_id="default"
    ) -> typing.AsyncIterable[typing.Union[typing.Tuple[
            HotwordDetected, TopicArgs], HotwordError]]:
        """Handle a successful hotword detection"""
        try:
            assert (len(self.model_ids) >
                    keyword_index), f"Missing {keyword_index} in models"

            yield (
                HotwordDetected(
                    site_id=site_id,
                    model_id=self.model_ids[keyword_index],
                    current_sensitivity=self.sensitivities[keyword_index],
                    model_version="",
                    model_type="personal",
                    lang=self.lang,
                ),
                {
                    "wakeword_id": wakeword_id
                },
            )
        except Exception as e:
            _LOGGER.exception("handle_detection")
            yield HotwordError(error=str(e),
                               context=str(keyword_index),
                               site_id=site_id)
    async def handle_get_hotwords(
        self, get_hotwords: GetHotwords
    ) -> typing.AsyncIterable[typing.Union[Hotwords, HotwordError]]:
        """Report available hotwords"""
        try:
            models: typing.List[Hotword] = []

            # Each keyword is in a separate Raven instance
            for raven in self.ravens:
                # Assume that the directory name is something like
                # "okay-rhasspy" for the keyword "okay rhasspy".
                models.append(
                    Hotword(
                        model_id=raven.keyword_name,
                        model_words=re.sub(r"[_-]+", " ", raven.keyword_name),
                    ))

            yield Hotwords(models=models,
                           id=get_hotwords.id,
                           site_id=get_hotwords.site_id)

        except Exception as e:
            _LOGGER.exception("handle_get_hotwords")
            yield HotwordError(error=str(e),
                               context=str(get_hotwords),
                               site_id=get_hotwords.site_id)
    async def handle_detection(
        self,
    ) -> typing.AsyncIterable[typing.Union[typing.Tuple[
            HotwordDetected, TopicArgs], HotwordError]]:
        """Handle a successful hotword detection"""
        try:
            wakeword_id = self.wakeword_id
            if not wakeword_id:
                # Use file name
                wakeword_id = self.model_path.stem

            yield (
                HotwordDetected(
                    site_id=self.last_audio_site_id,
                    model_id=self.model_id,
                    current_sensitivity=self.sensitivity,
                    model_version="",
                    model_type="personal",
                ),
                {
                    "wakeword_id": wakeword_id
                },
            )
        except Exception as e:
            _LOGGER.exception("handle_detection")
            yield HotwordError(
                error=str(e),
                context=str(self.model_path),
                site_id=self.last_audio_site_id,
            )
    async def handle_detection(
        self, model_index: int, wakeword_id: str, site_info: SiteInfo
    ) -> typing.AsyncIterable[typing.Union[typing.Tuple[
            HotwordDetected, TopicArgs], HotwordError]]:
        """Handle a successful hotword detection"""
        try:
            assert (len(site_info.model_ids) >
                    model_index), f"Missing {model_index} in models"
            sensitivity = 0.5

            if model_index < len(self.models):
                sensitivity = self.models[model_index].float_sensitivity()

            yield (
                HotwordDetected(
                    site_id=site_info.site_id,
                    model_id=site_info.model_ids[model_index],
                    current_sensitivity=sensitivity,
                    model_version="",
                    model_type="personal",
                    lang=self.lang,
                ),
                {
                    "wakeword_id": wakeword_id
                },
            )
        except Exception as e:
            _LOGGER.exception("handle_detection")
            yield HotwordError(error=str(e),
                               context=str(model_index),
                               site_id=site_info.site_id)
Example #7
0
    async def handle_detection(
        self, matching_indexes: typing.List[int]
    ) -> typing.AsyncIterable[
        typing.Union[typing.Tuple[HotwordDetected, TopicArgs], HotwordError]
    ]:
        """Handle a successful hotword detection"""
        try:
            template = self.raven.templates[matching_indexes[0]]
            wakeword_id = self.wakeword_id
            if not wakeword_id:
                wakeword_id = template.name

            yield (
                HotwordDetected(
                    site_id=self.last_audio_site_id,
                    model_id=template.name,
                    current_sensitivity=self.raven.distance_threshold,
                    model_version="",
                    model_type="personal",
                ),
                {"wakeword_id": wakeword_id},
            )
        except Exception as e:
            _LOGGER.exception("handle_detection")
            yield HotwordError(
                error=str(e),
                context=str(matching_indexes),
                site_id=self.last_audio_site_id,
            )
Example #8
0
    async def handle_get_hotwords(
        self, get_hotwords: GetHotwords
    ) -> typing.AsyncIterable[typing.Union[Hotwords, HotwordError]]:
        """Report available hotwords"""
        try:
            yield Hotwords(models=[], id=get_hotwords.id, site_id=get_hotwords.site_id)

        except Exception as e:
            _LOGGER.exception("handle_get_hotwords")
            yield HotwordError(
                error=str(e), context=str(get_hotwords), site_id=get_hotwords.site_id
            )
Example #9
0
    async def handle_get_hotwords(
        self, get_hotwords: GetHotwords
    ) -> typing.AsyncIterable[typing.Union[Hotwords, HotwordError]]:
        """Report available hotwords"""
        try:
            if self.model_dirs:
                # Add all models from model dirs
                model_paths = []
                for model_dir in self.model_dirs:
                    if not model_dir.is_dir():
                        _LOGGER.warning("Model directory missing: %s",
                                        str(model_dir))
                        continue

                    for model_file in model_dir.iterdir():
                        if model_file.is_file() and (model_file.suffix
                                                     in [".umdl", ".pmdl"]):
                            model_paths.append(model_file)
            else:
                # Add current model(s) only
                model_paths = [Path(model.model_path) for model in self.models]

            hotword_models: typing.List[Hotword] = []
            for model_path in model_paths:
                model_words = " ".join(
                    model_path.with_suffix("").name.split("_"))
                model_type = "universal" if model_path.suffix == ".umdl" else "personal"

                hotword_models.append(
                    Hotword(
                        model_id=model_path.name,
                        model_words=model_words,
                        model_type=model_type,
                    ))

            yield Hotwords(models=hotword_models,
                           id=get_hotwords.id,
                           site_id=get_hotwords.site_id)

        except Exception as e:
            _LOGGER.exception("handle_get_hotwords")
            yield HotwordError(error=str(e),
                               context=str(get_hotwords),
                               site_id=get_hotwords.site_id)
    async def handle_record_example(
        self, record_example: RecordHotwordExample
    ) -> typing.AsyncIterable[typing.Union[typing.Tuple[
            HotwordExampleRecorded, TopicArgs], HotwordError]]:
        """Record an example of a hotword."""
        try:
            if self.recording_example:
                _LOGGER.warning("Cancelling previous recording")
                self.example_recorder.stop()

            # Start recording
            assert self.loop, "No loop"
            self.example_future = self.loop.create_future()
            self.example_recorder.start()
            self.recording_example = True

            # Wait for result
            _LOGGER.debug("Recording example (id=%s)", record_example.id)
            example_audio = await self.example_future
            assert isinstance(example_audio, bytes)

            # Trim silence
            _LOGGER.debug("Trimming silence from example")
            example_audio = trim_silence(example_audio)

            # Convert to WAV format
            wav_data = self.to_wav_bytes(example_audio)

            yield (
                HotwordExampleRecorded(wav_bytes=wav_data),
                {
                    "site_id": record_example.site_id,
                    "request_id": record_example.id
                },
            )

        except Exception as e:
            _LOGGER.exception("handle_record_example")
            yield HotwordError(
                error=str(e),
                context=str(record_example),
                site_id=record_example.site_id,
            )
    async def handle_get_hotwords(
        self, get_hotwords: GetHotwords
    ) -> typing.AsyncIterable[typing.Union[Hotwords, HotwordError]]:
        """Report available hotwords"""
        try:
            if self.keyword_dirs:
                # Add all models from keyword dir
                model_paths = []
                for keyword_dir in self.keyword_dirs:
                    if not keyword_dir.is_dir():
                        _LOGGER.warning("Missing keyword dir: %s",
                                        str(keyword_dir))
                        continue

                    for keyword_file in keyword_dir.glob("*.ppn"):
                        model_paths.append(keyword_file)
            else:
                # Add current model(s) only
                model_paths = [Path(model_id) for model_id in self.model_ids]

            models: typing.List[Hotword] = []
            for ppn_file in model_paths:
                words = ppn_file.with_suffix("").name.split("_")
                if len(words) == 1:
                    # porcupine.ppn -> "porcupine"
                    model_words = words[0]
                else:
                    # smart_mirror_linux.ppn -> "smart mirror"
                    model_words = " ".join(words[:-1])

                models.append(
                    Hotword(model_id=ppn_file.name, model_words=model_words))

            yield Hotwords(models=models,
                           id=get_hotwords.id,
                           site_id=get_hotwords.site_id)

        except Exception as e:
            _LOGGER.exception("handle_get_hotwords")
            yield HotwordError(error=str(e),
                               context=str(get_hotwords),
                               site_id=get_hotwords.site_id)