mirror of
https://github.com/home-assistant/core.git
synced 2026-08-31 10:16:17 -05:00
Preregister nexia zone devices to avoid via_device race in sub-sub-devices (#179942)
This commit is contained in:
@@ -62,20 +62,33 @@ async def async_setup_entry(hass: HomeAssistant, entry: NexiaConfigEntry) -> boo
|
||||
await coordinator.async_config_entry_first_refresh()
|
||||
entry.runtime_data = coordinator
|
||||
|
||||
# Register thermostat devices before forwarding platforms so zone sub-devices
|
||||
# can resolve their via_device_id regardless of platform setup order.
|
||||
device_registry = dr.async_get(hass)
|
||||
for thermostat_id in nexia_home.get_thermostat_ids():
|
||||
device_registry.async_get_or_create(
|
||||
config_entry_id=entry.entry_id,
|
||||
identifiers={(DOMAIN, thermostat_id)}, # type: ignore[arg-type] # until fix issue #139773
|
||||
)
|
||||
_preregister_devices(hass, entry, nexia_home)
|
||||
|
||||
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def _preregister_devices(
|
||||
hass: HomeAssistant, entry: NexiaConfigEntry, nexia_home: NexiaHome
|
||||
) -> None:
|
||||
"""Register devices before forwarding platforms so sub-devices resolve via_device_id regardless of setup order."""
|
||||
device_registry = dr.async_get(hass)
|
||||
for thermostat_id in nexia_home.get_thermostat_ids():
|
||||
thermostat = nexia_home.get_thermostat_by_id(thermostat_id)
|
||||
device_registry.async_get_or_create(
|
||||
config_entry_id=entry.entry_id,
|
||||
identifiers={(DOMAIN, thermostat_id)}, # type: ignore[arg-type] # until fix issue #139773
|
||||
)
|
||||
for zone_id in thermostat.get_zone_ids():
|
||||
zone = thermostat.get_zone_by_id(zone_id)
|
||||
device_registry.async_get_or_create(
|
||||
config_entry_id=entry.entry_id,
|
||||
identifiers={(DOMAIN, zone_id)}, # type: ignore[arg-type] # until fix issue #139773
|
||||
suggested_area=zone.get_name(),
|
||||
)
|
||||
|
||||
|
||||
async def async_unload_entry(hass: HomeAssistant, entry: NexiaConfigEntry) -> bool:
|
||||
"""Unload a config entry."""
|
||||
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
|
||||
|
||||
@@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, override
|
||||
from nexia.thermostat import NexiaThermostat
|
||||
from nexia.zone import NexiaThermostatZone
|
||||
|
||||
from homeassistant.const import ATTR_IDENTIFIERS, ATTR_NAME, ATTR_SUGGESTED_AREA
|
||||
from homeassistant.const import ATTR_IDENTIFIERS, ATTR_NAME
|
||||
from homeassistant.helpers import device_registry as dr
|
||||
from homeassistant.helpers.device_registry import DeviceInfo
|
||||
from homeassistant.helpers.dispatcher import (
|
||||
@@ -103,13 +103,11 @@ class NexiaThermostatZoneEntity(NexiaThermostatEntity):
|
||||
"""Initialize the entity."""
|
||||
super().__init__(coordinator, zone.thermostat, unique_id)
|
||||
self._zone = zone
|
||||
zone_name = self._zone.get_name()
|
||||
if TYPE_CHECKING:
|
||||
assert self._attr_device_info is not None
|
||||
self._attr_device_info |= {
|
||||
ATTR_IDENTIFIERS: {(DOMAIN, zone.zone_id)}, # type: ignore[arg-type] # until fix issue #139773
|
||||
ATTR_NAME: zone_name,
|
||||
ATTR_SUGGESTED_AREA: zone_name,
|
||||
ATTR_NAME: zone.get_name(),
|
||||
"via_device_id": dr.async_get_device_id_by_identifier(
|
||||
self.coordinator.hass,
|
||||
(DOMAIN, zone.thermostat.thermostat_id), # type: ignore[arg-type] # until fix issue #139773
|
||||
|
||||
@@ -5,12 +5,14 @@ from unittest.mock import NonCallableMock, patch
|
||||
import aiohttp
|
||||
from nexia.home import NexiaHome
|
||||
|
||||
from homeassistant.components.nexia import _preregister_devices
|
||||
from homeassistant.components.nexia.const import DOMAIN
|
||||
from homeassistant.config_entries import ConfigEntryState
|
||||
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
||||
from homeassistant.setup import async_setup_component
|
||||
from homeassistant.util import slugify
|
||||
|
||||
from .conftest import setup_integration
|
||||
|
||||
@@ -77,6 +79,39 @@ async def test_migrate_entry_minor_version_1_2(hass: HomeAssistant) -> None:
|
||||
assert entry.unique_id == "123456"
|
||||
|
||||
|
||||
async def test_device_preregistration(
|
||||
hass: HomeAssistant, mock_nexia_home: NexiaHome, device_registry: dr.DeviceRegistry
|
||||
) -> None:
|
||||
"""Test all thermostat and zone devices are preregistered."""
|
||||
entry = MockConfigEntry(domain=DOMAIN)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
_preregister_devices(hass, entry, mock_nexia_home)
|
||||
|
||||
thermostat_ids = mock_nexia_home.get_thermostat_ids()
|
||||
assert len(thermostat_ids) > 0
|
||||
|
||||
for thermostat_id in thermostat_ids:
|
||||
thermostat = mock_nexia_home.get_thermostat_by_id(thermostat_id)
|
||||
device = device_registry.async_get_device_by_identifier(
|
||||
(DOMAIN, thermostat.thermostat_id), # type: ignore[arg-type] # until fix issue #139773
|
||||
entry.entry_id,
|
||||
)
|
||||
assert device is not None
|
||||
|
||||
zone_ids = thermostat.get_zone_ids()
|
||||
assert len(zone_ids) > 0
|
||||
|
||||
for zone_id in zone_ids:
|
||||
zone = thermostat.get_zone_by_id(zone_id)
|
||||
device = device_registry.async_get_device_by_identifier(
|
||||
(DOMAIN, zone.zone_id), # type: ignore[arg-type] # until fix issue #139773
|
||||
entry.entry_id,
|
||||
)
|
||||
assert device is not None
|
||||
assert device.area_id == slugify(zone.get_name())
|
||||
|
||||
|
||||
async def test_device_via_device_links(
|
||||
hass: HomeAssistant,
|
||||
patch_nexia_home: NexiaHome,
|
||||
@@ -86,14 +121,15 @@ async def test_device_via_device_links(
|
||||
config_entry = await setup_integration(hass, patch_nexia_home)
|
||||
|
||||
thermostat_device = device_registry.async_get_device_by_identifier(
|
||||
(DOMAIN, 2000000), # type: ignore[arg-type] # until fix issue #139773
|
||||
(DOMAIN, 2000004), # type: ignore[arg-type] # until fix issue #139773
|
||||
config_entry.entry_id,
|
||||
)
|
||||
assert thermostat_device is not None
|
||||
|
||||
zone_device = device_registry.async_get_device_by_identifier(
|
||||
(DOMAIN, 100), # type: ignore[arg-type] # until fix issue #139773
|
||||
(DOMAIN, 500), # type: ignore[arg-type] # until fix issue #139773
|
||||
config_entry.entry_id,
|
||||
)
|
||||
assert zone_device is not None
|
||||
assert zone_device.via_device_id == thermostat_device.id
|
||||
assert zone_device.area_id == "center_nativezone"
|
||||
|
||||
Reference in New Issue
Block a user