1 """HTTP views to interact with the entity registry."""
3 from __future__
import annotations
7 import voluptuous
as vol
9 from homeassistant
import config_entries
14 config_validation
as cv,
15 device_registry
as dr,
16 entity_registry
as er,
23 """Enable the Entity Registry views."""
25 websocket_api.async_register_command(hass, websocket_get_entities)
26 websocket_api.async_register_command(hass, websocket_get_entity)
27 websocket_api.async_register_command(hass, websocket_list_entities_for_display)
28 websocket_api.async_register_command(hass, websocket_list_entities)
29 websocket_api.async_register_command(hass, websocket_remove_entity)
30 websocket_api.async_register_command(hass, websocket_update_entity)
34 @websocket_api.websocket_command({vol.Required("type"):
"config/entity_registry/list"})
41 """Handle list registry entries command."""
42 registry = er.async_get(hass)
45 f
'{{"id":{msg["id"]},"type": "{websocket_api.TYPE_RESULT}",'
46 '"success":true,"result": ['
51 entry.partial_json_repr
52 for entry
in registry.entities.values()
53 if entry.partial_json_repr
is not None
56 msg_json = b
"".join((msg_json_prefix, inner, b
"]}"))
57 connection.send_message(msg_json)
60 _ENTITY_CATEGORIES_JSON =
json_dumps(er.ENTITY_CATEGORY_INDEX_TO_VALUE)
63 @websocket_api.websocket_command(
{vol.Required("type"):
"config/entity_registry/list_for_display"}
71 """Handle list registry entries command."""
72 registry = er.async_get(hass)
75 f
'{{"id":{msg["id"]},"type":"{websocket_api.TYPE_RESULT}","success":true,'
76 f
'"result":{{"entity_categories":{_ENTITY_CATEGORIES_JSON},"entities":['
81 entry.display_json_repr
82 for entry
in registry.entities.values()
83 if entry.disabled_by
is None and entry.display_json_repr
is not None
86 msg_json = b
"".join((msg_json_prefix, inner, b
"]}}"))
87 connection.send_message(msg_json)
90 @websocket_api.websocket_command(
{
vol.Required("type"):
"config/entity_registry/get",
91 vol.Required(
"entity_id"): cv.entity_id,
100 """Handle get entity registry entry command.
104 registry = er.async_get(hass)
106 if (entry := registry.entities.get(msg[
"entity_id"]))
is None:
107 connection.send_message(
108 websocket_api.error_message(msg[
"id"], ERR_NOT_FOUND,
"Entity not found")
112 connection.send_message(
113 websocket_api.result_message(msg[
"id"], entry.extended_dict)
117 @websocket_api.websocket_command(
{
vol.Required("type"):
"config/entity_registry/get_entries",
118 vol.Required(
"entity_ids"): cv.entity_ids,
127 """Handle get entity registry entries command.
131 registry = er.async_get(hass)
133 entity_ids = msg[
"entity_ids"]
134 entries: dict[str, dict[str, Any] |
None] = {}
135 for entity_id
in entity_ids:
136 entry = registry.entities.get(entity_id)
137 entries[entity_id] = entry.extended_dict
if entry
else None
139 connection.send_message(websocket_api.result_message(msg[
"id"], entries))
143 @websocket_api.websocket_command(
{
vol.Required("type"):
"config/entity_registry/update",
144 vol.Required(
"entity_id"): cv.entity_id,
146 vol.Optional(
"aliases"): list,
147 vol.Optional(
"area_id"): vol.Any(str,
None),
157 vol.Optional(
"categories"): cv.schema_with_slug_keys(vol.Any(str,
None)),
158 vol.Optional(
"device_class"): vol.Any(str,
None),
159 vol.Optional(
"icon"): vol.Any(str,
None),
160 vol.Optional(
"labels"): [str],
161 vol.Optional(
"name"): vol.Any(str,
None),
162 vol.Optional(
"new_entity_id"): str,
164 vol.Optional(
"disabled_by"): vol.Any(
167 vol.Coerce(er.RegistryEntryDisabler),
168 er.RegistryEntryDisabler.USER.value,
172 vol.Optional(
"hidden_by"): vol.Any(
175 vol.Coerce(er.RegistryEntryHider),
176 er.RegistryEntryHider.USER.value,
179 vol.Inclusive(
"options_domain",
"entity_option"): str,
180 vol.Inclusive(
"options",
"entity_option"): vol.Any(
None, dict),
189 """Handle update entity websocket command.
193 registry = er.async_get(hass)
195 entity_id = msg[
"entity_id"]
196 if not (entity_entry := registry.async_get(entity_id)):
197 connection.send_message(
198 websocket_api.error_message(msg[
"id"], ERR_NOT_FOUND,
"Entity not found")
214 changes[key] = msg[key]
218 changes[
"aliases"] = set(msg[
"aliases"])
222 changes[
"labels"] = set(msg[
"labels"])
224 if "disabled_by" in msg
and msg[
"disabled_by"]
is None:
226 if entity_entry.device_id:
227 device_registry = dr.async_get(hass)
228 device = device_registry.async_get(entity_entry.device_id)
229 if device
and device.disabled:
230 connection.send_message(
231 websocket_api.error_message(
232 msg[
"id"],
"invalid_info",
"Device is disabled"
238 if "categories" in msg:
239 categories = entity_entry.categories.copy()
240 for scope, category_id
in msg[
"categories"].items():
241 if scope
in categories
and category_id
is None:
243 del categories[scope]
244 elif category_id
is not None:
246 categories[scope] = category_id
247 changes[
"categories"] = categories
251 entity_entry = registry.async_update_entity(entity_id, **changes)
252 except ValueError
as err:
253 connection.send_message(
254 websocket_api.error_message(msg[
"id"],
"invalid_info",
str(err))
258 if "new_entity_id" in msg:
259 entity_id = msg[
"new_entity_id"]
262 if "options_domain" in msg:
263 entity_entry = registry.async_update_entity_options(
264 entity_id, msg[
"options_domain"], msg[
"options"]
266 except ValueError
as err:
267 connection.send_message(
268 websocket_api.error_message(msg[
"id"],
"invalid_info",
str(err))
272 result: dict[str, Any] = {
"entity_entry": entity_entry.extended_dict}
273 if "disabled_by" in changes
and changes[
"disabled_by"]
is None:
276 not (config_entry_id := entity_entry.config_entry_id)
277 or (config_entry := hass.config_entries.async_get_entry(config_entry_id))
278 and not config_entry.supports_unload
280 result[
"require_restart"] =
True
282 result[
"reload_delay"] = config_entries.RELOAD_AFTER_UPDATE_DELAY
283 connection.send_result(msg[
"id"], result)
287 @websocket_api.websocket_command(
{
vol.Required("type"):
"config/entity_registry/remove",
288 vol.Required(
"entity_id"): cv.entity_id,
297 """Handle remove entity websocket command.
301 registry = er.async_get(hass)
303 if msg[
"entity_id"]
not in registry.entities:
304 connection.send_message(
305 websocket_api.error_message(msg[
"id"], ERR_NOT_FOUND,
"Entity not found")
309 registry.async_remove(msg[
"entity_id"])
310 connection.send_message(websocket_api.result_message(msg[
"id"]))
311
None websocket_update_entity(HomeAssistant hass, websocket_api.ActiveConnection connection, dict[str, Any] msg)
bool async_setup(HomeAssistant hass)
None websocket_get_entities(HomeAssistant hass, websocket_api.ActiveConnection connection, dict[str, Any] msg)
None websocket_remove_entity(HomeAssistant hass, websocket_api.ActiveConnection connection, dict[str, Any] msg)
None websocket_list_entities(HomeAssistant hass, websocket_api.ActiveConnection connection, dict[str, Any] msg)
None websocket_list_entities_for_display(HomeAssistant hass, websocket_api.ActiveConnection connection, dict[str, Any] msg)
None websocket_get_entity(HomeAssistant hass, websocket_api.ActiveConnection connection, dict[str, Any] msg)