-
Notifications
You must be signed in to change notification settings - Fork 66
feat: add stronger mop washing support #765
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,8 +1,11 @@ | ||
| """Trait for wash towel mode.""" | ||
|
|
||
| from roborock.data import WashTowelMode | ||
| from functools import cached_property | ||
|
|
||
| from roborock.data import WashTowelMode, WashTowelModes, get_wash_towel_modes | ||
| from roborock.device_features import is_wash_n_fill_dock | ||
| from roborock.devices.traits.v1 import common | ||
| from roborock.devices.traits.v1.device_features import DeviceFeaturesTrait | ||
| from roborock.roborock_typing import RoborockCommand | ||
|
|
||
|
|
||
|
|
@@ -11,3 +14,30 @@ class WashTowelModeTrait(WashTowelMode, common.V1TraitMixin): | |
|
|
||
| command = RoborockCommand.GET_WASH_TOWEL_MODE | ||
| requires_dock_type = is_wash_n_fill_dock | ||
|
|
||
| def __init__( | ||
| self, | ||
| device_feature_trait: DeviceFeaturesTrait | None = None, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My understanding is this will always be set so it won't ever be None. Is that righT? (Can simplify a check below) |
||
| wash_mode: WashTowelModes | None = None, | ||
| ) -> None: | ||
Lash-L marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| super().__init__() | ||
| self.device_feature_trait = device_feature_trait | ||
| self.wash_mode = wash_mode | ||
|
|
||
| @cached_property | ||
| def wash_towel_mode_options(self) -> list[WashTowelModes]: | ||
| if self.device_feature_trait is None: | ||
| return [] | ||
| return get_wash_towel_modes(self.device_feature_trait) | ||
|
|
||
| async def set_wash_towel_mode(self, mode: WashTowelModes) -> None: | ||
| """Set the wash towel mode.""" | ||
| await self.rpc_channel.send_command(RoborockCommand.SET_WASH_TOWEL_MODE, params={"wash_mode": mode.code}) | ||
|
|
||
| async def start_wash(self) -> None: | ||
| """Start washing the mop.""" | ||
| await self.rpc_channel.send_command(RoborockCommand.APP_START_WASH) | ||
|
|
||
| async def stop_wash(self) -> None: | ||
| """Stop washing the mop.""" | ||
| await self.rpc_channel.send_command(RoborockCommand.APP_STOP_WASH) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,12 +4,15 @@ | |
|
|
||
| import pytest | ||
|
|
||
| from roborock.data import RoborockDockTypeCode, RoborockDockWashTowelModeCode | ||
| from roborock.data import ( | ||
| RoborockDockTypeCode, | ||
| WashTowelModes, | ||
| ) | ||
| from roborock.devices.device import RoborockDevice | ||
| from roborock.devices.traits.v1.wash_towel_mode import WashTowelModeTrait | ||
| from roborock.roborock_typing import RoborockCommand | ||
|
|
||
| WASH_TOWEL_MODE_DATA = [{"wash_mode": RoborockDockWashTowelModeCode.smart}] | ||
| WASH_TOWEL_MODE_DATA = {"wash_mode": WashTowelModes.SMART.code} | ||
|
|
||
|
|
||
| @pytest.fixture(name="wash_towel_mode") | ||
|
|
@@ -50,7 +53,7 @@ async def test_wash_towel_mode_available( | |
| ] | ||
| ) | ||
|
|
||
| assert wash_towel_mode.wash_mode == RoborockDockWashTowelModeCode.smart | ||
| assert wash_towel_mode.wash_mode == WashTowelModes.SMART | ||
|
|
||
|
|
||
| @pytest.mark.parametrize( | ||
|
|
@@ -65,3 +68,133 @@ async def test_unsupported_wash_towel_mode( | |
| ) -> None: | ||
| """Test that the trait is not available for unsupported dock types.""" | ||
| assert wash_towel_mode is None | ||
|
|
||
|
|
||
| @pytest.mark.parametrize( | ||
| ("dock_type_code"), | ||
| [(RoborockDockTypeCode.s8_dock)], | ||
| ) | ||
| @pytest.mark.parametrize( | ||
| ("wash_mode"), | ||
| [ | ||
| (WashTowelModes.SMART), | ||
| (WashTowelModes.LIGHT), | ||
| ], | ||
| ) | ||
| async def test_set_wash_towel_mode( | ||
| wash_towel_mode: WashTowelModeTrait | None, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this doesn't need to be |
||
| mock_rpc_channel: AsyncMock, | ||
| wash_mode: WashTowelModes, | ||
| dock_type_code: RoborockDockTypeCode, | ||
| ) -> None: | ||
| """Test setting the wash towel mode.""" | ||
| assert wash_towel_mode is not None | ||
|
|
||
| await wash_towel_mode.set_wash_towel_mode(wash_mode) | ||
|
|
||
| mock_rpc_channel.send_command.assert_called_with( | ||
| RoborockCommand.SET_WASH_TOWEL_MODE, params={"wash_mode": wash_mode.code} | ||
| ) | ||
|
|
||
|
|
||
| @pytest.mark.parametrize( | ||
| ("dock_type_code"), | ||
| [(RoborockDockTypeCode.s8_dock)], | ||
| ) | ||
| async def test_start_wash( | ||
| wash_towel_mode: WashTowelModeTrait | None, | ||
| mock_rpc_channel: AsyncMock, | ||
| dock_type_code: RoborockDockTypeCode, | ||
| ) -> None: | ||
| """Test starting the wash.""" | ||
| assert wash_towel_mode is not None | ||
|
|
||
| await wash_towel_mode.start_wash() | ||
|
|
||
| mock_rpc_channel.send_command.assert_called_with(RoborockCommand.APP_START_WASH) | ||
|
|
||
|
|
||
| @pytest.mark.parametrize( | ||
| ("dock_type_code"), | ||
| [(RoborockDockTypeCode.s8_dock)], | ||
| ) | ||
| async def test_stop_wash( | ||
| wash_towel_mode: WashTowelModeTrait | None, | ||
| mock_rpc_channel: AsyncMock, | ||
| dock_type_code: RoborockDockTypeCode, | ||
| ) -> None: | ||
| """Test stopping the wash.""" | ||
| assert wash_towel_mode is not None | ||
|
|
||
| await wash_towel_mode.stop_wash() | ||
|
|
||
| mock_rpc_channel.send_command.assert_called_with(RoborockCommand.APP_STOP_WASH) | ||
|
|
||
|
|
||
| @pytest.mark.parametrize( | ||
| ("dock_type_code"), | ||
| [(RoborockDockTypeCode.s8_dock)], | ||
| ) | ||
| @pytest.mark.parametrize( | ||
| ( | ||
| "is_super_deep_wash_supported", | ||
| "is_dirty_replenish_clean_supported", | ||
| "expected_modes", | ||
| ), | ||
| [ | ||
| ( | ||
| False, | ||
| False, | ||
| [WashTowelModes.LIGHT, WashTowelModes.BALANCED, WashTowelModes.DEEP], | ||
| ), | ||
| ( | ||
| True, | ||
| False, | ||
| [ | ||
| WashTowelModes.LIGHT, | ||
| WashTowelModes.BALANCED, | ||
| WashTowelModes.DEEP, | ||
| WashTowelModes.SUPER_DEEP, | ||
| ], | ||
| ), | ||
| ( | ||
| False, | ||
| True, | ||
| [ | ||
| WashTowelModes.LIGHT, | ||
| WashTowelModes.BALANCED, | ||
| WashTowelModes.DEEP, | ||
| WashTowelModes.SMART, | ||
| ], | ||
| ), | ||
| ( | ||
| True, | ||
| True, | ||
| [ | ||
| WashTowelModes.LIGHT, | ||
| WashTowelModes.BALANCED, | ||
| WashTowelModes.DEEP, | ||
| WashTowelModes.SMART, | ||
| ], | ||
| ), | ||
| ], | ||
| ) | ||
| async def test_wash_towel_mode_options( | ||
| wash_towel_mode: WashTowelModeTrait | None, | ||
| dock_type_code: RoborockDockTypeCode, | ||
| is_super_deep_wash_supported: bool, | ||
| is_dirty_replenish_clean_supported: bool, | ||
| expected_modes: list[WashTowelModes], | ||
| ) -> None: | ||
| """Test what modes are available based on device features.""" | ||
| assert wash_towel_mode is not None | ||
| # We need to clear the cached property to ensure it re-reads the features | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this really required? My impression is we're testing with a new instance of |
||
| if "wash_towel_mode_options" in wash_towel_mode.__dict__: | ||
| del wash_towel_mode.__dict__["wash_towel_mode_options"] | ||
|
|
||
| # Mock the device features | ||
| assert wash_towel_mode.device_feature_trait is not None | ||
| wash_towel_mode.device_feature_trait.is_super_deep_wash_supported = is_super_deep_wash_supported | ||
| wash_towel_mode.device_feature_trait.is_dirty_replenish_clean_supported = is_dirty_replenish_clean_supported | ||
|
|
||
| assert wash_towel_mode.wash_towel_mode_options == expected_modes | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about initializing this outside the loop before entering? This would be similar to how it works in the constructor where you first create the types that have special argument, then create the rest that haven't been set. This code will ignore it if its set already.