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:
@@ -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]
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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]
|
||||
|
||||
Reference in New Issue
Block a user