Skip to content

feat: add better cleaning mode support#817

Open
Lash-L wants to merge 4 commits intomainfrom
cleaning_mode
Open

feat: add better cleaning mode support#817
Lash-L wants to merge 4 commits intomainfrom
cleaning_mode

Conversation

@Lash-L
Copy link
Copy Markdown
Collaborator

@Lash-L Lash-L commented Apr 25, 2026

Adds a clean mode selector

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 25, 2026

Codecov Report

❌ Patch coverage is 93.49112% with 11 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
roborock/data/v1/v1_clean_modes.py 87.67% 5 Missing and 4 partials ⚠️
tests/devices/traits/v1/test_status.py 97.53% 1 Missing and 1 partial ⚠️
Files with missing lines Coverage Δ
roborock/devices/traits/v1/status.py 96.66% <100.00%> (+1.11%) ⬆️
tests/devices/traits/v1/test_status.py 98.62% <97.53%> (-1.38%) ⬇️
roborock/data/v1/v1_clean_modes.py 85.40% <87.67%> (+2.94%) ⬆️

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a high-level “cleaning mode” abstraction for V1 devices (vacuum / vac+mop / mop / custom / smart), including mode classification from status codes and RPC payload generation for setting modes.

Changes:

  • Introduces CleaningModes plus helpers to compute supported options, classify current mode, and build SET_CLEAN_MOTOR_MODE payloads.
  • Exposes cleaning-mode options/current mode/name and adds set_cleaning_mode() on StatusTrait.
  • Adds/extends unit tests for cleaning mode behavior and updates the V1 device snapshot output.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
roborock/data/v1/v1_clean_modes.py Adds CleaningModes and implements option discovery, payload generation, and current-mode classification.
roborock/devices/traits/v1/status.py Surfaces cleaning-mode APIs on StatusTrait (options/current/name/get/set).
tests/devices/traits/v1/test_status.py Adds a focused test suite for cleaning-mode options, classification, and RPC payloads.
tests/devices/__snapshots__/test_v1_device.ambr Updates snapshot to include newly exposed cleaning-mode fields.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread roborock/data/v1/v1_clean_modes.py Outdated
Comment thread tests/devices/traits/v1/test_status.py
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread roborock/data/v1/v1_clean_modes.py Outdated
Comment thread roborock/devices/traits/v1/status.py Outdated
Comment thread tests/devices/traits/v1/test_status.py
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

roborock/data/v1/v1_clean_modes.py:304

  • is_smart_mode_set() has the same int-vs-enum comparison issue as is_mode_customized(): when water_mode/clean_mode/mop_mode are ints from device status, expressions like water_mode == WaterModes.SMART_MODE will always be False. Compare using .code or reverse operand order (e.g., WaterModes.SMART_MODE == water_mode) so SMART_MODE is correctly detected.
    return (
        water_mode == WaterModes.SMART_MODE
        or clean_mode == VacuumModes.SMART_MODE
        or mop_mode == CleanRoutes.SMART_MODE
    )

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread roborock/data/v1/v1_clean_modes.py
Comment thread tests/devices/traits/v1/test_status.py Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

roborock/data/v1/v1_clean_modes.py:304

  • is_smart_mode_set() has the same int-vs-RoborockModeEnum comparison issue as is_mode_customized() (e.g., water_mode == WaterModes.SMART_MODE). When callers pass integer codes, these checks will always be False because the int is on the left. Compare against .code values or flip the comparisons so the enum’s __eq__ can handle ints.
    return (
        water_mode == WaterModes.SMART_MODE
        or clean_mode == VacuumModes.SMART_MODE
        or mop_mode == CleanRoutes.SMART_MODE
    )

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@Lash-L Lash-L requested a review from allenporter April 25, 2026 15:54
SUPER_DEEP = ("super_deep", 8)


class CleaningModes(StrEnum):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CleaningMode?

return options


def get_mop_only_vacuum_mode(features: DeviceFeatures) -> VacuumModes:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is getting the vaccuum mode when the vacuum is in mop only mode?

)

@property
def cleaning_mode_name(self) -> str | None:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be current_cleaning_mode_name?

return cleaning_mode.value

def get_cleaning_mode_parameters(self, cleaning_mode: str | CleaningModes) -> list[dict[str, int]]:
"""Get the RPC payload for the selected high-level cleaning mode."""
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was going to say this can be private, but really I think it can just be inlined. in set_cleaning_mode

SUPER_DEEP = ("super_deep", 8)


class CleaningModes(StrEnum):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some pydoc here describing how this differs from the other lower level modes would be useful. Basically never use those and always use this?

return WaterModes.STANDARD.code


def _get_clean_motor_mode_params(mode: CleaningModes, features: DeviceFeatures) -> tuple[int, int, int]:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be using the enum types instead of the code everywhere in this file, then only convert to the code when added to the params dict

return [params]


def get_current_cleaning_mode(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One thought is that this could be on CleaningModes as a classmethod like CleaningModes.from_modes
or similarlyget_cleaning_mode_parameters can be CleaningModes.get_params(...)

I think the only advantage could be the names would be shorter, but otherwise its not to different than what is here and can just be a style choice (optional)



def get_current_cleaning_mode(
clean_mode: int | None,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this also take the enum values instead of the codes?

def get_cleaning_mode_parameters(cleaning_mode: str | CleaningModes, features: DeviceFeatures) -> list[dict[str, int]]:
"""Get the RPC payload for switching the high-level cleaning mode."""
try:
mode = CleaningModes(cleaning_mode)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'd say do the string to enum conversation as high up as possible and just take the enum here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants