Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions homeassistant/components/poolside/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,11 +132,11 @@ def _async_register_devices(
"""Register the controller hub and its pool device sub-devices up front.

Pool devices may carry no entities until their InformationFields state
arrives, and via_device needs the hub to already exist, so both are
arrives, and they are linked to the hub by its device id, so both are
created explicitly instead of as a side effect of entity setup.
"""
device_registry = dr.async_get(hass)
device_registry.async_get_or_create(
hub = device_registry.async_get_or_create(
config_entry_id=entry.entry_id,
identifiers={(DOMAIN, client.controller_uuid)},
name=site.name,
Expand All @@ -147,7 +147,7 @@ def _async_register_devices(
device_registry.async_get_or_create(
config_entry_id=entry.entry_id,
identifiers={(DOMAIN, device.uuid)},
via_device=(DOMAIN, client.controller_uuid),
via_device_id=hub.id,
name=device.name,
manufacturer="Poolside",
model=device.device_type,
Expand Down
35 changes: 35 additions & 0 deletions tests/components/poolside/test_pool_devices.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import json
from typing import Any
from unittest.mock import patch

from aiopoolside import PoolsideCommandError, PoolsideDevice
import pytest
Expand Down Expand Up @@ -937,3 +938,37 @@ async def test_setup_succeeds_without_pool_device_support(

assert mock_config_entry.state is ConfigEntryState.LOADED
assert mock_config_entry.runtime_data.pool_devices == []


async def test_pool_devices_linked_by_device_id(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_poolside_client: FakePoolsideClient,
device_registry: dr.DeviceRegistry,
) -> None:
"""Pool devices are linked to the controller by its device id.

`via_device` (by identifier) is deprecated and stops working in 2027.8.
"""
calls: list[dict[str, Any]] = []
original = device_registry.async_get_or_create

def record(**kwargs: Any) -> dr.DeviceEntry:
calls.append(kwargs)
return original(**kwargs)

with patch.object(device_registry, "async_get_or_create", side_effect=record):
await setup_entry(hass, mock_config_entry)

controller = device_registry.async_get_device({(DOMAIN, TEST_CONTROLLER_UUID)})
assert controller is not None
# The explicit registration that links the pump (entities attaching to it
# register it again, without a link).
[pump_call] = [
c
for c in calls
if c["identifiers"] == {(DOMAIN, PUMP_UUID)}
and ("via_device" in c or "via_device_id" in c)
]
assert "via_device" not in pump_call
assert pump_call["via_device_id"] == controller.id