Skip to content

Commit 9db60c8

Browse files
Diegorro98MartinHjelmare
authored andcommitted
Do not fetch disconnected Home Connect appliances (#142200)
* Do not fetch disconnected Home Connect appliances * Apply suggestions Co-authored-by: Martin Hjelmare <[email protected]> * Update docstring --------- Co-authored-by: Martin Hjelmare <[email protected]>
1 parent c43a468 commit 9db60c8

File tree

2 files changed

+87
-16
lines changed

2 files changed

+87
-16
lines changed

homeassistant/components/home_connect/coordinator.py

+23-9
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,19 @@ def update(self, other: HomeConnectApplianceData) -> None:
7373
self.settings.update(other.settings)
7474
self.status.update(other.status)
7575

76+
@classmethod
77+
def empty(cls, appliance: HomeAppliance) -> HomeConnectApplianceData:
78+
"""Return empty data."""
79+
return cls(
80+
commands=set(),
81+
events={},
82+
info=appliance,
83+
options={},
84+
programs=[],
85+
settings={},
86+
status={},
87+
)
88+
7689

7790
class HomeConnectCoordinator(
7891
DataUpdateCoordinator[dict[str, HomeConnectApplianceData]]
@@ -358,15 +371,7 @@ async def _async_setup(self) -> None:
358371
model=appliance.vib,
359372
)
360373
if appliance.ha_id not in self.data:
361-
self.data[appliance.ha_id] = HomeConnectApplianceData(
362-
commands=set(),
363-
events={},
364-
info=appliance,
365-
options={},
366-
programs=[],
367-
settings={},
368-
status={},
369-
)
374+
self.data[appliance.ha_id] = HomeConnectApplianceData.empty(appliance)
370375
else:
371376
self.data[appliance.ha_id].info.connected = appliance.connected
372377
old_appliances.remove(appliance.ha_id)
@@ -402,6 +407,15 @@ async def _get_appliance_data(
402407
name=appliance.name,
403408
model=appliance.vib,
404409
)
410+
if not appliance.connected:
411+
_LOGGER.debug(
412+
"Appliance %s is not connected, skipping data fetch",
413+
appliance.ha_id,
414+
)
415+
if appliance_data_to_update:
416+
appliance_data_to_update.info.connected = False
417+
return appliance_data_to_update
418+
return HomeConnectApplianceData.empty(appliance)
405419
try:
406420
settings = {
407421
setting.key: setting

tests/components/home_connect/test_coordinator.py

+64-7
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,14 @@
5454

5555
from tests.common import MockConfigEntry, async_fire_time_changed
5656

57+
INITIAL_FETCH_CLIENT_METHODS = [
58+
"get_settings",
59+
"get_status",
60+
"get_all_programs",
61+
"get_available_commands",
62+
"get_available_program",
63+
]
64+
5765

5866
@pytest.fixture
5967
def platforms() -> list[str]:
@@ -214,15 +222,32 @@ async def test_coordinator_failure_refresh_and_stream(
214222
assert state.state != STATE_UNAVAILABLE
215223

216224

225+
@pytest.mark.parametrize(
226+
"appliance",
227+
["Dishwasher"],
228+
indirect=True,
229+
)
230+
async def test_coordinator_not_fetching_on_disconnected_appliance(
231+
config_entry: MockConfigEntry,
232+
integration_setup: Callable[[MagicMock], Awaitable[bool]],
233+
setup_credentials: None,
234+
client: MagicMock,
235+
appliance: HomeAppliance,
236+
) -> None:
237+
"""Test that the coordinator does not fetch anything on disconnected appliance."""
238+
appliance.connected = False
239+
240+
assert config_entry.state == ConfigEntryState.NOT_LOADED
241+
await integration_setup(client)
242+
assert config_entry.state == ConfigEntryState.LOADED
243+
244+
for method in INITIAL_FETCH_CLIENT_METHODS:
245+
assert getattr(client, method).call_count == 0
246+
247+
217248
@pytest.mark.parametrize(
218249
"mock_method",
219-
[
220-
"get_settings",
221-
"get_status",
222-
"get_all_programs",
223-
"get_available_commands",
224-
"get_available_program",
225-
],
250+
INITIAL_FETCH_CLIENT_METHODS,
226251
)
227252
async def test_coordinator_update_failing(
228253
mock_method: str,
@@ -551,3 +576,35 @@ async def test_devices_updated_on_refresh(
551576
assert not device_registry.async_get_device({(DOMAIN, appliances[0].ha_id)})
552577
for appliance in appliances[2:3]:
553578
assert device_registry.async_get_device({(DOMAIN, appliance.ha_id)})
579+
580+
581+
@pytest.mark.parametrize("appliance", ["Washer"], indirect=True)
582+
async def test_paired_disconnected_devices_not_fetching(
583+
hass: HomeAssistant,
584+
config_entry: MockConfigEntry,
585+
integration_setup: Callable[[MagicMock], Awaitable[bool]],
586+
setup_credentials: None,
587+
client: MagicMock,
588+
appliance: HomeAppliance,
589+
) -> None:
590+
"""Test that Home Connect API is not fetched after pairing a disconnected device."""
591+
client.get_home_appliances = AsyncMock(return_value=ArrayOfHomeAppliances([]))
592+
assert config_entry.state == ConfigEntryState.NOT_LOADED
593+
assert await integration_setup(client)
594+
assert config_entry.state == ConfigEntryState.LOADED
595+
596+
appliance.connected = False
597+
await client.add_events(
598+
[
599+
EventMessage(
600+
appliance.ha_id,
601+
EventType.PAIRED,
602+
data=ArrayOfEvents([]),
603+
)
604+
]
605+
)
606+
await hass.async_block_till_done()
607+
608+
client.get_specific_appliance.assert_awaited_once_with(appliance.ha_id)
609+
for method in INITIAL_FETCH_CLIENT_METHODS:
610+
assert getattr(client, method).call_count == 0

0 commit comments

Comments
 (0)