diff --git a/homeassistant/components/tado/entity.py b/homeassistant/components/tado/entity.py index bb92880d99b4..2771d86d8e94 100644 --- a/homeassistant/components/tado/entity.py +++ b/homeassistant/components/tado/entity.py @@ -2,6 +2,7 @@ import logging +from homeassistant.helpers import device_registry as dr from homeassistant.helpers.device_registry import DeviceInfo from homeassistant.helpers.update_coordinator import CoordinatorEntity @@ -28,11 +29,15 @@ class TadoDeviceEntity(TadoCoordinatorEntity): self._device_info = device_info self.device_name = device_info["serialNo"] self.device_id = device_info["shortSerialNo"] - via_device: tuple[str, str] | None = None + via_device_id: str | None = None if device_info["deviceType"] not in TADO_BRIDGE_MODELS: for device in coordinator.data["device"].values(): if device["deviceType"] in TADO_BRIDGE_MODELS: - via_device = (DOMAIN, device["shortSerialNo"]) + via_device_id = dr.async_get_device_id_by_identifier( + coordinator.hass, + (DOMAIN, device["shortSerialNo"]), + config_entry_id=coordinator.config_entry.entry_id, + ) break self._attr_device_info = DeviceInfo( @@ -43,8 +48,8 @@ class TadoDeviceEntity(TadoCoordinatorEntity): sw_version=device_info["currentFwVersion"], model=device_info["deviceType"], ) - if via_device: - self._attr_device_info["via_device"] = via_device + if via_device_id: + self._attr_device_info["via_device_id"] = via_device_id class TadoHomeEntity(TadoCoordinatorEntity): diff --git a/tests/components/tado/fixtures/devices.json b/tests/components/tado/fixtures/devices.json index a9313ae051b2..144790c94ec3 100644 --- a/tests/components/tado/fixtures/devices.json +++ b/tests/components/tado/fixtures/devices.json @@ -34,5 +34,18 @@ "capabilities": ["INSIDE_TEMPERATURE_MEASUREMENT", "IDENTIFY"] }, "childLockEnabled": false + }, + { + "deviceType": "IB01", + "currentFwVersion": "62.7", + "characteristics": { + "capabilities": [] + }, + "serialNo": "IB1234", + "shortSerialNo": "IB1234", + "connectionState": { + "value": true, + "timestamp": "2020-03-23T18:30:07.377Z" + } } ] diff --git a/tests/components/tado/snapshots/test_binary_sensor.ambr b/tests/components/tado/snapshots/test_binary_sensor.ambr index c5dda35039e1..29d927509d15 100644 --- a/tests/components/tado/snapshots/test_binary_sensor.ambr +++ b/tests/components/tado/snapshots/test_binary_sensor.ambr @@ -869,6 +869,57 @@ 'state': 'off', }) # --- +# name: test_entities[binary_sensor.ib1234_connection_state-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'binary_sensor', + 'entity_category': None, + 'entity_id': 'binary_sensor.ib1234_connection_state', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Connection state', + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Connection state', + 'platform': 'tado', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'connection_state', + 'unique_id': 'connection state IB1234 1', + 'unit_of_measurement': None, + }) +# --- +# name: test_entities[binary_sensor.ib1234_connection_state-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + : 'connectivity', + : 'IB1234 Connection state', + }), + 'context': , + 'entity_id': 'binary_sensor.ib1234_connection_state', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'on', + }) +# --- # name: test_entities[binary_sensor.second_water_heater_second_water_heater_connectivity-entry] EntityRegistryEntrySnapshot({ 'aliases': list([ diff --git a/tests/components/tado/snapshots/test_diagnostics.ambr b/tests/components/tado/snapshots/test_diagnostics.ambr index 1125cc777065..1ea74be559ed 100644 --- a/tests/components/tado/snapshots/test_diagnostics.ambr +++ b/tests/components/tado/snapshots/test_diagnostics.ambr @@ -3,6 +3,20 @@ dict({ 'data': dict({ 'device': dict({ + 'IB1234': dict({ + 'characteristics': dict({ + 'capabilities': list([ + ]), + }), + 'connectionState': dict({ + 'timestamp': '2020-03-23T18:30:07.377Z', + 'value': True, + }), + 'currentFwVersion': '62.7', + 'deviceType': 'IB01', + 'serialNo': 'IB1234', + 'shortSerialNo': 'IB1234', + }), 'WR1': dict({ 'accessPointWiFi': dict({ 'ssid': 'tado8480', diff --git a/tests/components/tado/test_init.py b/tests/components/tado/test_init.py index 10acd8eef594..afbbf8a25eac 100644 --- a/tests/components/tado/test_init.py +++ b/tests/components/tado/test_init.py @@ -6,10 +6,12 @@ import time from unittest.mock import patch from PyTado.http import Http +import pytest from homeassistant.components.tado import DOMAIN from homeassistant.const import CONF_PASSWORD, CONF_USERNAME from homeassistant.core import HomeAssistant +from homeassistant.helpers import device_registry as dr from tests.common import MockConfigEntry @@ -32,6 +34,25 @@ async def test_v1_migration(hass: HomeAssistant) -> None: assert CONF_USERNAME not in entry.data +@pytest.mark.usefixtures("init_integration") +async def test_device_via_device_links( + hass: HomeAssistant, device_registry: dr.DeviceRegistry +) -> None: + """Test that child devices link to the bridge via via_device_id.""" + config_entry = hass.config_entries.async_entries(DOMAIN)[0] + + bridge_device = device_registry.async_get_device_by_identifier( + (DOMAIN, "IB1234"), config_entry.entry_id + ) + assert bridge_device is not None + + child_device = device_registry.async_get_device_by_identifier( + (DOMAIN, "WR1"), config_entry.entry_id + ) + assert child_device is not None + assert child_device.via_device_id == bridge_device.id + + async def test_refresh_token_threading_lock(hass: HomeAssistant) -> None: """Test that threading.Lock in Http._refresh_token serializes concurrent calls."""