mirror of
https://github.com/home-assistant/core.git
synced 2026-09-26 01:11:51 -04:00
Log a warning when a delayed voice command fails (#182492)
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
920e59e65a
commit
0b034a6d29
@@ -457,20 +457,8 @@ class TimerManager:
|
||||
timer.finish()
|
||||
|
||||
if timer.conversation_command:
|
||||
from homeassistant.components.conversation import ( # noqa: PLC0415
|
||||
async_converse,
|
||||
)
|
||||
|
||||
self.hass.async_create_background_task(
|
||||
async_converse(
|
||||
self.hass,
|
||||
timer.conversation_command,
|
||||
conversation_id=None,
|
||||
context=Context(),
|
||||
language=timer.language,
|
||||
agent_id=timer.conversation_agent_id,
|
||||
device_id=timer.device_id,
|
||||
),
|
||||
self._async_run_conversation_command(timer),
|
||||
"timer assist command",
|
||||
)
|
||||
elif timer.device_id in self.handlers:
|
||||
@@ -483,6 +471,33 @@ class TimerManager:
|
||||
timer.device_id,
|
||||
)
|
||||
|
||||
async def _async_run_conversation_command(self, timer: TimerInfo) -> None:
|
||||
"""Run the delayed command of a finished timer."""
|
||||
from homeassistant.components.conversation import ( # noqa: PLC0415
|
||||
async_converse,
|
||||
)
|
||||
|
||||
assert timer.conversation_command is not None
|
||||
|
||||
result = await async_converse(
|
||||
self.hass,
|
||||
timer.conversation_command,
|
||||
conversation_id=None,
|
||||
context=Context(),
|
||||
language=timer.language,
|
||||
agent_id=timer.conversation_agent_id,
|
||||
device_id=timer.device_id,
|
||||
)
|
||||
|
||||
# Nothing is listening to the response, so an error is only visible here.
|
||||
if result.response.response_type is intent.IntentResponseType.ERROR:
|
||||
_LOGGER.warning(
|
||||
"Delayed command failed: command=%s, code=%s, response=%s",
|
||||
timer.conversation_command,
|
||||
result.response.error_code,
|
||||
result.response.speech.get("plain", {}).get("speech", ""),
|
||||
)
|
||||
|
||||
def is_timer_device(self, device_id: str) -> bool:
|
||||
"""Return True if device has been registered to handle timer events."""
|
||||
return device_id in self.handlers
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
"""Tests for intent timers."""
|
||||
|
||||
import asyncio
|
||||
from collections.abc import Callable
|
||||
import logging
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
|
||||
import pytest
|
||||
@@ -32,6 +34,9 @@ from homeassistant.setup import async_setup_component
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
DELAYED_COMMAND = "turn on the lights"
|
||||
DELAYED_COMMAND_ERROR = "Sorry, I am not aware of any device called lights"
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def init_components(hass: HomeAssistant) -> None:
|
||||
@@ -1526,6 +1531,75 @@ async def test_start_timer_with_conversation_command(
|
||||
assert mock_converse.call_args.args[1] == test_command
|
||||
|
||||
|
||||
def _delayed_command_acted() -> intent.IntentResponse:
|
||||
"""Return the response of a delayed command that acted."""
|
||||
return intent.IntentResponse(language="en")
|
||||
|
||||
|
||||
def _delayed_command_failed() -> intent.IntentResponse:
|
||||
"""Return the response of a delayed command that could not act."""
|
||||
response = intent.IntentResponse(language="en")
|
||||
response.async_set_error(
|
||||
intent.IntentResponseErrorCode.NO_VALID_TARGETS, DELAYED_COMMAND_ERROR
|
||||
)
|
||||
return response
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("init_components")
|
||||
@pytest.mark.parametrize(
|
||||
("make_response", "expected_warnings"),
|
||||
[
|
||||
pytest.param(_delayed_command_acted, [], id="command_acted"),
|
||||
pytest.param(
|
||||
_delayed_command_failed,
|
||||
[
|
||||
f"Delayed command failed: command={DELAYED_COMMAND},"
|
||||
f" code=no_valid_targets, response={DELAYED_COMMAND_ERROR}"
|
||||
],
|
||||
id="command_failed",
|
||||
),
|
||||
],
|
||||
)
|
||||
async def test_start_timer_conversation_command_result_logged(
|
||||
hass: HomeAssistant,
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
make_response: Callable[[], intent.IntentResponse],
|
||||
expected_warnings: list[str],
|
||||
) -> None:
|
||||
"""Test that a delayed command which could not act is logged.
|
||||
|
||||
Nothing listens to the response of a delayed command, so an error is
|
||||
otherwise invisible.
|
||||
"""
|
||||
with patch(
|
||||
"homeassistant.components.conversation.async_converse",
|
||||
return_value=conversation.ConversationResult(response=make_response()),
|
||||
):
|
||||
result = await intent.async_handle(
|
||||
hass,
|
||||
"test",
|
||||
intent.INTENT_START_TIMER,
|
||||
{
|
||||
"seconds": {"value": 0},
|
||||
"conversation_command": {"value": DELAYED_COMMAND},
|
||||
},
|
||||
device_id="test_device",
|
||||
conversation_agent_id="test_agent",
|
||||
)
|
||||
|
||||
assert result.response_type is intent.IntentResponseType.ACTION_DONE
|
||||
|
||||
# The delayed command runs in a background task
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
assert [
|
||||
record.getMessage()
|
||||
for record in caplog.records
|
||||
if record.name == "homeassistant.components.intent.timers"
|
||||
and record.levelno == logging.WARNING
|
||||
] == expected_warnings
|
||||
|
||||
|
||||
async def test_start_timer_with_sentence_trigger_validation(
|
||||
hass: HomeAssistant, init_components
|
||||
) -> None:
|
||||
|
||||
Reference in New Issue
Block a user