3 # © Copyright 2021-2022, Scott Gasch
5 """A module to serve as a local client library around HTTP calls to
6 the Google Assistant via a local gateway.
12 from dataclasses import dataclass
13 from typing import Optional
16 import speech_recognition as sr # type: ignore
20 logger = logging.getLogger(__name__)
22 parser = config.add_commandline_args(
23 f"Google Assistant ({__file__})",
24 "Args related to contacting the Google Assistant",
27 "--google_assistant_bridge",
29 default="http://kiosk.house:3000",
31 help="How to contact the Google Assistant bridge",
34 "--google_assistant_username",
36 metavar="GOOGLE_ACCOUNT",
37 default="scott.gasch",
38 help="The user account for talking to Google Assistant",
44 """A response wrapper."""
49 audio_transcription: Optional[str] = None # None if not available.
53 success: {self.success}
54 response: {self.response}
55 audio_transcription: {self.audio_transcription}
56 audio_url: {self.audio_url}"""
59 def tell_google(cmd: str, *, recognize_speech=True) -> GoogleResponse:
60 """Alias for ask_google."""
61 return ask_google(cmd, recognize_speech=recognize_speech)
64 def ask_google(cmd: str, *, recognize_speech=True) -> GoogleResponse:
65 """Send a command string to Google via the google_assistant_bridge as the
66 user google_assistant_username and return the response. If recognize_speech
67 is True, perform speech recognition on the audio response from Google so as
68 to translate it into text (best effort, YMMV).
70 logging.debug("Asking google: '%s'", cmd)
73 "user": config.config['google_assistant_username'],
75 url = f"{config.config['google_assistant_bridge']}/assistant"
76 r = requests.post(url, json=payload)
80 audio_transcription: Optional[str] = ""
81 if r.status_code == 200:
84 success = bool(j["success"])
85 response = j["response"] if success else j["error"]
87 logger.debug('Google request succeeded.')
89 logger.debug("Google said: '%s'", response)
90 audio = f"{config.config['google_assistant_bridge']}{j['audio']}"
92 recognizer = sr.Recognizer()
93 r = requests.get(audio)
94 if r.status_code == 200:
96 speech = sr.AudioData(
102 audio_transcription = recognizer.recognize_google(
105 logger.debug("Transcription: '%s'", audio_transcription)
106 except sr.UnknownValueError as e:
108 msg = 'Unable to parse Google assistant\'s response.'
110 warnings.warn(msg, stacklevel=3)
111 audio_transcription = None
112 return GoogleResponse(
116 audio_transcription=audio_transcription,
119 message = f'HTTP request to {url} with {payload} failed; code {r.status_code}'
120 logger.error(message)
121 return GoogleResponse(
125 audio_transcription=audio_transcription,