From bf54582d762c6e9f2d56eceaebb902eff975c6ea Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Mon, 5 Nov 2018 13:21:03 +0100 Subject: [PATCH] Cloud conf (#18216) * Add original config to entityfilter * Add alexa/google config to cloud status call * Lint --- homeassistant/components/cloud/__init__.py | 4 +-- homeassistant/components/cloud/http_api.py | 6 ++++ homeassistant/helpers/entityfilter.py | 28 +++++++++------ tests/components/cloud/test_http_api.py | 40 +++++++++++++++++++--- tests/helpers/test_entityfilter.py | 16 +++++++-- 5 files changed, 74 insertions(+), 20 deletions(-) diff --git a/homeassistant/components/cloud/__init__.py b/homeassistant/components/cloud/__init__.py index ba2d41a9feb..bc486eb7ead 100644 --- a/homeassistant/components/cloud/__init__.py +++ b/homeassistant/components/cloud/__init__.py @@ -122,7 +122,7 @@ class Cloud: self.hass = hass self.mode = mode self.alexa_config = alexa - self._google_actions = google_actions + self.google_actions_user_conf = google_actions self._gactions_config = None self._prefs = None self.id_token = None @@ -180,7 +180,7 @@ class Cloud: def gactions_config(self): """Return the Google Assistant config.""" if self._gactions_config is None: - conf = self._google_actions + conf = self.google_actions_user_conf def should_expose(entity): """If an entity should be exposed.""" diff --git a/homeassistant/components/cloud/http_api.py b/homeassistant/components/cloud/http_api.py index 0df4a39406e..cb62d773dfd 100644 --- a/homeassistant/components/cloud/http_api.py +++ b/homeassistant/components/cloud/http_api.py @@ -11,6 +11,8 @@ from homeassistant.components.http import HomeAssistantView from homeassistant.components.http.data_validator import ( RequestDataValidator) from homeassistant.components import websocket_api +from homeassistant.components.alexa import smart_home as alexa_sh +from homeassistant.components.google_assistant import smart_home as google_sh from . import auth_api from .const import DOMAIN, REQUEST_TIMEOUT @@ -307,5 +309,9 @@ def _account_data(cloud): 'email': claims['email'], 'cloud': cloud.iot.state, 'google_enabled': cloud.google_enabled, + 'google_entities': cloud.google_actions_user_conf['filter'].config, + 'google_domains': list(google_sh.DOMAIN_TO_GOOGLE_TYPES), 'alexa_enabled': cloud.alexa_enabled, + 'alexa_entities': cloud.alexa_config.should_expose.config, + 'alexa_domains': list(alexa_sh.ENTITY_ADAPTERS), } diff --git a/homeassistant/helpers/entityfilter.py b/homeassistant/helpers/entityfilter.py index c9554488aa7..141fc912275 100644 --- a/homeassistant/helpers/entityfilter.py +++ b/homeassistant/helpers/entityfilter.py @@ -10,6 +10,18 @@ CONF_INCLUDE_ENTITIES = 'include_entities' CONF_EXCLUDE_DOMAINS = 'exclude_domains' CONF_EXCLUDE_ENTITIES = 'exclude_entities' + +def _convert_filter(config): + filt = generate_filter( + config[CONF_INCLUDE_DOMAINS], + config[CONF_INCLUDE_ENTITIES], + config[CONF_EXCLUDE_DOMAINS], + config[CONF_EXCLUDE_ENTITIES], + ) + filt.config = config + return filt + + FILTER_SCHEMA = vol.All( vol.Schema({ vol.Optional(CONF_EXCLUDE_DOMAINS, default=[]): @@ -18,13 +30,7 @@ FILTER_SCHEMA = vol.All( vol.Optional(CONF_INCLUDE_DOMAINS, default=[]): vol.All(cv.ensure_list, [cv.string]), vol.Optional(CONF_INCLUDE_ENTITIES, default=[]): cv.entity_ids, - }), - lambda config: generate_filter( - config[CONF_INCLUDE_DOMAINS], - config[CONF_INCLUDE_ENTITIES], - config[CONF_EXCLUDE_DOMAINS], - config[CONF_EXCLUDE_ENTITIES], - )) + }), _convert_filter) def generate_filter(include_domains, include_entities, @@ -64,8 +70,8 @@ def generate_filter(include_domains, include_entities, # Case 4 - both includes and excludes specified # Case 4a - include domain specified - # - if domain is included, and entity not excluded, pass - # - if domain is not included, and entity not included, fail + # - if domain is included, pass if entity not excluded + # - if domain is not included, pass if entity is included # note: if both include and exclude domains specified, # the exclude domains are ignored if include_d: @@ -79,8 +85,8 @@ def generate_filter(include_domains, include_entities, return entity_filter_4a # Case 4b - exclude domain specified - # - if domain is excluded, and entity not included, fail - # - if domain is not excluded, and entity not excluded, pass + # - if domain is excluded, pass if entity is included + # - if domain is not excluded, pass if entity not excluded if exclude_d: def entity_filter_4b(entity_id): """Return filter function for case 4b.""" diff --git a/tests/components/cloud/test_http_api.py b/tests/components/cloud/test_http_api.py index e27760bd6ed..a8128c8d3e0 100644 --- a/tests/components/cloud/test_http_api.py +++ b/tests/components/cloud/test_http_api.py @@ -35,6 +35,16 @@ def setup_api(hass): 'relayer': 'relayer', 'google_actions_sync_url': GOOGLE_ACTIONS_SYNC_URL, 'subscription_info_url': SUBSCRIPTION_INFO_URL, + 'google_actions': { + 'filter': { + 'include_domains': 'light' + } + }, + 'alexa': { + 'filter': { + 'include_entities': ['light.kitchen', 'switch.ac'] + } + } }) return mock_cloud_prefs(hass) @@ -325,17 +335,37 @@ async def test_websocket_status(hass, hass_ws_client, mock_cloud_fixture): }, 'test') hass.data[DOMAIN].iot.state = iot.STATE_CONNECTED client = await hass_ws_client(hass) - await client.send_json({ - 'id': 5, - 'type': 'cloud/status' - }) - response = await client.receive_json() + + with patch.dict( + 'homeassistant.components.google_assistant.smart_home.' + 'DOMAIN_TO_GOOGLE_TYPES', {'light': None}, clear=True + ), patch.dict('homeassistant.components.alexa.smart_home.ENTITY_ADAPTERS', + {'switch': None}, clear=True): + await client.send_json({ + 'id': 5, + 'type': 'cloud/status' + }) + response = await client.receive_json() assert response['result'] == { 'logged_in': True, 'email': 'hello@home-assistant.io', 'cloud': 'connected', 'alexa_enabled': True, + 'alexa_entities': { + 'include_domains': [], + 'include_entities': ['light.kitchen', 'switch.ac'], + 'exclude_domains': [], + 'exclude_entities': [], + }, + 'alexa_domains': ['switch'], 'google_enabled': True, + 'google_entities': { + 'include_domains': ['light'], + 'include_entities': [], + 'exclude_domains': [], + 'exclude_entities': [], + }, + 'google_domains': ['light'], } diff --git a/tests/helpers/test_entityfilter.py b/tests/helpers/test_entityfilter.py index 944224a34d1..13e5bc1d273 100644 --- a/tests/helpers/test_entityfilter.py +++ b/tests/helpers/test_entityfilter.py @@ -1,5 +1,5 @@ """The tests for the EntityFilter component.""" -from homeassistant.helpers.entityfilter import generate_filter +from homeassistant.helpers.entityfilter import generate_filter, FILTER_SCHEMA def test_no_filters_case_1(): @@ -78,7 +78,7 @@ def test_exclude_domain_case4b(): assert testfilter("sun.sun") is True -def testno_domain_case4c(): +def test_no_domain_case4c(): """Test case 4c - include and exclude specified, with no domains.""" incl_dom = {} incl_ent = {'binary_sensor.working'} @@ -93,3 +93,15 @@ def testno_domain_case4c(): assert testfilter("binary_sensor.working") assert testfilter("binary_sensor.another") is False assert testfilter("sun.sun") is False + + +def test_filter_schema(): + """Test filter schema.""" + conf = { + 'include_domains': ['light'], + 'include_entities': ['switch.kitchen'], + 'exclude_domains': ['cover'], + 'exclude_entities': ['light.kitchen'] + } + filt = FILTER_SCHEMA(conf) + assert filt.config == conf