3 """A module to serve as a local client library around HTTP calls to
4 the Google Assistant via a local gateway."""
8 from typing import NamedTuple, Optional
11 import speech_recognition as sr # type: ignore
15 logger = logging.getLogger(__name__)
17 parser = config.add_commandline_args(
18 f"Google Assistant ({__file__})",
19 "Args related to contacting the Google Assistant",
22 "--google_assistant_bridge",
24 default="http://kiosk.house:3000",
26 help="How to contact the Google Assistant bridge",
29 "--google_assistant_username",
31 metavar="GOOGLE_ACCOUNT",
32 default="scott.gasch",
33 help="The user account for talking to Google Assistant",
37 class GoogleResponse(NamedTuple):
38 """A response wrapper."""
43 audio_transcription: Optional[str] # None if not available.
47 success: {self.success}
48 response: {self.response}
49 audio_transcription: {self.audio_transcription}
50 audio_url: {self.audio_url}"""
53 def tell_google(cmd: str, *, recognize_speech=True) -> GoogleResponse:
54 """Alias for ask_google."""
55 return ask_google(cmd, recognize_speech=recognize_speech)
58 def ask_google(cmd: str, *, recognize_speech=True) -> GoogleResponse:
59 """Send a command string to Google via the google_assistant_bridge as the
60 user google_assistant_username and return the response. If recognize_speech
61 is True, perform speech recognition on the audio response from Google so as
62 to translate it into text (best effort, YMMV).
64 logging.debug("Asking google: '%s'", cmd)
67 "user": config.config['google_assistant_username'],
69 url = f"{config.config['google_assistant_bridge']}/assistant"
70 r = requests.post(url, json=payload)
74 audio_transcription: Optional[str] = ""
75 if r.status_code == 200:
78 success = bool(j["success"])
79 response = j["response"] if success else j["error"]
81 logger.debug('Google request succeeded.')
83 logger.debug("Google said: '%s'", response)
84 audio = f"{config.config['google_assistant_bridge']}{j['audio']}"
86 recognizer = sr.Recognizer()
87 r = requests.get(audio)
88 if r.status_code == 200:
90 speech = sr.AudioData(
96 audio_transcription = recognizer.recognize_google(
99 logger.debug("Transcription: '%s'", audio_transcription)
100 except sr.UnknownValueError as e:
102 msg = 'Unable to parse Google assistant\'s response.'
104 warnings.warn(msg, stacklevel=3)
105 audio_transcription = None
106 return GoogleResponse(
110 audio_transcription=audio_transcription,
113 message = f'HTTP request to {url} with {payload} failed; code {r.status_code}'
114 logger.error(message)
115 return GoogleResponse(
119 audio_transcription=audio_transcription,