mirror of
https://github.com/home-assistant/core.git
synced 2025-04-24 09:17:53 +00:00
emulated_hue: allow customization within emulated_hue configuration (#11981)
* emulated_hue: add entities configuration * emulated_hue: update tests to include new entities attribute
This commit is contained in:
parent
766875f702
commit
5426e5c875
@ -39,6 +39,9 @@ CONF_OFF_MAPS_TO_ON_DOMAINS = 'off_maps_to_on_domains'
|
||||
CONF_EXPOSE_BY_DEFAULT = 'expose_by_default'
|
||||
CONF_EXPOSED_DOMAINS = 'exposed_domains'
|
||||
CONF_TYPE = 'type'
|
||||
CONF_ENTITIES = 'entities'
|
||||
CONF_ENTITY_NAME = 'name'
|
||||
CONF_ENTITY_HIDDEN = 'hidden'
|
||||
|
||||
TYPE_ALEXA = 'alexa'
|
||||
TYPE_GOOGLE = 'google_home'
|
||||
@ -52,6 +55,11 @@ DEFAULT_EXPOSED_DOMAINS = [
|
||||
]
|
||||
DEFAULT_TYPE = TYPE_GOOGLE
|
||||
|
||||
CONFIG_ENTITY_SCHEMA = vol.Schema({
|
||||
vol.Optional(CONF_ENTITY_NAME): cv.string,
|
||||
vol.Optional(CONF_ENTITY_HIDDEN): cv.boolean
|
||||
})
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
DOMAIN: vol.Schema({
|
||||
vol.Optional(CONF_HOST_IP): cv.string,
|
||||
@ -63,11 +71,14 @@ CONFIG_SCHEMA = vol.Schema({
|
||||
vol.Optional(CONF_EXPOSE_BY_DEFAULT): cv.boolean,
|
||||
vol.Optional(CONF_EXPOSED_DOMAINS): cv.ensure_list,
|
||||
vol.Optional(CONF_TYPE, default=DEFAULT_TYPE):
|
||||
vol.Any(TYPE_ALEXA, TYPE_GOOGLE)
|
||||
vol.Any(TYPE_ALEXA, TYPE_GOOGLE),
|
||||
vol.Optional(CONF_ENTITIES):
|
||||
vol.Schema({cv.entity_id: CONFIG_ENTITY_SCHEMA})
|
||||
})
|
||||
}, extra=vol.ALLOW_EXTRA)
|
||||
|
||||
ATTR_EMULATED_HUE = 'emulated_hue'
|
||||
ATTR_EMULATED_HUE_NAME = 'emulated_hue_name'
|
||||
ATTR_EMULATED_HUE_HIDDEN = 'emulated_hue_hidden'
|
||||
|
||||
|
||||
@ -183,6 +194,8 @@ class Config(object):
|
||||
self.advertise_port = conf.get(
|
||||
CONF_ADVERTISE_PORT) or self.listen_port
|
||||
|
||||
self.entities = conf.get(CONF_ENTITIES, {})
|
||||
|
||||
def entity_id_to_number(self, entity_id):
|
||||
"""Get a unique number for the entity id."""
|
||||
if self.type == TYPE_ALEXA:
|
||||
@ -215,6 +228,14 @@ class Config(object):
|
||||
assert isinstance(number, str)
|
||||
return self.numbers.get(number)
|
||||
|
||||
def get_entity_name(self, entity):
|
||||
"""Get the name of an entity."""
|
||||
if entity.entity_id in self.entities and \
|
||||
CONF_ENTITY_NAME in self.entities[entity.entity_id]:
|
||||
return self.entities[entity.entity_id][CONF_ENTITY_NAME]
|
||||
|
||||
return entity.attributes.get(ATTR_EMULATED_HUE_NAME, entity.name)
|
||||
|
||||
def is_entity_exposed(self, entity):
|
||||
"""Determine if an entity should be exposed on the emulated bridge.
|
||||
|
||||
@ -227,6 +248,12 @@ class Config(object):
|
||||
domain = entity.domain.lower()
|
||||
explicit_expose = entity.attributes.get(ATTR_EMULATED_HUE, None)
|
||||
explicit_hidden = entity.attributes.get(ATTR_EMULATED_HUE_HIDDEN, None)
|
||||
|
||||
if entity.entity_id in self.entities and \
|
||||
CONF_ENTITY_HIDDEN in self.entities[entity.entity_id]:
|
||||
explicit_hidden = \
|
||||
self.entities[entity.entity_id][CONF_ENTITY_HIDDEN]
|
||||
|
||||
if explicit_expose is True or explicit_hidden is False:
|
||||
expose = True
|
||||
elif explicit_expose is False or explicit_hidden is True:
|
||||
|
@ -24,9 +24,6 @@ from homeassistant.components.http import HomeAssistantView
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
ATTR_EMULATED_HUE = 'emulated_hue'
|
||||
ATTR_EMULATED_HUE_NAME = 'emulated_hue_name'
|
||||
|
||||
HUE_API_STATE_ON = 'on'
|
||||
HUE_API_STATE_BRI = 'bri'
|
||||
|
||||
@ -77,7 +74,7 @@ class HueAllLightsStateView(HomeAssistantView):
|
||||
|
||||
number = self.config.entity_id_to_number(entity.entity_id)
|
||||
json_response[number] = entity_to_json(
|
||||
entity, state, brightness)
|
||||
self.config, entity, state, brightness)
|
||||
|
||||
return self.json(json_response)
|
||||
|
||||
@ -110,7 +107,7 @@ class HueOneLightStateView(HomeAssistantView):
|
||||
|
||||
state, brightness = get_entity_state(self.config, entity)
|
||||
|
||||
json_response = entity_to_json(entity, state, brightness)
|
||||
json_response = entity_to_json(self.config, entity, state, brightness)
|
||||
|
||||
return self.json(json_response)
|
||||
|
||||
@ -344,10 +341,8 @@ def get_entity_state(config, entity):
|
||||
return (final_state, final_brightness)
|
||||
|
||||
|
||||
def entity_to_json(entity, is_on=None, brightness=None):
|
||||
def entity_to_json(config, entity, is_on=None, brightness=None):
|
||||
"""Convert an entity to its Hue bridge JSON representation."""
|
||||
name = entity.attributes.get(ATTR_EMULATED_HUE_NAME, entity.name)
|
||||
|
||||
return {
|
||||
'state':
|
||||
{
|
||||
@ -356,7 +351,7 @@ def entity_to_json(entity, is_on=None, brightness=None):
|
||||
'reachable': True
|
||||
},
|
||||
'type': 'Dimmable light',
|
||||
'name': name,
|
||||
'name': config.get_entity_name(entity),
|
||||
'modelid': 'HASS123',
|
||||
'uniqueid': entity.entity_id,
|
||||
'swversion': '123'
|
||||
|
@ -121,7 +121,14 @@ def hass_hue(loop, hass):
|
||||
def hue_client(loop, hass_hue, test_client):
|
||||
"""Create web client for emulated hue api."""
|
||||
web_app = hass_hue.http.app
|
||||
config = Config(None, {'type': 'alexa'})
|
||||
config = Config(None, {
|
||||
emulated_hue.CONF_TYPE: emulated_hue.TYPE_ALEXA,
|
||||
emulated_hue.CONF_ENTITIES: {
|
||||
'light.bed_light': {
|
||||
emulated_hue.CONF_ENTITY_HIDDEN: True
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
HueUsernameView().register(web_app.router)
|
||||
HueAllLightsStateView(config).register(web_app.router)
|
||||
@ -145,7 +152,7 @@ def test_discover_lights(hue_client):
|
||||
|
||||
# Make sure the lights we added to the config are there
|
||||
assert 'light.ceiling_lights' in devices
|
||||
assert 'light.bed_light' in devices
|
||||
assert 'light.bed_light' not in devices
|
||||
assert 'script.set_kitchen_light' in devices
|
||||
assert 'light.kitchen_lights' not in devices
|
||||
assert 'media_player.living_room' in devices
|
||||
@ -186,19 +193,23 @@ def test_get_light_state(hass_hue, hue_client):
|
||||
assert result_json['light.ceiling_lights']['state'][HUE_API_STATE_BRI] == \
|
||||
127
|
||||
|
||||
# Turn bedroom light off
|
||||
# Turn office light off
|
||||
yield from hass_hue.services.async_call(
|
||||
light.DOMAIN, const.SERVICE_TURN_OFF,
|
||||
{
|
||||
const.ATTR_ENTITY_ID: 'light.bed_light'
|
||||
const.ATTR_ENTITY_ID: 'light.ceiling_lights'
|
||||
},
|
||||
blocking=True)
|
||||
|
||||
bedroom_json = yield from perform_get_light_state(
|
||||
hue_client, 'light.bed_light', 200)
|
||||
office_json = yield from perform_get_light_state(
|
||||
hue_client, 'light.ceiling_lights', 200)
|
||||
|
||||
assert bedroom_json['state'][HUE_API_STATE_ON] is False
|
||||
assert bedroom_json['state'][HUE_API_STATE_BRI] == 0
|
||||
assert office_json['state'][HUE_API_STATE_ON] is False
|
||||
assert office_json['state'][HUE_API_STATE_BRI] == 0
|
||||
|
||||
# Make sure bedroom light isn't accessible
|
||||
yield from perform_get_light_state(
|
||||
hue_client, 'light.bed_light', 404)
|
||||
|
||||
# Make sure kitchen light isn't accessible
|
||||
yield from perform_get_light_state(
|
||||
@ -213,29 +224,35 @@ def test_put_light_state(hass_hue, hue_client):
|
||||
# Turn the bedroom light on first
|
||||
yield from hass_hue.services.async_call(
|
||||
light.DOMAIN, const.SERVICE_TURN_ON,
|
||||
{const.ATTR_ENTITY_ID: 'light.bed_light',
|
||||
{const.ATTR_ENTITY_ID: 'light.ceiling_lights',
|
||||
light.ATTR_BRIGHTNESS: 153},
|
||||
blocking=True)
|
||||
|
||||
bed_light = hass_hue.states.get('light.bed_light')
|
||||
assert bed_light.state == STATE_ON
|
||||
assert bed_light.attributes[light.ATTR_BRIGHTNESS] == 153
|
||||
ceiling_lights = hass_hue.states.get('light.ceiling_lights')
|
||||
assert ceiling_lights.state == STATE_ON
|
||||
assert ceiling_lights.attributes[light.ATTR_BRIGHTNESS] == 153
|
||||
|
||||
# Go through the API to turn it off
|
||||
bedroom_result = yield from perform_put_light_state(
|
||||
ceiling_result = yield from perform_put_light_state(
|
||||
hass_hue, hue_client,
|
||||
'light.bed_light', False)
|
||||
'light.ceiling_lights', False)
|
||||
|
||||
bedroom_result_json = yield from bedroom_result.json()
|
||||
ceiling_result_json = yield from ceiling_result.json()
|
||||
|
||||
assert bedroom_result.status == 200
|
||||
assert 'application/json' in bedroom_result.headers['content-type']
|
||||
assert ceiling_result.status == 200
|
||||
assert 'application/json' in ceiling_result.headers['content-type']
|
||||
|
||||
assert len(bedroom_result_json) == 1
|
||||
assert len(ceiling_result_json) == 1
|
||||
|
||||
# Check to make sure the state changed
|
||||
bed_light = hass_hue.states.get('light.bed_light')
|
||||
assert bed_light.state == STATE_OFF
|
||||
ceiling_lights = hass_hue.states.get('light.ceiling_lights')
|
||||
assert ceiling_lights.state == STATE_OFF
|
||||
|
||||
# Make sure we can't change the bedroom light state
|
||||
bedroom_result = yield from perform_put_light_state(
|
||||
hass_hue, hue_client,
|
||||
'light.bed_light', True)
|
||||
assert bedroom_result.status == 404
|
||||
|
||||
# Make sure we can't change the kitchen light state
|
||||
kitchen_result = yield from perform_put_light_state(
|
||||
|
Loading…
x
Reference in New Issue
Block a user