Cloud: Add Alexa report state (#24536)
* Cloud: Add Alexa report state * Lint * Lint * Only track state changes when we are logged inpull/24601/head
parent
5ab1996d3f
commit
a02b69db38
|
@ -1,14 +1,26 @@
|
|||
"""Config helpers for Alexa."""
|
||||
from .state_report import async_enable_proactive_mode
|
||||
|
||||
|
||||
class AbstractConfig:
|
||||
"""Hold the configuration for Alexa."""
|
||||
|
||||
_unsub_proactive_report = None
|
||||
|
||||
def __init__(self, hass):
|
||||
"""Initialize abstract config."""
|
||||
self.hass = hass
|
||||
|
||||
@property
|
||||
def supports_auth(self):
|
||||
"""Return if config supports auth."""
|
||||
return False
|
||||
|
||||
@property
|
||||
def should_report_state(self):
|
||||
"""Return if states should be proactively reported."""
|
||||
return False
|
||||
|
||||
@property
|
||||
def endpoint(self):
|
||||
"""Endpoint for report state."""
|
||||
|
@ -19,6 +31,30 @@ class AbstractConfig:
|
|||
"""Return entity config."""
|
||||
return {}
|
||||
|
||||
@property
|
||||
def is_reporting_states(self):
|
||||
"""Return if proactive mode is enabled."""
|
||||
return self._unsub_proactive_report is not None
|
||||
|
||||
async def async_enable_proactive_mode(self):
|
||||
"""Enable proactive mode."""
|
||||
if self._unsub_proactive_report is None:
|
||||
self._unsub_proactive_report = self.hass.async_create_task(
|
||||
async_enable_proactive_mode(self.hass, self)
|
||||
)
|
||||
resp = await self._unsub_proactive_report
|
||||
|
||||
# Failed to start reporting.
|
||||
if resp is None:
|
||||
self._unsub_proactive_report = None
|
||||
|
||||
async def async_disable_proactive_mode(self):
|
||||
"""Disable proactive mode."""
|
||||
unsub_func = await self._unsub_proactive_report
|
||||
if unsub_func:
|
||||
unsub_func()
|
||||
self._unsub_proactive_report = None
|
||||
|
||||
def should_expose(self, entity_id):
|
||||
"""If an entity should be exposed."""
|
||||
# pylint: disable=no-self-use
|
||||
|
|
|
@ -87,6 +87,8 @@ async def async_api_accept_grant(hass, config, directive, context):
|
|||
|
||||
if config.supports_auth:
|
||||
await config.async_accept_grant(auth_code)
|
||||
|
||||
if config.should_report_state:
|
||||
await async_enable_proactive_mode(hass, config)
|
||||
|
||||
return directive.response(
|
||||
|
|
|
@ -25,6 +25,7 @@ class AlexaConfig(AbstractConfig):
|
|||
|
||||
def __init__(self, hass, config):
|
||||
"""Initialize Alexa config."""
|
||||
super().__init__(hass)
|
||||
self._config = config
|
||||
|
||||
if config.get(CONF_CLIENT_ID) and config.get(CONF_CLIENT_SECRET):
|
||||
|
@ -38,6 +39,11 @@ class AlexaConfig(AbstractConfig):
|
|||
"""Return if config supports auth."""
|
||||
return self._auth is not None
|
||||
|
||||
@property
|
||||
def should_report_state(self):
|
||||
"""Return if we should proactively report states."""
|
||||
return self._auth is not None
|
||||
|
||||
@property
|
||||
def endpoint(self):
|
||||
"""Endpoint for report state."""
|
||||
|
@ -73,7 +79,7 @@ async def async_setup(hass, config):
|
|||
smart_home_config = AlexaConfig(hass, config)
|
||||
hass.http.register_view(SmartHomeView(smart_home_config))
|
||||
|
||||
if smart_home_config.supports_auth:
|
||||
if smart_home_config.should_report_state:
|
||||
await async_enable_proactive_mode(hass, smart_home_config)
|
||||
|
||||
|
||||
|
|
|
@ -21,24 +21,23 @@ async def async_enable_proactive_mode(hass, smart_home_config):
|
|||
|
||||
Proactive mode makes this component report state changes to Alexa.
|
||||
"""
|
||||
if smart_home_config.async_get_access_token is None:
|
||||
# no function to call to get token
|
||||
return
|
||||
|
||||
if await smart_home_config.async_get_access_token() is None:
|
||||
# not ready yet
|
||||
return
|
||||
|
||||
async def async_entity_state_listener(changed_entity, old_state,
|
||||
new_state):
|
||||
if not smart_home_config.should_expose(changed_entity):
|
||||
_LOGGER.debug("Not exposing %s because filtered by config",
|
||||
changed_entity)
|
||||
if not new_state:
|
||||
return
|
||||
|
||||
if new_state.domain not in ENTITY_ADAPTERS:
|
||||
return
|
||||
|
||||
if not smart_home_config.should_expose(changed_entity):
|
||||
_LOGGER.debug("Not exposing %s because filtered by config",
|
||||
changed_entity)
|
||||
return
|
||||
|
||||
alexa_changed_entity = \
|
||||
ENTITY_ADAPTERS[new_state.domain](hass, smart_home_config,
|
||||
new_state)
|
||||
|
@ -49,7 +48,7 @@ async def async_enable_proactive_mode(hass, smart_home_config):
|
|||
alexa_changed_entity)
|
||||
return
|
||||
|
||||
hass.helpers.event.async_track_state_change(
|
||||
return hass.helpers.event.async_track_state_change(
|
||||
MATCH_ALL, async_entity_state_listener
|
||||
)
|
||||
|
||||
|
@ -94,7 +93,7 @@ async def async_send_changereport_message(hass, config, alexa_entity):
|
|||
allow_redirects=True)
|
||||
|
||||
except (asyncio.TimeoutError, aiohttp.ClientError):
|
||||
_LOGGER.error("Timeout calling LWA to get auth token.")
|
||||
_LOGGER.error("Timeout sending report to Alexa.")
|
||||
return None
|
||||
|
||||
response_text = await response.text()
|
||||
|
|
|
@ -2,8 +2,11 @@
|
|||
import asyncio
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
|
||||
import aiohttp
|
||||
from hass_nabucasa import cloud_api
|
||||
from hass_nabucasa.client import CloudClient as Interface
|
||||
|
||||
from homeassistant.core import callback
|
||||
|
@ -17,22 +20,41 @@ from homeassistant.const import CLOUD_NEVER_EXPOSED_ENTITIES
|
|||
from homeassistant.helpers.typing import HomeAssistantType
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
||||
from homeassistant.util.aiohttp import MockRequest
|
||||
from homeassistant.util.dt import utcnow
|
||||
|
||||
from . import utils
|
||||
from .const import (
|
||||
CONF_ENTITY_CONFIG, CONF_FILTER, DOMAIN, DISPATCHER_REMOTE_UPDATE,
|
||||
PREF_SHOULD_EXPOSE, DEFAULT_SHOULD_EXPOSE,
|
||||
PREF_DISABLE_2FA, DEFAULT_DISABLE_2FA)
|
||||
PREF_DISABLE_2FA, DEFAULT_DISABLE_2FA, RequireRelink)
|
||||
from .prefs import CloudPreferences
|
||||
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AlexaConfig(alexa_config.AbstractConfig):
|
||||
"""Alexa Configuration."""
|
||||
|
||||
def __init__(self, config, prefs):
|
||||
def __init__(self, hass, config, prefs, cloud):
|
||||
"""Initialize the Alexa config."""
|
||||
super().__init__(hass)
|
||||
self._config = config
|
||||
self._prefs = prefs
|
||||
self._cloud = cloud
|
||||
self._token = None
|
||||
self._token_valid = None
|
||||
prefs.async_listen_updates(self.async_prefs_updated)
|
||||
|
||||
@property
|
||||
def supports_auth(self):
|
||||
"""Return if config supports auth."""
|
||||
return True
|
||||
|
||||
@property
|
||||
def should_report_state(self):
|
||||
"""Return if states should be proactively reported."""
|
||||
return self._prefs.alexa_report_state
|
||||
|
||||
@property
|
||||
def endpoint(self):
|
||||
|
@ -57,6 +79,34 @@ class AlexaConfig(alexa_config.AbstractConfig):
|
|||
return entity_config.get(
|
||||
PREF_SHOULD_EXPOSE, DEFAULT_SHOULD_EXPOSE)
|
||||
|
||||
async def async_get_access_token(self):
|
||||
"""Get an access token."""
|
||||
if self._token_valid is not None and self._token_valid < utcnow():
|
||||
return self._token
|
||||
|
||||
resp = await cloud_api.async_alexa_access_token(self._cloud)
|
||||
body = await resp.json()
|
||||
|
||||
if resp.status == 400:
|
||||
if body['reason'] in ('RefreshTokenNotFound', 'UnknownRegion'):
|
||||
raise RequireRelink
|
||||
|
||||
return None
|
||||
|
||||
self._token = body['access_token']
|
||||
self._token_valid = utcnow() + timedelta(seconds=body['expires_in'])
|
||||
return self._token
|
||||
|
||||
async def async_prefs_updated(self, prefs):
|
||||
"""Handle updated preferences."""
|
||||
if self.should_report_state == self.is_reporting_states:
|
||||
return
|
||||
|
||||
if self.should_report_state:
|
||||
await self.async_enable_proactive_mode()
|
||||
else:
|
||||
await self.async_disable_proactive_mode()
|
||||
|
||||
|
||||
class CloudClient(Interface):
|
||||
"""Interface class for Home Assistant Cloud."""
|
||||
|
@ -70,9 +120,9 @@ class CloudClient(Interface):
|
|||
self._websession = websession
|
||||
self.google_user_config = google_config
|
||||
self.alexa_user_config = alexa_cfg
|
||||
|
||||
self.alexa_config = AlexaConfig(alexa_cfg, prefs)
|
||||
self._alexa_config = None
|
||||
self._google_config = None
|
||||
self.cloud = None
|
||||
|
||||
@property
|
||||
def base_path(self) -> Path:
|
||||
|
@ -109,6 +159,15 @@ class CloudClient(Interface):
|
|||
"""Return true if we want start a remote connection."""
|
||||
return self._prefs.remote_enabled
|
||||
|
||||
@property
|
||||
def alexa_config(self) -> AlexaConfig:
|
||||
"""Return Alexa config."""
|
||||
if self._alexa_config is None:
|
||||
self._alexa_config = AlexaConfig(
|
||||
self._hass, self.alexa_user_config, self._prefs, self.cloud)
|
||||
|
||||
return self._alexa_config
|
||||
|
||||
@property
|
||||
def google_config(self) -> ga_h.Config:
|
||||
"""Return Google config."""
|
||||
|
@ -151,6 +210,13 @@ class CloudClient(Interface):
|
|||
|
||||
return self._google_config
|
||||
|
||||
async def async_initialize(self, cloud) -> None:
|
||||
"""Initialize the client."""
|
||||
self.cloud = cloud
|
||||
|
||||
if self.alexa_config.should_report_state and self.cloud.is_logged_in:
|
||||
await self.alexa_config.async_enable_proactive_mode()
|
||||
|
||||
async def cleanups(self) -> None:
|
||||
"""Cleanup some stuff after logout."""
|
||||
self._google_config = None
|
||||
|
|
|
@ -10,12 +10,14 @@ PREF_CLOUDHOOKS = 'cloudhooks'
|
|||
PREF_CLOUD_USER = 'cloud_user'
|
||||
PREF_GOOGLE_ENTITY_CONFIGS = 'google_entity_configs'
|
||||
PREF_ALEXA_ENTITY_CONFIGS = 'alexa_entity_configs'
|
||||
PREF_ALEXA_REPORT_STATE = 'alexa_report_state'
|
||||
PREF_OVERRIDE_NAME = 'override_name'
|
||||
PREF_DISABLE_2FA = 'disable_2fa'
|
||||
PREF_ALIASES = 'aliases'
|
||||
PREF_SHOULD_EXPOSE = 'should_expose'
|
||||
DEFAULT_SHOULD_EXPOSE = True
|
||||
DEFAULT_DISABLE_2FA = False
|
||||
DEFAULT_ALEXA_REPORT_STATE = False
|
||||
|
||||
CONF_ALEXA = 'alexa'
|
||||
CONF_ALIASES = 'aliases'
|
||||
|
@ -43,3 +45,7 @@ class InvalidTrustedNetworks(Exception):
|
|||
|
||||
class InvalidTrustedProxies(Exception):
|
||||
"""Raised when invalid trusted proxies config."""
|
||||
|
||||
|
||||
class RequireRelink(Exception):
|
||||
"""The skill needs to be relinked."""
|
||||
|
|
|
@ -19,7 +19,7 @@ from homeassistant.components.google_assistant import helpers as google_helpers
|
|||
from .const import (
|
||||
DOMAIN, REQUEST_TIMEOUT, PREF_ENABLE_ALEXA, PREF_ENABLE_GOOGLE,
|
||||
PREF_GOOGLE_SECURE_DEVICES_PIN, InvalidTrustedNetworks,
|
||||
InvalidTrustedProxies)
|
||||
InvalidTrustedProxies, PREF_ALEXA_REPORT_STATE)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
@ -363,6 +363,7 @@ async def websocket_subscription(hass, connection, msg):
|
|||
vol.Required('type'): 'cloud/update_prefs',
|
||||
vol.Optional(PREF_ENABLE_GOOGLE): bool,
|
||||
vol.Optional(PREF_ENABLE_ALEXA): bool,
|
||||
vol.Optional(PREF_ALEXA_REPORT_STATE): bool,
|
||||
vol.Optional(PREF_GOOGLE_SECURE_DEVICES_PIN): vol.Any(None, str),
|
||||
})
|
||||
async def websocket_update_prefs(hass, connection, msg):
|
||||
|
@ -424,7 +425,6 @@ def _account_data(cloud):
|
|||
'prefs': client.prefs.as_dict(),
|
||||
'google_entities': client.google_user_config['filter'].config,
|
||||
'alexa_entities': client.alexa_user_config['filter'].config,
|
||||
'alexa_domains': list(alexa_entities.ENTITY_ADAPTERS),
|
||||
'remote_domain': remote.instance_domain,
|
||||
'remote_connected': remote.is_connected,
|
||||
'remote_certificate': certificate,
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
"name": "Cloud",
|
||||
"documentation": "https://www.home-assistant.io/components/cloud",
|
||||
"requirements": [
|
||||
"hass-nabucasa==0.14"
|
||||
"hass-nabucasa==0.15"
|
||||
],
|
||||
"dependencies": [
|
||||
"http",
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
"""Preference management for cloud."""
|
||||
from ipaddress import ip_address
|
||||
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.util.logging import async_create_catching_coro
|
||||
|
||||
from .const import (
|
||||
DOMAIN, PREF_ENABLE_ALEXA, PREF_ENABLE_GOOGLE, PREF_ENABLE_REMOTE,
|
||||
PREF_GOOGLE_SECURE_DEVICES_PIN, PREF_CLOUDHOOKS, PREF_CLOUD_USER,
|
||||
PREF_GOOGLE_ENTITY_CONFIGS, PREF_OVERRIDE_NAME, PREF_DISABLE_2FA,
|
||||
PREF_ALIASES, PREF_SHOULD_EXPOSE, PREF_ALEXA_ENTITY_CONFIGS,
|
||||
PREF_ALEXA_REPORT_STATE, DEFAULT_ALEXA_REPORT_STATE,
|
||||
InvalidTrustedNetworks, InvalidTrustedProxies)
|
||||
|
||||
STORAGE_KEY = DOMAIN
|
||||
|
@ -21,6 +25,7 @@ class CloudPreferences:
|
|||
self._hass = hass
|
||||
self._store = hass.helpers.storage.Store(STORAGE_VERSION, STORAGE_KEY)
|
||||
self._prefs = None
|
||||
self._listeners = []
|
||||
|
||||
async def async_initialize(self):
|
||||
"""Finish initializing the preferences."""
|
||||
|
@ -40,11 +45,17 @@ class CloudPreferences:
|
|||
|
||||
self._prefs = prefs
|
||||
|
||||
@callback
|
||||
def async_listen_updates(self, listener):
|
||||
"""Listen for updates to the preferences."""
|
||||
self._listeners.append(listener)
|
||||
|
||||
async def async_update(self, *, google_enabled=_UNDEF,
|
||||
alexa_enabled=_UNDEF, remote_enabled=_UNDEF,
|
||||
google_secure_devices_pin=_UNDEF, cloudhooks=_UNDEF,
|
||||
cloud_user=_UNDEF, google_entity_configs=_UNDEF,
|
||||
alexa_entity_configs=_UNDEF):
|
||||
alexa_entity_configs=_UNDEF,
|
||||
alexa_report_state=_UNDEF):
|
||||
"""Update user preferences."""
|
||||
for key, value in (
|
||||
(PREF_ENABLE_GOOGLE, google_enabled),
|
||||
|
@ -55,18 +66,26 @@ class CloudPreferences:
|
|||
(PREF_CLOUD_USER, cloud_user),
|
||||
(PREF_GOOGLE_ENTITY_CONFIGS, google_entity_configs),
|
||||
(PREF_ALEXA_ENTITY_CONFIGS, alexa_entity_configs),
|
||||
(PREF_ALEXA_REPORT_STATE, alexa_report_state),
|
||||
):
|
||||
if value is not _UNDEF:
|
||||
self._prefs[key] = value
|
||||
|
||||
if remote_enabled is True and self._has_local_trusted_network:
|
||||
self._prefs[PREF_ENABLE_REMOTE] = False
|
||||
raise InvalidTrustedNetworks
|
||||
|
||||
if remote_enabled is True and self._has_local_trusted_proxies:
|
||||
self._prefs[PREF_ENABLE_REMOTE] = False
|
||||
raise InvalidTrustedProxies
|
||||
|
||||
await self._store.async_save(self._prefs)
|
||||
|
||||
for listener in self._listeners:
|
||||
self._hass.async_create_task(
|
||||
async_create_catching_coro(listener(self))
|
||||
)
|
||||
|
||||
async def async_update_google_entity_config(
|
||||
self, *, entity_id, override_name=_UNDEF, disable_2fa=_UNDEF,
|
||||
aliases=_UNDEF, should_expose=_UNDEF):
|
||||
|
@ -134,6 +153,7 @@ class CloudPreferences:
|
|||
PREF_GOOGLE_SECURE_DEVICES_PIN: self.google_secure_devices_pin,
|
||||
PREF_GOOGLE_ENTITY_CONFIGS: self.google_entity_configs,
|
||||
PREF_ALEXA_ENTITY_CONFIGS: self.alexa_entity_configs,
|
||||
PREF_ALEXA_REPORT_STATE: self.alexa_report_state,
|
||||
PREF_CLOUDHOOKS: self.cloudhooks,
|
||||
PREF_CLOUD_USER: self.cloud_user,
|
||||
}
|
||||
|
@ -156,6 +176,12 @@ class CloudPreferences:
|
|||
"""Return if Alexa is enabled."""
|
||||
return self._prefs[PREF_ENABLE_ALEXA]
|
||||
|
||||
@property
|
||||
def alexa_report_state(self):
|
||||
"""Return if Alexa report state is enabled."""
|
||||
return self._prefs.get(PREF_ALEXA_REPORT_STATE,
|
||||
DEFAULT_ALEXA_REPORT_STATE)
|
||||
|
||||
@property
|
||||
def google_enabled(self):
|
||||
"""Return if Google is enabled."""
|
||||
|
|
|
@ -9,7 +9,7 @@ bcrypt==3.1.6
|
|||
certifi>=2018.04.16
|
||||
cryptography==2.6.1
|
||||
distro==1.4.0
|
||||
hass-nabucasa==0.14
|
||||
hass-nabucasa==0.15
|
||||
home-assistant-frontend==20190614.0
|
||||
importlib-metadata==0.15
|
||||
jinja2>=2.10
|
||||
|
|
|
@ -562,7 +562,7 @@ habitipy==0.2.0
|
|||
hangups==0.4.9
|
||||
|
||||
# homeassistant.components.cloud
|
||||
hass-nabucasa==0.14
|
||||
hass-nabucasa==0.15
|
||||
|
||||
# homeassistant.components.mqtt
|
||||
hbmqtt==0.9.4
|
||||
|
|
|
@ -145,7 +145,7 @@ ha-ffmpeg==2.0
|
|||
hangups==0.4.9
|
||||
|
||||
# homeassistant.components.cloud
|
||||
hass-nabucasa==0.14
|
||||
hass-nabucasa==0.15
|
||||
|
||||
# homeassistant.components.mqtt
|
||||
hbmqtt==0.9.4
|
||||
|
|
|
@ -38,7 +38,7 @@ class MockConfig(config.AbstractConfig):
|
|||
pass
|
||||
|
||||
|
||||
DEFAULT_CONFIG = MockConfig()
|
||||
DEFAULT_CONFIG = MockConfig(None)
|
||||
|
||||
|
||||
def get_new_request(namespace, name, endpoint=None):
|
||||
|
|
|
@ -1012,7 +1012,7 @@ async def test_exclude_filters(hass):
|
|||
hass.states.async_set(
|
||||
'cover.deny', 'off', {'friendly_name': "Blocked cover"})
|
||||
|
||||
alexa_config = MockConfig()
|
||||
alexa_config = MockConfig(hass)
|
||||
alexa_config.should_expose = entityfilter.generate_filter(
|
||||
include_domains=[],
|
||||
include_entities=[],
|
||||
|
@ -1045,7 +1045,7 @@ async def test_include_filters(hass):
|
|||
hass.states.async_set(
|
||||
'group.allow', 'off', {'friendly_name': "Allowed group"})
|
||||
|
||||
alexa_config = MockConfig()
|
||||
alexa_config = MockConfig(hass)
|
||||
alexa_config.should_expose = entityfilter.generate_filter(
|
||||
include_domains=['automation', 'group'],
|
||||
include_entities=['script.deny'],
|
||||
|
@ -1072,7 +1072,7 @@ async def test_never_exposed_entities(hass):
|
|||
hass.states.async_set(
|
||||
'group.allow', 'off', {'friendly_name': "Allowed group"})
|
||||
|
||||
alexa_config = MockConfig()
|
||||
alexa_config = MockConfig(hass)
|
||||
alexa_config.should_expose = entityfilter.generate_filter(
|
||||
include_domains=['group'],
|
||||
include_entities=[],
|
||||
|
@ -1155,7 +1155,7 @@ async def test_entity_config(hass):
|
|||
hass.states.async_set(
|
||||
'light.test_1', 'on', {'friendly_name': "Test light 1"})
|
||||
|
||||
alexa_config = MockConfig()
|
||||
alexa_config = MockConfig(hass)
|
||||
alexa_config.entity_config = {
|
||||
'light.test_1': {
|
||||
'name': 'Config name',
|
||||
|
|
|
@ -3,6 +3,8 @@ import pytest
|
|||
|
||||
from unittest.mock import patch
|
||||
|
||||
from homeassistant.components.cloud import prefs
|
||||
|
||||
from . import mock_cloud, mock_cloud_prefs
|
||||
|
||||
|
||||
|
@ -18,3 +20,11 @@ def mock_cloud_fixture(hass):
|
|||
"""Fixture for cloud component."""
|
||||
mock_cloud(hass)
|
||||
return mock_cloud_prefs(hass)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def cloud_prefs(hass):
|
||||
"""Fixture for cloud preferences."""
|
||||
cloud_prefs = prefs.CloudPreferences(hass)
|
||||
await cloud_prefs.async_initialize()
|
||||
return cloud_prefs
|
||||
|
|
|
@ -8,7 +8,7 @@ import pytest
|
|||
from homeassistant.core import State
|
||||
from homeassistant.setup import async_setup_component
|
||||
from homeassistant.components.cloud import (
|
||||
DOMAIN, ALEXA_SCHEMA, prefs, client)
|
||||
DOMAIN, ALEXA_SCHEMA, client)
|
||||
from homeassistant.components.cloud.const import (
|
||||
PREF_ENABLE_ALEXA, PREF_ENABLE_GOOGLE)
|
||||
from tests.components.alexa import test_smart_home as test_alexa
|
||||
|
@ -254,18 +254,41 @@ async def test_google_config_should_2fa(
|
|||
assert not cloud_client.google_config.should_2fa(state)
|
||||
|
||||
|
||||
async def test_alexa_config_expose_entity_prefs(hass):
|
||||
async def test_alexa_config_expose_entity_prefs(hass, cloud_prefs):
|
||||
"""Test Alexa config should expose using prefs."""
|
||||
cloud_prefs = prefs.CloudPreferences(hass)
|
||||
await cloud_prefs.async_initialize()
|
||||
entity_conf = {
|
||||
'should_expose': False
|
||||
}
|
||||
await cloud_prefs.async_update(alexa_entity_configs={
|
||||
'light.kitchen': entity_conf
|
||||
})
|
||||
conf = client.AlexaConfig(ALEXA_SCHEMA({}), cloud_prefs)
|
||||
conf = client.AlexaConfig(hass, ALEXA_SCHEMA({}), cloud_prefs, None)
|
||||
|
||||
assert not conf.should_expose('light.kitchen')
|
||||
entity_conf['should_expose'] = True
|
||||
assert conf.should_expose('light.kitchen')
|
||||
|
||||
|
||||
async def test_alexa_config_report_state(hass, cloud_prefs):
|
||||
"""Test Alexa config should expose using prefs."""
|
||||
conf = client.AlexaConfig(hass, ALEXA_SCHEMA({}), cloud_prefs, None)
|
||||
|
||||
assert cloud_prefs.alexa_report_state is False
|
||||
assert conf.should_report_state is False
|
||||
assert conf.is_reporting_states is False
|
||||
|
||||
with patch.object(conf, 'async_get_access_token',
|
||||
return_value=mock_coro("hello")):
|
||||
await cloud_prefs.async_update(alexa_report_state=True)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert cloud_prefs.alexa_report_state is True
|
||||
assert conf.should_report_state is True
|
||||
assert conf.is_reporting_states is True
|
||||
|
||||
await cloud_prefs.async_update(alexa_report_state=False)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert cloud_prefs.alexa_report_state is False
|
||||
assert conf.should_report_state is False
|
||||
assert conf.is_reporting_states is False
|
||||
|
|
|
@ -363,6 +363,7 @@ async def test_websocket_status(hass, hass_ws_client, mock_cloud_fixture,
|
|||
'google_entity_configs': {},
|
||||
'google_secure_devices_pin': None,
|
||||
'alexa_entity_configs': {},
|
||||
'alexa_report_state': False,
|
||||
'remote_enabled': False,
|
||||
},
|
||||
'alexa_entities': {
|
||||
|
@ -371,7 +372,6 @@ async def test_websocket_status(hass, hass_ws_client, mock_cloud_fixture,
|
|||
'exclude_domains': [],
|
||||
'exclude_entities': [],
|
||||
},
|
||||
'alexa_domains': ['switch'],
|
||||
'google_entities': {
|
||||
'include_domains': ['light'],
|
||||
'include_entities': [],
|
||||
|
|
Loading…
Reference in New Issue