Handle grpc errors in Google Assistant SDK (#146438)
parent
7da1671b06
commit
b9e8cfb291
|
@ -12,6 +12,7 @@ import aiohttp
|
|||
from aiohttp import web
|
||||
from gassist_text import TextAssistant
|
||||
from google.oauth2.credentials import Credentials
|
||||
from grpc import RpcError
|
||||
|
||||
from homeassistant.components.http import HomeAssistantView
|
||||
from homeassistant.components.media_player import (
|
||||
|
@ -25,6 +26,7 @@ from homeassistant.components.media_player import (
|
|||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import ATTR_ENTITY_ID, CONF_ACCESS_TOKEN
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers.config_entry_oauth2_flow import OAuth2Session
|
||||
from homeassistant.helpers.event import async_call_later
|
||||
|
||||
|
@ -83,7 +85,17 @@ async def async_send_text_commands(
|
|||
) as assistant:
|
||||
command_response_list = []
|
||||
for command in commands:
|
||||
resp = await hass.async_add_executor_job(assistant.assist, command)
|
||||
try:
|
||||
resp = await hass.async_add_executor_job(assistant.assist, command)
|
||||
except RpcError as err:
|
||||
_LOGGER.error(
|
||||
"Failed to send command '%s' to Google Assistant: %s",
|
||||
command,
|
||||
err,
|
||||
)
|
||||
raise HomeAssistantError(
|
||||
translation_domain=DOMAIN, translation_key="grpc_error"
|
||||
) from err
|
||||
text_response = resp[0]
|
||||
_LOGGER.debug("command: %s\nresponse: %s", command, text_response)
|
||||
audio_response = resp[2]
|
||||
|
|
|
@ -57,5 +57,10 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"exceptions": {
|
||||
"grpc_error": {
|
||||
"message": "Failed to communicate with Google Assistant"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import time
|
|||
from unittest.mock import call, patch
|
||||
|
||||
import aiohttp
|
||||
from grpc import RpcError
|
||||
import pytest
|
||||
|
||||
from homeassistant.components import conversation
|
||||
|
@ -13,6 +14,7 @@ from homeassistant.components.google_assistant_sdk import DOMAIN
|
|||
from homeassistant.components.google_assistant_sdk.const import SUPPORTED_LANGUAGE_CODES
|
||||
from homeassistant.config_entries import ConfigEntryState
|
||||
from homeassistant.core import Context, HomeAssistant
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.setup import async_setup_component
|
||||
from homeassistant.util.dt import utcnow
|
||||
|
||||
|
@ -231,11 +233,34 @@ async def test_send_text_command_expired_token_refresh_failure(
|
|||
{"command": "turn on tv"},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert any(entry.async_get_active_flows(hass, {"reauth"})) == requires_reauth
|
||||
|
||||
|
||||
async def test_send_text_command_grpc_error(
|
||||
hass: HomeAssistant,
|
||||
setup_integration: ComponentSetup,
|
||||
) -> None:
|
||||
"""Test service call send_text_command when RpcError is raised."""
|
||||
await setup_integration()
|
||||
|
||||
command = "turn on home assistant unsupported device"
|
||||
with (
|
||||
patch(
|
||||
"homeassistant.components.google_assistant_sdk.helpers.TextAssistant.assist",
|
||||
side_effect=RpcError(),
|
||||
) as mock_assist_call,
|
||||
pytest.raises(HomeAssistantError),
|
||||
):
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
"send_text_command",
|
||||
{"command": command},
|
||||
blocking=True,
|
||||
)
|
||||
mock_assist_call.assert_called_once_with(command)
|
||||
|
||||
|
||||
async def test_send_text_command_media_player(
|
||||
hass: HomeAssistant,
|
||||
setup_integration: ComponentSetup,
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
from unittest.mock import call, patch
|
||||
|
||||
from grpc import RpcError
|
||||
import pytest
|
||||
|
||||
from homeassistant.components import notify
|
||||
|
@ -9,6 +10,7 @@ from homeassistant.components.google_assistant_sdk import DOMAIN
|
|||
from homeassistant.components.google_assistant_sdk.const import SUPPORTED_LANGUAGE_CODES
|
||||
from homeassistant.components.google_assistant_sdk.notify import broadcast_commands
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
|
||||
from .conftest import ComponentSetup, ExpectedCredentials
|
||||
|
||||
|
@ -45,8 +47,8 @@ async def test_broadcast_no_targets(
|
|||
notify.DOMAIN,
|
||||
DOMAIN,
|
||||
{notify.ATTR_MESSAGE: message},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
mock_text_assistant.assert_called_once_with(
|
||||
ExpectedCredentials(), language_code, audio_out=False
|
||||
)
|
||||
|
@ -54,6 +56,30 @@ async def test_broadcast_no_targets(
|
|||
mock_text_assistant.assert_has_calls([call().__enter__().assist(expected_command)])
|
||||
|
||||
|
||||
async def test_broadcast_grpc_error(
|
||||
hass: HomeAssistant,
|
||||
setup_integration: ComponentSetup,
|
||||
) -> None:
|
||||
"""Test broadcast handling when RpcError is raised."""
|
||||
await setup_integration()
|
||||
|
||||
with (
|
||||
patch(
|
||||
"homeassistant.components.google_assistant_sdk.helpers.TextAssistant.assist",
|
||||
side_effect=RpcError(),
|
||||
) as mock_assist_call,
|
||||
pytest.raises(HomeAssistantError),
|
||||
):
|
||||
await hass.services.async_call(
|
||||
notify.DOMAIN,
|
||||
DOMAIN,
|
||||
{notify.ATTR_MESSAGE: "Dinner is served"},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
mock_assist_call.assert_called_once_with("broadcast Dinner is served")
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("language_code", "message", "target", "expected_command"),
|
||||
[
|
||||
|
@ -103,8 +129,8 @@ async def test_broadcast_one_target(
|
|||
notify.DOMAIN,
|
||||
DOMAIN,
|
||||
{notify.ATTR_MESSAGE: message, notify.ATTR_TARGET: [target]},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
mock_assist_call.assert_called_once_with(expected_command)
|
||||
|
||||
|
||||
|
@ -127,8 +153,8 @@ async def test_broadcast_two_targets(
|
|||
notify.DOMAIN,
|
||||
DOMAIN,
|
||||
{notify.ATTR_MESSAGE: message, notify.ATTR_TARGET: [target1, target2]},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
mock_assist_call.assert_has_calls(
|
||||
[call(expected_command1), call(expected_command2)]
|
||||
)
|
||||
|
@ -148,8 +174,8 @@ async def test_broadcast_empty_message(
|
|||
notify.DOMAIN,
|
||||
DOMAIN,
|
||||
{notify.ATTR_MESSAGE: ""},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
mock_assist_call.assert_not_called()
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue