Google Assistant SDK: Allow responses for send_text_command (#95966)

google_assistant_sdk.send_text_command response
This commit is contained in:
tronikos 2023-08-12 13:20:01 -07:00 committed by GitHub
parent 79991c32dc
commit bdaa2285fc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 47 additions and 12 deletions

View file

@ -1,6 +1,8 @@
"""Support for Google Assistant SDK."""
from __future__ import annotations
import dataclasses
import aiohttp
from gassist_text import TextAssistant
from google.oauth2.credentials import Credentials
@ -9,7 +11,12 @@ import voluptuous as vol
from homeassistant.components import conversation
from homeassistant.config_entries import ConfigEntry, ConfigEntryState
from homeassistant.const import CONF_ACCESS_TOKEN, CONF_NAME, Platform
from homeassistant.core import HomeAssistant, ServiceCall
from homeassistant.core import (
HomeAssistant,
ServiceCall,
ServiceResponse,
SupportsResponse,
)
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
from homeassistant.helpers import config_validation as cv, discovery, intent
from homeassistant.helpers.config_entry_oauth2_flow import (
@ -101,19 +108,30 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
async def async_setup_service(hass: HomeAssistant) -> None:
"""Add the services for Google Assistant SDK."""
async def send_text_command(call: ServiceCall) -> None:
async def send_text_command(call: ServiceCall) -> ServiceResponse:
"""Send a text command to Google Assistant SDK."""
commands: list[str] = call.data[SERVICE_SEND_TEXT_COMMAND_FIELD_COMMAND]
media_players: list[str] | None = call.data.get(
SERVICE_SEND_TEXT_COMMAND_FIELD_MEDIA_PLAYER
)
await async_send_text_commands(hass, commands, media_players)
command_response_list = await async_send_text_commands(
hass, commands, media_players
)
if call.return_response:
return {
"responses": [
dataclasses.asdict(command_response)
for command_response in command_response_list
]
}
return None
hass.services.async_register(
DOMAIN,
SERVICE_SEND_TEXT_COMMAND,
send_text_command,
schema=SERVICE_SEND_TEXT_COMMAND_SCHEMA,
supports_response=SupportsResponse.OPTIONAL,
)

View file

@ -1,6 +1,7 @@
"""Helper classes for Google Assistant SDK integration."""
from __future__ import annotations
from dataclasses import dataclass
from http import HTTPStatus
import logging
from typing import Any
@ -48,9 +49,16 @@ DEFAULT_LANGUAGE_CODES = {
}
@dataclass
class CommandResponse:
"""Response from a single command to Google Assistant Service."""
text: str
async def async_send_text_commands(
hass: HomeAssistant, commands: list[str], media_players: list[str] | None = None
) -> None:
) -> list[CommandResponse]:
"""Send text commands to Google Assistant Service."""
# There can only be 1 entry (config_flow has single_instance_allowed)
entry: ConfigEntry = hass.config_entries.async_entries(DOMAIN)[0]
@ -68,6 +76,7 @@ async def async_send_text_commands(
with TextAssistant(
credentials, language_code, audio_out=bool(media_players)
) as assistant:
command_response_list = []
for command in commands:
resp = assistant.assist(command)
text_response = resp[0]
@ -91,6 +100,8 @@ async def async_send_text_commands(
},
blocking=True,
)
command_response_list.append(CommandResponse(text_response))
return command_response_list
def default_language_code(hass: HomeAssistant):

View file

@ -162,20 +162,26 @@ async def test_send_text_commands(
command1 = "open the garage door"
command2 = "1234"
command1_response = "what's the PIN?"
command2_response = "opened the garage door"
with patch(
"homeassistant.components.google_assistant_sdk.helpers.TextAssistant"
) as mock_text_assistant:
await hass.services.async_call(
"homeassistant.components.google_assistant_sdk.helpers.TextAssistant.assist",
side_effect=[
(command1_response, None, None),
(command2_response, None, None),
],
) as mock_assist_call:
response = await hass.services.async_call(
DOMAIN,
"send_text_command",
{"command": [command1, command2]},
blocking=True,
return_response=True,
)
mock_text_assistant.assert_called_once_with(
ExpectedCredentials(), "en-US", audio_out=False
)
mock_text_assistant.assert_has_calls([call().__enter__().assist(command1)])
mock_text_assistant.assert_has_calls([call().__enter__().assist(command2)])
assert response == {
"responses": [{"text": command1_response}, {"text": command2_response}]
}
mock_assist_call.assert_has_calls([call(command1), call(command2)])
@pytest.mark.parametrize(