1
0
mirror of https://github.com/home-assistant/core.git synced 2025-12-24 04:50:05 +00:00

Refactor dynamic entity setup of Xbox integration (#155176)

This commit is contained in:
Manu
2025-10-27 15:43:56 +01:00
committed by GitHub
parent 6819b0ce5b
commit ce5538e615
4 changed files with 51 additions and 78 deletions

View File

@@ -5,7 +5,6 @@ from __future__ import annotations
from collections.abc import Callable
from dataclasses import dataclass
from enum import StrEnum
from functools import partial
from xbox.webapi.api.provider.people.models import Person
from yarl import URL
@@ -18,7 +17,7 @@ from homeassistant.components.binary_sensor import (
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from .coordinator import XboxConfigEntry, XboxUpdateCoordinator
from .coordinator import XboxConfigEntry
from .entity import XboxBaseEntity, check_deprecated_entity
@@ -111,15 +110,30 @@ async def async_setup_entry(
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up Xbox Live friends."""
xuids_added: set[str] = set()
coordinator = entry.runtime_data
update_friends = partial(
async_update_friends, hass, coordinator, {}, async_add_entities
)
@callback
def add_entities() -> None:
nonlocal xuids_added
entry.async_on_unload(coordinator.async_add_listener(update_friends))
current_xuids = set(coordinator.data.presence)
if new_xuids := current_xuids - xuids_added:
for xuid in new_xuids:
async_add_entities(
[
XboxBinarySensorEntity(coordinator, xuid, description)
for description in SENSOR_DESCRIPTIONS
if check_deprecated_entity(
hass, xuid, description, BINARY_SENSOR_DOMAIN
)
]
)
xuids_added |= new_xuids
xuids_added &= current_xuids
update_friends()
coordinator.async_add_listener(add_entities)
add_entities()
class XboxBinarySensorEntity(XboxBaseEntity, BinarySensorEntity):
@@ -142,31 +156,3 @@ class XboxBinarySensorEntity(XboxBaseEntity, BinarySensorEntity):
if (fn := self.entity_description.entity_picture_fn) is not None
else super().entity_picture
)
@callback
def async_update_friends(
hass: HomeAssistant,
coordinator: XboxUpdateCoordinator,
current: dict[str, list[XboxBinarySensorEntity]],
async_add_entities,
) -> None:
"""Update friends."""
new_ids = set(coordinator.data.presence)
current_ids = set(current)
# Process new favorites, add them to Home Assistant
new_entities: list[XboxBinarySensorEntity] = []
for xuid in new_ids - current_ids:
current[xuid] = []
for description in SENSOR_DESCRIPTIONS:
entity = XboxBinarySensorEntity(coordinator, xuid, description)
if check_deprecated_entity(hass, entity, BINARY_SENSOR_DOMAIN):
current[xuid].append(entity)
new_entities = new_entities + current[xuid]
if new_entities:
async_add_entities(new_entities)
# Process deleted favorites, remove them from Home Assistant
for xuid in current_ids - new_ids:
del current[xuid]

View File

@@ -200,20 +200,19 @@ class XboxUpdateCoordinator(DataUpdateCoordinator[XboxData]):
)
if (
self.current_friends
- (new_friends := {x.xuid for x in presence_data.values()})
self.current_friends - (new_friends := set(presence_data))
or not self.current_friends
):
self.remove_stale_devices(presence_data)
self.remove_stale_devices(new_friends)
self.current_friends = new_friends
return XboxData(new_console_data, presence_data)
def remove_stale_devices(self, presence_data: dict[str, Person]) -> None:
def remove_stale_devices(self, xuids: set[str]) -> None:
"""Remove stale devices from registry."""
device_reg = dr.async_get(self.hass)
identifiers = {(DOMAIN, xuid) for xuid in set(presence_data)} | {
identifiers = {(DOMAIN, xuid) for xuid in xuids} | {
(DOMAIN, console.id) for console in self.consoles.result
}

View File

@@ -98,17 +98,18 @@ def entity_used_in(hass: HomeAssistant, entity_id: str) -> list[str]:
def check_deprecated_entity(
hass: HomeAssistant,
entity: XboxBaseEntity,
xuid: str,
entity_description: EntityDescription,
entity_domain: str,
) -> bool:
"""Check for deprecated entity and remove it."""
if not getattr(entity.entity_description, "deprecated", False):
if not getattr(entity_description, "deprecated", False):
return True
ent_reg = er.async_get(hass)
if entity_id := ent_reg.async_get_entity_id(
entity_domain,
DOMAIN,
f"{entity.xuid}_{entity.entity_description.key}",
f"{xuid}_{entity_description.key}",
):
ent_reg.async_remove(entity_id)

View File

@@ -6,7 +6,6 @@ from collections.abc import Callable
from dataclasses import dataclass
from datetime import UTC, datetime
from enum import StrEnum
from functools import partial
from xbox.webapi.api.provider.people.models import Person
@@ -20,7 +19,7 @@ from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.helpers.typing import StateType
from .coordinator import XboxConfigEntry, XboxUpdateCoordinator
from .coordinator import XboxConfigEntry
from .entity import XboxBaseEntity, check_deprecated_entity
@@ -94,14 +93,30 @@ async def async_setup_entry(
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up Xbox Live friends."""
xuids_added: set[str] = set()
coordinator = config_entry.runtime_data
update_friends = partial(
async_update_friends, hass, coordinator, {}, async_add_entities
)
@callback
def add_entities() -> None:
nonlocal xuids_added
config_entry.async_on_unload(coordinator.async_add_listener(update_friends))
update_friends()
current_xuids = set(coordinator.data.presence)
if new_xuids := current_xuids - xuids_added:
for xuid in new_xuids:
async_add_entities(
[
XboxSensorEntity(coordinator, xuid, description)
for description in SENSOR_DESCRIPTIONS
if check_deprecated_entity(
hass, xuid, description, SENSOR_DOMAIN
)
]
)
xuids_added |= new_xuids
xuids_added &= current_xuids
coordinator.async_add_listener(add_entities)
add_entities()
class XboxSensorEntity(XboxBaseEntity, SensorEntity):
@@ -113,31 +128,3 @@ class XboxSensorEntity(XboxBaseEntity, SensorEntity):
def native_value(self) -> StateType | datetime:
"""Return the state of the requested attribute."""
return self.entity_description.value_fn(self.data)
@callback
def async_update_friends(
hass: HomeAssistant,
coordinator: XboxUpdateCoordinator,
current: dict[str, list[XboxSensorEntity]],
async_add_entities,
) -> None:
"""Update friends."""
new_ids = set(coordinator.data.presence)
current_ids = set(current)
# Process new favorites, add them to Home Assistant
new_entities: list[XboxSensorEntity] = []
for xuid in new_ids - current_ids:
current[xuid] = []
for description in SENSOR_DESCRIPTIONS:
entity = XboxSensorEntity(coordinator, xuid, description)
if check_deprecated_entity(hass, entity, SENSOR_DOMAIN):
current[xuid].append(entity)
new_entities = new_entities + current[xuid]
if new_entities:
async_add_entities(new_entities)
# Process deleted favorites, remove them from Home Assistant
for xuid in current_ids - new_ids:
del current[xuid]