diff --git a/homeassistant/components/fritz/image.py b/homeassistant/components/fritz/image.py index d14c562bd76..aa1ede5a185 100644 --- a/homeassistant/components/fritz/image.py +++ b/homeassistant/components/fritz/image.py @@ -5,6 +5,8 @@ from __future__ import annotations from io import BytesIO import logging +from requests.exceptions import RequestException + from homeassistant.components.image import ImageEntity from homeassistant.config_entries import ConfigEntry from homeassistant.const import EntityCategory @@ -78,7 +80,13 @@ class FritzGuestWifiQRImage(FritzBoxBaseEntity, ImageEntity): async def async_update(self) -> None: """Update the image entity data.""" - qr_bytes = await self._fetch_image() + try: + qr_bytes = await self._fetch_image() + except RequestException: + self._current_qr_bytes = None + self._attr_image_last_updated = None + self.async_write_ha_state() + return if self._current_qr_bytes != qr_bytes: dt_now = dt_util.utcnow() diff --git a/tests/components/fritz/test_image.py b/tests/components/fritz/test_image.py index cbcbded5692..da5b8a76d27 100644 --- a/tests/components/fritz/test_image.py +++ b/tests/components/fritz/test_image.py @@ -4,12 +4,13 @@ from http import HTTPStatus from unittest.mock import patch import pytest +from requests.exceptions import ReadTimeout from syrupy.assertion import SnapshotAssertion from homeassistant.components.fritz.const import DOMAIN from homeassistant.components.image import DOMAIN as IMAGE_DOMAIN from homeassistant.config_entries import ConfigEntryState -from homeassistant.const import Platform +from homeassistant.const import STATE_UNKNOWN, Platform from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_registry import async_get as async_get_entity_registry from homeassistant.setup import async_setup_component @@ -170,3 +171,43 @@ async def test_image_update( assert resp_body != resp_body_new assert resp_body_new == snapshot + + +@pytest.mark.parametrize(("fc_data"), [({**MOCK_FB_SERVICES, **GUEST_WIFI_ENABLED})]) +async def test_image_update_unavailable( + hass: HomeAssistant, + fc_class_mock, + fh_class_mock, +) -> None: + """Test image update when fritzbox is unavailable.""" + + # setup component with image platform only + with patch( + "homeassistant.components.fritz.PLATFORMS", + [Platform.IMAGE], + ): + entry = MockConfigEntry(domain=DOMAIN, data=MOCK_USER_DATA) + entry.add_to_hass(hass) + assert await async_setup_component(hass, DOMAIN, {}) + + await hass.async_block_till_done() + assert entry.state == ConfigEntryState.LOADED + + state = hass.states.get("image.mock_title_guestwifi") + assert state + + # fritzbox becomes unavailable + fc_class_mock().call_action_side_effect(ReadTimeout) + async_fire_time_changed(hass, utcnow() + timedelta(seconds=60)) + await hass.async_block_till_done() + + state = hass.states.get("image.mock_title_guestwifi") + assert state.state == STATE_UNKNOWN + + # fritzbox is available again + fc_class_mock().call_action_side_effect(None) + async_fire_time_changed(hass, utcnow() + timedelta(seconds=60)) + await hass.async_block_till_done() + + state = hass.states.get("image.mock_title_guestwifi") + assert state.state != STATE_UNKNOWN