diff --git a/homeassistant/components/config/area_registry.py b/homeassistant/components/config/area_registry.py index e9cdc523686..c8dc7450183 100644 --- a/homeassistant/components/config/area_registry.py +++ b/homeassistant/components/config/area_registry.py @@ -38,6 +38,7 @@ def websocket_list_areas( { vol.Required("type"): "config/area_registry/create", vol.Optional("aliases"): list, + vol.Optional("icon"): str, vol.Required("name"): str, vol.Optional("picture"): vol.Any(str, None), } @@ -97,6 +98,7 @@ def websocket_delete_area( vol.Required("type"): "config/area_registry/update", vol.Optional("aliases"): list, vol.Required("area_id"): str, + vol.Optional("icon"): vol.Any(str, None), vol.Optional("name"): str, vol.Optional("picture"): vol.Any(str, None), } @@ -133,6 +135,7 @@ def _entry_dict(entry: AreaEntry) -> dict[str, Any]: return { "aliases": list(entry.aliases), "area_id": entry.id, + "icon": entry.icon, "name": entry.name, "picture": entry.picture, } diff --git a/homeassistant/helpers/area_registry.py b/homeassistant/helpers/area_registry.py index b3da01114d3..26da98e3fac 100644 --- a/homeassistant/helpers/area_registry.py +++ b/homeassistant/helpers/area_registry.py @@ -33,6 +33,7 @@ class AreaEntry: """Area Registry Entry.""" aliases: set[str] + icon: str | None id: str name: str normalized_name: str @@ -107,6 +108,11 @@ class AreaRegistryStore(Store[dict[str, list[dict[str, Any]]]]): for area in old_data["areas"]: area["aliases"] = [] + if old_minor_version < 4: + # Version 1.4 adds icon + for area in old_data["areas"]: + area["icon"] = None + if old_major_version > 1: raise NotImplementedError return old_data @@ -161,6 +167,7 @@ class AreaRegistry: name: str, *, aliases: set[str] | None = None, + icon: str | None = None, picture: str | None = None, ) -> AreaEntry: """Create a new area.""" @@ -172,6 +179,7 @@ class AreaRegistry: area_id = self._generate_area_id(name) area = AreaEntry( aliases=aliases or set(), + icon=icon, id=area_id, name=name, normalized_name=normalized_name, @@ -207,12 +215,17 @@ class AreaRegistry: area_id: str, *, aliases: set[str] | UndefinedType = UNDEFINED, + icon: str | None | UndefinedType = UNDEFINED, name: str | UndefinedType = UNDEFINED, picture: str | None | UndefinedType = UNDEFINED, ) -> AreaEntry: """Update name of area.""" updated = self._async_update( - area_id, aliases=aliases, name=name, picture=picture + area_id, + aliases=aliases, + icon=icon, + name=name, + picture=picture, ) self.hass.bus.async_fire( EVENT_AREA_REGISTRY_UPDATED, {"action": "update", "area_id": area_id} @@ -225,6 +238,7 @@ class AreaRegistry: area_id: str, *, aliases: set[str] | UndefinedType = UNDEFINED, + icon: str | None | UndefinedType = UNDEFINED, name: str | UndefinedType = UNDEFINED, picture: str | None | UndefinedType = UNDEFINED, ) -> AreaEntry: @@ -235,6 +249,7 @@ class AreaRegistry: for attr_name, value in ( ("aliases", aliases), + ("icon", icon), ("picture", picture), ): if value is not UNDEFINED and value != getattr(old, attr_name): @@ -264,6 +279,7 @@ class AreaRegistry: normalized_name = normalize_area_name(area["name"]) areas[area["id"]] = AreaEntry( aliases=set(area["aliases"]), + icon=area["icon"], id=area["id"], name=area["name"], normalized_name=normalized_name, @@ -286,8 +302,9 @@ class AreaRegistry: data["areas"] = [ { "aliases": list(entry.aliases), - "name": entry.name, + "icon": entry.icon, "id": entry.id, + "name": entry.name, "picture": entry.picture, } for entry in self.areas.values() diff --git a/tests/components/config/test_area_registry.py b/tests/components/config/test_area_registry.py index c012104a2db..1d1e14173f7 100644 --- a/tests/components/config/test_area_registry.py +++ b/tests/components/config/test_area_registry.py @@ -22,7 +22,10 @@ async def test_list_areas( """Test list entries.""" area1 = area_registry.async_create("mock 1") area2 = area_registry.async_create( - "mock 2", aliases={"alias_1", "alias_2"}, picture="/image/example.png" + "mock 2", + aliases={"alias_1", "alias_2"}, + icon="mdi:garage", + picture="/image/example.png", ) await client.send_json({"id": 1, "type": "config/area_registry/list"}) @@ -32,12 +35,14 @@ async def test_list_areas( { "aliases": [], "area_id": area1.id, + "icon": None, "name": "mock 1", "picture": None, }, { "aliases": unordered(["alias_1", "alias_2"]), "area_id": area2.id, + "icon": "mdi:garage", "name": "mock 2", "picture": "/image/example.png", }, @@ -58,6 +63,7 @@ async def test_create_area( assert msg["result"] == { "aliases": [], "area_id": ANY, + "icon": None, "name": "mock", "picture": None, } @@ -68,6 +74,7 @@ async def test_create_area( { "id": 2, "aliases": ["alias_1", "alias_2"], + "icon": "mdi:garage", "name": "mock 2", "picture": "/image/example.png", "type": "config/area_registry/create", @@ -79,6 +86,7 @@ async def test_create_area( assert msg["result"] == { "aliases": unordered(["alias_1", "alias_2"]), "area_id": ANY, + "icon": "mdi:garage", "name": "mock 2", "picture": "/image/example.png", } @@ -148,6 +156,7 @@ async def test_update_area( "id": 1, "aliases": ["alias_1", "alias_2"], "area_id": area.id, + "icon": "mdi:garage", "name": "mock 2", "picture": "/image/example.png", "type": "config/area_registry/update", @@ -159,6 +168,7 @@ async def test_update_area( assert msg["result"] == { "aliases": unordered(["alias_1", "alias_2"]), "area_id": area.id, + "icon": "mdi:garage", "name": "mock 2", "picture": "/image/example.png", } @@ -169,6 +179,7 @@ async def test_update_area( "id": 2, "aliases": ["alias_1", "alias_1"], "area_id": area.id, + "icon": None, "picture": None, "type": "config/area_registry/update", } @@ -179,6 +190,7 @@ async def test_update_area( assert msg["result"] == { "aliases": ["alias_1"], "area_id": area.id, + "icon": None, "name": "mock 2", "picture": None, } diff --git a/tests/helpers/test_area_registry.py b/tests/helpers/test_area_registry.py index fd74da547d4..8a7c023ced8 100644 --- a/tests/helpers/test_area_registry.py +++ b/tests/helpers/test_area_registry.py @@ -40,7 +40,12 @@ async def test_create_area( area = area_registry.async_create("mock") assert area == ar.AreaEntry( - name="mock", normalized_name=ANY, aliases=set(), id=ANY, picture=None + aliases=set(), + icon=None, + id=ANY, + name="mock", + normalized_name=ANY, + picture=None, ) assert len(area_registry.areas) == 1 @@ -56,10 +61,11 @@ async def test_create_area( ) assert area == ar.AreaEntry( + aliases={"alias_1", "alias_2"}, + icon=None, + id=ANY, name="mock 2", normalized_name=ANY, - aliases={"alias_1", "alias_2"}, - id=ANY, picture="/image/example.png", ) assert len(area_registry.areas) == 2 @@ -139,16 +145,18 @@ async def test_update_area( updated_area = area_registry.async_update( area.id, aliases={"alias_1", "alias_2"}, + icon="mdi:garage", name="mock1", picture="/image/example.png", ) assert updated_area != area assert updated_area == ar.AreaEntry( + aliases={"alias_1", "alias_2"}, + icon="mdi:garage", + id=ANY, name="mock1", normalized_name=ANY, - aliases={"alias_1", "alias_2"}, - id=ANY, picture="/image/example.png", ) assert len(area_registry.areas) == 1 @@ -250,6 +258,7 @@ async def test_loading_area_from_storage( { "aliases": ["alias_1", "alias_2"], "id": "12345A", + "icon": "mdi:garage", "name": "mock", "picture": "blah", } @@ -287,7 +296,15 @@ async def test_migration_from_1_1( "minor_version": ar.STORAGE_VERSION_MINOR, "key": ar.STORAGE_KEY, "data": { - "areas": [{"aliases": [], "id": "12345A", "name": "mock", "picture": None}] + "areas": [ + { + "aliases": [], + "icon": None, + "id": "12345A", + "name": "mock", + "picture": None, + } + ] }, }