From 0b40b6f06bdaa5ede6f14a420d796f73c6eedae6 Mon Sep 17 00:00:00 2001 From: tronikos Date: Thu, 6 Jul 2023 06:52:20 +0000 Subject: [PATCH] google_assistant_sdk.send_text_command response --- .../google_assistant_sdk/__init__.py | 24 ++++++++++++++++--- .../google_assistant_sdk/helpers.py | 13 +++++++++- .../google_assistant_sdk/test_init.py | 22 ++++++++++------- 3 files changed, 47 insertions(+), 12 deletions(-) diff --git a/homeassistant/components/google_assistant_sdk/__init__.py b/homeassistant/components/google_assistant_sdk/__init__.py index db2a8d9512ed4a..59d7448daed956 100644 --- a/homeassistant/components/google_assistant_sdk/__init__.py +++ b/homeassistant/components/google_assistant_sdk/__init__.py @@ -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 @@ 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, ) diff --git a/homeassistant/components/google_assistant_sdk/helpers.py b/homeassistant/components/google_assistant_sdk/helpers.py index 1d89e208cedbe1..5ae39c98f3c11e 100644 --- a/homeassistant/components/google_assistant_sdk/helpers.py +++ b/homeassistant/components/google_assistant_sdk/helpers.py @@ -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 @@ } +@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): diff --git a/tests/components/google_assistant_sdk/test_init.py b/tests/components/google_assistant_sdk/test_init.py index 99f264e4a3a0f2..ba5686ba078446 100644 --- a/tests/components/google_assistant_sdk/test_init.py +++ b/tests/components/google_assistant_sdk/test_init.py @@ -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(