Skip to content

feat: live Q7 (B01) map updates from unsolicited map pushes - #912

Open
andig wants to merge 1 commit into
Python-roborock:mainfrom
andig:feat/q7-live-map-push
Open

feat: live Q7 (B01) map updates from unsolicited map pushes#912
andig wants to merge 1 commit into
Python-roborock:mainfrom
andig:feat/q7-live-map-push

Conversation

@andig

@andig andig commented Aug 4, 2026

Copy link
Copy Markdown

Summary

Q7 (B01) devices stream full SCMap frames (protocol 301 MAP_RESPONSE) on their own during cleaning — no polling, request or heartbeat needed. This wires those pushes into MapContentTrait so the rendered map stays current for the device lifetime.

Relevant to #827: the DP-110 heartbeat discussion there applies to Q10/ss-class devices. Verified from a plain MQTT subscription that sc-class Q7s (roborock.vacuum.sc05, fw 03.01.80) push a ~25 KB mapType: 0 frame roughly every 10 s during a clean (alongside prop.post DPS updates), so Q7 needs no heartbeat at all. Also the Q7 side of #739.

Changes

  • B01Q7Channel.subscribe_map_pushes(): decodes unsolicited MAP_RESPONSE frames with the device map key; undecodable frames are logged and skipped.
  • MapContentTrait.update_from_push(): re-parses pushed frames, updates the cached image/map data and notifies update listeners (TraitUpdateListener); malformed frames are dropped without clearing the cached map.
  • Q7PropertiesApi.start()/close(): subscribe for the device lifetime, wired into RoborockDevice.connect()/close() like V1 and Q10.

Validation

  • 2 new unit tests: push updates cache + notifies listener + unsubscribes on close; malformed push keeps previous content and stays silent.
  • Full test suite passes locally; ruff check/format clean.
  • Live-tested against a real sc05: a 45 s clean delivered 4 pushed frames through the new path, with the robot pose moving across frames and returning to the dock.

Independent of (but designed together with) the companion map-geometry PR #911 — with both, the pushed frames carry live robot pose and path, giving a live map without polling.

🤖 Generated with Claude Code

Copilot AI lite review requested due to automatic review settings August 4, 2026 10:31
@andig
andig force-pushed the feat/q7-live-map-push branch from 05bcb82 to 06c7845 Compare August 4, 2026 10:34

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 adds support for Roborock Q7 (B01 / sc-class) devices to keep map rendering up-to-date by subscribing to unsolicited protocol-301 MAP_RESPONSE pushes and flowing those frames into the Q7 MapContentTrait cache + update listeners for the lifetime of a connected device.

Changes:

  • Add Q7MapRpcChannel.subscribe_map_pushes() and wire it into B01Q7Channel to decode pushed MAP_RESPONSE frames.
  • Extend Q7 MapContentTrait with update_from_push() + listener notifications to update cached map/image from pushed frames.
  • Start/stop Q7 map-push subscription via Q7PropertiesApi.start()/close() and hook those into RoborockDevice.connect()/close(), with tests covering push updates and parse-failure behavior.

Reviewed changes

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

Show a summary per file
File Description
tests/devices/traits/b01/q7/test_map_content.py Adds unit tests for push-driven map cache updates and parse-failure behavior.
tests/devices/traits/b01/q7/conftest.py Extends FakeQ7Channel with a subscribe_map_pushes() test hook.
roborock/devices/traits/b01/q7/map_content.py Adds push update handling, caching, and update listener notifications for Q7 map content.
roborock/devices/traits/b01/q7/init.py Adds start()/close() lifecycle methods to manage the map-push subscription.
roborock/devices/rpc/b01_q7_channel.py Introduces subscribe_map_pushes() to decode unsolicited MAP_RESPONSE frames via the map key.
roborock/devices/device.py Wires Q7 properties start()/close() into device connect/close lifecycle.

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

Comment thread roborock/devices/traits/b01/q7/__init__.py
Comment thread roborock/devices/rpc/b01_q7_channel.py
Q7 devices stream full SCMap frames (protocol 301) on their own during
cleaning — no polling or request is needed. Verified against a live
Q7 Series (roborock.vacuum.sc05): a short clean produced a pushed frame
roughly every 10 seconds.

- B01Q7Channel.subscribe_map_pushes() decodes unsolicited MAP_RESPONSE
  frames with the device map key.
- MapContentTrait.update_from_push() re-parses pushed frames and notifies
  update listeners; malformed frames are dropped without clearing the
  cached map.
- Q7PropertiesApi.start()/close() subscribe for the device lifetime, wired
  up in RoborockDevice.connect()/close() like V1 and Q10.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@andig
andig force-pushed the feat/q7-live-map-push branch from 06c7845 to 2584105 Compare August 4, 2026 10:41
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.

2 participants