Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions homeassistant/components/cloud/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ def __init__(self, hass, mode, alexa, google_actions,
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
Expand Down Expand Up @@ -180,7 +180,7 @@ def user_info_path(self):
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."""
Expand Down
6 changes: 6 additions & 0 deletions homeassistant/components/cloud/http_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
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
Expand Down Expand Up @@ -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),
}
28 changes: 17 additions & 11 deletions homeassistant/helpers/entityfilter.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,18 @@
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=[]):
Expand All @@ -18,13 +30,7 @@
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,
Expand Down Expand Up @@ -64,8 +70,8 @@ def entity_filter_3(entity_id):

# 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:
Expand All @@ -79,8 +85,8 @@ def entity_filter_4a(entity_id):
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."""
Expand Down
40 changes: 35 additions & 5 deletions tests/components/cloud/test_http_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -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'],
}


Expand Down
16 changes: 14 additions & 2 deletions tests/helpers/test_entityfilter.py
Original file line number Diff line number Diff line change
@@ -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():
Expand Down Expand Up @@ -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'}
Expand All @@ -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