Initialize docker stack repo
This commit is contained in:
@@ -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)
|
||||
Reference in New Issue
Block a user