Skip to content

Add selective room cleaning to vacuum clean module#1660

Merged
rytilahti merged 6 commits into
python-kasa:masterfrom
epg-pers:feature/vacuum-room-cleaning
Jul 11, 2026
Merged

Add selective room cleaning to vacuum clean module#1660
rytilahti merged 6 commits into
python-kasa:masterfrom
epg-pers:feature/vacuum-room-cleaning

Conversation

@epg-pers

Copy link
Copy Markdown
Contributor

Summary

Adds support for selective room cleaning to the existing Clean module:

  • clean_rooms(room_ids: list[int], map_id: int | None = None) - sends setSwitchClean with clean_mode: 3 and the verified payload to clean specific rooms
  • get_rooms(map_id: int | None = None) - on-demand call to getMapData returning the filtered list of room areas
  • current_map_id property - exposes the active map ID from getMapInfo, which is now included in the polling query

Background

The correct setSwitchClean payload for selective room cleaning was reverse-engineered by intercepting live device traffic while the official Tapo app performed a room clean (getSwitchClean readback). Key findings:

  • clean_mode: 2 is spot clean — the room_list field is silently ignored
  • clean_mode: 3 is selective room clean
  • room_list is a plain int[] of room IDs (the pixel values used in the LZ4 map), not an array of objects
  • start_type: 1 is required

This was verified working on an RV30 Max Plus (EU) running firmware 1.3.2, documented in https://github.com/epg-pers/tapo-rv30-ha and discussed in #1592.

Test plan

  • All 48 existing + new tests pass against both RV20 and RV30 fixtures
  • test_clean_rooms - verifies correct setSwitchClean payload with default map ID
  • test_clean_rooms_explicit_map_id - verifies explicit map_id is used when provided
  • test_clean_rooms_empty_raises - verifies ValueError on empty room list
  • test_get_rooms / test_get_rooms_explicit_map_id - verifies getMapData call and room filtering

@epg-pers epg-pers mentioned this pull request Feb 23, 2026
Add clean_rooms() to send selective room clean commands using
clean_mode 3 with the verified setSwitchClean payload, and
get_rooms() to query the room list from the device on demand.
Add getMapInfo to the polling query to expose current_map_id.

Tested on RV30 Max Plus (EU) firmware 1.3.2.
@epg-pers
epg-pers force-pushed the feature/vacuum-room-cleaning branch from 3a5234c to cba457a Compare February 23, 2026 22:00
@codecov

codecov Bot commented Feb 23, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 90.66667% with 7 lines in your changes missing coverage. Please review.
✅ Project coverage is 93.29%. Comparing base (932f3e2) to head (dd3ac76).
⚠️ Report is 18 commits behind head on master.

Files with missing lines Patch % Lines
kasa/smart/modules/clean.py 90.66% 5 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1660      +/-   ##
==========================================
+ Coverage   93.22%   93.29%   +0.06%     
==========================================
  Files         157      157              
  Lines        9818     9932     +114     
  Branches     1003     1022      +19     
==========================================
+ Hits         9153     9266     +113     
+ Misses        472      471       -1     
- Partials      193      195       +2     

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

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@rytilahti rytilahti left a comment

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.

Thanks for the pull request, @epg-pers! See some initial comments inline.

I am trying to think ahead how to integrate this with downstreams, I guess we would need to add support for parameters for Feature actions to make it easier to integrate, e.g., to home assistant?

Comment thread kasa/smart/modules/clean.py
Comment thread kasa/smart/modules/clean.py
Comment thread kasa/smart/modules/clean.py Outdated
Comment thread kasa/smart/modules/clean.py Outdated
Comment thread kasa/smart/modules/clean.py Outdated
Comment thread kasa/smart/modules/clean.py Outdated
@davidefiocco

davidefiocco commented Feb 28, 2026

Copy link
Copy Markdown
Contributor

Hello! @epg-pers I tested this with my RV30(UN) 1.0, firmware 1.2.2 Build 240627, AES transport, and it worked beautifully!

I took a stab at integrating zones too, and it worked, but I would have never managed without your work!

In order to progress with different modes, I triggered each cleaning mode from the Tapo app (room, zone, custom, home advanced, home standard) and polled getCleanStatus / getSwitchClean / getVacStatus via the local API to observe which clean_status and clean_mode values the device reported. Then I replayed those values in setSwitchClean payloads locally and verified that the vacuum actually started the expected mode (checked by looking at the vacuum IRL and via the app).

One thing I couldn't figure out and trigger properly is the "Home Advanced Cleaning", but the others (spot, rooms, zones) would be covered.

In case you're curious, I extended this also trying to factor in @rytilahti's suggestions here master...davidefiocco:python-kasa:feat/room-cleaning-improvements in case it can be useful for inspiration (and zones could be added in a separate PR). It worked for me!

@epg-pers

Copy link
Copy Markdown
Contributor Author

Hello! @epg-pers I tested this with my RV30(UN) 1.0, firmware 1.2.2 Build 240627, AES transport, and it worked beautifully!

I took a stab at integrating zones too, and it worked, but I would have never managed without your work!

