Skip to content

feat: Add initial Q10 support for Status Trait#769

Merged
allenporter merged 7 commits intoPython-roborock:mainfrom
allenporter:q10-status-trait
Feb 15, 2026
Merged

feat: Add initial Q10 support for Status Trait#769
allenporter merged 7 commits intoPython-roborock:mainfrom
allenporter:q10-status-trait

Conversation

@allenporter
Copy link
Contributor

For now there is a central refresh mechanism for all traits which can be revisited in the future. The properties API listens for updates and fans them out to traits, which listen for apporopriate DPS values they are responsible for. This adds a way to map dps values to dataclass fields, and reuses the exisitng Roborock base data for parsing updates. Comments have been added to the code base to describe how additional traits can be added following this pattern.

This is modeled after the ideas we explored in #709 and #692 but has been even further simplified.

issue #767

For now there is a central refresh mechanism for all traits which can be revisited in the future. The properties API listens for updates and fans them out to traits, which listen for apporopriate DPS values they are responsible for. This adds a way to map dps values to dataclass fields, and reuses the exisitng Roborock base data for parsing updates.
Copilot AI review requested due to automatic review settings February 14, 2026 17:45
For now there is a central refresh mechanism for all traits which can be revisited in the future. The properties API listens for updates and fans them out to traits, which listen for apporopriate DPS values they are responsible for. This adds a way to map dps values to dataclass fields, and reuses the exisitng Roborock base data for parsing updates.
Copy link
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

This PR adds initial support for the Status trait in Q10 B01 devices, implementing a streaming-based architecture for property updates. The implementation follows a trait-based pattern where device Data Points (DPS) are mapped to dataclass fields using metadata annotations, and a central subscription loop distributes updates to individual traits.

Changes:

  • Added StatusTrait for Q10 devices with support for battery, status, fan level, water level, cleaning mode, and other status fields
  • Implemented a streaming architecture using subscribe_stream() method for processing continuous device messages
  • Refactored RoborockBase.convert_dict() into a reusable static method to support trait updates
  • Added DpsDataConverter utility for mapping DPS values to dataclass fields using metadata annotations

Reviewed changes

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

Show a summary per file
File Description
tests/devices/traits/b01/q10/test_status.py Comprehensive tests for StatusTrait streaming updates and refresh functionality
roborock/devices/transport/mqtt_channel.py Added subscribe_stream() async generator for consuming message streams
roborock/devices/traits/b01/q10/status.py StatusTrait implementation wrapping Q10Status dataclass
roborock/devices/traits/b01/q10/common.py DpsDataConverter utility for mapping DPS to dataclass fields
roborock/devices/traits/b01/q10/init.py Q10PropertiesApi with lifecycle management and subscription loop
roborock/devices/rpc/b01_q10_channel.py stream_decoded_responses() generator for decoded DPS messages
roborock/devices/device.py Integration of Q10 properties lifecycle in device connect/close
roborock/data/containers.py Refactored convert_dict() as reusable static method
roborock/data/b01_q10/b01_q10_containers.py Q10Status dataclass with DPS metadata annotations

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

@allenporter allenporter requested a review from Lash-L February 14, 2026 18:02
Copy link
Collaborator

@Lash-L Lash-L left a comment

Choose a reason for hiding this comment

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

Looks awesome - just a few small comments. most are not actionable

data: str


@dataclass
Copy link
Collaborator

Choose a reason for hiding this comment

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

Not needed here - but I wonder if there is a way we can avoid having to do dataclass. Pydantic base models don't, but we do which is odd

@classmethod
def from_dataclass(cls, dataclass_type: type[RoborockBase]):
"""Initialize the converter for a specific RoborockBase-derived class."""
dps_type_map: dict[B01_Q10_DP, type] = {}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nothing wrong here - just stylistically(the naming), B01_Q10_DP feels off. I think it was me who originally added it, but maybe we should change as a follow up

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think just like DataPoint could work given its in a module, but yeah, happy to address in a followup.

Copy link
Contributor Author

@allenporter allenporter left a comment

Choose a reason for hiding this comment

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

Addressed feedback

@allenporter allenporter requested a review from Lash-L February 14, 2026 23:33
@Lash-L
Copy link
Collaborator

Lash-L commented Feb 15, 2026

Lgtm - thanks great approach

@allenporter allenporter merged commit 38d336b into Python-roborock:main Feb 15, 2026
7 checks passed
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