Adding entities at runtime

Hi, I’m upgrading an already implementing component (LCN) to an integration using the config_entry workflow. Unfortunately the data entry framework is not sufficient to get the whole configuration done. So I basically can only use it for setting up a hub. Attached to this hub are the system specific hardware devices which offer switches, sensors, and much more. The system does not offer any functionality to automatically detect the configuration of the connected hardware devices so this had to be done by editing the configuration.yaml in the past.
All this led me to the development of a new frontend configuration panel explicitly for the LCN component (just like Zigbee or Z-Wave). What I can do at the moment is to scan the hub for connected hardware devices.
In the next step, I’d like to create the entities representing the sensors and switches connected to the hardware devices. At the moment it is only possible to input all the relevant parameters using the configuration panel and pass the information to Hass using the WebSocket API.
But how do I create the new entity (e.g. a switch) based on the parameters and add it to Hass while the system is running?
What I do at the moment to create the entity at runtime is basically the following (which is almost taken from the way it is done during platform setup):

entity = LcnSwitchEntity(hass, entity_config)

entity_component = hass.data['switch']  # EntityComponent for switch
entity_platform = component._platforms[config_entry.entry_id]  # correspondig EntityPlatform for LCN

hass.async_add_job(entity_platform.async_add_entities([entity]))

Here LcnSwitchEntity is the platform specific entity for a switch and entity_config is a dictionary with the entitiy specific configuration.
Although this works like a charm I wonder if this is the intended way. For example there are two things I don’t like:

  1. obtaining the EntityComponent using the hass.data object
  2. getting the EntityPlatform using the protected _platforms attribute

I would have expected that there are some helper methods to obtain the right EntityComponent / EntityPlatform or at least to add a new entity to a platform/component after setup. But I didn’t find anything in the code.

Did I miss something? Is there a better or intended way of adding entities at runtime?

I submitted a PR for a new integration with kind of the same functionality “add a newly discovered entity after initial startup”. I’ve used the load and unload platform methode described in developer doc

  1. async_forward_entry_unload to unload the platform and their entities
  2. Add the newly discovered entity to the existing config_entry
  3. async_forward_entry_setup to load the platform with all entities again

Specific code here
I’m not sure if this is the most efficient way (completely unload the whole platform), but at least it is based on standard available helper methods. Still waiting for review by one of the core developers…

1 Like

Thank you for bringing this to my attention! Although it might not be the most efficient way, I think it’s better just to change the config_entry and let the platform setup do the rest. Keeping the config_entry and the registries in sync (as I tried to do it) is certainly error-prone.

Hi All,

I am facing the same issue with my custom component where the error
ValueError: Config entry has already been setup!
raises in the log whenever I re-execute
hass.config_entries.async_forward_entry_setup(config_entry, platform)
to register a new entity with the same platform on the existing Hubs config_entry.

Was there any “better” solution in how to add entities at runtime? meantime?

My issue is with using this workaround/solution is, that with every device registering at the Hub ALL entities coming from this hub are “reconnected” (so every time a new device connects which provides multiple entities from different platforms, every existing device on the Hub is requested again for its configuration and status etc.) - that’s a lot of unnecessary traffic which slows down Home Assistant highly… :frowning: