Implement entity and domain exclude/include for Alexa (#10647)

* Implement entity and domain exclude/include for Alexa

* Switch to using generate_filter

* Use proper domain for turn on/off calls except for groups where we must use the generic homeassistant.turn_on/off

* travis fixes

* Untangle

* Lint
pull/10644/merge
Robbie Trencheny 2017-11-17 21:10:24 -08:00 committed by Paulus Schoutsen
parent 64a393b377
commit 1317297191
7 changed files with 233 additions and 75 deletions

View File

@ -1,5 +1,6 @@
"""Support for alexa Smart Home Skill API."""
import asyncio
from collections import namedtuple
import logging
import math
from uuid import uuid4
@ -72,8 +73,11 @@ MAPPING_COMPONENT = {
}
Config = namedtuple('AlexaConfig', 'filter')
@asyncio.coroutine
def async_handle_message(hass, message):
def async_handle_message(hass, config, message):
"""Handle incoming API messages."""
assert message[API_DIRECTIVE][API_HEADER]['payloadVersion'] == '3'
@ -89,7 +93,7 @@ def async_handle_message(hass, message):
"Unsupported API request %s/%s", namespace, name)
return api_error(message)
return (yield from funct_ref(hass, message))
return (yield from funct_ref(hass, config, message))
def api_message(request, name='Response', namespace='Alexa', payload=None):
@ -138,7 +142,7 @@ def api_error(request, error_type='INTERNAL_ERROR', error_message=""):
@HANDLERS.register(('Alexa.Discovery', 'Discover'))
@asyncio.coroutine
def async_api_discovery(hass, request):
def async_api_discovery(hass, config, request):
"""Create a API formatted discovery response.
Async friendly.
@ -146,7 +150,14 @@ def async_api_discovery(hass, request):
discovery_endpoints = []
for entity in hass.states.async_all():
if not config.filter(entity.entity_id):
_LOGGER.debug("Not exposing %s because filtered by config",
entity.entity_id)
continue
if entity.attributes.get(ATTR_ALEXA_HIDDEN, False):
_LOGGER.debug("Not exposing %s because alexa_hidden is true",
entity.entity_id)
continue
class_data = MAPPING_COMPONENT.get(entity.domain)
@ -207,7 +218,7 @@ def async_api_discovery(hass, request):
def extract_entity(funct):
"""Decorator for extract entity object from request."""
@asyncio.coroutine
def async_api_entity_wrapper(hass, request):
def async_api_entity_wrapper(hass, config, request):
"""Process a turn on request."""
entity_id = request[API_ENDPOINT]['endpointId'].replace('#', '.')
@ -218,7 +229,7 @@ def extract_entity(funct):
request[API_HEADER]['name'], entity_id)
return api_error(request, error_type='NO_SUCH_ENDPOINT')
return (yield from funct(hass, request, entity))
return (yield from funct(hass, config, request, entity))
return async_api_entity_wrapper
@ -226,9 +237,13 @@ def extract_entity(funct):
@HANDLERS.register(('Alexa.PowerController', 'TurnOn'))
@extract_entity
@asyncio.coroutine
def async_api_turn_on(hass, request, entity):
def async_api_turn_on(hass, config, request, entity):
"""Process a turn on request."""
yield from hass.services.async_call(ha.DOMAIN, SERVICE_TURN_ON, {
domain = entity.domain
if entity.domain == group.DOMAIN:
domain = ha.DOMAIN
yield from hass.services.async_call(domain, SERVICE_TURN_ON, {
ATTR_ENTITY_ID: entity.entity_id
}, blocking=True)
@ -238,9 +253,13 @@ def async_api_turn_on(hass, request, entity):
@HANDLERS.register(('Alexa.PowerController', 'TurnOff'))
@extract_entity
@asyncio.coroutine
def async_api_turn_off(hass, request, entity):
def async_api_turn_off(hass, config, request, entity):
"""Process a turn off request."""
yield from hass.services.async_call(ha.DOMAIN, SERVICE_TURN_OFF, {
domain = entity.domain
if entity.domain == group.DOMAIN:
domain = ha.DOMAIN
yield from hass.services.async_call(domain, SERVICE_TURN_OFF, {
ATTR_ENTITY_ID: entity.entity_id
}, blocking=True)
@ -250,7 +269,7 @@ def async_api_turn_off(hass, request, entity):
@HANDLERS.register(('Alexa.BrightnessController', 'SetBrightness'))
@extract_entity
@asyncio.coroutine
def async_api_set_brightness(hass, request, entity):
def async_api_set_brightness(hass, config, request, entity):
"""Process a set brightness request."""
brightness = int(request[API_PAYLOAD]['brightness'])
@ -265,7 +284,7 @@ def async_api_set_brightness(hass, request, entity):
@HANDLERS.register(('Alexa.BrightnessController', 'AdjustBrightness'))
@extract_entity
@asyncio.coroutine
def async_api_adjust_brightness(hass, request, entity):
def async_api_adjust_brightness(hass, config, request, entity):
"""Process a adjust brightness request."""
brightness_delta = int(request[API_PAYLOAD]['brightnessDelta'])
@ -289,7 +308,7 @@ def async_api_adjust_brightness(hass, request, entity):
@HANDLERS.register(('Alexa.ColorController', 'SetColor'))
@extract_entity
@asyncio.coroutine
def async_api_set_color(hass, request, entity):
def async_api_set_color(hass, config, request, entity):
"""Process a set color request."""
supported = entity.attributes.get(ATTR_SUPPORTED_FEATURES)
rgb = color_util.color_hsb_to_RGB(
@ -317,7 +336,7 @@ def async_api_set_color(hass, request, entity):
@HANDLERS.register(('Alexa.ColorTemperatureController', 'SetColorTemperature'))
@extract_entity
@asyncio.coroutine
def async_api_set_color_temperature(hass, request, entity):
def async_api_set_color_temperature(hass, config, request, entity):
"""Process a set color temperature request."""
kelvin = int(request[API_PAYLOAD]['colorTemperatureInKelvin'])
@ -333,7 +352,7 @@ def async_api_set_color_temperature(hass, request, entity):
('Alexa.ColorTemperatureController', 'DecreaseColorTemperature'))
@extract_entity
@asyncio.coroutine
def async_api_decrease_color_temp(hass, request, entity):
def async_api_decrease_color_temp(hass, config, request, entity):
"""Process a decrease color temperature request."""
current = int(entity.attributes.get(light.ATTR_COLOR_TEMP))
max_mireds = int(entity.attributes.get(light.ATTR_MAX_MIREDS))
@ -351,7 +370,7 @@ def async_api_decrease_color_temp(hass, request, entity):
('Alexa.ColorTemperatureController', 'IncreaseColorTemperature'))
@extract_entity
@asyncio.coroutine
def async_api_increase_color_temp(hass, request, entity):
def async_api_increase_color_temp(hass, config, request, entity):
"""Process a increase color temperature request."""
current = int(entity.attributes.get(light.ATTR_COLOR_TEMP))
min_mireds = int(entity.attributes.get(light.ATTR_MIN_MIREDS))
@ -368,7 +387,7 @@ def async_api_increase_color_temp(hass, request, entity):
@HANDLERS.register(('Alexa.SceneController', 'Activate'))
@extract_entity
@asyncio.coroutine
def async_api_activate(hass, request, entity):
def async_api_activate(hass, config, request, entity):
"""Process a activate request."""
yield from hass.services.async_call(entity.domain, SERVICE_TURN_ON, {
ATTR_ENTITY_ID: entity.entity_id
@ -380,7 +399,7 @@ def async_api_activate(hass, request, entity):
@HANDLERS.register(('Alexa.PercentageController', 'SetPercentage'))
@extract_entity
@asyncio.coroutine
def async_api_set_percentage(hass, request, entity):
def async_api_set_percentage(hass, config, request, entity):
"""Process a set percentage request."""
percentage = int(request[API_PAYLOAD]['percentage'])
service = None
@ -411,7 +430,7 @@ def async_api_set_percentage(hass, request, entity):
@HANDLERS.register(('Alexa.PercentageController', 'AdjustPercentage'))
@extract_entity
@asyncio.coroutine
def async_api_adjust_percentage(hass, request, entity):
def async_api_adjust_percentage(hass, config, request, entity):
"""Process a adjust percentage request."""
percentage_delta = int(request[API_PAYLOAD]['percentageDelta'])
service = None
@ -459,7 +478,7 @@ def async_api_adjust_percentage(hass, request, entity):
@HANDLERS.register(('Alexa.LockController', 'Lock'))
@extract_entity
@asyncio.coroutine
def async_api_lock(hass, request, entity):
def async_api_lock(hass, config, request, entity):
"""Process a lock request."""
yield from hass.services.async_call(entity.domain, SERVICE_LOCK, {
ATTR_ENTITY_ID: entity.entity_id
@ -472,7 +491,7 @@ def async_api_lock(hass, request, entity):
@HANDLERS.register(('Alexa.LockController', 'Unlock'))
@extract_entity
@asyncio.coroutine
def async_api_unlock(hass, request, entity):
def async_api_unlock(hass, config, request, entity):
"""Process a unlock request."""
yield from hass.services.async_call(entity.domain, SERVICE_UNLOCK, {
ATTR_ENTITY_ID: entity.entity_id
@ -484,7 +503,7 @@ def async_api_unlock(hass, request, entity):
@HANDLERS.register(('Alexa.Speaker', 'SetVolume'))
@extract_entity
@asyncio.coroutine
def async_api_set_volume(hass, request, entity):
def async_api_set_volume(hass, config, request, entity):
"""Process a set volume request."""
volume = round(float(request[API_PAYLOAD]['volume'] / 100), 2)
@ -502,7 +521,7 @@ def async_api_set_volume(hass, request, entity):
@HANDLERS.register(('Alexa.Speaker', 'AdjustVolume'))
@extract_entity
@asyncio.coroutine
def async_api_adjust_volume(hass, request, entity):
def async_api_adjust_volume(hass, config, request, entity):
"""Process a adjust volume request."""
volume_delta = int(request[API_PAYLOAD]['volume'])
@ -531,7 +550,7 @@ def async_api_adjust_volume(hass, request, entity):
@HANDLERS.register(('Alexa.Speaker', 'SetMute'))
@extract_entity
@asyncio.coroutine
def async_api_set_mute(hass, request, entity):
def async_api_set_mute(hass, config, request, entity):
"""Process a set mute request."""
mute = bool(request[API_PAYLOAD]['mute'])
@ -550,7 +569,7 @@ def async_api_set_mute(hass, request, entity):
@HANDLERS.register(('Alexa.PlaybackController', 'Play'))
@extract_entity
@asyncio.coroutine
def async_api_play(hass, request, entity):
def async_api_play(hass, config, request, entity):
"""Process a play request."""
data = {
ATTR_ENTITY_ID: entity.entity_id
@ -565,7 +584,7 @@ def async_api_play(hass, request, entity):
@HANDLERS.register(('Alexa.PlaybackController', 'Pause'))
@extract_entity
@asyncio.coroutine
def async_api_pause(hass, request, entity):
def async_api_pause(hass, config, request, entity):
"""Process a pause request."""
data = {
ATTR_ENTITY_ID: entity.entity_id
@ -580,7 +599,7 @@ def async_api_pause(hass, request, entity):
@HANDLERS.register(('Alexa.PlaybackController', 'Stop'))
@extract_entity
@asyncio.coroutine
def async_api_stop(hass, request, entity):
def async_api_stop(hass, config, request, entity):
"""Process a stop request."""
data = {
ATTR_ENTITY_ID: entity.entity_id
@ -595,7 +614,7 @@ def async_api_stop(hass, request, entity):
@HANDLERS.register(('Alexa.PlaybackController', 'Next'))
@extract_entity
@asyncio.coroutine
def async_api_next(hass, request, entity):
def async_api_next(hass, config, request, entity):
"""Process a next request."""
data = {
ATTR_ENTITY_ID: entity.entity_id
@ -611,7 +630,7 @@ def async_api_next(hass, request, entity):
@HANDLERS.register(('Alexa.PlaybackController', 'Previous'))
@extract_entity
@asyncio.coroutine
def async_api_previous(hass, request, entity):
def async_api_previous(hass, config, request, entity):
"""Process a previous request."""
data = {
ATTR_ENTITY_ID: entity.entity_id

View File

@ -9,7 +9,9 @@ import voluptuous as vol
from homeassistant.const import (
EVENT_HOMEASSISTANT_START, CONF_REGION, CONF_MODE)
from homeassistant.helpers import entityfilter
from homeassistant.util import dt as dt_util
from homeassistant.components.alexa import smart_home
from . import http_api, iot
from .const import CONFIG_DIR, DOMAIN, SERVERS
@ -18,6 +20,8 @@ REQUIREMENTS = ['warrant==0.5.0']
_LOGGER = logging.getLogger(__name__)
CONF_ALEXA = 'alexa'
CONF_ALEXA_FILTER = 'filter'
CONF_COGNITO_CLIENT_ID = 'cognito_client_id'
CONF_RELAYER = 'relayer'
CONF_USER_POOL_ID = 'user_pool_id'
@ -26,6 +30,13 @@ MODE_DEV = 'development'
DEFAULT_MODE = MODE_DEV
DEPENDENCIES = ['http']
ALEXA_SCHEMA = vol.Schema({
vol.Optional(
CONF_ALEXA_FILTER,
default=lambda: entityfilter.generate_filter([], [], [], [])
): entityfilter.FILTER_SCHEMA,
})
CONFIG_SCHEMA = vol.Schema({
DOMAIN: vol.Schema({
vol.Optional(CONF_MODE, default=DEFAULT_MODE):
@ -35,6 +46,7 @@ CONFIG_SCHEMA = vol.Schema({
vol.Required(CONF_USER_POOL_ID): str,
vol.Required(CONF_REGION): str,
vol.Required(CONF_RELAYER): str,
vol.Optional(CONF_ALEXA): ALEXA_SCHEMA
}),
}, extra=vol.ALLOW_EXTRA)
@ -47,6 +59,10 @@ def async_setup(hass, config):
else:
kwargs = {CONF_MODE: DEFAULT_MODE}
if CONF_ALEXA not in kwargs:
kwargs[CONF_ALEXA] = ALEXA_SCHEMA({})
kwargs[CONF_ALEXA] = smart_home.Config(**kwargs[CONF_ALEXA])
cloud = hass.data[DOMAIN] = Cloud(hass, **kwargs)
@asyncio.coroutine
@ -64,10 +80,11 @@ class Cloud:
"""Store the configuration of the cloud connection."""
def __init__(self, hass, mode, cognito_client_id=None, user_pool_id=None,
region=None, relayer=None):
region=None, relayer=None, alexa=None):
"""Create an instance of Cloud."""
self.hass = hass
self.mode = mode
self.alexa_config = alexa
self.id_token = None
self.access_token = None
self.refresh_token = None

View File

@ -206,7 +206,9 @@ 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."""
return (yield from smart_home.async_handle_message(hass, payload))
return (yield from smart_home.async_handle_message(hass,
cloud.alexa_config,
payload))
@HANDLERS.register('cloud')

