Skip to content

fix: use freeClean for T90 PRO OMNI room cleaning - #1710

Open
digitalvir wants to merge 1 commit into
DeebotUniverse:devfrom
digitalvir:t90-v2-room-clean-support
Open

digitalvir wants to merge 1 commit into
DeebotUniverse:devfrom
digitalvir:t90-v2-room-clean-support

Conversation

@digitalvir

@digitalvir digitalvir commented Jul 22, 2026

Copy link
Copy Markdown

This PR now contains only the remaining T90 PRO OMNI room-clean command fix.

Map support and the 12-field T90 room parser were merged independently in #1757, so this branch has been rebased onto current dev and deliberately drops the overlapping map/capability work.

The remaining change makes T90 room cleaning serialize through clean_V2 with content.type = freeClean, which is the command shape verified against a real T90 PRO OMNI.

Validation:

  • focused freeClean payload regression test
  • Ruff and mypy on changed files
  • full suite: 751 passed; 4 snapshots passed

Copilot AI lite review requested due to automatic review settings July 22, 2026 16:33
@digitalvir
digitalvir marked this pull request as draft July 22, 2026 16:39

Copilot AI left a comment

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.

Pull request overview

This PR updates the twunby (DEEBOT T90 PRO OMNI) hardware profile to use the V2 room-cleaning command format and a V2-compatible room/map refresh path, avoiding unsupported map refresh commands that previously caused rcp not support failures.

Changes:

  • Switch twunby room cleaning to CleanV2 + CleanAreaV2 (producing clean_V2 with content.type=freeClean and content.value="1,5" for a one-pass room clean).
  • Add CapabilityMap for twunby that refreshes rooms via GetCachedMapInfo and supports position + map sets via GetPos and GetMapSetV2, while disabling MajorMapEvent / MapTraceEvent refresh commands.
  • Add a hardware test asserting the above command/capability wiring for twunby.

Reviewed changes

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

File Description
deebot_client/hardware/twunby.py Switches twunby to V2 room cleaning and configures map capabilities to use cached map info + V2 map sets while avoiding unsupported major-map/trace refreshes.
tests/hardware/test_init.py Adds a regression test verifying twunby uses V2 room-clean args and the intended map refresh command set.

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

@digitalvir

Copy link
Copy Markdown
Author

Closing this for now. I want to keep validating the T90 support locally before proposing anything upstream.

@digitalvir digitalvir closed this Jul 22, 2026
@digitalvir digitalvir reopened this Jul 22, 2026
@digitalvir
digitalvir marked this pull request as ready for review July 22, 2026 19:02
Copilot AI review requested due to automatic review settings July 22, 2026 19:02

Copilot AI left a comment

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.

Pull request overview

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

return cls._get_handling_success_with_subset_command_args(data, subset_ids)

@staticmethod
def _is_named_room_subset(subset: list[str]) -> bool:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This check is not stable and we need a better way to detect the different schemas

@edenhaus
edenhaus marked this pull request as draft August 1, 2026 14:02
Copilot AI review requested due to automatic review settings August 2, 2026 15:01
@digitalvir

Copy link
Copy Markdown
Author

Addressed the schema-detection review feedback in bfc9a2e.

The previous revision made the named-room detection broader for all getMapSet_V2 room subsets with at least 10 fields. I narrowed that back down so the existing 10-field and 11-field named-room formats continue to use the same behavior they had before, without adding new validation to schemas I cannot test directly.

The only new schema detection now is for the observed T90 12-field room rows. That path requires exactly 12 fields and validates the parts present in the captured T90 payload shape: numeric id/icon/coordinate/flag fields, non-empty room name, and the expected count-speed-water clean config field. Anything that does not match the known 10/11 formats or this observed T90 12-field shape falls through to the existing GetMapSubSet path.

Validation rerun locally:

  • uv run pytest tests/commands/json/map/test_init.py::test_getMapSetV2_rooms_v2 tests/commands/json/map/test_init.py::test_getMapSetV2_rooms_v2_with_extra_fields tests/commands/json/map/test_init.py::test_getMapSetV2_rooms_v2_t90_with_two_extra_fields tests/hardware/test_init.py::test_twunby_uses_v2_room_cleaning_and_maps
  • uvx ruff==0.15.20 check deebot_client/commands/json/map/__init__.py tests/commands/json/map/test_init.py tests/hardware/test_init.py deebot_client/hardware/twunby.py
  • uv run --group lint mypy deebot_client/commands/json/map/__init__.py deebot_client/hardware/twunby.py tests/commands/json/map/test_init.py tests/hardware/test_init.py

Copilot AI left a comment

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.

Pull request overview

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

Suppressed comments (1)

deebot_client/commands/json/map/init.py:283

  • The new room-subset gate still only treats exactly 10- or 11-field rows as “named-room” subsets, and only accepts 12-field rows if they match the T90-specific validator. This is stricter than the PR description (“at least 10 fields”) and may regress future models that append additional trailing fields (e.g., 13+) but keep the same leading schema (id/name/clean-config). Consider accepting any subset row with >=10 fields as named-room subsets (while still validating numeric id + non-empty name) to avoid incorrectly falling back to the legacy GetMapSubSet triggering path.
        subset_len = len(subsets[0]) if subsets else 0
        if subsets and (
            subset_len in (10, 11)
            or all(cls._is_t90_named_room_subset(subset) for subset in subsets)
        ):

