123 lines
4.3 KiB
Python
123 lines
4.3 KiB
Python
"""Support for Yandex Smart Home."""
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
from typing import Any
|
|
|
|
from aiohttp.web import Request, Response
|
|
from homeassistant.components.http import HomeAssistantView
|
|
from homeassistant.core import HomeAssistant, callback
|
|
|
|
from .const import CONFIG, DOMAIN
|
|
from .helpers import Config
|
|
from .smart_home import RequestData, async_devices, async_handle_message
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
|
|
@callback
|
|
def async_register_http(hass: HomeAssistant):
|
|
"""Register HTTP views for Yandex Smart Home."""
|
|
hass.http.register_view(YandexSmartHomeUnauthorizedView())
|
|
hass.http.register_view(YandexSmartHomePingView())
|
|
hass.http.register_view(YandexSmartHomeView())
|
|
|
|
|
|
class YandexSmartHomeView:
|
|
@staticmethod
|
|
def _get_config(request: Request) -> Config | None:
|
|
return request.app['hass'].data[DOMAIN][CONFIG]
|
|
|
|
def _is_direct_connection(self, request: Request) -> bool:
|
|
"""Check if integration configured to use direct connection."""
|
|
config = self._get_config(request)
|
|
if not config:
|
|
return False
|
|
|
|
return config.is_direct_connection
|
|
|
|
|
|
class YandexSmartHomeUnauthorizedView(HomeAssistantView, YandexSmartHomeView):
|
|
"""Handle Yandex Smart Home unauthorized requests."""
|
|
|
|
url = f'/api/{DOMAIN}/v1.0'
|
|
name = f'api:{DOMAIN}:unauthorized'
|
|
requires_auth = False
|
|
|
|
async def head(self, request: Request) -> Response:
|
|
"""Handle Yandex Smart Home HEAD requests."""
|
|
_LOGGER.debug('Request: %s (HEAD)' % request.url)
|
|
|
|
if not self._is_direct_connection(request):
|
|
_LOGGER.debug('Integration is not enabled or use cloud connection')
|
|
return Response(status=404)
|
|
|
|
return Response(status=200)
|
|
|
|
|
|
class YandexSmartHomePingView(HomeAssistantView, YandexSmartHomeView):
|
|
"""Handle Yandex Smart Home ping requests."""
|
|
|
|
url = f'/api/{DOMAIN}/v1.0/ping'
|
|
name = f'api:{DOMAIN}:unauthorized'
|
|
requires_auth = False
|
|
|
|
# noinspection PyMethodMayBeStatic
|
|
async def get(self, request: Request) -> Response:
|
|
"""Handle Yandex Smart Home Get requests."""
|
|
_LOGGER.debug('Request: %s (GET)' % request.url)
|
|
|
|
if not self._is_direct_connection(request):
|
|
return Response(text='Error: Integration is not enabled or use cloud connection', status=503)
|
|
|
|
data = RequestData(self._get_config(request), None, 'ping')
|
|
devices_sync_response = await async_devices(request.app['hass'], data, {})
|
|
device_count = len(devices_sync_response['devices'])
|
|
|
|
return Response(text=f'OK: {device_count}', status=200)
|
|
|
|
|
|
class YandexSmartHomeView(YandexSmartHomeUnauthorizedView, YandexSmartHomeView):
|
|
"""Handle Yandex Smart Home requests."""
|
|
|
|
url = f'/api/{DOMAIN}/v1.0'
|
|
extra_urls = [
|
|
url + '/user/unlink',
|
|
url + '/user/devices',
|
|
url + '/user/devices/query',
|
|
url + '/user/devices/action',
|
|
]
|
|
name = f'api:{DOMAIN}'
|
|
requires_auth = True
|
|
|
|
async def _async_handle_request(self, request: Request, message: dict[str, Any] | None = None) -> Response:
|
|
if not self._is_direct_connection(request):
|
|
_LOGGER.debug('Integration is not enabled or use cloud connection')
|
|
return Response(status=404)
|
|
|
|
data = RequestData(
|
|
config=self._get_config(request),
|
|
request_user_id=request['hass_user'].id,
|
|
request_id=request.headers.get('X-Request-Id'),
|
|
user_id=request['hass_user'].id,
|
|
)
|
|
action = request.path.replace(self.url, '', 1)
|
|
|
|
result = await async_handle_message(request.app['hass'], data, action, message or {})
|
|
response = self.json(result)
|
|
_LOGGER.debug(f'Response: {response.text}')
|
|
return response
|
|
|
|
async def post(self, request: Request) -> Response:
|
|
"""Handle Yandex Smart Home POST requests."""
|
|
_LOGGER.debug('Request: %s (POST data: %s)' % (request.url, await request.text()))
|
|
if str(request.url).endswith('/user/unlink'):
|
|
return await self._async_handle_request(request)
|
|
|
|
return await self._async_handle_request(request, await request.json())
|
|
|
|
async def get(self, request: Request) -> Response:
|
|
"""Handle Yandex Smart Home GET requests."""
|
|
_LOGGER.debug('Request: %s' % request.url)
|
|
return await self._async_handle_request(request)
|