diff --git a/homeassistant/components/intellifire/__init__.py b/homeassistant/components/intellifire/__init__.py index 8a32515212034..77171044e9b9a 100644 --- a/homeassistant/components/intellifire/__init__.py +++ b/homeassistant/components/intellifire/__init__.py @@ -143,7 +143,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: IntellifireConfigEntry) try: fireplace: UnifiedFireplace = ( await UnifiedFireplace.build_fireplace_from_common( - _construct_common_data(entry) + _construct_common_data(entry), + polling_enabled=False, ) ) LOGGER.debug("Waiting for Fireplace to Initialize") diff --git a/homeassistant/components/intellifire/coordinator.py b/homeassistant/components/intellifire/coordinator.py index dc9aa45d58bcd..c2eb374c3a14c 100644 --- a/homeassistant/components/intellifire/coordinator.py +++ b/homeassistant/components/intellifire/coordinator.py @@ -4,6 +4,7 @@ from datetime import timedelta +import aiohttp from intellifire4py import UnifiedFireplace from intellifire4py.control import IntelliFireController from intellifire4py.model import IntelliFirePollData @@ -11,8 +12,9 @@ from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant +from homeassistant.exceptions import ConfigEntryAuthFailed from homeassistant.helpers.device_registry import DeviceInfo -from homeassistant.helpers.update_coordinator import DataUpdateCoordinator +from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed from .const import DOMAIN, LOGGER @@ -52,6 +54,14 @@ def control_api(self) -> IntelliFireController: return self.fireplace.control_api async def _async_update_data(self) -> IntelliFirePollData: + try: + await self.fireplace.perform_poll() + except aiohttp.ClientResponseError as err: + if err.status == 403: + raise ConfigEntryAuthFailed("Authentication failed") from err + raise UpdateFailed(f"Error communicating with fireplace: {err}") from err + except (aiohttp.ClientError, TimeoutError) as err: + raise UpdateFailed(f"Error communicating with fireplace: {err}") from err return self.fireplace.data @property diff --git a/tests/components/intellifire/conftest.py b/tests/components/intellifire/conftest.py index a82deba64ee92..008e1db9fc3b4 100644 --- a/tests/components/intellifire/conftest.py +++ b/tests/components/intellifire/conftest.py @@ -257,6 +257,8 @@ def mock_fp(mock_common_data_local) -> Generator[AsyncMock]: mock_instance.set_read_mode = AsyncMock() mock_instance.set_control_mode = AsyncMock() + mock_instance.perform_poll = AsyncMock() + mock_instance.async_validate_connectivity = AsyncMock( return_value=(True, False) ) diff --git a/tests/components/intellifire/test_init.py b/tests/components/intellifire/test_init.py index 307a9df812c50..ac689a164b5ba 100644 --- a/tests/components/intellifire/test_init.py +++ b/tests/components/intellifire/test_init.py @@ -342,3 +342,32 @@ async def test_update_options_no_change( mock_fp.set_control_mode.assert_not_called() # But async_request_refresh should still be called coordinator.async_request_refresh.assert_called_once() + + +async def test_coordinator_performs_poll( + hass: HomeAssistant, + mock_config_entry_current: MockConfigEntry, + mock_apis_single_fp, +) -> None: + """Test that the library only polls when instructed by the coordinator. + + The library auto-polls by default; ensure the coordinator disables that + and drives polling explicitly via perform_poll(). + """ + _mock_local, _mock_cloud, mock_fp = mock_apis_single_fp + + with patch( + "homeassistant.components.intellifire.UnifiedFireplace.build_fireplace_from_common", + new_callable=AsyncMock, + return_value=mock_fp, + ) as mock_build: + mock_config_entry_current.add_to_hass(hass) + await hass.config_entries.async_setup(mock_config_entry_current.entry_id) + await hass.async_block_till_done() + + # Verify the fireplace was constructed with library background polling disabled + mock_build.assert_awaited_once() + assert mock_build.call_args.kwargs.get("polling_enabled") is False + + # Verify the coordinator drove exactly one poll during initial refresh + mock_fp.perform_poll.assert_awaited_once()