120 lines
3.6 KiB
Python
120 lines
3.6 KiB
Python
|
"""The HTTP api to control the cloud integration."""
|
||
|
import asyncio
|
||
|
import logging
|
||
|
|
||
|
import voluptuous as vol
|
||
|
import async_timeout
|
||
|
|
||
|
from homeassistant.components.http import HomeAssistantView
|
||
|
|
||
|
from . import cloud_api
|
||
|
from .const import DOMAIN, REQUEST_TIMEOUT
|
||
|
|
||
|
_LOGGER = logging.getLogger(__name__)
|
||
|
|
||
|
|
||
|
@asyncio.coroutine
|
||
|
def async_setup(hass):
|
||
|
"""Initialize the HTTP api."""
|
||
|
hass.http.register_view(CloudLoginView)
|
||
|
hass.http.register_view(CloudLogoutView)
|
||
|
hass.http.register_view(CloudAccountView)
|
||
|
|
||
|
|
||
|
class CloudLoginView(HomeAssistantView):
|
||
|
"""Login to Home Assistant cloud."""
|
||
|
|
||
|
url = '/api/cloud/login'
|
||
|
name = 'api:cloud:login'
|
||
|
schema = vol.Schema({
|
||
|
vol.Required('username'): str,
|
||
|
vol.Required('password'): str,
|
||
|
})
|
||
|
|
||
|
@asyncio.coroutine
|
||
|
def post(self, request):
|
||
|
"""Validate config and return results."""
|
||
|
try:
|
||
|
data = yield from request.json()
|
||
|
except ValueError:
|
||
|
_LOGGER.error('Login with invalid JSON')
|
||
|
return self.json_message('Invalid JSON.', 400)
|
||
|
|
||
|
try:
|
||
|
self.schema(data)
|
||
|
except vol.Invalid as err:
|
||
|
_LOGGER.error('Login with invalid formatted data')
|
||
|
return self.json_message(
|
||
|
'Message format incorrect: {}'.format(err), 400)
|
||
|
|
||
|
hass = request.app['hass']
|
||
|
phase = 1
|
||
|
try:
|
||
|
with async_timeout.timeout(REQUEST_TIMEOUT, loop=hass.loop):
|
||
|
cloud = yield from cloud_api.async_login(
|
||
|
hass, data['username'], data['password'])
|
||
|
|
||
|
phase += 1
|
||
|
|
||
|
with async_timeout.timeout(REQUEST_TIMEOUT, loop=hass.loop):
|
||
|
yield from cloud.async_refresh_account_info()
|
||
|
|
||
|
except cloud_api.Unauthenticated:
|
||
|
return self.json_message(
|
||
|
'Authentication failed (phase {}).'.format(phase), 401)
|
||
|
except cloud_api.UnknownError:
|
||
|
return self.json_message(
|
||
|
'Unknown error occurred (phase {}).'.format(phase), 500)
|
||
|
except asyncio.TimeoutError:
|
||
|
return self.json_message(
|
||
|
'Unable to reach Home Assistant cloud '
|
||
|
'(phase {}).'.format(phase), 502)
|
||
|
|
||
|
hass.data[DOMAIN]['cloud'] = cloud
|
||
|
return self.json(cloud.account)
|
||
|
|
||
|
|
||
|
class CloudLogoutView(HomeAssistantView):
|
||
|
"""Log out of the Home Assistant cloud."""
|
||
|
|
||
|
url = '/api/cloud/logout'
|
||
|
name = 'api:cloud:logout'
|
||
|
|
||
|
@asyncio.coroutine
|
||
|
def post(self, request):
|
||
|
"""Validate config and return results."""
|
||
|
hass = request.app['hass']
|
||
|
try:
|
||
|
with async_timeout.timeout(REQUEST_TIMEOUT, loop=hass.loop):
|
||
|
yield from \
|
||
|
hass.data[DOMAIN]['cloud'].async_revoke_access_token()
|
||
|
|
||
|
hass.data[DOMAIN].pop('cloud')
|
||
|
|
||
|
return self.json({
|
||
|
'result': 'ok',
|
||
|
})
|
||
|
except asyncio.TimeoutError:
|
||
|
return self.json_message("Could not reach the server.", 502)
|
||
|
except cloud_api.UnknownError as err:
|
||
|
return self.json_message(
|
||
|
"Error communicating with the server ({}).".format(err.status),
|
||
|
502)
|
||
|
|
||
|
|
||
|
class CloudAccountView(HomeAssistantView):
|
||
|
"""Log out of the Home Assistant cloud."""
|
||
|
|
||
|
url = '/api/cloud/account'
|
||
|
name = 'api:cloud:account'
|
||
|
|
||
|
@asyncio.coroutine
|
||
|
def get(self, request):
|
||
|
"""Validate config and return results."""
|
||
|
hass = request.app['hass']
|
||
|
|
||
|
if 'cloud' not in hass.data[DOMAIN]:
|
||
|
return self.json_message('Not logged in', 400)
|
||
|
|
||
|
return self.json(hass.data[DOMAIN]['cloud'].account)
|