Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Entity registry #11979

Merged
merged 15 commits into from
Jan 30, 2018
Merged

Entity registry #11979

merged 15 commits into from
Jan 30, 2018

Conversation

balloob
Copy link
Member

@balloob balloob commented Jan 28, 2018

Description:

Initial implementation of an entity registry:

  • Ensures that objects with a unique ID will be given the same entity id each time.
  • Allows users to update the entity registry file to rename entity ids (requires restart for now)
  • Entity Component will enforce that registered entity IDs are not given to other entities
  • Entity registry is written to disk 10 seconds after a new entry is registered. Registering another entry will reset that timer.

To do:

  • tests
  • check all existing unique ID implementations are fine
  • Entities that have no unique ID will never be given an entity ID that has previously been registered.

Breaking change:
It's no longer supported to add the same entity twice to Home Assistant. In the past Home Assistant would filter it out based on unique id, now it's up to the platform to make sure this doesn't happen.

Related issue (if applicable): fixes #11533

Pull request in home-assistant.github.io with documentation (if applicable): home-assistant/home-assistant.github.io#<home-assistant.github.io PR number goes here>

Example entry for configuration.yaml (if applicable):

Checklist:

  • The code change is tested and works locally.

If the code does not interact with devices:

  • Local tests with tox run successfully. Your PR cannot be merged unless tests pass
  • Tests have been added to verify that the new code works.

@@ -381,13 +380,9 @@ def _async_process_config(hass, config, component):