In order to progress with different modes, I triggered each cleaning mode from the Tapo app (room, zone, custom, home advanced, home standard) and polled getCleanStatus / getSwitchClean / getVacStatus via the local API to observe which clean_status and clean_mode values the device reported. Then I replayed those values in setSwitchClean payloads locally and verified that the vacuum actually started the expected mode (checked by looking at the vacuum IRL and via the app).

One thing I couldn't figure out and trigger properly is the "Home Advanced Cleaning", but the others (spot, rooms, zones) would be covered.

In case you're curious, I extended this also trying to factor in @rytilahti's suggestions here master...davidefiocco:python-kasa:feat/room-cleaning-improvements in case it can be useful for inspiration (and zones could be added in a separate PR). It worked for me!

That's great do hear. It sounds like you followed a similar strategy to me; trigger action from the app > poll the device locally to understand what was set > attempt the same payload locally. Feel free to add your additions to this PR. I haven't had much time this week to revisit @rytilahti suggestions.

@davidefiocco

davidefiocco commented Mar 1, 2026

Copy link
Copy Markdown
Contributor

Feel free to add your additions to this PR.

Sure! @epg-pers, I've prepared a commit addressing @rytilahti's review feedback (enums, dataclasses, base64 name decoding, clean_type property) with rooms only, no zones yet.

All 54 tests pass and pre-commit checks are clean.
You can see the diff here: epg-pers/python-kasa@feature/vacuum-room-cleaning...davidefiocco:python-kasa:feature/vacuum-room-cleaning-review-fixes

You could either:

  • Add me as a collaborator on your fork so I can push directly to your branch, or
  • Pull my changes into your branch:
git remote add davidefiocco https://github.com/davidefiocco/python-kasa.git
git fetch davidefiocco feature/vacuum-room-cleaning-review-fixes
git merge davidefiocco/feature/vacuum-room-cleaning-review-fixes

And if needed I can try to chime in response to @rytilahti's comments above.

@epg-pers

epg-pers commented Mar 2, 2026

Copy link
Copy Markdown
Contributor Author

@davidefiocco thanks for doing the legwork on rytilahti's suggestions, ive merged your branch in. 54 tests passing and pre-commit clean. @rytilahti really appreciate the detailed review feedback, the enums, dataclass, and base64 name decoding are all in now. Let me know if there is anything else you would like changed.

@rytilahti rytilahti left a comment

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.

Just a couple of minor nits, nice to see the progress here! Feel free to comment and/or close my previous comments, just to make it visible if they are still pending.

Comment thread kasa/smart/modules/clean.py Outdated
Comment thread kasa/smart/modules/clean.py
Comment thread kasa/smart/modules/clean.py
@davidefiocco

davidefiocco commented Mar 22, 2026

Copy link
Copy Markdown
Contributor

Hey @epg-pers !
I believe this PR is genuinely useful and thus as before I tried to address @rytilahti's remarks in the same way as last time.

You can check the new diff via epg-pers/python-kasa@feature/vacuum-room-cleaning...davidefiocco:python-kasa:feature/vacuum-room-cleaning-review-fixes and merge on your branch via

git fetch davidefiocco feature/vacuum-room-cleaning-review-fixes
git merge davidefiocco/feature/vacuum-room-cleaning-review-fixes

This time I addressed debug logging, the requested blank line and typed FanSpeed. Added two tests, all tests pass, linters happy. If you merge this to your branch, I am glad to try to respond to all comments by @rytilahti in your behalf. Still, I am afraid that we'll need yet another iteration because there are some rough edges to discuss.

I also added a fixture from my device, and added that separately in #1665, but couldn't add map data in it yet (I experience errors if I try).

@github-actions

Copy link
Copy Markdown

There hasn't been any activity on this pull request recently. This pull request has been automatically marked as stale because of that and will be closed if no further activity occurs within 7 days.
If you are the author of this PR, please leave a comment if you want to keep it open. Also, please rebase your PR onto the latest dev branch to ensure that it's up to date with the latest changes.
Thank you for your contribution!

@github-actions github-actions Bot added the stale label Jun 21, 2026
@github-actions github-actions Bot closed this Jun 29, 2026
@rytilahti rytilahti reopened this Jul 5, 2026
@github-actions github-actions Bot removed the stale label Jul 6, 2026
@rytilahti rytilahti added this to the 0.11 milestone Jul 6, 2026
@rytilahti rytilahti added the enhancement New feature or request label Jul 6, 2026
@rytilahti

Copy link
Copy Markdown
Member

@davidefiocco, I merged your branch to @epg-pers' branch behind this PR, thanks to both of you for this! I tested with my own vacuum & I am planning to improve this with some ideas I have in a separate PR, so I will just merge this now.

@davidefiocco

Copy link
Copy Markdown
Contributor

Fantastic news, thanks for consolidating this @rytilahti!!

@rytilahti
rytilahti enabled auto-merge (squash) July 11, 2026 13:02
@rytilahti
rytilahti merged commit aba457a into python-kasa:master Jul 11, 2026
21 of 22 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants