mirror of
https://github.com/home-assistant/core.git
synced 2025-07-08 13:57:10 +00:00
Update Roborock Map on status change (#140873)
* update map on status change * Update tests/components/roborock/test_image.py Co-authored-by: Allen Porter <allen.porter@gmail.com> * update code to handle state logic within async_update_data * Update homeassistant/components/roborock/coordinator.py Co-authored-by: Allen Porter <allen.porter@gmail.com> * move previous_state and allow update on None --------- Co-authored-by: Allen Porter <allen.porter@gmail.com>
This commit is contained in:
parent
de1823070f
commit
1cae866da9
@ -279,6 +279,7 @@ class RoborockDataUpdateCoordinator(DataUpdateCoordinator[DeviceProp]):
|
||||
|
||||
async def _async_update_data(self) -> DeviceProp:
|
||||
"""Update data via library."""
|
||||
previous_state = self.roborock_device_info.props.status.state_name
|
||||
try:
|
||||
# Update device props and standard api information
|
||||
await self._update_device_prop()
|
||||
@ -288,11 +289,14 @@ class RoborockDataUpdateCoordinator(DataUpdateCoordinator[DeviceProp]):
|
||||
|
||||
# If the vacuum is currently cleaning and it has been IMAGE_CACHE_INTERVAL
|
||||
# since the last map update, you can update the map.
|
||||
if (
|
||||
self.current_map is not None
|
||||
and self.roborock_device_info.props.status.in_cleaning
|
||||
and (dt_util.utcnow() - self.maps[self.current_map].last_updated)
|
||||
> IMAGE_CACHE_INTERVAL
|
||||
new_status = self.roborock_device_info.props.status
|
||||
if self.current_map is not None and (
|
||||
(
|
||||
new_status.in_cleaning
|
||||
and (dt_util.utcnow() - self.maps[self.current_map].last_updated)
|
||||
> IMAGE_CACHE_INTERVAL
|
||||
)
|
||||
or previous_state != new_status.state_name
|
||||
):
|
||||
try:
|
||||
await self.update_map()
|
||||
|
@ -11,6 +11,7 @@ from roborock import RoborockException
|
||||
from vacuum_map_parser_base.map_data import ImageConfig, ImageData
|
||||
|
||||
from homeassistant.components.roborock import DOMAIN
|
||||
from homeassistant.components.roborock.const import V1_LOCAL_NOT_CLEANING_INTERVAL
|
||||
from homeassistant.config_entries import ConfigEntryState
|
||||
from homeassistant.const import Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
@ -158,9 +159,6 @@ async def test_fail_to_load_image(
|
||||
) -> None:
|
||||
"""Test that we gracefully handle failing to load an image."""
|
||||
with (
|
||||
patch(
|
||||
"homeassistant.components.roborock.coordinator.RoborockMapDataParser.parse",
|
||||
) as parse_map,
|
||||
patch(
|
||||
"homeassistant.components.roborock.roborock_storage.Path.exists",
|
||||
return_value=True,
|
||||
@ -177,8 +175,6 @@ async def test_fail_to_load_image(
|
||||
await hass.config_entries.async_reload(setup_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
assert read_bytes.call_count == 4
|
||||
# Ensure that we never updated the map manually since we couldn't load it.
|
||||
assert parse_map.call_count == 0
|
||||
assert "Unable to read map file" in caplog.text
|
||||
|
||||
|
||||
@ -298,3 +294,52 @@ async def test_index_error_map(
|
||||
# last_updated timestamp.
|
||||
assert resp.ok
|
||||
assert previous_state == hass.states.get("image.roborock_s7_maxv_upstairs").state
|
||||
|
||||
|
||||
async def test_map_status_change(
|
||||
hass: HomeAssistant,
|
||||
setup_entry: MockConfigEntry,
|
||||
hass_client: ClientSessionGenerator,
|
||||
) -> None:
|
||||
"""Test floor plan map image is correctly updated on status change."""
|
||||
assert len(hass.states.async_all("image")) == 4
|
||||
|
||||
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")
|
||||
assert resp.status == HTTPStatus.OK
|
||||
old_body = await resp.read()
|
||||
assert old_body[0:4] == b"\x89PNG"
|
||||
|
||||
# Call a second time. This interval does not directly trigger a map update, but does
|
||||
# trigger a status update which detects the state has changed and uddates the map
|
||||
now = dt_util.utcnow() + V1_LOCAL_NOT_CLEANING_INTERVAL
|
||||
|
||||
# Copy the device prop so we don't override it
|
||||
prop = copy.deepcopy(PROP)
|
||||
prop.status.state_name = "testing"
|
||||
new_map_data = copy.deepcopy(MAP_DATA)
|
||||
new_map_data.image = ImageData(
|
||||
100, 10, 10, 10, 10, ImageConfig(), Image.new("RGB", (2, 2)), lambda p: p
|
||||
)
|
||||
with (
|
||||
patch(
|
||||
"homeassistant.components.roborock.coordinator.RoborockLocalClientV1.get_prop",
|
||||
return_value=prop,
|
||||
),
|
||||
patch(
|
||||
"homeassistant.components.roborock.coordinator.dt_util.utcnow",
|
||||
return_value=now,
|
||||
),
|
||||
patch(
|
||||
"homeassistant.components.roborock.coordinator.RoborockMapDataParser.parse",
|
||||
return_value=new_map_data,
|
||||
),
|
||||
):
|
||||
async_fire_time_changed(hass, now)
|
||||
resp = await client.get("/api/image_proxy/image.roborock_s7_maxv_upstairs")
|
||||
assert resp.status == HTTPStatus.OK
|
||||
assert resp.status == HTTPStatus.OK
|
||||
body = await resp.read()
|
||||
assert body is not None
|
||||
assert body != old_body
|
||||
|
Loading…
x
Reference in New Issue
Block a user