def in_started(self, message: Any, sender: RhasspyActor) -> None: """Handle messages in started state.""" if isinstance(message, RecognizeIntent): post_url = urljoin(self.hass_config["url"], "api/conversation/process") # Send to Home Assistant kwargs = hass_request_kwargs(self.hass_config, self.pem_file) kwargs["json"] = {"text": message.text} if self.pem_file is not None: kwargs["verify"] = self.pem_file # POST to /api/conversation/process response = requests.post(post_url, **kwargs) response.raise_for_status() response_json = response.json() # Extract speech if self.handle_speech: speech = pydash.get(response_json, "speech.plain.speech", "") if speech: # Forward to TTS system self._logger.debug("Handling speech") self.send(sender, SpeakSentence(speech)) # Return empty intent since conversation doesn't give it to us intent = empty_intent() intent["text"] = message.text intent["raw_text"] = message.text intent["speech_confidence"] = message.confidence self.send(message.receiver or sender, IntentRecognized(intent))
def in_ready(self, message: Any, sender: RhasspyActor) -> None: """Handle messages in ready state.""" if isinstance(message, HandleIntent): self.receiver = message.receiver or sender intent = message.intent try: self._logger.debug(self.command) # JSON -> STDIN -> STDOUT -> JSON json_input = json.dumps(intent).encode() output = subprocess.run( self.command, check=True, input=json_input, stdout=subprocess.PIPE).stdout.decode() intent = json.loads(output) self._logger.debug(intent) # Check for speech speech = intent.get("speech", {}) speech_text = speech.get("text", "") if speech_text and self.speech_actor: self.send(self.speech_actor, SpeakSentence(speech_text)) except Exception as e: self._logger.exception("in_started") intent["error"] = str(e) if self.forward_to_hass and self.hass_handler: self.transition("forwarding") self.send(self.hass_handler, ForwardIntent(intent)) else: # No forwarding self.send(self.receiver, IntentHandled(intent))
def in_ready(self, message: Any, sender: RhasspyActor) -> None: """Handle messages in ready state.""" if isinstance(message, HandleIntent): self.receiver = message.receiver or sender intent = message.intent try: # JSON -> Remote -> JSON response = requests.post(self.remote_url, json=message.intent) response.raise_for_status() intent = response.json() self._logger.debug(intent) # Check for speech speech = intent.get("speech", {}) speech_text = speech.get("text", "") if speech_text and self.speech_actor: self.send(self.speech_actor, SpeakSentence(speech_text)) except Exception as e: self._logger.exception("in_started") intent["error"] = str(e) if self.forward_to_hass and self.hass_handler: self.transition("forwarding") self.send(self.hass_handler, ForwardIntent(intent)) else: # No forwarding self.send(self.receiver, IntentHandled(intent))
def in_ready(self, message: Any, sender: RhasspyActor) -> None: """Handle messages in rady state.""" if isinstance(message, SpeakSentence): self.wav_data = bytes() self.receiver = message.receiver or sender try: voice = message.voice or self.voice language_code = message.language or self.language_code self.wav_data = self.speak(message.sentence, voice, language_code) if message.play: self.enable_wake = False if self.wake and self.disable_wake: # Disable wake word self.send(self.wake, PauseListeningForWakeWord()) self.enable_wake = self.wake_on_start self.transition("speaking") self.send( self.player, PlayWavData(self.wav_data, siteId=message.siteId)) else: self.transition("ready") self.send(self.receiver, SentenceSpoken(self.wav_data)) except Exception: self._logger.exception("speak") # Try fallback system try: assert (self.fallback_actor is not None), "No fallback text to speech system" self._logger.debug("Falling back to %s", self.fallback_actor) self.transition("speaking") self.send( self.fallback_actor, SpeakSentence( message.sentence, play=message.play, voice=message.voice, language=message.language, siteId=message.siteId, ), ) except Exception: # Give up self.transition("ready") self.send(self.receiver, SentenceSpoken(bytes())) elif isinstance(message, Configured): # Fallback actor is configured pass
async def speak_sentence( self, sentence: str, play: bool = True, language: Optional[str] = None, voice: Optional[str] = None, ) -> SentenceSpoken: """Speak an entire sentence using text to speech system.""" assert self.actor_system is not None with self.actor_system.private() as sys: result = await sys.async_ask( self.dialogue_manager, SpeakSentence(sentence, play=play, language=language, voice=voice), ) assert isinstance(result, SentenceSpoken), result return result
def forward_intent(self, intent_name: str, event_type: str, slots: Dict[str, Any]): """Forward existing event to Home Assistant.""" if self.handle_type == HomeAssistantHandleType.INTENT: # Call /api/intent/handle post_url = urljoin(self.hass_config["url"], "api/intent/handle") # Send to Home Assistant kwargs = hass_request_kwargs(self.hass_config, self.pem_file) kwargs["json"] = {"name": intent_name, "data": slots} if self.pem_file is not None: kwargs["verify"] = self.pem_file response = requests.post(post_url, **kwargs) response.raise_for_status() intent = response.json() self._logger.debug(intent) # Check for speech speech_text = intent.get("speech", {}).get("plain", {}).get("speech", "") if speech_text and self.speech_actor: self.send(self.speech_actor, SpeakSentence(speech_text)) else: # Send event post_url = urljoin(self.hass_config["url"], "api/events/" + event_type) # Send to Home Assistant kwargs = hass_request_kwargs(self.hass_config, self.pem_file) kwargs["json"] = slots if self.pem_file is not None: kwargs["verify"] = self.pem_file response = requests.post(post_url, **kwargs) self._logger.debug("POSTed intent to %s", post_url) response.raise_for_status()
def handle_any(self, message: Any, sender: RhasspyActor) -> None: """Handle messages in any state.""" if isinstance(message, ListenForCommand): # Force voice command self.handle = message.handle self.intent_receiver = message.receiver or sender self.listen_timeout_sec = message.timeout self.listen_entities = message.entities self.transition("awake") elif isinstance(message, GetVoiceCommand): # Record voice command, but don't do anything with it self.send( self.command, ListenForCommand(message.receiver or sender, timeout=message.timeout), ) elif isinstance(message, TranscribeWav): # speech -> text self.send( self.decoder, TranscribeWav(message.wav_data, sender, handle=message.handle), ) elif isinstance(message, RecognizeIntent): # text -> intent self.send( self.recognizer, RecognizeIntent( message.text, confidence=message.confidence, receiver=sender, handle=message.handle, ), ) elif isinstance(message, HandleIntent): # intent -> action self.send(self.handler, HandleIntent(message.intent, sender)) # Forward to MQTT (hermes) if self.mqtt is not None: self.send(self.mqtt, IntentRecognized(message.intent)) elif isinstance(message, GetWordPhonemes): # eSpeak -> CMU self.send( self.word_pronouncer, GetWordPhonemes(message.word, receiver=sender) ) elif isinstance(message, SpeakWord): # eSpeak -> WAV self.send(self.word_pronouncer, SpeakWord(message.word, receiver=sender)) elif isinstance(message, GetWordPronunciations): # word -> [CMU] self.send( self.word_pronouncer, GetWordPronunciations(message.words, n=message.n, receiver=sender), ) elif isinstance(message, SpeakSentence): # text -> speech self.send( self.speech, SpeakSentence( message.sentence, receiver=sender, play=message.play, voice=message.voice, language=message.language, ), ) elif isinstance(message, TrainProfile): # Training self.reload_actors_after_training = message.reload_actors self.send(self.wake, StopListeningForWakeWord()) self.training_receiver = message.receiver or sender self.transition("training_sentences") # self.send(self.sentence_generator, GenerateSentences()) elif isinstance(message, StartRecordingToBuffer): # Record WAV self.send(self.recorder, message) elif isinstance(message, StopRecordingToBuffer): # Stop recording WAV self.send( self.recorder, StopRecordingToBuffer(message.buffer_name, message.receiver or sender), ) elif isinstance(message, StateTransition): # Track state of every actor self.handle_transition(message, sender) elif isinstance(message, GetActorStates): self.send(sender, self.actor_states) elif isinstance(message, WakeupMessage): pass elif isinstance(message, WavPlayed): pass elif isinstance(message, GetProblems): # Report problems from child actors self.send(sender, Problems(self.problems)) else: self.handle_forward(message, sender)