From 8c41e21b7fdbf26c45025156302477fd23e8a721 Mon Sep 17 00:00:00 2001 From: Luke Lashley Date: Sun, 22 Feb 2026 10:44:29 -0500 Subject: [PATCH] Bump python-robroock to 4.17.1 (#163765) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ludovic BOUÉ --- homeassistant/components/roborock/entity.py | 4 ++-- .../components/roborock/manifest.json | 2 +- homeassistant/components/roborock/models.py | 4 ++-- homeassistant/components/roborock/select.py | 20 ++++++++++------ .../components/roborock/strings.json | 4 ++++ homeassistant/components/roborock/vacuum.py | 10 +++++--- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- tests/components/roborock/conftest.py | 23 ++++++++++++++++++- 9 files changed, 53 insertions(+), 18 deletions(-) diff --git a/homeassistant/components/roborock/entity.py b/homeassistant/components/roborock/entity.py index bb2c22195fb..0f780dd9d81 100644 --- a/homeassistant/components/roborock/entity.py +++ b/homeassistant/components/roborock/entity.py @@ -2,8 +2,8 @@ from typing import Any -from roborock.data import Status from roborock.devices.traits.v1.command import CommandTrait +from roborock.devices.traits.v1.status import StatusTrait from roborock.exceptions import RoborockException from roborock.roborock_typing import RoborockCommand @@ -94,7 +94,7 @@ class RoborockCoordinatedEntityV1( self._attr_unique_id = unique_id @property - def _device_status(self) -> Status: + def _device_status(self) -> StatusTrait: """Return the status of the device.""" data = self.coordinator.data return data.status diff --git a/homeassistant/components/roborock/manifest.json b/homeassistant/components/roborock/manifest.json index f84a22a2d08..a17f9e5c7dc 100644 --- a/homeassistant/components/roborock/manifest.json +++ b/homeassistant/components/roborock/manifest.json @@ -20,7 +20,7 @@ "loggers": ["roborock"], "quality_scale": "silver", "requirements": [ - "python-roborock==4.15.0", + "python-roborock==4.17.1", "vacuum-map-parser-roborock==0.1.4" ] } diff --git a/homeassistant/components/roborock/models.py b/homeassistant/components/roborock/models.py index 6715e370a5d..4da759ede2b 100644 --- a/homeassistant/components/roborock/models.py +++ b/homeassistant/components/roborock/models.py @@ -12,8 +12,8 @@ from roborock.data import ( HomeDataDevice, HomeDataProduct, NetworkInfo, - Status, ) +from roborock.devices.traits.v1.status import StatusTrait from vacuum_map_parser_base.map_data import MapData _LOGGER = logging.getLogger(__name__) @@ -23,7 +23,7 @@ _LOGGER = logging.getLogger(__name__) class DeviceState: """Data about the current state of a device.""" - status: Status + status: StatusTrait dnd_timer: DnDTimer consumable: Consumable clean_summary: CleanSummaryWithDetail diff --git a/homeassistant/components/roborock/select.py b/homeassistant/components/roborock/select.py index cc22d016fd7..b63217c0e43 100644 --- a/homeassistant/components/roborock/select.py +++ b/homeassistant/components/roborock/select.py @@ -92,25 +92,31 @@ SELECT_DESCRIPTIONS: list[RoborockSelectDescription] = [ key="water_box_mode", translation_key="mop_intensity", api_command=RoborockCommand.SET_WATER_BOX_CUSTOM_MODE, - value_fn=lambda api: api.status.water_box_mode_name, + value_fn=lambda api: api.status.water_mode_name, entity_category=EntityCategory.CONFIG, options_lambda=lambda api: ( - api.status.water_box_mode.keys() - if api.status.water_box_mode is not None + [mode.value for mode in api.status.water_mode_options] + if api.status.water_mode_options else None ), - parameter_lambda=lambda key, api: [api.status.get_mop_intensity_code(key)], + parameter_lambda=lambda key, api: [ + {v: k for k, v in api.status.water_mode_mapping.items()}[key] + ], ), RoborockSelectDescription( key="mop_mode", translation_key="mop_mode", api_command=RoborockCommand.SET_MOP_MODE, - value_fn=lambda api: api.status.mop_mode_name, + value_fn=lambda api: api.status.mop_route_name, entity_category=EntityCategory.CONFIG, options_lambda=lambda api: ( - api.status.mop_mode.keys() if api.status.mop_mode is not None else None + [mode.value for mode in api.status.mop_route_options] + if api.status.mop_route_options + else None ), - parameter_lambda=lambda key, api: [api.status.get_mop_mode_code(key)], + parameter_lambda=lambda key, api: [ + {v: k for k, v in api.status.mop_route_mapping.items()}[key] + ], ), RoborockSelectDescription( key="dust_collection_mode", diff --git a/homeassistant/components/roborock/strings.json b/homeassistant/components/roborock/strings.json index a40178670b8..7609ec9cf42 100644 --- a/homeassistant/components/roborock/strings.json +++ b/homeassistant/components/roborock/strings.json @@ -118,9 +118,12 @@ "max": "Max", "medium": "[%key:common::state::medium%]", "mild": "Mild", + "min": "Min", "moderate": "Moderate", "off": "[%key:common::state::off%]", + "slight": "Slight", "smart_mode": "[%key:component::roborock::entity::select::mop_mode::state::smart_mode%]", + "standard": "[%key:component::roborock::entity::select::mop_mode::state::standard%]", "vac_followed_by_mop": "Vacuum followed by mop" } }, @@ -448,6 +451,7 @@ "max_plus": "Max plus", "medium": "[%key:common::state::medium%]", "off": "[%key:common::state::off%]", + "off_raise_main_brush": "Off (raised brush)", "quiet": "Quiet", "silent": "Silent", "smart_mode": "[%key:component::roborock::entity::select::mop_mode::state::smart_mode%]", diff --git a/homeassistant/components/roborock/vacuum.py b/homeassistant/components/roborock/vacuum.py index a60bee25881..9b95e7f28bd 100644 --- a/homeassistant/components/roborock/vacuum.py +++ b/homeassistant/components/roborock/vacuum.py @@ -124,7 +124,7 @@ class RoborockVacuum(RoborockCoordinatedEntityV1, StateVacuumEntity): @property def fan_speed_list(self) -> list[str]: """Get the list of available fan speeds.""" - return self._device_status.fan_power_options + return [mode.value for mode in self._device_status.fan_speed_options] @property def activity(self) -> VacuumActivity | None: @@ -135,7 +135,7 @@ class RoborockVacuum(RoborockCoordinatedEntityV1, StateVacuumEntity): @property def fan_speed(self) -> str | None: """Return the fan speed of the vacuum cleaner.""" - return self._device_status.fan_power_name + return self._device_status.fan_speed_name async def async_start(self) -> None: """Start the vacuum.""" @@ -174,7 +174,11 @@ class RoborockVacuum(RoborockCoordinatedEntityV1, StateVacuumEntity): """Set vacuum fan speed.""" await self.send( RoborockCommand.SET_CUSTOM_MODE, - [self._device_status.get_fan_speed_code(fan_speed)], + [ + {v: k for k, v in self._device_status.fan_speed_mapping.items()}[ + fan_speed + ] + ], ) async def async_set_vacuum_goto_position(self, x: int, y: int) -> None: diff --git a/requirements_all.txt b/requirements_all.txt index 239f949d95b..c7470902aef 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2627,7 +2627,7 @@ python-rabbitair==0.0.8 python-ripple-api==0.0.3 # homeassistant.components.roborock -python-roborock==4.15.0 +python-roborock==4.17.1 # homeassistant.components.smarttub python-smarttub==0.0.47 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 7a399c7a47e..2498c0a4b4f 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -2220,7 +2220,7 @@ python-pooldose==0.8.2 python-rabbitair==0.0.8 # homeassistant.components.roborock -python-roborock==4.15.0 +python-roborock==4.17.1 # homeassistant.components.smarttub python-smarttub==0.0.47 diff --git a/tests/components/roborock/conftest.py b/tests/components/roborock/conftest.py index 7e3655782d4..cf2c499a7ca 100644 --- a/tests/components/roborock/conftest.py +++ b/tests/components/roborock/conftest.py @@ -10,7 +10,14 @@ from typing import Any from unittest.mock import AsyncMock, Mock, PropertyMock, patch import pytest -from roborock import HomeDataRoom, MultiMapsListMapInfo, RoborockCategory +from roborock import ( + CleanRoutes, + HomeDataRoom, + MultiMapsListMapInfo, + RoborockCategory, + VacuumModes, + WaterModes, +) from roborock.data import ( CombinedMapInfo, DnDTimer, @@ -307,6 +314,20 @@ def create_v1_properties(network_info: NetworkInfo) -> AsyncMock: trait_spec=StatusTrait, dataclass_template=STATUS, ) + _fan_speed_mapping = {m.code: m.value for m in VacuumModes} + _water_mode_mapping = {m.code: m.value for m in WaterModes} + _mop_route_mapping = {m.code: m.value for m in CleanRoutes} + v1_properties.status.fan_speed_options = list(VacuumModes) + v1_properties.status.fan_speed_mapping = _fan_speed_mapping + v1_properties.status.fan_speed_name = _fan_speed_mapping.get(STATUS.fan_power) + v1_properties.status.water_mode_options = list(WaterModes) + v1_properties.status.water_mode_mapping = _water_mode_mapping + v1_properties.status.water_mode_name = _water_mode_mapping.get( + STATUS.water_box_mode + ) + v1_properties.status.mop_route_options = list(CleanRoutes) + v1_properties.status.mop_route_mapping = _mop_route_mapping + v1_properties.status.mop_route_name = _mop_route_mapping.get(STATUS.mop_mode) v1_properties.dnd = make_dnd_timer(dataclass_template=DND_TIMER) v1_properties.clean_summary = make_mock_trait( trait_spec=CleanSummaryTrait,