diff --git a/custom_components/yandex_station/__init__.py b/custom_components/yandex_station/__init__.py index 0ef35fc..76045ef 100644 --- a/custom_components/yandex_station/__init__.py +++ b/custom_components/yandex_station/__init__.py @@ -50,7 +50,6 @@ "button", "climate", "camera", - "conversation", "cover", "humidifier", "light", @@ -121,6 +120,13 @@ async def async_setup(hass: HomeAssistant, hass_config: dict): await _init_services(hass) await _setup_entry_from_config(hass) + try: + from . import conversation + + PLATFORMS.append("conversation") + except ImportError as e: + _LOGGER.warning(repr(e)) # supported from 2024.5 + hass.http.register_view(utils.StreamingView(hass)) return True diff --git a/custom_components/yandex_station/conversation.py b/custom_components/yandex_station/conversation.py index 2e97632..a49ee03 100644 --- a/custom_components/yandex_station/conversation.py +++ b/custom_components/yandex_station/conversation.py @@ -1,12 +1,13 @@ import logging -from typing import Literal -from homeassistant.components import conversation +from homeassistant.components.conversation import ( + ConversationEntity, + ConversationEntityFeature, + ConversationInput, + ConversationResult, +) from homeassistant.helpers.entity import DeviceInfo -from homeassistant.core import HomeAssistant, callback -from homeassistant.config_entries import ConfigEntry -from homeassistant.helpers.entity_platform import AddEntitiesCallback -from homeassistant.helpers import intent +from homeassistant.helpers.intent import IntentResponse, IntentResponseErrorCode from homeassistant.util import ulid from .core.const import DOMAIN @@ -15,14 +16,9 @@ _LOGGER = logging.getLogger(__name__) -SUPPORTED_LANGUAGES = ["ru"] - -async def async_setup_entry( - hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback -) -> None: +async def async_setup_entry(hass, entry, async_add_entities): quasar: YandexQuasar = hass.data[DOMAIN][entry.unique_id] - async_add_entities( [ YandexConversation(quasar, speaker) @@ -32,36 +28,28 @@ async def async_setup_entry( ) -class YandexConversation( - conversation.ConversationEntity, conversation.AbstractConversationAgent -): - """Yandex conversation agent.""" +class YandexConversation(ConversationEntity): + _attr_entity_registry_enabled_default = False + _attr_supported_features = ConversationEntityFeature.CONTROL def __init__(self, quasar: YandexQuasar, device: dict) -> None: - super().__init__() self.quasar = quasar self.device = device + self._attr_name = device["name"] + " Алиса" + self._attr_unique_id = device["quasar_info"]["device_id"] + "_conversation" + self._attr_device_info = DeviceInfo( identifiers={(DOMAIN, device["quasar_info"]["device_id"])}, name=self.device["name"], ) - self._attr_name = device["name"] + " Алиса" - self._attr_unique_id = device["quasar_info"]["device_id"] + "_conversation" - self._attr_supported_features = conversation.ConversationEntityFeature.CONTROL - - self.entity_id = f"conversation.yandex_station_{self._attr_unique_id.lower()}" @property - def supported_languages(self) -> list[str] | Literal["*"]: - """Return a list of supported languages.""" - return SUPPORTED_LANGUAGES + def supported_languages(self) -> list[str]: + return ["ru"] - async def async_process( - self, user_input: conversation.ConversationInput - ) -> conversation.ConversationResult: - """Process a sentence.""" - intent_response = intent.IntentResponse(language=user_input.language) + async def async_process(self, user_input: ConversationInput) -> ConversationResult: + response = IntentResponse(language=user_input.language) if user_input.conversation_id is None: conversation_id = ulid.ulid_now() @@ -73,42 +61,28 @@ async def async_process( conversation_id = user_input.conversation_id entity: YandexStation = self.device.get("entity") - if not entity: - intent_response.async_set_error( - intent.IntentResponseErrorCode.UNKNOWN, - f"Яндекс станция {self.device['quasar_info']['device_id']} не найдена", - ) - return conversation.ConversationResult( - response=intent_response, conversation_id=conversation_id + if entity and entity.glagol: + card = await entity.glagol.send( + {"command": "sendText", "text": user_input.text} ) - - response = self.hass.loop.create_future() - - @callback - def event_filter(event_data): - return ( - event_data.get("request_id") == conversation_id - and event_data.get("entity_id") == entity.entity_id + if card: + if text := card.get("text"): + response.async_set_speech(text) + elif error := card.get("error"): + response.async_set_error( + IntentResponseErrorCode.FAILED_TO_HANDLE, error + ) + else: + response.async_set_error( + IntentResponseErrorCode.NO_INTENT_MATCH, "Нет текстового ответа" + ) + else: + response.async_set_error( + IntentResponseErrorCode.FAILED_TO_HANDLE, "Неизвестная ошибка" + ) + else: + response.async_set_error( + IntentResponseErrorCode.UNKNOWN, "Алиса недоступна" ) - @callback - async def response_listener(event): - response.set_result(event.data["text"]) - - remove_listener = self.hass.bus.async_listen( - f"{DOMAIN}_response", response_listener, event_filter - ) - - await entity.async_play_media( - media_type=f"question:{conversation_id}", media_id=user_input.text - ) - - await response - - remove_listener() - - intent_response.async_set_speech(response.result()) - - return conversation.ConversationResult( - response=intent_response, conversation_id=conversation_id - ) + return ConversationResult(response=response, conversation_id=conversation_id) diff --git a/hacs.json b/hacs.json index 3d56413..10df822 100644 --- a/hacs.json +++ b/hacs.json @@ -1,6 +1,6 @@ { "name": "Yandex.Station", - "homeassistant": "2024.5.0", + "homeassistant": "2023.2.0", "render_readme": true, "country": "RU" }