Ensure gardena image goes back to unknown on render fails (#180431)

This commit is contained in:
Joakim Plate
2026-08-27 19:39:40 +02:00
committed by GitHub
parent 4c6fba2712
commit e81abcf8cd
3 changed files with 44 additions and 3 deletions
@@ -97,9 +97,17 @@ class GardenaBluetoothImage(GardenaBluetoothEntity, ImageEntity):
def _handle_coordinator_update(self) -> None:
if (image := self._render()) != self._image:
self._image = image
self._attr_image_last_updated = dt_util.utcnow()
self._attr_image_last_updated = dt_util.utcnow() if image else None
super()._handle_coordinator_update()
@property
@override
def entity_picture(self) -> str | None:
"""Return a link to the image, or none while there is nothing to show."""
if self._image is None:
return None
return super().entity_picture
@override
async def async_image(self) -> bytes | None:
"""Return bytes of image."""
@@ -254,7 +254,6 @@
StateSnapshot({
'attributes': ReadOnlyDict({
<ImageEntityStateAttribute.ACCESS_TOKEN: 'access_token'>: '1',
<EntityStateAttribute.ENTITY_PICTURE: 'entity_picture'>: '/api/image_proxy/image.mock_title_contour_4?token=1',
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Mock Title Contour 4',
}),
'context': <ANY>,
@@ -306,7 +305,6 @@
StateSnapshot({
'attributes': ReadOnlyDict({
<ImageEntityStateAttribute.ACCESS_TOKEN: 'access_token'>: '1',
<EntityStateAttribute.ENTITY_PICTURE: 'entity_picture'>: '/api/image_proxy/image.mock_title_contour_5?token=1',
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Mock Title Contour 5',
}),
'context': <ANY>,
@@ -154,12 +154,47 @@ async def test_image_without_contour(
state = hass.states.get("image.mock_title_contour_4")
assert state
assert state.state == "unknown"
assert "entity_picture" not in state.attributes
client = await hass_client()
resp = await client.get("/api/image_proxy/image.mock_title_contour_4")
assert resp.status == HTTPStatus.INTERNAL_SERVER_ERROR
@pytest.mark.usefixtures("mock_contours")
async def test_contour_cleared_after_being_present(
hass: HomeAssistant,
hass_client: ClientSessionGenerator,
mock_read_char_raw: dict[str, bytes | Exception],
scan_step: Callable[[], Awaitable[None]],
) -> None:
"""Test a contour that is taught and then cleared goes back to unknown."""
await setup_entry(
hass, platforms=[Platform.IMAGE], service_info=AQUA_CONTOUR_SERVICE_INFO
)
state = hass.states.get(ENTITY_ID)
assert state
assert state.state != "unknown"
assert "entity_picture" in state.attributes
client = await hass_client()
resp = await client.get(f"/api/image_proxy/{ENTITY_ID}")
assert resp.status == HTTPStatus.OK
mock_read_char_raw[AquaContourContours.contour_points_1.unique_id] = b""
for _ in range(SEGMENTED_SCAN_COUNT):
await scan_step()
state = hass.states.get(ENTITY_ID)
assert state
assert state.state == "unknown"
assert "entity_picture" not in state.attributes
resp = await client.get(f"/api/image_proxy/{ENTITY_ID}")
assert resp.status == HTTPStatus.INTERNAL_SERVER_ERROR
async def test_active_contour_follows_position(
hass: HomeAssistant,
hass_client: ClientSessionGenerator,