Fix bug with all Roborock maps being set to the wrong map when empty (#138493)

* Fix bug with all maps being set to the same when empty

* fix parens

* fix other parens

* rework some of the logic

* few small updates

* Remove test that is no longer relevant

* remove updated time bump
This commit is contained in:
Luke Lashley 2025-03-11 10:31:20 -04:00 committed by GitHub
parent ca33d7263f
commit 3c57b12cd1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 11 additions and 51 deletions

View File

@ -117,19 +117,6 @@ class RoborockMap(RoborockCoordinatedEntityV1, ImageEntity):
"""Return if this map is the currently selected map."""
return self.map_flag == self.coordinator.current_map
def is_map_valid(self) -> bool:
"""Update the map if it is valid.
Update this map if it is the currently active map, and the
vacuum is cleaning, or if it has never been set at all.
"""
return self.cached_map == b"" or (
self.is_selected
and self.image_last_updated is not None
and self.coordinator.roborock_device_info.props.status is not None
and bool(self.coordinator.roborock_device_info.props.status.in_cleaning)
)
async def async_added_to_hass(self) -> None:
"""When entity is added to hass load any previously cached maps from disk."""
await super().async_added_to_hass()
@ -142,15 +129,22 @@ class RoborockMap(RoborockCoordinatedEntityV1, ImageEntity):
# Bump last updated every third time the coordinator runs, so that async_image
# will be called and we will evaluate on the new coordinator data if we should
# update the cache.
if (
dt_util.utcnow() - self.image_last_updated
).total_seconds() > IMAGE_CACHE_INTERVAL and self.is_map_valid():
if self.is_selected and (
(
(dt_util.utcnow() - self.image_last_updated).total_seconds()
> IMAGE_CACHE_INTERVAL
and self.coordinator.roborock_device_info.props.status is not None
and bool(self.coordinator.roborock_device_info.props.status.in_cleaning)
)
or self.cached_map == b""
):
# This will tell async_image it should update.
self._attr_image_last_updated = dt_util.utcnow()
super()._handle_coordinator_update()
async def async_image(self) -> bytes | None:
"""Update the image if it is not cached."""
if self.is_map_valid():
if self.is_selected:
response = await asyncio.gather(
*(
self.cloud_api.get_map_v1(),

View File

@ -3,7 +3,6 @@
import copy
from datetime import timedelta
from http import HTTPStatus
import io
from unittest.mock import patch
from PIL import Image
@ -111,39 +110,6 @@ async def test_floorplan_image_failed_parse(
assert not resp.ok
async def test_load_stored_image(
hass: HomeAssistant,
hass_client: ClientSessionGenerator,
setup_entry: MockConfigEntry,
) -> None:
"""Test that we correctly load an image from storage when it already exists."""
img_byte_arr = io.BytesIO()
MAP_DATA.image.data.save(img_byte_arr, format="PNG")
img_bytes = img_byte_arr.getvalue()
# Load the image on demand, which should queue it to be cached on disk
client = await hass_client()
resp = await client.get("/api/image_proxy/image.roborock_s7_maxv_upstairs")
assert resp.status == HTTPStatus.OK
with patch(
"homeassistant.components.roborock.image.RoborockMapDataParser.parse",
) as parse_map:
# Reload the config entry so that the map is saved in storage and entities exist.
await hass.config_entries.async_reload(setup_entry.entry_id)
await hass.async_block_till_done()
assert hass.states.get("image.roborock_s7_maxv_upstairs") is not None
client = await hass_client()
resp = await client.get("/api/image_proxy/image.roborock_s7_maxv_upstairs")
# Test that we can get the image and it correctly serialized and unserialized.
assert resp.status == HTTPStatus.OK
body = await resp.read()
assert body == img_bytes
# Ensure that we never tried to update the map, and only used the cached image.
assert parse_map.call_count == 0
async def test_fail_to_save_image(
hass: HomeAssistant,
hass_client: ClientSessionGenerator,