diff --git a/CHANGELOG.md b/CHANGELOG.md index 95051eda6..d6a9e0c41 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ Versions from 0.40 and up ## Ongoing +- Various updates: Core PR's [#176905](https://github.com/home-assistant/core/pull/176905), [#177963](https://github.com/home-assistant/core/pull/177963), [#178164](https://github.com/home-assistant/core/pull/178164), [#178334](https://github.com/home-assistant/core/pull/178334), [#180236](https://github.com/home-assistant/core/pull/180236), and fixes - Correct test-function header with more than 5 arguments via PR [#1118](https://github.com/plugwise/plugwise-beta/pull/1118) - Implement @pytest.mark.usefixtures() via PR [#1117](https://github.com/plugwise/plugwise-beta/pull/1117) - Correct climate and water_heater unique_id's via PR [#1098](https://github.com/plugwise/plugwise-beta/pull/1098) diff --git a/custom_components/plugwise/coordinator.py b/custom_components/plugwise/coordinator.py index 4d59282b6..000e9893b 100644 --- a/custom_components/plugwise/coordinator.py +++ b/custom_components/plugwise/coordinator.py @@ -184,10 +184,12 @@ def _remove_devices(self, removed_devices: set[str]) -> None: """Clean registries when removed devices found.""" device_reg = dr.async_get(self.hass) for device_id in removed_devices: - if (device_entry := device_reg.async_get_device({(DOMAIN, device_id)})) is not None: - device_reg.async_update_device( - device_entry.id, remove_config_entry_id=self.config_entry.entry_id + if ( + device_entry := device_reg.async_get_device_by_identifier( + (DOMAIN, device_id), self.config_entry.entry_id ) + ) is not None: + device_reg.async_remove_device(device_entry.id) LOGGER.debug( "%s %s %s removed from device_registry", DOMAIN, @@ -219,7 +221,11 @@ def _update_device_firmware(self, data: dict[str, GwEntityData]) -> None: def _update_firmware_in_dr(self, device_id: str, firmware: str | None) -> bool: """Update device sw_version in device_registry.""" device_reg = dr.async_get(self.hass) - if (device_entry := device_reg.async_get_device({(DOMAIN, device_id)})) is not None: + if ( + device_entry := device_reg.async_get_device_by_identifier( + (DOMAIN, device_id), self.config_entry.entry_id + ) + ) is not None: device_reg.async_update_device(device_entry.id, sw_version=firmware) LOGGER.debug( "Firmware in device_registry updated for %s %s %s", diff --git a/custom_components/plugwise/entity.py b/custom_components/plugwise/entity.py index 19ff29043..6dacd249e 100644 --- a/custom_components/plugwise/entity.py +++ b/custom_components/plugwise/entity.py @@ -4,11 +4,12 @@ from plugwise.constants import GwEntityData -from homeassistant.const import ATTR_NAME, ATTR_VIA_DEVICE, CONF_HOST +from homeassistant.const import ATTR_NAME, CONF_HOST from homeassistant.helpers.device_registry import ( CONNECTION_NETWORK_MAC, CONNECTION_ZIGBEE, DeviceInfo, + async_get_device_id_by_identifier, ) from homeassistant.helpers.update_coordinator import CoordinatorEntity @@ -78,7 +79,11 @@ def __init__( self._attr_device_info.update( { ATTR_NAME: self.device.get(ATTR_NAME), - ATTR_VIA_DEVICE: (DOMAIN, gateway_id), + "via_device_id": async_get_device_id_by_identifier( + coordinator.hass, + (DOMAIN, gateway_id), + config_entry_id=entry.entry_id, + ), } ) diff --git a/tests/components/plugwise/conftest.py b/tests/components/plugwise/conftest.py index 70da35c41..f4473f8c7 100644 --- a/tests/components/plugwise/conftest.py +++ b/tests/components/plugwise/conftest.py @@ -329,6 +329,7 @@ def mock_smile_legacy_anna() -> Generator[MagicMock]: api.async_update.return_value = data api.connect.return_value = Version("1.8.22") + api.cooling_present = False api.gateway_id = "0000aaaa0000aaaa0000aaaa0000aa00" api.heater_id = "04e4cbfe7f4340f090f85ec3b9e6a950" api.reboot = False diff --git a/tests/components/plugwise/test_init.py b/tests/components/plugwise/test_init.py index 427d0e2de..da638e0f8 100644 --- a/tests/components/plugwise/test_init.py +++ b/tests/components/plugwise/test_init.py @@ -161,8 +161,8 @@ async def test_device_in_dr( await hass.config_entries.async_setup(mock_config_entry.entry_id) await hass.async_block_till_done() - device_entry = device_registry.async_get_device( - identifiers={(DOMAIN, "a455b61e52394b2db5081ce025a430f3")} + device_entry = device_registry.async_get_device_by_identifier( + (DOMAIN, "a455b61e52394b2db5081ce025a430f3"), mock_config_entry.entry_id ) assert device_entry.hw_version == "AME Smile 2.0 board" assert device_entry.manufacturer == "Plugwise" @@ -172,6 +172,28 @@ async def test_device_in_dr( assert device_entry.sw_version == "4.4.2" +@pytest.mark.parametrize("chosen_env", ["m_adam_heating"], indirect=True) +@pytest.mark.parametrize("cooling_present", [False], indirect=True) +async def test_device_via_device_links( + hass: HomeAssistant, + mock_config_entry: MockConfigEntry, + mock_smile_adam_heat_cool: MagicMock, + device_registry: dr.DeviceRegistry, + init_integration: MockConfigEntry, +) -> None: + """Test that a non-gateway device links to the gateway via via_device_id.""" + gateway_device = device_registry.async_get_device_by_identifier( + (DOMAIN, "da224107914542988a88561b4452b0f6"), mock_config_entry.entry_id + ) + assert gateway_device is not None + + child_device = device_registry.async_get_device_by_identifier( + (DOMAIN, "14df5c4dc8cb4ba69f9d1ac0eaf7c5c6"), mock_config_entry.entry_id + ) + assert child_device is not None + assert child_device.via_device_id == gateway_device.id + + async def check_migration( hass: HomeAssistant, mock_config_entry: MockConfigEntry, @@ -348,8 +370,8 @@ async def test_update_device( len(dr.async_entries_for_config_entry(device_registry, mock_config_entry.entry_id)) == 11 ) - device_entry = device_registry.async_get_device( - identifiers={(DOMAIN, "01234567890abcdefghijklmnopqrstu")} + device_entry = device_registry.async_get_device_by_identifier( + (DOMAIN, "01234567890abcdefghijklmnopqrstu"), mock_config_entry.entry_id ) assert device_entry is not None @@ -375,17 +397,18 @@ async def test_update_device( len(dr.async_entries_for_config_entry(device_registry, mock_config_entry.entry_id)) == 10 ) - device_entry = device_registry.async_get_device( - identifiers={(DOMAIN, "1772a4ea304041adb83f357b751341ff")} + device_entry = device_registry.async_get_device_by_identifier( + (DOMAIN, "1772a4ea304041adb83f357b751341ff"), mock_config_entry.entry_id ) assert device_entry is None -@pytest.mark.usefixtures("mock_config_entry") @pytest.mark.parametrize("chosen_env", ["m_adam_heating"], indirect=True) @pytest.mark.parametrize("cooling_present", [False], indirect=True) async def test_delete_removed_device( hass: HomeAssistant, + mock_config_entry: MockConfigEntry, + *, mock_smile_adam_heat_cool: MagicMock, device_registry: dr.DeviceRegistry, init_integration: MockConfigEntry, @@ -394,8 +417,8 @@ async def test_delete_removed_device( """Test device removal at integration init.""" data = mock_smile_adam_heat_cool.async_update.return_value - device_entry = device_registry.async_get_device( - identifiers={(DOMAIN, "14df5c4dc8cb4ba69f9d1ac0eaf7c5c6")} + device_entry = device_registry.async_get_device_by_identifier( + (DOMAIN, "14df5c4dc8cb4ba69f9d1ac0eaf7c5c6"), mock_config_entry.entry_id ) assert device_entry is not None @@ -405,17 +428,18 @@ async def test_delete_removed_device( async_fire_time_changed(hass) await hass.async_block_till_done() - device_entry = device_registry.async_get_device( - identifiers={(DOMAIN, "14df5c4dc8cb4ba69f9d1ac0eaf7c5c6")} + device_entry = device_registry.async_get_device_by_identifier( + (DOMAIN, "14df5c4dc8cb4ba69f9d1ac0eaf7c5c6"), mock_config_entry.entry_id ) assert device_entry is None -@pytest.mark.usefixtures("mock_config_entry") @pytest.mark.parametrize("chosen_env", ["m_adam_heating"], indirect=True) @pytest.mark.parametrize("cooling_present", [False], indirect=True) async def test_update_device_firmware( hass: HomeAssistant, + mock_config_entry: MockConfigEntry, + *, mock_smile_adam_heat_cool: MagicMock, device_registry: dr.DeviceRegistry, init_integration: MockConfigEntry, @@ -424,8 +448,8 @@ async def test_update_device_firmware( """Test device firmware update via coordinator.""" data = mock_smile_adam_heat_cool.async_update.return_value - device_entry = device_registry.async_get_device( - identifiers={(DOMAIN, "da224107914542988a88561b4452b0f6")} + device_entry = device_registry.async_get_device_by_identifier( + (DOMAIN, "da224107914542988a88561b4452b0f6"), mock_config_entry.entry_id ) assert device_entry is not None assert str(device_entry.sw_version) == "3.9.0" @@ -436,8 +460,8 @@ async def test_update_device_firmware( async_fire_time_changed(hass) await hass.async_block_till_done() - device_entry = device_registry.async_get_device( - identifiers={(DOMAIN, "da224107914542988a88561b4452b0f6")} + device_entry = device_registry.async_get_device_by_identifier( + (DOMAIN, "da224107914542988a88561b4452b0f6"), mock_config_entry.entry_id ) assert device_entry is not None assert str(device_entry.sw_version) == "3.10.13"