parent
0100f87ff2
commit
47e31dc9ee
143 changed files with 1584 additions and 1761 deletions
|
@ -1,4 +1,9 @@
|
|||
"""Component to integrate the Home Assistant cloud."""
|
||||
"""
|
||||
Component to integrate the Home Assistant cloud.
|
||||
|
||||
For more details about this component, please refer to the documentation at
|
||||
https://home-assistant.io/components/cloud/
|
||||
"""
|
||||
import asyncio
|
||||
from datetime import datetime
|
||||
import json
|
||||
|
@ -26,18 +31,18 @@ REQUIREMENTS = ['warrant==0.6.1']
|
|||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
CONF_ALEXA = 'alexa'
|
||||
CONF_GOOGLE_ACTIONS = 'google_actions'
|
||||
CONF_FILTER = 'filter'
|
||||
CONF_ALIASES = 'aliases'
|
||||
CONF_COGNITO_CLIENT_ID = 'cognito_client_id'
|
||||
CONF_ENTITY_CONFIG = 'entity_config'
|
||||
CONF_FILTER = 'filter'
|
||||
CONF_GOOGLE_ACTIONS = 'google_actions'
|
||||
CONF_RELAYER = 'relayer'
|
||||
CONF_USER_POOL_ID = 'user_pool_id'
|
||||
CONF_ALIASES = 'aliases'
|
||||
|
||||
MODE_DEV = 'development'
|
||||
DEFAULT_MODE = 'production'
|
||||
DEPENDENCIES = ['http']
|
||||
|
||||
CONF_ENTITY_CONFIG = 'entity_config'
|
||||
MODE_DEV = 'development'
|
||||
|
||||
ALEXA_ENTITY_SCHEMA = vol.Schema({
|
||||
vol.Optional(alexa_sh.CONF_DESCRIPTION): cv.string,
|
||||
|
@ -149,7 +154,7 @@ class Cloud:
|
|||
|
||||
@property
|
||||
def subscription_expired(self):
|
||||
"""Return a boolen if the subscription has expired."""
|
||||
"""Return a boolean if the subscription has expired."""
|
||||
return dt_util.utcnow() > self.expiration_date
|
||||
|
||||
@property
|
||||
|
@ -195,8 +200,8 @@ class Cloud:
|
|||
if not jwt_success:
|
||||
return False
|
||||
|
||||
self.hass.bus.async_listen_once(EVENT_HOMEASSISTANT_START,
|
||||
self._start_cloud)
|
||||
self.hass.bus.async_listen_once(
|
||||
EVENT_HOMEASSISTANT_START, self._start_cloud)
|
||||
|
||||
return True
|
||||
|
||||
|
@ -248,7 +253,7 @@ class Cloud:
|
|||
for token in 'id_token', 'access_token':
|
||||
self._decode_claims(info[token])
|
||||
except ValueError as err: # Raised when token is invalid
|
||||
_LOGGER.warning('Found invalid token %s: %s', token, err)
|
||||
_LOGGER.warning("Found invalid token %s: %s", token, err)
|
||||
return
|
||||
|
||||
self.id_token = info['id_token']
|
||||
|
@ -282,15 +287,15 @@ class Cloud:
|
|||
header = jwt.get_unverified_header(token)
|
||||
except jose_exceptions.JWTError as err:
|
||||
raise ValueError(str(err)) from None
|
||||
kid = header.get("kid")
|
||||
kid = header.get('kid')
|
||||
|
||||
if kid is None:
|
||||
raise ValueError('No kid in header')
|
||||
raise ValueError("No kid in header")
|
||||
|
||||
# Locate the key for this kid
|
||||
key = None
|
||||
for key_dict in self.jwt_keyset["keys"]:
|
||||
if key_dict["kid"] == kid:
|
||||
for key_dict in self.jwt_keyset['keys']:
|
||||
if key_dict['kid'] == kid:
|
||||
key = key_dict
|
||||
break
|
||||
if not key:
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
"""Package to communicate with the authentication API."""
|
||||
import logging
|
||||
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
@ -22,7 +21,7 @@ class UserNotConfirmed(CloudError):
|
|||
|
||||
|
||||
class ExpiredCode(CloudError):
|
||||
"""Raised when an expired code is encoutered."""
|
||||
"""Raised when an expired code is encountered."""
|
||||
|
||||
|
||||
class InvalidCode(CloudError):
|
||||
|
@ -38,7 +37,7 @@ class PasswordChangeRequired(CloudError):
|
|||
|
||||
|
||||
class UnknownError(CloudError):
|
||||
"""Raised when an unknown error occurrs."""
|
||||
"""Raised when an unknown error occurs."""
|
||||
|
||||
|
||||
AWS_EXCEPTIONS = {
|
||||
|
@ -98,7 +97,7 @@ def resend_email_confirm(cloud, email):
|
|||
|
||||
|
||||
def forgot_password(cloud, email):
|
||||
"""Initiate forgotten password flow."""
|
||||
"""Initialize forgotten password flow."""
|
||||
from botocore.exceptions import ClientError
|
||||
|
||||
cognito = _cognito(cloud, username=email)
|
||||
|
|
|
@ -3,8 +3,8 @@ import asyncio
|
|||
from functools import wraps
|
||||
import logging
|
||||
|
||||
import voluptuous as vol
|
||||
import async_timeout
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.http import (
|
||||
HomeAssistantView, RequestDataValidator)
|
||||
|
@ -17,7 +17,7 @@ _LOGGER = logging.getLogger(__name__)
|
|||
|
||||
@asyncio.coroutine
|
||||
def async_setup(hass):
|
||||
"""Initialize the HTTP api."""
|
||||
"""Initialize the HTTP API."""
|
||||
hass.http.register_view(CloudLoginView)
|
||||
hass.http.register_view(CloudLogoutView)
|
||||
hass.http.register_view(CloudAccountView)
|
||||
|
@ -40,7 +40,7 @@ _CLOUD_ERRORS = {
|
|||
|
||||
|
||||
def _handle_cloud_errors(handler):
|
||||
"""Helper method to handle auth errors."""
|
||||
"""Handle auth errors."""
|
||||
@asyncio.coroutine
|
||||
@wraps(handler)
|
||||
def error_handler(view, request, *args, **kwargs):
|
||||
|
|
|
@ -12,7 +12,6 @@ from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
|||
from . import auth_api
|
||||
from .const import MESSAGE_EXPIRATION
|
||||
|
||||
|
||||
HANDLERS = Registry()
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
@ -85,7 +84,7 @@ class CloudIoT:
|
|||
})
|
||||
self.tries = 0
|
||||
|
||||
_LOGGER.info('Connected')
|
||||
_LOGGER.info("Connected")
|
||||
self.state = STATE_CONNECTED
|
||||
|
||||
while not client.closed:
|
||||
|
@ -107,7 +106,7 @@ class CloudIoT:
|
|||
disconnect_warn = 'Received invalid JSON.'
|
||||
break
|
||||
|
||||
_LOGGER.debug('Received message: %s', msg)
|
||||
_LOGGER.debug("Received message: %s", msg)
|
||||
|
||||
response = {
|
||||
'msgid': msg['msgid'],
|
||||
|
@ -126,14 +125,14 @@ class CloudIoT:
|
|||
response['error'] = 'unknown-handler'
|
||||
|
||||
except Exception: # pylint: disable=broad-except
|
||||
_LOGGER.exception('Error handling message')
|
||||
_LOGGER.exception("Error handling message")
|
||||
response['error'] = 'exception'
|
||||
|
||||
_LOGGER.debug('Publishing message: %s', response)
|
||||
_LOGGER.debug("Publishing message: %s", response)
|
||||
yield from client.send_json(response)
|
||||
|
||||
except auth_api.CloudError:
|
||||
_LOGGER.warning('Unable to connect: Unable to refresh token.')
|
||||
_LOGGER.warning("Unable to connect: Unable to refresh token.")
|
||||
|
||||
except client_exceptions.WSServerHandshakeError as err:
|
||||
if err.code == 401:
|
||||
|
@ -141,18 +140,18 @@ class CloudIoT:
|
|||
self.close_requested = True
|
||||
# Should we notify user?
|
||||
else:
|
||||
_LOGGER.warning('Unable to connect: %s', err)
|
||||
_LOGGER.warning("Unable to connect: %s", err)
|
||||
|
||||
except client_exceptions.ClientError as err:
|
||||
_LOGGER.warning('Unable to connect: %s', err)
|
||||
_LOGGER.warning("Unable to connect: %s", err)
|
||||
|
||||
except Exception: # pylint: disable=broad-except
|
||||
if not self.close_requested:
|
||||
_LOGGER.exception('Unexpected error')
|
||||
_LOGGER.exception("Unexpected error")
|
||||
|
||||
finally:
|
||||
if disconnect_warn is not None:
|
||||
_LOGGER.warning('Connection closed: %s', disconnect_warn)
|
||||
_LOGGER.warning("Connection closed: %s", disconnect_warn)
|
||||
|
||||
if remove_hass_stop_listener is not None:
|
||||
remove_hass_stop_listener()
|
||||
|
@ -169,7 +168,7 @@ class CloudIoT:
|
|||
self.tries += 1
|
||||
|
||||
try:
|
||||
# Sleep 0, 5, 10, 15 … up to 30 seconds between retries
|
||||
# Sleep 0, 5, 10, 15 ... up to 30 seconds between retries
|
||||
self.retry_task = hass.async_add_job(asyncio.sleep(
|
||||
min(30, (self.tries - 1) * 5), loop=hass.loop))
|
||||
yield from self.retry_task
|
||||
|
@ -205,8 +204,8 @@ def async_handle_message(hass, cloud, handler_name, payload):
|
|||
@asyncio.coroutine
|
||||
def async_handle_alexa(hass, cloud, payload):
|
||||
"""Handle an incoming IoT message for Alexa."""
|
||||
result = yield from alexa.async_handle_message(hass, cloud.alexa_config,
|
||||
payload)
|
||||
result = yield from alexa.async_handle_message(
|
||||
hass, cloud.alexa_config, payload)
|
||||
return result
|
||||
|
||||
|
||||
|
@ -214,8 +213,8 @@ def async_handle_alexa(hass, cloud, payload):
|
|||
@asyncio.coroutine
|
||||
def async_handle_google_actions(hass, cloud, payload):
|
||||
"""Handle an incoming IoT message for Google Actions."""
|
||||
result = yield from ga.async_handle_message(hass, cloud.gactions_config,
|
||||
payload)
|
||||
result = yield from ga.async_handle_message(
|
||||
hass, cloud.gactions_config, payload)
|
||||
return result
|
||||
|
||||
|
||||
|
@ -227,9 +226,9 @@ def async_handle_cloud(hass, cloud, payload):
|
|||
|
||||
if action == 'logout':
|
||||
yield from cloud.logout()
|
||||
_LOGGER.error('You have been logged out from Home Assistant cloud: %s',
|
||||
_LOGGER.error("You have been logged out from Home Assistant cloud: %s",
|
||||
payload['reason'])
|
||||
else:
|
||||
_LOGGER.warning('Received unknown cloud action: %s', action)
|
||||
_LOGGER.warning("Received unknown cloud action: %s", action)
|
||||
|
||||
return None
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue