Initialize docker stack repo

This commit is contained in:
g4st3r
2026-03-07 17:28:59 +00:00
commit 319d4eeb3e
458 changed files with 67215 additions and 0 deletions

View File

@@ -0,0 +1,170 @@
"""The Yandex Smart Home request handlers."""
import logging
from typing import Any, Callable, Coroutine
from homeassistant.const import ATTR_ENTITY_ID
from homeassistant.core import HomeAssistant
from homeassistant.util.decorator import Registry
from .const import ATTR_CAPABILITY, ATTR_ERROR_CODE, EVENT_DEVICE_ACTION
from .device import Device, async_get_device_description, async_get_device_states, async_get_devices
from .helpers import ActionNotAllowed, APIError, RequestData
from .schema import (
ActionRequest,
ActionResult,
ActionResultCapability,
ActionResultCapabilityState,
ActionResultDevice,
DeviceDescription,
DeviceList,
DeviceStates,
FailedActionResult,
Response,
ResponseCode,
ResponsePayload,
StatesRequest,
SuccessActionResult,
)
_LOGGER = logging.getLogger(__name__)
HANDLERS: Registry[
str,
Callable[
[HomeAssistant, RequestData, str],
Coroutine[Any, Any, ResponsePayload | None],
],
] = Registry()
async def async_handle_request(hass: HomeAssistant, data: RequestData, action: str, payload: str) -> Response:
"""Handle incoming API request."""
handler = HANDLERS.get(action)
if handler is None:
_LOGGER.error(f"Unexpected action '{action}'")
return Response(request_id=data.request_id)
try:
return Response(request_id=data.request_id, payload=await handler(hass, data, payload))
except APIError as err:
_LOGGER.error(f"{err.message} ({err.code})")
return Response(request_id=data.request_id)
except Exception:
# return always 200 due to blocking error on device page
_LOGGER.exception("Unexpected exception")
return Response(request_id=data.request_id)
@HANDLERS.register("/user/devices")
async def async_device_list(hass: HomeAssistant, data: RequestData, _payload: str) -> DeviceList:
"""Handle request that return information about supported user devices.
https://yandex.ru/dev/dialogs/smart-home/doc/reference/get-devices.html
"""
assert data.request_user_id
devices: list[DeviceDescription] = []
for device in await async_get_devices(hass, data.entry_data):
if (description := await async_get_device_description(hass, device)) is not None:
devices.append(description)
data.entry_data.link_platform(data.platform)
return DeviceList(user_id=data.request_user_id, devices=devices)
@HANDLERS.register("/user/devices/query")
async def async_devices_query(hass: HomeAssistant, data: RequestData, payload: str) -> DeviceStates:
"""Handle request that return information about the states of user devices.
https://yandex.ru/dev/dialogs/smart-home/doc/reference/post-devices-query.html
"""
request = StatesRequest.parse_raw(payload)
states = await async_get_device_states(hass, data.entry_data, [rd.id for rd in request.devices])
return DeviceStates(devices=states)
@HANDLERS.register("/user/devices/action")
async def async_devices_action(hass: HomeAssistant, data: RequestData, payload: str) -> ActionResult:
"""Handle request that changes current state of user devices.
https://yandex.ru/dev/dialogs/smart-home/doc/reference/post-action.html
"""
request = ActionRequest.parse_raw(payload)
results: list[ActionResultDevice] = []
for device_id, actions in [(rd.id, rd.capabilities) for rd in request.payload.devices]:
state = hass.states.get(device_id)
device = Device(hass, data.entry_data, device_id, state)
if state and not device.should_expose:
data.entry_data.mark_entity_unexposed(state.entity_id)
if device.unavailable:
hass.bus.async_fire(
EVENT_DEVICE_ACTION,
{ATTR_ENTITY_ID: device_id, ATTR_ERROR_CODE: ResponseCode.DEVICE_UNREACHABLE.value},
context=data.context,
)
results.append(
ActionResultDevice(
id=device_id, action_result=FailedActionResult(error_code=ResponseCode.DEVICE_UNREACHABLE)
)
)
continue
capability_results: list[ActionResultCapability] = []
for action in actions:
try:
value = await device.execute(data.context, action)
hass.bus.async_fire(
EVENT_DEVICE_ACTION,
{ATTR_ENTITY_ID: device_id, ATTR_CAPABILITY: action.as_dict()},
context=data.context,
)
except (APIError, ActionNotAllowed) as err:
if isinstance(err, APIError):
_LOGGER.error(f"{err.message} ({err.code.value})")
hass.bus.async_fire(
EVENT_DEVICE_ACTION,
{ATTR_ENTITY_ID: device_id, ATTR_CAPABILITY: action.as_dict(), ATTR_ERROR_CODE: err.code.value},
context=data.context,
)
capability_results.append(
ActionResultCapability(
type=action.type,
state=ActionResultCapabilityState(
instance=action.state.instance,
action_result=FailedActionResult(error_code=ResponseCode(err.code)),
),
)
)
continue
capability_results.append(
ActionResultCapability(
type=action.type,
state=ActionResultCapabilityState(
instance=action.state.instance,
value=value,
action_result=SuccessActionResult(),
),
)
)
results.append(ActionResultDevice(id=device_id, capabilities=capability_results))
return ActionResult(devices=results)
@HANDLERS.register("/user/unlink")
async def async_user_unlink(_hass: HomeAssistant, data: RequestData, _payload: str) -> None:
"""Handle request indicates that the user has unlink the account.
https://yandex.ru/dev/dialogs/smart-home/doc/reference/unlink.html
"""
data.entry_data.unlink_platform(data.platform)