@digitalvir
digitalvir force-pushed the t90-v2-room-clean-support branch from bfc9a2e to dcfc70e Compare August 5, 2026 22:35
Copilot AI review requested due to automatic review settings August 5, 2026 22:35
@digitalvir
digitalvir marked this pull request as ready for review August 5, 2026 22:35
@digitalvir

Copy link
Copy Markdown
Author

Rebased this PR onto current dev (a094504c) and marked it ready for review.

The branch still keeps the schema-detection change intentionally conservative: existing 10-field and 11-field named-room formats keep their previous behavior, while the new detection only accepts the observed T90 12-field room rows with the fields we can validate from the captured payload.

Validation rerun after rebase:

  • uv run pytest tests/commands/json/map/test_init.py::test_getMapSetV2_rooms_v2 tests/commands/json/map/test_init.py::test_getMapSetV2_rooms_v2_with_extra_fields tests/commands/json/map/test_init.py::test_getMapSetV2_rooms_v2_t90_with_two_extra_fields tests/hardware/test_init.py::test_twunby_uses_v2_room_cleaning_and_maps
  • uvx ruff==0.15.20 check deebot_client/commands/json/map/__init__.py tests/commands/json/map/test_init.py tests/hardware/test_init.py deebot_client/hardware/twunby.py
  • uv run --group lint mypy deebot_client/commands/json/map/__init__.py deebot_client/hardware/twunby.py tests/commands/json/map/test_init.py tests/hardware/test_init.py
  • uv run pytest (751 passed, 4 snapshots passed, one existing pytest deprecation warning)

Copilot AI left a comment

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.

Pull request overview

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

Suppressed comments (3)

deebot_client/commands/json/map/init.py:327

  • PR description says to accept named V2 room subset rows with at least 10 fields, but _is_t90_named_room_subset currently requires exactly 12 fields, so any 13+ field variant would be rejected even if the required fields are present. Allowing 12+ fields (and making _is_int tolerant of non-string values) keeps the parser forward-compatible while still validating the known required indices.
    def _is_t90_named_room_subset(cls, subset: list[str]) -> bool:
        if len(subset) != 12:
            return False

        if not str(subset[1]).strip():

deebot_client/commands/json/map/init.py:286

  • The subset field index comments look 1-based, but the code uses 0-based indices (subset[0] for id and subset[1] for name). This mismatch makes the new format documentation harder to follow and increases the risk of future parsing bugs.
            # subset values
            # 1 -> id
            # 2 -> name

deebot_client/commands/json/map/init.py:283

  • The V2 named-room subset parsing gate accepts 10/11-field rows without validating the PR-stated requirements (numeric room id + non-empty room name), and it will also reject future 12+ field variants unless they match the T90-specific validator. Adding a lightweight per-row id/name validation here avoids int(...) crashes and better matches the stated "at least 10 fields" contract.

This issue also appears on line 323 of the same file.

        subset_len = len(subsets[0]) if subsets else 0
        if subsets and (
            subset_len in (10, 11)
            or all(cls._is_t90_named_room_subset(subset) for subset in subsets)
        ):

Rhapsodyan pushed a commit to Rhapsodyan/client.py that referenced this pull request Aug 6, 2026
The X9 PRO OMNI rejects the legacy clean/spotArea area command with
'20003: rcp not support' (issue DeebotUniverse#1477). Start already used clean_V2,
but area cleaning still used the legacy CleanArea command.

Switch the area capability to the V2 freeClean command shape
(CleanAreaV2 with CleanMode.FREE_CLEAN), same approach as the T90
PRO OMNI profile (PR DeebotUniverse#1710). Tested on a real X9 PRO OMNI: selected
room cleaning starts correctly (mop wash cycle first, then cleans).
@digitalvir
digitalvir force-pushed the t90-v2-room-clean-support branch from dcfc70e to 66cac8c Compare August 18, 2026 15:07
@digitalvir digitalvir changed the title Add V2 room support for DEEBOT T90 PRO OMNI fix: use freeClean for T90 PRO OMNI room cleaning Aug 18, 2026
@digitalvir

Copy link
Copy Markdown
Author

Rebased and deliberately narrowed this PR to the remaining T90 room-clean command fix.

#1757 now owns the map capability and 12-field room-parser work, so this branch drops that overlap and keeps only the clean_V2/freeClean serialization required for T90 room cleaning.

Validation on 66cac8c:

  • focused freeClean payload test: passed
  • Ruff and mypy on changed files: passed
  • full suite: 751 passed; 4 snapshots passed

The original parser-focused changes-requested feedback is therefore superseded by upstream #1757. This PR is now ready for review solely as the freeClean room-cleaning fix.

@codecov

codecov Bot commented Sep 10, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 96.26%. Comparing base (5453eba) to head (66cac8c).
⚠️ Report is 16 commits behind head on dev.

Additional details and impacted files
@@           Coverage Diff           @@
##              dev    #1710   +/-   ##
=======================================
  Coverage   96.26%   96.26%           
=======================================
  Files         161      161           
  Lines        6399     6402    +3     
  Branches      368      368           
=======================================
+ Hits         6160     6163    +3     
  Misses        172      172           
  Partials       67       67           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@codspeed

codspeed Bot commented Sep 10, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 226 untouched benchmarks


Comparing digitalvir:t90-v2-room-clean-support (66cac8c) with dev (5453eba)

Open in CodSpeed

@pascalgottret

pascalgottret commented Sep 16, 2026

Copy link
Copy Markdown

not sure if this is the right place to answer, however, I already included this change into a custom integration and now everything seems to work. Many thanks for that terrific work! Except the multiselection of rooms for one clean process does not work. It will only process the first selected room. Not sure if this is already known.

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.

4 participants