Optimize is_entity_exposed in emulated_hue by removing deprec… (#32718)

* emulated_hue: Optimize is_entity_exposed

Switch all list transversals in is_entity_exposed to
hash lookups

get_deprecated is now only called if explict_expose is
set

This funciton was iterating multiple lists per enitity
every time there was an update.  It was responsible for
a chunk of execution time when there are large number
of entities in home assistant.

* Complete deprecation of ATTR_EMULATED_HUE attribute

* Complete deprecation of ATTR_EMULATED_HUE attribute (remove const)

* Remove ATTR_EMULATED_HUE_HIDDEN and Rewrite tests
This commit is contained in:
J. Nick Koston 2020-03-13 23:47:47 -05:00 committed by GitHub
parent aa972b0005
commit 750ed2facd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 27 additions and 70 deletions

View File

@ -9,7 +9,6 @@ from homeassistant.components.http import real_ip
from homeassistant.const import EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP from homeassistant.const import EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP
from homeassistant.exceptions import HomeAssistantError from homeassistant.exceptions import HomeAssistantError
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.deprecation import get_deprecated
from homeassistant.util.json import load_json, save_json from homeassistant.util.json import load_json, save_json
from .hue_api import ( from .hue_api import (
@ -91,9 +90,7 @@ CONFIG_SCHEMA = vol.Schema(
extra=vol.ALLOW_EXTRA, extra=vol.ALLOW_EXTRA,
) )
ATTR_EMULATED_HUE = "emulated_hue"
ATTR_EMULATED_HUE_NAME = "emulated_hue_name" ATTR_EMULATED_HUE_NAME = "emulated_hue_name"
ATTR_EMULATED_HUE_HIDDEN = "emulated_hue_hidden"
async def async_setup(hass, yaml_config): async def async_setup(hass, yaml_config):
@ -220,7 +217,9 @@ class Config:
# Get domains that are exposed by default when expose_by_default is # Get domains that are exposed by default when expose_by_default is
# True # True
self.exposed_domains = conf.get(CONF_EXPOSED_DOMAINS, DEFAULT_EXPOSED_DOMAINS) self.exposed_domains = set(
conf.get(CONF_EXPOSED_DOMAINS, DEFAULT_EXPOSED_DOMAINS)
)
# Calculated effective advertised IP and port for network isolation # Calculated effective advertised IP and port for network isolation
self.advertise_ip = conf.get(CONF_ADVERTISE_IP) or self.host_ip_addr self.advertise_ip = conf.get(CONF_ADVERTISE_IP) or self.host_ip_addr
@ -229,6 +228,12 @@ class Config:
self.entities = conf.get(CONF_ENTITIES, {}) self.entities = conf.get(CONF_ENTITIES, {})
self._entities_with_hidden_attr_in_config = dict()
for entity_id in self.entities:
hidden_value = self.entities[entity_id].get(CONF_ENTITY_HIDDEN, None)
if hidden_value is not None:
self._entities_with_hidden_attr_in_config[entity_id] = hidden_value
def entity_id_to_number(self, entity_id): def entity_id_to_number(self, entity_id):
"""Get a unique number for the entity id.""" """Get a unique number for the entity id."""
if self.type == TYPE_ALEXA: if self.type == TYPE_ALEXA:
@ -280,35 +285,18 @@ class Config:
# Ignore entities that are views # Ignore entities that are views
return False return False
domain = entity.domain.lower() if entity.entity_id in self._entities_with_hidden_attr_in_config:
explicit_expose = entity.attributes.get(ATTR_EMULATED_HUE, None) return not self._entities_with_hidden_attr_in_config[entity.entity_id]
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:
expose = False
else:
expose = None
get_deprecated(
entity.attributes, ATTR_EMULATED_HUE_HIDDEN, ATTR_EMULATED_HUE, None
)
domain_exposed_by_default = (
self.expose_by_default and domain in self.exposed_domains
)
if not self.expose_by_default:
return False
# Expose an entity if the entity's domain is exposed by default and # Expose an entity if the entity's domain is exposed by default and
# the configuration doesn't explicitly exclude it from being # the configuration doesn't explicitly exclude it from being
# exposed, or if the entity is explicitly exposed # exposed, or if the entity is explicitly exposed
is_default_exposed = domain_exposed_by_default and expose is not False if entity.domain in self.exposed_domains:
return True
return is_default_exposed or expose return False
def _load_json(filename): def _load_json(filename):

View File

@ -130,51 +130,9 @@ def hass_hue(loop, hass):
) )
) )
# Kitchen light is explicitly excluded from being exposed
kitchen_light_entity = hass.states.get("light.kitchen_lights")
attrs = dict(kitchen_light_entity.attributes)
attrs[emulated_hue.ATTR_EMULATED_HUE] = False
hass.states.async_set(
kitchen_light_entity.entity_id, kitchen_light_entity.state, attributes=attrs
)
# create a lamp without brightness support # create a lamp without brightness support
hass.states.async_set("light.no_brightness", "on", {}) hass.states.async_set("light.no_brightness", "on", {})
# Ceiling Fan is explicitly excluded from being exposed
ceiling_fan_entity = hass.states.get("fan.ceiling_fan")
attrs = dict(ceiling_fan_entity.attributes)
attrs[emulated_hue.ATTR_EMULATED_HUE_HIDDEN] = True
hass.states.async_set(
ceiling_fan_entity.entity_id, ceiling_fan_entity.state, attributes=attrs
)
# Expose the script
script_entity = hass.states.get("script.set_kitchen_light")
attrs = dict(script_entity.attributes)
attrs[emulated_hue.ATTR_EMULATED_HUE] = True
hass.states.async_set(
script_entity.entity_id, script_entity.state, attributes=attrs
)
# Expose cover
cover_entity = hass.states.get("cover.living_room_window")
attrs = dict(cover_entity.attributes)
attrs[emulated_hue.ATTR_EMULATED_HUE_HIDDEN] = False
hass.states.async_set(cover_entity.entity_id, cover_entity.state, attributes=attrs)
# Expose Hvac
hvac_entity = hass.states.get("climate.hvac")
attrs = dict(hvac_entity.attributes)
attrs[emulated_hue.ATTR_EMULATED_HUE_HIDDEN] = False
hass.states.async_set(hvac_entity.entity_id, hvac_entity.state, attributes=attrs)
# Expose HeatPump
hp_entity = hass.states.get("climate.heatpump")
attrs = dict(hp_entity.attributes)
attrs[emulated_hue.ATTR_EMULATED_HUE_HIDDEN] = False
hass.states.async_set(hp_entity.entity_id, hp_entity.state, attributes=attrs)
return hass return hass
@ -188,7 +146,18 @@ def hue_client(loop, hass_hue, aiohttp_client):
emulated_hue.CONF_TYPE: emulated_hue.TYPE_ALEXA, emulated_hue.CONF_TYPE: emulated_hue.TYPE_ALEXA,
emulated_hue.CONF_ENTITIES: { emulated_hue.CONF_ENTITIES: {
"light.bed_light": {emulated_hue.CONF_ENTITY_HIDDEN: True}, "light.bed_light": {emulated_hue.CONF_ENTITY_HIDDEN: True},
# Kitchen light is explicitly excluded from being exposed
"light.kitchen_lights": {emulated_hue.CONF_ENTITY_HIDDEN: True},
# Ceiling Fan is explicitly excluded from being exposed
"fan.ceiling_fan": {emulated_hue.CONF_ENTITY_HIDDEN: True},
# Expose the script
"script.set_kitchen_light": {emulated_hue.CONF_ENTITY_HIDDEN: False},
# Expose cover
"cover.living_room_window": {emulated_hue.CONF_ENTITY_HIDDEN: False}, "cover.living_room_window": {emulated_hue.CONF_ENTITY_HIDDEN: False},
# Expose Hvac
"climate.hvac": {emulated_hue.CONF_ENTITY_HIDDEN: False},
# Expose HeatPump
"climate.heatpump": {emulated_hue.CONF_ENTITY_HIDDEN: False},
}, },
}, },
) )