diff --git a/homeassistant/components/freebox/__init__.py b/homeassistant/components/freebox/__init__.py index b3163741cdc9..6c5a66e284f4 100644 --- a/homeassistant/components/freebox/__init__.py +++ b/homeassistant/components/freebox/__init__.py @@ -8,7 +8,7 @@ from freebox_api.exceptions import HttpRequestError from homeassistant.const import CONF_HOST, CONF_PORT, EVENT_HOMEASSISTANT_STOP, Platform from homeassistant.core import Event, HomeAssistant from homeassistant.exceptions import ConfigEntryNotReady -from homeassistant.helpers import entity_registry as er +from homeassistant.helpers import device_registry as dr, entity_registry as er from homeassistant.helpers.event import async_track_time_interval from .const import DOMAIN, PLATFORMS @@ -96,6 +96,12 @@ async def async_setup_entry(hass: HomeAssistant, entry: FreeboxConfigEntry) -> b entry.runtime_data = router + # Register the router device up front so child devices (home devices, disks) + # can deterministically resolve it as their via_device on any platform. + dr.async_get(hass).async_get_or_create( + config_entry_id=entry.entry_id, **router.device_info + ) + await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) async def async_close_connection(event: Event) -> None: diff --git a/homeassistant/components/freebox/entity.py b/homeassistant/components/freebox/entity.py index 6b2b32a61b41..ddc694014e9e 100644 --- a/homeassistant/components/freebox/entity.py +++ b/homeassistant/components/freebox/entity.py @@ -54,7 +54,11 @@ class FreeboxHomeEntity(Entity): model=self._model, name=node["label"].strip(), sw_version=self._firmware, - via_device=(DOMAIN, router.mac), + via_device_id=dr.async_get_device_id_by_identifier( + router.hass, + (DOMAIN, router.mac), + config_entry_id=router.config_entry.entry_id, + ), ) async def async_update_signal(self) -> None: diff --git a/homeassistant/components/freebox/router.py b/homeassistant/components/freebox/router.py index dc88284824fd..dfc1bfa58331 100644 --- a/homeassistant/components/freebox/router.py +++ b/homeassistant/components/freebox/router.py @@ -108,6 +108,7 @@ class FreeboxRouter: ) -> None: """Initialize a Freebox router.""" self.hass = hass + self.config_entry = entry self._host = entry.data[CONF_HOST] self._port = entry.data[CONF_PORT] diff --git a/homeassistant/components/freebox/sensor.py b/homeassistant/components/freebox/sensor.py index dfaa036a1b09..6f28dbbbb540 100644 --- a/homeassistant/components/freebox/sensor.py +++ b/homeassistant/components/freebox/sensor.py @@ -17,6 +17,7 @@ from homeassistant.const import ( UnitOfTemperature, ) from homeassistant.core import HomeAssistant, callback +from homeassistant.helpers import device_registry as dr from homeassistant.helpers.device_registry import DeviceInfo from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback @@ -246,9 +247,10 @@ class FreeboxDiskSensor(FreeboxSensor): model=disk["model"], name=f"Disk {disk['id']}", sw_version=disk["firmware"], - via_device=( - DOMAIN, - router.mac, + via_device_id=dr.async_get_device_id_by_identifier( + router.hass, + (DOMAIN, router.mac), + config_entry_id=router.config_entry.entry_id, ), ) diff --git a/tests/components/freebox/test_init.py b/tests/components/freebox/test_init.py index f1ef3e6f308d..60d5cf1f1b43 100644 --- a/tests/components/freebox/test_init.py +++ b/tests/components/freebox/test_init.py @@ -169,6 +169,27 @@ async def test_unique_id_migration( ) +@pytest.mark.usefixtures("router") +async def test_home_device_via_device( + hass: HomeAssistant, + device_registry: dr.DeviceRegistry, +) -> None: + """Test home devices are linked to the router device via via_device_id.""" + entry = await setup_platform(hass, BINARY_SENSOR_DOMAIN) + + router_device = device_registry.async_get_device_by_identifier( + (DOMAIN, MOCK_MAC), entry.entry_id + ) + assert router_device is not None + + pir_node_id = 26 # Détecteur from fixture + pir_device = device_registry.async_get_device_by_identifier( + (DOMAIN, pir_node_id), entry.entry_id + ) + assert pir_device is not None + assert pir_device.via_device_id == router_device.id + + async def test_home_device_label_sync( hass: HomeAssistant, device_registry: dr.DeviceRegistry,