# Don't create tasks and await them all. The order is important as
# groups get a number based on creation order.
group = yield from Group.async_create_group(
yield from Group.async_create_group(
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

async_create_group already adds the group. Old code was adding each group twice.

@MartinHjelmare
Copy link
Member

Looks good so far 👍.

I'm wondering about the relative imports. Is that now preferred, or do we not care about mixing absolute and relative imports?

@balloob
Copy link
Member Author

balloob commented Jan 28, 2018

I... don't know about relative imports

@@ -19,11 +19,13 @@
from homeassistant.util.async import (
run_callback_threadsafe, run_coroutine_threadsafe)
import homeassistant.util.dt as dt_util
from .entity_registry import EntityRegistry
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a relative import.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I meant I don't know if I like them more

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, then I'll employ a lax attitude until someone says otherwise, if it shows up in another PR. 🍹

@balloob balloob requested review from rytilahti and a team as code owners January 28, 2018 08:17
@andrey-git
Copy link
Contributor

Why did you removed unique_id implementations in some cases and left it in others?

@callback
def async_get_or_create(self, domain, platform, unique_id, *,
suggested_object_id=None):
"""Get entity. Creat if it doesn't exist."""
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Creat -> Create

@@ -14,15 +14,15 @@
from homeassistant.helpers.entity import Entity, generate_entity_id
from homeassistant.helpers.entity_component import (
EntityComponent, DEFAULT_SCAN_INTERVAL, SLOW_SETUP_WARNING)
from homeassistant.helpers import entity_component
from homeassistant.helpers import entity_component, entity_registry

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'homeassistant.helpers.entity_registry' imported but unused

@balloob
Copy link
Member Author

balloob commented Jan 28, 2018

@andrey-git I have removed several implementations of unique ID that were not unique. For example, they would depend on the name of a device.

Unique ID has to be unique no matter the configuration. Serial numbers, device IDs, Mac addresses and BT addresses are great unique IDs. IP address is not perfect and I was in doubt if they should stay as part of unique id.

@balloob
Copy link
Member Author

balloob commented Jan 28, 2018

I've done one more review and restored some unique ID implementations that I removed earlier.

Copy link
Member

@rytilahti rytilahti left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a couple of comments, but I have a couple of questions:

  • IP addresses should not be used as unique IDs in general, considering how common address renewals can be?
  • Does or should this play somehow together with discovered devices? Most of the time you either get a mac address (id or mac on my devices) over mdns, or an uuid (udn is part of the upnp standard). Should autodetected components be adapted accordingly to use this information?

@@ -180,7 +180,7 @@ def set(self, settings):
@property
def unique_id(self):
"""Return the ID of this AC."""
return "{}.{}".format(self.__class__, self._api.ip_address)
return self._api.ip_address
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be something else than the IP address?

@@ -170,7 +170,7 @@ def available(self) -> bool:
@property
def unique_id(self):
"""Return the ID of this light."""
return '{}.{}'.format(self.__class__, self._ipaddr)
return self._ipaddr
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IP address also here.

@@ -70,7 +70,7 @@ def __init__(self, device):
@property
def unique_id(self):
"""Return the ID of this light."""
return "{}.{}".format(self.__class__, self._address)
return self._address
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This probably also should be removed?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bluetooth address.

@@ -178,7 +178,7 @@ def effect_list(self):
@property
def unique_id(self) -> str:
"""Return the ID of this light."""
return "{}.{}".format(self.__class__, self._ipaddr)
return self._ipaddr
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IP address. These devices would have two ways to obtain a unique identifier (either by using miio's proprietary api, a bit no-go as the current component uses a different one) or via mdns (mac field).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I agree, IP address is not a good thing to see as uniqueness. Will remove them.

PATH_REGISTRY = 'entity_registry.yaml'
SAVE_DELAY = 10
Entry = namedtuple('EntityRegistryEntry',
'entity_id,unique_id,platform,domain')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be worth using attrs instead of namedtuples in general, see http://www.attrs.org/en/stable/why.html#namedtuples

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't want to add another dependency. If anything, we would use a backport of the data classes that are being added to Python 3.7.

For the current use case namedtuples will be enough.

@balloob
Copy link
Member Author

balloob commented Jan 28, 2018

@rytilahti discovered entities should use the same source for unique ID as configured entities. I have another proposal to better deal with discovered entities: #11947

Copy link
Member

@pvizeli pvizeli left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like it.

For homematic, we have a unique ID, but they is unique for the device a not for the entity. I.e. a switch with two channel create 2 switch entity but they have the same device ID. what is the idea of that to solve it? Actual we generate unique entity_id but only copy this is not the nice way. We discovery also all this device.

@balloob
Copy link
Member Author

balloob commented Jan 29, 2018

If a device has a unique ID and 2 channels, you can make a unique id by combining the unique ID and the channel id.

@Kane610
Copy link
Member

Kane610 commented Jan 29, 2018

Would it be possible to add functionality to query the registry to do a lookup of entity_id or unique_id?

@balloob
Copy link
Member Author

balloob commented Jan 29, 2018

There is the get_or_create function and there is an is_registered function.

@balloob
Copy link
Member Author

balloob commented Jan 30, 2018

So I see a lot of reviews and "I like it" statements. Is it ok to merge?

@balloob balloob mentioned this pull request Jan 30, 2018
@andrey-git
Copy link
Contributor

I think it is important that eventually IDs can be changed without restarting.
If the current Entity Registry design doesn't hinder that - I'm ok with merging.

@balloob
Copy link
Member Author

balloob commented Jan 30, 2018

That will be possible with the current design. It's something I want to be allow people to do via the UI.

Rough Implementation:

  • Entity Platform will register with EntityRegistry as a rename listener
  • Add method EntityRegistry#async_rename_entity_id
  • Entity Platform gets notified:
    hass.states.async_remove(old_entity_id)
    entity.entity_id = new_entity_id
    yield from entity.async_update_ha_state()

@pvizeli pvizeli merged commit e51427b into dev Jan 30, 2018
@pvizeli pvizeli deleted the entity-registry branch January 30, 2018 10:44
@pvizeli
Copy link
Member

pvizeli commented Jan 30, 2018

I will implement unique_id as entity_id on homematic

@balloob
Copy link
Member Author

balloob commented Jan 30, 2018

You don't have to set entity_id. When registering an entity id, the registry will use the available device name or a combination of platform and unique id.

@pvizeli
Copy link
Member

pvizeli commented Jan 31, 2018

Yes, I don't set it, I set only the name :)

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

RFC: Entity Registry
8 participants