mirror of
https://github.com/home-assistant/core.git
synced 2025-04-23 08:47:57 +00:00
Add config and diagnostic entities (#57528)
* Add config entity concept * Rename is_config_entity to entity_category * Add test * Add 'diagnostic' entity category
This commit is contained in:
parent
24509503bb
commit
4b3d423767
@ -177,6 +177,7 @@ def _entry_dict(entry):
|
||||
"name": entry.name,
|
||||
"icon": entry.icon,
|
||||
"platform": entry.platform,
|
||||
"entity_category": entry.entity_category,
|
||||
}
|
||||
|
||||
|
||||
|
@ -704,3 +704,6 @@ CLOUD_NEVER_EXPOSED_ENTITIES: Final[list[str]] = ["group.all_locks"]
|
||||
|
||||
# The ID of the Home Assistant Cast App
|
||||
CAST_APP_ID_HOMEASSISTANT: Final = "B12CE3CA"
|
||||
|
||||
ENTITY_CATEGORY_CONFIG: Final = "config"
|
||||
ENTITY_CATEGORY_DIAGNOSTIC: Final = "diagnostic"
|
||||
|
@ -11,7 +11,7 @@ import logging
|
||||
import math
|
||||
import sys
|
||||
from timeit import default_timer as timer
|
||||
from typing import Any, TypedDict, final
|
||||
from typing import Any, Literal, TypedDict, final
|
||||
|
||||
from homeassistant.config import DATA_CUSTOMIZE
|
||||
from homeassistant.const import (
|
||||
@ -180,6 +180,7 @@ class EntityDescription:
|
||||
key: str
|
||||
|
||||
device_class: str | None = None
|
||||
entity_category: Literal["config", "diagnostic"] | None = None
|
||||
entity_registry_enabled_default: bool = True
|
||||
force_update: bool = False
|
||||
icon: str | None = None
|
||||
@ -238,6 +239,7 @@ class Entity(ABC):
|
||||
_attr_context_recent_time: timedelta = timedelta(seconds=5)
|
||||
_attr_device_class: str | None
|
||||
_attr_device_info: DeviceInfo | None = None
|
||||
_attr_entity_category: str | None
|
||||
_attr_entity_picture: str | None = None
|
||||
_attr_entity_registry_enabled_default: bool
|
||||
_attr_extra_state_attributes: MutableMapping[str, Any]
|
||||
@ -404,6 +406,15 @@ class Entity(ABC):
|
||||
"""Return the attribution."""
|
||||
return self._attr_attribution
|
||||
|
||||
@property
|
||||
def entity_category(self) -> str | None:
|
||||
"""Return the category of the entity, if any."""
|
||||
if hasattr(self, "_attr_entity_category"):
|
||||
return self._attr_entity_category
|
||||
if hasattr(self, "entity_description"):
|
||||
return self.entity_description.entity_category
|
||||
return None
|
||||
|
||||
# DO NOT OVERWRITE
|
||||
# These properties and methods are either managed by Home Assistant or they
|
||||
# are used to perform a very specific function. Overwriting these may
|
||||
|
@ -501,6 +501,7 @@ class EntityPlatform:
|
||||
unit_of_measurement=entity.unit_of_measurement,
|
||||
original_name=entity.name,
|
||||
original_icon=entity.icon,
|
||||
entity_category=entity.entity_category,
|
||||
)
|
||||
|
||||
entity.registry_entry = entry
|
||||
|
@ -106,6 +106,7 @@ class RegistryEntry:
|
||||
# As set by integration
|
||||
original_name: str | None = attr.ib(default=None)
|
||||
original_icon: str | None = attr.ib(default=None)
|
||||
entity_category: str | None = attr.ib(default=None)
|
||||
domain: str = attr.ib(init=False, repr=False)
|
||||
|
||||
@domain.default
|
||||
@ -256,6 +257,7 @@ class EntityRegistry:
|
||||
unit_of_measurement: str | None = None,
|
||||
original_name: str | None = None,
|
||||
original_icon: str | None = None,
|
||||
entity_category: str | None = None,
|
||||
) -> RegistryEntry:
|
||||
"""Get entity. Create if it doesn't exist."""
|
||||
config_entry_id = None
|
||||
@ -276,6 +278,7 @@ class EntityRegistry:
|
||||
unit_of_measurement=unit_of_measurement or UNDEFINED,
|
||||
original_name=original_name or UNDEFINED,
|
||||
original_icon=original_icon or UNDEFINED,
|
||||
entity_category=entity_category or UNDEFINED,
|
||||
# When we changed our slugify algorithm, we invalidated some
|
||||
# stored entity IDs with either a __ or ending in _.
|
||||
# Fix introduced in 0.86 (Jan 23, 2019). Next line can be
|
||||
@ -310,6 +313,7 @@ class EntityRegistry:
|
||||
unit_of_measurement=unit_of_measurement,
|
||||
original_name=original_name,
|
||||
original_icon=original_icon,
|
||||
entity_category=entity_category,
|
||||
)
|
||||
self._register_entry(entity)
|
||||
_LOGGER.info("Registered new %s.%s entity: %s", domain, platform, entity_id)
|
||||
@ -418,6 +422,7 @@ class EntityRegistry:
|
||||
unit_of_measurement: str | None | UndefinedType = UNDEFINED,
|
||||
original_name: str | None | UndefinedType = UNDEFINED,
|
||||
original_icon: str | None | UndefinedType = UNDEFINED,
|
||||
entity_category: str | None | UndefinedType = UNDEFINED,
|
||||
) -> RegistryEntry:
|
||||
"""Private facing update properties method."""
|
||||
old = self.entities[entity_id]
|
||||
@ -438,6 +443,7 @@ class EntityRegistry:
|
||||
("unit_of_measurement", unit_of_measurement),
|
||||
("original_name", original_name),
|
||||
("original_icon", original_icon),
|
||||
("entity_category", entity_category),
|
||||
):
|
||||
if value is not UNDEFINED and value != getattr(old, attr_name):
|
||||
new_values[attr_name] = value
|
||||
@ -523,6 +529,7 @@ class EntityRegistry:
|
||||
unit_of_measurement=entity.get("unit_of_measurement"),
|
||||
original_name=entity.get("original_name"),
|
||||
original_icon=entity.get("original_icon"),
|
||||
entity_category=entity.get("entity_category"),
|
||||
)
|
||||
|
||||
self.entities = entities
|
||||
@ -555,6 +562,7 @@ class EntityRegistry:
|
||||
"unit_of_measurement": entry.unit_of_measurement,
|
||||
"original_name": entry.original_name,
|
||||
"original_icon": entry.original_icon,
|
||||
"entity_category": entry.entity_category,
|
||||
}
|
||||
for entry in self.entities.values()
|
||||
]
|
||||
|
@ -1,6 +1,4 @@
|
||||
"""Test entity_registry API."""
|
||||
from collections import OrderedDict
|
||||
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.config import entity_registry
|
||||
@ -31,18 +29,22 @@ def device_registry(hass):
|
||||
|
||||
async def test_list_entities(hass, client):
|
||||
"""Test list entries."""
|
||||
entities = OrderedDict()
|
||||
entities["test_domain.name"] = RegistryEntry(
|
||||
entity_id="test_domain.name",
|
||||
unique_id="1234",
|
||||
platform="test_platform",
|
||||
name="Hello World",
|
||||
mock_registry(
|
||||
hass,
|
||||
{
|
||||
"test_domain.name": RegistryEntry(
|
||||
entity_id="test_domain.name",
|
||||
unique_id="1234",
|
||||
platform="test_platform",
|
||||
name="Hello World",
|
||||
),
|
||||
"test_domain.no_name": RegistryEntry(
|
||||
entity_id="test_domain.no_name",
|
||||
unique_id="6789",
|
||||
platform="test_platform",
|
||||
),
|
||||
},
|
||||
)
|
||||
entities["test_domain.no_name"] = RegistryEntry(
|
||||
entity_id="test_domain.no_name", unique_id="6789", platform="test_platform"
|
||||
)
|
||||
|
||||
mock_registry(hass, entities)
|
||||
|
||||
await client.send_json({"id": 5, "type": "config/entity_registry/list"})
|
||||
msg = await client.receive_json()
|
||||
@ -57,6 +59,7 @@ async def test_list_entities(hass, client):
|
||||
"name": "Hello World",
|
||||
"icon": None,
|
||||
"platform": "test_platform",
|
||||
"entity_category": None,
|
||||
},
|
||||
{
|
||||
"config_entry_id": None,
|
||||
@ -67,6 +70,7 @@ async def test_list_entities(hass, client):
|
||||
"name": None,
|
||||
"icon": None,
|
||||
"platform": "test_platform",
|
||||
"entity_category": None,
|
||||
},
|
||||
]
|
||||
|
||||
@ -108,6 +112,7 @@ async def test_get_entity(hass, client):
|
||||
"original_icon": None,
|
||||
"capabilities": None,
|
||||
"unique_id": "1234",
|
||||
"entity_category": None,
|
||||
}
|
||||
|
||||
await client.send_json(
|
||||
@ -132,6 +137,7 @@ async def test_get_entity(hass, client):
|
||||
"original_icon": None,
|
||||
"capabilities": None,
|
||||
"unique_id": "6789",
|
||||
"entity_category": None,
|
||||
}
|
||||
|
||||
|
||||
@ -187,6 +193,7 @@ async def test_update_entity(hass, client):
|
||||
"original_icon": None,
|
||||
"capabilities": None,
|
||||
"unique_id": "1234",
|
||||
"entity_category": None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -235,6 +242,7 @@ async def test_update_entity(hass, client):
|
||||
"original_icon": None,
|
||||
"capabilities": None,
|
||||
"unique_id": "1234",
|
||||
"entity_category": None,
|
||||
},
|
||||
"reload_delay": 30,
|
||||
}
|
||||
@ -289,6 +297,7 @@ async def test_update_entity_require_restart(hass, client):
|
||||
"original_icon": None,
|
||||
"capabilities": None,
|
||||
"unique_id": "1234",
|
||||
"entity_category": None,
|
||||
},
|
||||
"require_restart": True,
|
||||
}
|
||||
@ -390,6 +399,7 @@ async def test_update_entity_no_changes(hass, client):
|
||||
"original_icon": None,
|
||||
"capabilities": None,
|
||||
"unique_id": "1234",
|
||||
"entity_category": None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -470,6 +480,7 @@ async def test_update_entity_id(hass, client):
|
||||
"original_icon": None,
|
||||
"capabilities": None,
|
||||
"unique_id": "1234",
|
||||
"entity_category": None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -809,3 +809,23 @@ async def test_attribution_attribute(hass):
|
||||
|
||||
state = hass.states.get(mock_entity.entity_id)
|
||||
assert state.attributes.get(ATTR_ATTRIBUTION) == "Home Assistant"
|
||||
|
||||
|
||||
async def test_entity_category_property(hass):
|
||||
"""Test entity category property."""
|
||||
mock_entity1 = entity.Entity()
|
||||
mock_entity1.hass = hass
|
||||
mock_entity1.entity_description = entity.EntityDescription(
|
||||
key="abc", entity_category="ignore_me"
|
||||
)
|
||||
mock_entity1.entity_id = "hello.world"
|
||||
mock_entity1._attr_entity_category = "config"
|
||||
assert mock_entity1.entity_category == "config"
|
||||
|
||||
mock_entity2 = entity.Entity()
|
||||
mock_entity2.hass = hass
|
||||
mock_entity2.entity_description = entity.EntityDescription(
|
||||
key="abc", entity_category="config"
|
||||
)
|
||||
mock_entity2.entity_id = "hello.world"
|
||||
assert mock_entity2.entity_category == "config"
|
||||
|
Loading…
x
Reference in New Issue
Block a user