mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 13:17:32 +00:00
[esphome] Assist timers (#118275)
* [esphome] Assist timers * Add intent to manifest dependencies * Add test --------- Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
This commit is contained in:
parent
06d6f99964
commit
7f530ee0e4
@ -27,6 +27,7 @@ from awesomeversion import AwesomeVersion
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components import tag, zeroconf
|
||||
from homeassistant.components.intent import async_register_timer_handler
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import (
|
||||
ATTR_DEVICE_ID,
|
||||
@ -77,6 +78,7 @@ from .voice_assistant import (
|
||||
VoiceAssistantAPIPipeline,
|
||||
VoiceAssistantPipeline,
|
||||
VoiceAssistantUDPPipeline,
|
||||
handle_timer_event,
|
||||
)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
@ -517,6 +519,12 @@ class ESPHomeManager:
|
||||
handle_stop=self._handle_pipeline_stop,
|
||||
)
|
||||
)
|
||||
if flags & VoiceAssistantFeature.TIMERS:
|
||||
entry_data.disconnect_callbacks.add(
|
||||
async_register_timer_handler(
|
||||
hass, self.device_id, partial(handle_timer_event, cli)
|
||||
)
|
||||
)
|
||||
|
||||
cli.subscribe_states(entry_data.async_update_state)
|
||||
cli.subscribe_service_calls(self.async_on_service_call)
|
||||
|
@ -4,7 +4,7 @@
|
||||
"after_dependencies": ["zeroconf", "tag"],
|
||||
"codeowners": ["@OttoWinter", "@jesserockz", "@kbx81", "@bdraco"],
|
||||
"config_flow": true,
|
||||
"dependencies": ["assist_pipeline", "bluetooth"],
|
||||
"dependencies": ["assist_pipeline", "bluetooth", "intent"],
|
||||
"dhcp": [
|
||||
{
|
||||
"registered_devices": true
|
||||
|
@ -16,6 +16,7 @@ from aioesphomeapi import (
|
||||
VoiceAssistantCommandFlag,
|
||||
VoiceAssistantEventType,
|
||||
VoiceAssistantFeature,
|
||||
VoiceAssistantTimerEventType,
|
||||
)
|
||||
|
||||
from homeassistant.components import stt, tts
|
||||
@ -33,6 +34,7 @@ from homeassistant.components.assist_pipeline.error import (
|
||||
WakeWordDetectionAborted,
|
||||
WakeWordDetectionError,
|
||||
)
|
||||
from homeassistant.components.intent.timers import TimerEventType, TimerInfo
|
||||
from homeassistant.components.media_player import async_process_play_media_url
|
||||
from homeassistant.core import Context, HomeAssistant, callback
|
||||
|
||||
@ -65,6 +67,17 @@ _VOICE_ASSISTANT_EVENT_TYPES: EsphomeEnumMapper[
|
||||
}
|
||||
)
|
||||
|
||||
_TIMER_EVENT_TYPES: EsphomeEnumMapper[VoiceAssistantTimerEventType, TimerEventType] = (
|
||||
EsphomeEnumMapper(
|
||||
{
|
||||
VoiceAssistantTimerEventType.VOICE_ASSISTANT_TIMER_STARTED: TimerEventType.STARTED,
|
||||
VoiceAssistantTimerEventType.VOICE_ASSISTANT_TIMER_UPDATED: TimerEventType.UPDATED,
|
||||
VoiceAssistantTimerEventType.VOICE_ASSISTANT_TIMER_CANCELLED: TimerEventType.CANCELLED,
|
||||
VoiceAssistantTimerEventType.VOICE_ASSISTANT_TIMER_FINISHED: TimerEventType.FINISHED,
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class VoiceAssistantPipeline:
|
||||
"""Base abstract pipeline class."""
|
||||
@ -438,3 +451,23 @@ class VoiceAssistantAPIPipeline(VoiceAssistantPipeline):
|
||||
|
||||
self.started = False
|
||||
self.stop_requested = True
|
||||
|
||||
|
||||
def handle_timer_event(
|
||||
api_client: APIClient, event_type: TimerEventType, timer_info: TimerInfo
|
||||
) -> None:
|
||||
"""Handle timer events."""
|
||||
try:
|
||||
native_event_type = _TIMER_EVENT_TYPES.from_hass(event_type)
|
||||
except KeyError:
|
||||
_LOGGER.debug("Received unknown timer event type: %s", event_type)
|
||||
return
|
||||
|
||||
api_client.send_voice_assistant_timer_event(
|
||||
native_event_type,
|
||||
timer_info.id,
|
||||
timer_info.name,
|
||||
timer_info.seconds,
|
||||
timer_info.seconds_left,
|
||||
timer_info.is_active,
|
||||
)
|
||||
|
@ -1,13 +1,21 @@
|
||||
"""Test ESPHome voice assistant server."""
|
||||
|
||||
import asyncio
|
||||
from collections.abc import Callable
|
||||
from collections.abc import Awaitable, Callable
|
||||
import io
|
||||
import socket
|
||||
from unittest.mock import Mock, patch
|
||||
from unittest.mock import ANY, Mock, patch
|
||||
import wave
|
||||
|
||||
from aioesphomeapi import APIClient, VoiceAssistantEventType
|
||||
from aioesphomeapi import (
|
||||
APIClient,
|
||||
EntityInfo,
|
||||
EntityState,
|
||||
UserService,
|
||||
VoiceAssistantEventType,
|
||||
VoiceAssistantFeature,
|
||||
VoiceAssistantTimerEventType,
|
||||
)
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.assist_pipeline import (
|
||||
@ -25,6 +33,10 @@ from homeassistant.components.esphome.voice_assistant import (
|
||||
VoiceAssistantUDPPipeline,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import intent as intent_helper
|
||||
import homeassistant.helpers.device_registry as dr
|
||||
|
||||
from .conftest import MockESPHomeDevice
|
||||
|
||||
_TEST_INPUT_TEXT = "This is an input test"
|
||||
_TEST_OUTPUT_TEXT = "This is an output test"
|
||||
@ -720,3 +732,51 @@ async def test_wake_word_abort_exception(
|
||||
)
|
||||
|
||||
mock_handle_event.assert_not_called()
|
||||
|
||||
|
||||
async def test_timer_events(
|
||||
hass: HomeAssistant,
|
||||
mock_client: APIClient,
|
||||
mock_esphome_device: Callable[
|
||||
[APIClient, list[EntityInfo], list[UserService], list[EntityState]],
|
||||
Awaitable[MockESPHomeDevice],
|
||||
],
|
||||
) -> None:
|
||||
"""Test that injecting timer events results in the correct api client calls."""
|
||||
|
||||
mock_device: MockESPHomeDevice = await mock_esphome_device(
|
||||
mock_client=mock_client,
|
||||
entity_info=[],
|
||||
user_service=[],
|
||||
states=[],
|
||||
device_info={
|
||||
"voice_assistant_feature_flags": VoiceAssistantFeature.VOICE_ASSISTANT
|
||||
| VoiceAssistantFeature.TIMERS
|
||||
},
|
||||
)
|
||||
dev_reg = dr.async_get(hass)
|
||||
dev = dev_reg.async_get_device(
|
||||
connections={(dr.CONNECTION_NETWORK_MAC, mock_device.entry.unique_id)}
|
||||
)
|
||||
|
||||
await intent_helper.async_handle(
|
||||
hass,
|
||||
"test",
|
||||
intent_helper.INTENT_START_TIMER,
|
||||
{
|
||||
"name": {"value": "test timer"},
|
||||
"hours": {"value": 1},
|
||||
"minutes": {"value": 2},
|
||||
"seconds": {"value": 3},
|
||||
},
|
||||
device_id=dev.id,
|
||||
)
|
||||
|
||||
mock_client.send_voice_assistant_timer_event.assert_called_with(
|
||||
VoiceAssistantTimerEventType.VOICE_ASSISTANT_TIMER_STARTED,
|
||||
ANY,
|
||||
"test timer",
|
||||
3723,
|
||||
3723,
|
||||
True,
|
||||
)
|
||||
|
Loading…
x
Reference in New Issue
Block a user