diff --git a/custom_components/diveracontrol/__init__.py b/custom_components/diveracontrol/__init__.py index e98e0b9..7cc5dad 100644 --- a/custom_components/diveracontrol/__init__.py +++ b/custom_components/diveracontrol/__init__.py @@ -43,7 +43,10 @@ from .coordinator import DiveraCoordinator from .divera_api import DiveraAPIClient from .service import async_register_services -from .utils import get_cluster_coordinators_ucrs_from_config_hass +from .utils import ( + get_cluster_coordinators_ucrs_from_config_hass, + get_device_config_entry_ids, +) PLATFORMS: list[Platform] = [ Platform.CALENDAR, @@ -504,7 +507,7 @@ def _remove_old_entity_entries( and identifier[1] in config_entry.data.get(D_RELATIONS_KEY, {}) for identifier in d.identifiers ) - or not d.config_entry_id # Orphaned devices + or not get_device_config_entry_ids(d) # Orphaned devices ] # 3. Zusammenführen und Duplikate vermeiden @@ -521,7 +524,7 @@ def _remove_old_entity_entries( "Migration: removing old device %s (name=%s, config_entry_id=%s)", device.id, device.name_by_user or device.name, - device.config_entry_id, + get_device_config_entry_ids(device) or None, ) dev_reg.async_remove_device(device.id) diff --git a/custom_components/diveracontrol/device_action.py b/custom_components/diveracontrol/device_action.py index c97d9e1..d937f6a 100644 --- a/custom_components/diveracontrol/device_action.py +++ b/custom_components/diveracontrol/device_action.py @@ -29,7 +29,11 @@ PERM_STATUS_USER, PERM_STATUS_VEHICLE, ) -from .utils import get_translation, get_ucr_data_from_device +from .utils import ( + get_device_config_entry_ids, + get_translation, + get_ucr_data_from_device, +) ACTION_TYPES: tuple[str, ...] = ( "request_refresh", @@ -187,7 +191,7 @@ async def async_get_actions( device_registry = dr.async_get(hass) device = device_registry.async_get(device_id) - if not device or not device.config_entry_id: + if not device or not get_device_config_entry_ids(device): return [] try: diff --git a/custom_components/diveracontrol/utils.py b/custom_components/diveracontrol/utils.py index 1eeee11..5dfcefd 100644 --- a/custom_components/diveracontrol/utils.py +++ b/custom_components/diveracontrol/utils.py @@ -14,6 +14,31 @@ _LOGGER = logging.getLogger(__name__) +def get_device_config_entry_ids(device: Any) -> tuple[str, ...]: + """Return all config entry ids linked to a device. + + Home Assistant 2025.12 replaced ``DeviceEntry.config_entry_id`` with + ``primary_config_entry`` and a ``config_entries`` list. This helper works + with both the old and the new API. + + Args: + device: Device registry entry. + + Returns: + Tuple of config entry ids linked to the device. + """ + entry_id = getattr(device, "config_entry_id", None) + if entry_id: + return (entry_id,) + primary = getattr(device, "primary_config_entry", None) + if primary: + return ( + primary, + *(e for e in getattr(device, "config_entries", ()) if e and e != primary), + ) + return () + + def get_ucr_data_from_device( hass: HomeAssistant, device_id: str, @@ -36,18 +61,20 @@ def get_ucr_data_from_device( device_registry = dr.async_get(hass) device = device_registry.async_get(device_id) - if not device or not device.config_entry_id: + if not device or not get_device_config_entry_ids(device): raise HomeAssistantError( f"Device not found or has no config entries: {device_id}" ) - # Get config entry - config_entry_id = device.config_entry_id - if not config_entry_id: - raise HomeAssistantError(f"Config entry not found for device: {device_id}") + # Get config entry (prefer an entry belonging to this integration) + entry = None + for config_entry_id in get_device_config_entry_ids(device): + candidate = hass.config_entries.async_get_entry(config_entry_id) + if candidate and candidate.domain == DOMAIN: + entry = candidate + break - entry = hass.config_entries.async_get_entry(config_entry_id) - if not entry or entry.domain != DOMAIN: + if entry is None: raise HomeAssistantError(f"Invalid config entry for device: {device_id}") # Get cluster_id