View File

@ -25,7 +25,17 @@ DEPENDENCIES = ['mqtt']
DOMAIN = 'mqtt_statestream'
CONFIG_SCHEMA = vol.Schema({
DOMAIN: cv.FILTER_SCHEMA.extend({
DOMAIN: vol.Schema({
vol.Optional(CONF_EXCLUDE, default={}): vol.Schema({
vol.Optional(CONF_ENTITIES, default=[]): cv.entity_ids,
vol.Optional(CONF_DOMAINS, default=[]):
vol.All(cv.ensure_list, [cv.string])
}),
vol.Optional(CONF_INCLUDE, default={}): vol.Schema({
vol.Optional(CONF_ENTITIES, default=[]): cv.entity_ids,
vol.Optional(CONF_DOMAINS, default=[]):
vol.All(cv.ensure_list, [cv.string])
}),
vol.Required(CONF_BASE_TOPIC): valid_publish_topic,
vol.Optional(CONF_PUBLISH_ATTRIBUTES, default=False): cv.boolean,
vol.Optional(CONF_PUBLISH_TIMESTAMPS, default=False): cv.boolean

View File

@ -12,8 +12,7 @@ import voluptuous as vol
from homeassistant.loader import get_platform
from homeassistant.const import (
CONF_DOMAINS, CONF_ENTITIES, CONF_EXCLUDE, CONF_INCLUDE, CONF_PLATFORM,
CONF_SCAN_INTERVAL, TEMP_CELSIUS, TEMP_FAHRENHEIT,
CONF_PLATFORM, CONF_SCAN_INTERVAL, TEMP_CELSIUS, TEMP_FAHRENHEIT,
CONF_ALIAS, CONF_ENTITY_ID, CONF_VALUE_TEMPLATE, WEEKDAYS,
CONF_CONDITION, CONF_BELOW, CONF_ABOVE, CONF_TIMEOUT, SUN_EVENT_SUNSET,
SUN_EVENT_SUNRISE, CONF_UNIT_SYSTEM_IMPERIAL, CONF_UNIT_SYSTEM_METRIC)
@ -563,16 +562,3 @@ SCRIPT_SCHEMA = vol.All(
[vol.Any(SERVICE_SCHEMA, _SCRIPT_DELAY_SCHEMA,
_SCRIPT_WAIT_TEMPLATE_SCHEMA, EVENT_SCHEMA, CONDITION_SCHEMA)],
)
FILTER_SCHEMA = vol.Schema({
vol.Optional(CONF_EXCLUDE, default={}): vol.Schema({
vol.Optional(CONF_ENTITIES, default=[]): entity_ids,
vol.Optional(CONF_DOMAINS, default=[]):
vol.All(ensure_list, [string])
}),
vol.Optional(CONF_INCLUDE, default={}): vol.Schema({
vol.Optional(CONF_ENTITIES, default=[]): entity_ids,
vol.Optional(CONF_DOMAINS, default=[]):
vol.All(ensure_list, [string])
})
})

View File

@ -1,6 +1,30 @@
"""Helper class to implement include/exclude of entities and domains."""
import voluptuous as vol
from homeassistant.core import split_entity_id
from homeassistant.helpers import config_validation as cv
CONF_INCLUDE_DOMAINS = 'include_domains'
CONF_INCLUDE_ENTITIES = 'include_entities'
CONF_EXCLUDE_DOMAINS = 'exclude_domains'
CONF_EXCLUDE_ENTITIES = 'exclude_entities'
FILTER_SCHEMA = vol.All(
vol.Schema({
vol.Optional(CONF_EXCLUDE_DOMAINS, default=[]):
vol.All(cv.ensure_list, [cv.string]),
vol.Optional(CONF_EXCLUDE_ENTITIES, default=[]): cv.entity_ids,
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],
))
def generate_filter(include_domains, include_entities,

View File

@ -5,9 +5,12 @@ from uuid import uuid4
import pytest
from homeassistant.components.alexa import smart_home
from homeassistant.helpers import entityfilter
from tests.common import async_mock_service
DEFAULT_CONFIG = smart_home.Config(filter=lambda entity_id: True)
def get_new_request(namespace, name, endpoint=None):
"""Generate a new API message."""
@ -91,7 +94,7 @@ def test_wrong_version(hass):
msg['directive']['header']['payloadVersion'] = '2'
with pytest.raises(AssertionError):
yield from smart_home.async_handle_message(hass, msg)
yield from smart_home.async_handle_message(hass, DEFAULT_CONFIG, msg)
@asyncio.coroutine
@ -157,7 +160,8 @@ def test_discovery_request(hass):
'position': 85
})
msg = yield from smart_home.async_handle_message(hass, request)
msg = yield from smart_home.async_handle_message(
hass, DEFAULT_CONFIG, request)
assert 'event' in msg
msg = msg['event']
@ -319,6 +323,67 @@ def test_discovery_request(hass):
raise AssertionError("Unknown appliance!")
@asyncio.coroutine
def test_exclude_filters(hass):
"""Test exclusion filters."""
request = get_new_request('Alexa.Discovery', 'Discover')
# setup test devices
hass.states.async_set(
'switch.test', 'on', {'friendly_name': "Test switch"})
hass.states.async_set(
'script.deny', 'off', {'friendly_name': "Blocked script"})
hass.states.async_set(
'cover.deny', 'off', {'friendly_name': "Blocked cover"})
config = smart_home.Config(filter=entityfilter.generate_filter(
include_domains=[],
include_entities=[],
exclude_domains=['script'],
exclude_entities=['cover.deny'],
))
msg = yield from smart_home.async_handle_message(hass, config, request)
msg = msg['event']
assert len(msg['payload']['endpoints']) == 1
@asyncio.coroutine
def test_include_filters(hass):
"""Test inclusion filters."""
request = get_new_request('Alexa.Discovery', 'Discover')
# setup test devices
hass.states.async_set(
'switch.deny', 'on', {'friendly_name': "Blocked switch"})
hass.states.async_set(
'script.deny', 'off', {'friendly_name': "Blocked script"})
hass.states.async_set(
'automation.allow', 'off', {'friendly_name': "Allowed automation"})
hass.states.async_set(
'group.allow', 'off', {'friendly_name': "Allowed group"})
config = smart_home.Config(filter=entityfilter.generate_filter(
include_domains=['automation', 'group'],
include_entities=['script.deny'],
exclude_domains=[],
exclude_entities=[],
))
msg = yield from smart_home.async_handle_message(hass, config, request)
msg = msg['event']
assert len(msg['payload']['endpoints']) == 3
@asyncio.coroutine
def test_api_entity_not_exists(hass):
"""Test api turn on process without entity."""
@ -326,7 +391,8 @@ def test_api_entity_not_exists(hass):
call_switch = async_mock_service(hass, 'switch', 'turn_on')
msg = yield from smart_home.async_handle_message(hass, request)
msg = yield from smart_home.async_handle_message(
hass, DEFAULT_CONFIG, request)
assert 'event' in msg
msg = msg['event']
@ -341,7 +407,8 @@ def test_api_entity_not_exists(hass):
def test_api_function_not_implemented(hass):
"""Test api call that is not implemented to us."""
request = get_new_request('Alexa.HAHAAH', 'Sweet')
msg = yield from smart_home.async_handle_message(hass, request)
msg = yield from smart_home.async_handle_message(
hass, DEFAULT_CONFIG, request)
assert 'event' in msg
msg = msg['event']
@ -366,9 +433,15 @@ def test_api_turn_on(hass, domain):
'friendly_name': "Test {}".format(domain)
})
call = async_mock_service(hass, 'homeassistant', 'turn_on')
call_domain = domain
msg = yield from smart_home.async_handle_message(hass, request)
if domain == 'group':
call_domain = 'homeassistant'
call = async_mock_service(hass, call_domain, 'turn_on')
msg = yield from smart_home.async_handle_message(
hass, DEFAULT_CONFIG, request)
assert 'event' in msg
msg = msg['event']
@ -393,9 +466,15 @@ def test_api_turn_off(hass, domain):
'friendly_name': "Test {}".format(domain)
})
call = async_mock_service(hass, 'homeassistant', 'turn_off')
call_domain = domain
msg = yield from smart_home.async_handle_message(hass, request)
if domain == 'group':
call_domain = 'homeassistant'
call = async_mock_service(hass, call_domain, 'turn_off')
msg = yield from smart_home.async_handle_message(
hass, DEFAULT_CONFIG, request)
assert 'event' in msg
msg = msg['event']
@ -420,7 +499,8 @@ def test_api_set_brightness(hass):
call_light = async_mock_service(hass, 'light', 'turn_on')
msg = yield from smart_home.async_handle_message(hass, request)
msg = yield from smart_home.async_handle_message(
hass, DEFAULT_CONFIG, request)
assert 'event' in msg
msg = msg['event']
@ -450,7 +530,8 @@ def test_api_adjust_brightness(hass, result, adjust):
call_light = async_mock_service(hass, 'light', 'turn_on')
msg = yield from smart_home.async_handle_message(hass, request)
msg = yield from smart_home.async_handle_message(
hass, DEFAULT_CONFIG, request)
assert 'event' in msg
msg = msg['event']
@ -483,7 +564,8 @@ def test_api_set_color_rgb(hass):
call_light = async_mock_service(hass, 'light', 'turn_on')
msg = yield from smart_home.async_handle_message(hass, request)
msg = yield from smart_home.async_handle_message(
hass, DEFAULT_CONFIG, request)
assert 'event' in msg
msg = msg['event']
@ -516,7 +598,8 @@ def test_api_set_color_xy(hass):
call_light = async_mock_service(hass, 'light', 'turn_on')
msg = yield from smart_home.async_handle_message(hass, request)
msg = yield from smart_home.async_handle_message(
hass, DEFAULT_CONFIG, request)
assert 'event' in msg
msg = msg['event']
@ -544,7 +627,8 @@ def test_api_set_color_temperature(hass):
call_light = async_mock_service(hass, 'light', 'turn_on')
msg = yield from smart_home.async_handle_message(hass, request)
msg = yield from smart_home.async_handle_message(
hass, DEFAULT_CONFIG, request)
assert 'event' in msg
msg = msg['event']
@ -572,7 +656,8 @@ def test_api_decrease_color_temp(hass, result, initial):
call_light = async_mock_service(hass, 'light', 'turn_on')
msg = yield from smart_home.async_handle_message(hass, request)
msg = yield from smart_home.async_handle_message(
hass, DEFAULT_CONFIG, request)
assert 'event' in msg
msg = msg['event']
@ -600,7 +685,8 @@ def test_api_increase_color_temp(hass, result, initial):
call_light = async_mock_service(hass, 'light', 'turn_on')
msg = yield from smart_home.async_handle_message(hass, request)
msg = yield from smart_home.async_handle_message(
hass, DEFAULT_CONFIG, request)
assert 'event' in msg
msg = msg['event']
@ -626,7 +712,8 @@ def test_api_activate(hass, domain):
call = async_mock_service(hass, domain, 'turn_on')
msg = yield from smart_home.async_handle_message(hass, request)
msg = yield from smart_home.async_handle_message(
hass, DEFAULT_CONFIG, request)
assert 'event' in msg
msg = msg['event']
@ -651,7 +738,8 @@ def test_api_set_percentage_fan(hass):
call_fan = async_mock_service(hass, 'fan', 'set_speed')
msg = yield from smart_home.async_handle_message(hass, request)
msg = yield from smart_home.async_handle_message(
hass, DEFAULT_CONFIG, request)
assert 'event' in msg
msg = msg['event']
@ -679,7 +767,8 @@ def test_api_set_percentage_cover(hass):
call_cover = async_mock_service(hass, 'cover', 'set_cover_position')
msg = yield from smart_home.async_handle_message(hass, request)
msg = yield from smart_home.async_handle_message(
hass, DEFAULT_CONFIG, request)
assert 'event' in msg
msg = msg['event']
@ -709,7 +798,8 @@ def test_api_adjust_percentage_fan(hass, result, adjust):
call_fan = async_mock_service(hass, 'fan', 'set_speed')
msg = yield from smart_home.async_handle_message(hass, request)
msg = yield from smart_home.async_handle_message(
hass, DEFAULT_CONFIG, request)
assert 'event' in msg
msg = msg['event']
@ -740,7 +830,8 @@ def test_api_adjust_percentage_cover(hass, result, adjust):
call_cover = async_mock_service(hass, 'cover', 'set_cover_position')
msg = yield from smart_home.async_handle_message(hass, request)
msg = yield from smart_home.async_handle_message(
hass, DEFAULT_CONFIG, request)
assert 'event' in msg
msg = msg['event']
@ -766,7 +857,8 @@ def test_api_lock(hass, domain):
call = async_mock_service(hass, domain, 'lock')
msg = yield from smart_home.async_handle_message(hass, request)
msg = yield from smart_home.async_handle_message(
hass, DEFAULT_CONFIG, request)
assert 'event' in msg
msg = msg['event']
@ -791,7 +883,8 @@ def test_api_play(hass, domain):
call = async_mock_service(hass, domain, 'media_play')
msg = yield from smart_home.async_handle_message(hass, request)
msg = yield from smart_home.async_handle_message(
hass, DEFAULT_CONFIG, request)
assert 'event' in msg
msg = msg['event']
@ -816,7 +909,8 @@ def test_api_pause(hass, domain):
call = async_mock_service(hass, domain, 'media_pause')
msg = yield from smart_home.async_handle_message(hass, request)
msg = yield from smart_home.async_handle_message(
hass, DEFAULT_CONFIG, request)
assert 'event' in msg
msg = msg['event']
@ -841,7 +935,8 @@ def test_api_stop(hass, domain):
call = async_mock_service(hass, domain, 'media_stop')
msg = yield from smart_home.async_handle_message(hass, request)
msg = yield from smart_home.async_handle_message(
hass, DEFAULT_CONFIG, request)
assert 'event' in msg
msg = msg['event']
@ -866,7 +961,8 @@ def test_api_next(hass, domain):
call = async_mock_service(hass, domain, 'media_next_track')
msg = yield from smart_home.async_handle_message(hass, request)
msg = yield from smart_home.async_handle_message(
hass, DEFAULT_CONFIG, request)
assert 'event' in msg
msg = msg['event']
@ -891,7 +987,8 @@ def test_api_previous(hass, domain):
call = async_mock_service(hass, domain, 'media_previous_track')
msg = yield from smart_home.async_handle_message(hass, request)
msg = yield from smart_home.async_handle_message(
hass, DEFAULT_CONFIG, request)
assert 'event' in msg
msg = msg['event']
@ -918,7 +1015,8 @@ def test_api_set_volume(hass):
call_media_player = async_mock_service(hass, 'media_player', 'volume_set')
msg = yield from smart_home.async_handle_message(hass, request)
msg = yield from smart_home.async_handle_message(
hass, DEFAULT_CONFIG, request)
assert 'event' in msg
msg = msg['event']
@ -948,7 +1046,8 @@ def test_api_adjust_volume(hass, result, adjust):
call_media_player = async_mock_service(hass, 'media_player', 'volume_set')
msg = yield from smart_home.async_handle_message(hass, request)
msg = yield from smart_home.async_handle_message(
hass, DEFAULT_CONFIG, request)
assert 'event' in msg
msg = msg['event']
@ -976,7 +1075,8 @@ def test_api_mute(hass, domain):
call = async_mock_service(hass, domain, 'volume_mute')
msg = yield from smart_home.async_handle_message(hass, request)
msg = yield from smart_home.async_handle_message(
hass, DEFAULT_CONFIG, request)
assert 'event' in msg
msg = msg['event']