first commit

This commit is contained in:
Your Name
2024-01-11 15:10:51 +03:00
commit eddf07c652
602 changed files with 67154 additions and 0 deletions
@@ -0,0 +1,194 @@
"""Support for Yandex Smart Home API."""
from __future__ import annotations
import logging
from typing import Any
from homeassistant.const import STATE_UNAVAILABLE
from homeassistant.core import HomeAssistant
from homeassistant.helpers import area_registry, device_registry, entity_registry
from homeassistant.util.decorator import Registry
from .const import ERR_DEVICE_UNREACHABLE, ERR_INTERNAL_ERROR, EVENT_DEVICE_DISCOVERY
from .entity import YandexEntity
from .error import SmartHomeError
from .helpers import RequestData
HANDLERS = Registry()
_LOGGER = logging.getLogger(__name__)
async def async_handle_message(hass: HomeAssistant,
data: RequestData,
action: str,
message: dict[str, Any]) -> dict[str, Any]:
"""Handle incoming API messages."""
handler = HANDLERS.get(action)
if handler is None:
_LOGGER.error(f'Handler not found for {action!r}')
return {
'request_id': data.request_id,
'payload': {'error_code': ERR_INTERNAL_ERROR}
}
# noinspection PyBroadException
try:
result = await handler(hass, data, message)
except SmartHomeError as err:
_LOGGER.error('Handler error: %s %s', err.code, err.message)
return {
'request_id': data.request_id,
'payload': {'error_code': err.code}
}
except Exception:
_LOGGER.exception('Handler unexpected error')
return {
'request_id': data.request_id,
'payload': {'error_code': ERR_INTERNAL_ERROR}
}
if result is None:
return {'request_id': data.request_id}
return {
'request_id': data.request_id,
'payload': result
}
# noinspection PyUnusedLocal
@HANDLERS.register('/user/devices')
async def async_devices(hass: HomeAssistant, data: RequestData, message: dict[str, Any]):
"""Handle /user/devices request.
https://yandex.ru/dev/dialogs/alice/doc/smart-home/reference/get-devices-docpage/
"""
devices = []
ent_reg = entity_registry.async_get(hass)
dev_reg = device_registry.async_get(hass)
area_reg = area_registry.async_get(hass)
hass.bus.async_fire(EVENT_DEVICE_DISCOVERY, context=data.context)
for state in hass.states.async_all():
entity = YandexEntity(hass, data.config, state)
if not entity.should_expose:
continue
serialized = await entity.devices_serialize(ent_reg, dev_reg, area_reg)
if serialized is None:
_LOGGER.debug(f'Unsupported entity: {entity.state!r}')
continue
devices.append(serialized)
return {
'user_id': data.request_user_id,
'devices': devices,
}
@HANDLERS.register('/user/devices/query')
async def async_devices_query(hass, data, message):
"""Handle /user/devices/query request.
https://yandex.ru/dev/dialogs/alice/doc/smart-home/reference/post-devices-query-docpage/
"""
devices = []
for device in message.get('devices', []):
entity_id = device['id']
state = hass.states.get(entity_id)
if state is None:
devices.append({
'id': entity_id,
'error_code': ERR_DEVICE_UNREACHABLE
})
continue
entity = YandexEntity(hass, data.config, state)
if not entity.should_expose:
_LOGGER.warning(
f'State requested for unexposed entity {entity.entity_id}. Please either expose the entity via '
f'filters in component configuration or delete the device from Yandex.'
)
devices.append(entity.query_serialize())
return {'devices': devices}
@HANDLERS.register('/user/devices/action')
async def async_devices_execute(hass: HomeAssistant, data: RequestData, message: dict[str, Any]) -> dict[str, Any]:
"""Handle /user/devices/action request.
https://yandex.ru/dev/dialogs/alice/doc/smart-home/reference/post-action-docpage/
"""
devices = []
for device in message['payload']['devices']:
entity_id = device['id']
state = hass.states.get(entity_id)
if state is None or state.state == STATE_UNAVAILABLE:
devices.append({
'id': entity_id,
'error_code': ERR_DEVICE_UNREACHABLE,
})
continue
entity = YandexEntity(hass, data.config, state)
capabilities_result = []
for capability in device['capabilities']:
capability_type = capability['type']
instance = capability['state']['instance']
try:
value = await entity.execute(data, capability_type, instance, capability['state'])
except SmartHomeError as e:
_LOGGER.error(f'{e.code}: {e.message}')
capabilities_result.append({
'type': capability_type,
'state': {
'instance': instance,
'action_result': {
'status': 'ERROR',
'error_code': e.code
}
}
})
continue
result = {
'type': capability_type,
'state': {
'instance': instance,
'action_result': {
'status': 'DONE',
}
}
}
if value:
result['state']['value'] = value
capabilities_result.append(result)
devices.append({
'id': entity_id,
'capabilities': capabilities_result
})
return {'devices': devices}
# noinspection PyUnusedLocal
@HANDLERS.register('/user/unlink')
async def async_devices_disconnect(hass: HomeAssistant, data: RequestData, message: dict[str, Any]):
"""Handle /user/unlink request.
https://yandex.ru/dev/dialogs/alice/doc/smart-home/reference/unlink-docpage/
"""
return None