Entity registry (#11979)
* Entity#unique_id defaults to None * Initial commit entity registry * Clean up unique_id property * Lint * Add tests to entity component * Lint * Restore some unique ids * Spelling * Remove use of IP address for unique ID * Add tests * Add tests * Fix tests * Add some docs * Add one more test * Fix new test…
This commit is contained in:
parent
8e441ba03b
commit
e51427b284
47 changed files with 471 additions and 230 deletions
|
@ -8,10 +8,9 @@ from homeassistant.setup import async_prepare_setup_platform
|
|||
from homeassistant.const import (
|
||||
ATTR_ENTITY_ID, CONF_SCAN_INTERVAL, CONF_ENTITY_NAMESPACE,
|
||||
DEVICE_DEFAULT_NAME)
|
||||
from homeassistant.core import callback, valid_entity_id
|
||||
from homeassistant.core import callback, valid_entity_id, split_entity_id
|
||||
from homeassistant.exceptions import HomeAssistantError, PlatformNotReady
|
||||
from homeassistant.helpers import config_per_platform, discovery
|
||||
from homeassistant.helpers.entity import async_generate_entity_id
|
||||
from homeassistant.helpers.event import (
|
||||
async_track_time_interval, async_track_point_in_time)
|
||||
from homeassistant.helpers.service import extract_entity_ids
|
||||
|
@ -19,11 +18,13 @@ from homeassistant.util import slugify
|
|||
from homeassistant.util.async import (
|
||||
run_callback_threadsafe, run_coroutine_threadsafe)
|
||||
import homeassistant.util.dt as dt_util
|
||||
from .entity_registry import EntityRegistry
|
||||
|
||||
DEFAULT_SCAN_INTERVAL = timedelta(seconds=15)
|
||||
SLOW_SETUP_WARNING = 10
|
||||
SLOW_SETUP_MAX_WAIT = 60
|
||||
PLATFORM_NOT_READY_RETRIES = 10
|
||||
DATA_REGISTRY = 'entity_registry'
|
||||
|
||||
|
||||
class EntityComponent(object):
|
||||
|
@ -357,12 +358,20 @@ class EntityPlatform(object):
|
|||
if not new_entities:
|
||||
return
|
||||
|
||||
hass = self.component.hass
|
||||
component_entities = set(entity.entity_id for entity
|
||||
in self.component.entities)
|
||||
|
||||
registry = hass.data.get(DATA_REGISTRY)
|
||||
|
||||
if registry is None:
|
||||
registry = hass.data[DATA_REGISTRY] = EntityRegistry(hass)
|
||||
|
||||
yield from registry.async_ensure_loaded()
|
||||
|
||||
tasks = [
|
||||
self._async_add_entity(entity, update_before_add,
|
||||
component_entities)
|
||||
component_entities, registry)
|
||||
for entity in new_entities]
|
||||
|
||||
yield from asyncio.wait(tasks, loop=self.component.hass.loop)
|
||||
|
@ -378,15 +387,12 @@ class EntityPlatform(object):
|
|||
)
|
||||
|
||||
@asyncio.coroutine
|
||||
def _async_add_entity(self, entity, update_before_add, component_entities):
|
||||
def _async_add_entity(self, entity, update_before_add, component_entities,
|
||||
registry):
|
||||
"""Helper method to add an entity to the platform."""
|
||||
if entity is None:
|
||||
raise ValueError('Entity cannot be None')
|
||||
|
||||
# Do nothing if entity has already been added based on unique id.
|
||||
if entity in self.component.entities:
|
||||
return
|
||||
|
||||
entity.hass = self.component.hass
|
||||
entity.platform = self
|
||||
entity.parallel_updates = self.parallel_updates
|
||||
|
@ -400,17 +406,39 @@ class EntityPlatform(object):
|
|||
"%s: Error on device update!", self.platform)
|
||||
return
|
||||
|
||||
# Write entity_id to entity
|
||||
if getattr(entity, 'entity_id', None) is None:
|
||||
object_id = entity.name or DEVICE_DEFAULT_NAME
|
||||
suggested_object_id = None
|
||||
|
||||
# Get entity_id from unique ID registration
|
||||
if entity.unique_id is not None:
|
||||
if entity.entity_id is not None:
|
||||
suggested_object_id = split_entity_id(entity.entity_id)[1]
|
||||
else:
|
||||
suggested_object_id = entity.name
|
||||
|
||||
entry = registry.async_get_or_create(
|
||||
self.component.domain, self.platform, entity.unique_id,
|
||||
suggested_object_id=suggested_object_id)
|
||||
entity.entity_id = entry.entity_id
|
||||
|
||||
# We won't generate an entity ID if the platform has already set one
|
||||
# We will however make sure that platform cannot pick a registered ID
|
||||
elif (entity.entity_id is not None and
|
||||
registry.async_is_registered(entity.entity_id)):
|
||||
# If entity already registered, convert entity id to suggestion
|
||||
suggested_object_id = split_entity_id(entity.entity_id)[1]
|
||||
entity.entity_id = None
|
||||
|
||||
# Generate entity ID
|
||||
if entity.entity_id is None:
|
||||
suggested_object_id = \
|
||||
suggested_object_id or entity.name or DEVICE_DEFAULT_NAME
|
||||
|
||||
if self.entity_namespace is not None:
|
||||
object_id = '{} {}'.format(self.entity_namespace,
|
||||
object_id)
|
||||
suggested_object_id = '{} {}'.format(self.entity_namespace,
|
||||
suggested_object_id)
|
||||
|
||||
entity.entity_id = async_generate_entity_id(
|
||||
self.component.entity_id_format, object_id,
|
||||
component_entities)
|
||||
entity.entity_id = registry.async_generate_entity_id(
|
||||
self.component.domain, suggested_object_id)
|
||||
|
||||
# Make sure it is valid in case an entity set the value themselves
|
||||
if not valid_entity_id(entity.entity_id):
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue