feat: decode Q10 (B01/ss07) dpFault codes with a YXFault enum#863
Merged
allenporter merged 12 commits intoJul 6, 2026
Conversation
Add a Q10-specific YXFault enum (seeded from the ss07 app fault i18n) and an additive Q10Status.fault_name property. The raw fault int is untouched, so unknown/new codes are never lost. Addresses Python-roborock#855.
Retype the fault field from a raw int to YXFault | None and make fault_name a str accessor, matching B01Props.fault / fault_name on the Q7. Update the enum provenance notes from live hardware confirmation (10 codes) and drop the unconfirmed 569 label.
…schedule ignored mid-clean)
…efuses a too-soon empty)
allenporter
previously approved these changes
Jul 5, 2026
allenporter
approved these changes
Jul 6, 2026
Contributor
|
Thank you for the contribution! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Following through on #855 — this types
Q10Status.fault(DP 90, wired as a rawintin #792) the same way the Q7 handles it: aYXFault | Nonefield plus afault_nameaccessor, mirroringB01Props.fault/fault_name.Why a Q10-specific map (and not
B01Fault)Reusing the Q7
B01Fault— the obvious alternative — would actively mislabel this device: several shared codes mean different things on ss07. The divergent ones are hardware-confirmed on my unit (code fired live, in a context matching the label):B01Faultlabelrobot_suspendeddustbin_not_installedmain_brush_entangledA user seeing
570would be sent to untangle a brush that's fine — and when this device's brush actually was entangled (twice, two different objects jammed physically), it reported5(main_brush_stuck), not570.501is worse in the other direction: a benign "clean finished" reads as an error.Provenance (single ss07 unit, so all n=1)
hw-confirmedin the enum. Four of these were confirmed by deliberately engineering the condition and catching the code at the predicted moment: a due schedule ignored mid-clean (407), the dock bag removed (46 — fires at both dock-contact and clean-start; with the bag in, docking is clean), a third auto-empty requested too soon (569 — the dock refuses to run the cycle), and the bumper held in during commanded motion (2). (5additionally has physical ground truth: two separate real brush jams, each with a matching notification.)dpFaultnumbers — the interface only ever shows users translated strings, never the raw numbers, so reports quoting them may simply never occur. Treat this table as single-source; the per-code comments say which labels are hardware-backed vs spec-only.main_wheels_entangledfor 569 is another cross-model divergence.dpFaultis overloaded — some values are lifecycle, not errors (400 = scheduled clean starting, 501/502 = returning/recharge). The converse also holds and is noted in the docstring: the device can sit in its error state (dpStatus 12) withdpFaultstill 0 (observed live with the dust-bin module removed), so aNONEfault doesn't imply no error. Happy to also add the spec's blocking-vs-alert buckets in a follow-up if that's useful.Tradeoff: unmapped codes decode to
NoneTyping the field means an unmapped code goes through
from_code, fails conversion, and the field is leftNone(the library-wide enum-field behavior). The fault space is open-ended — a firmware update can mint new codes — so the raw number is lost exactly when it's most interesting. That's already true of every other enum field here and matches the Q7, so this follows the pattern; happy to reshape to keep the raw int reachable instead (e.g. anintfield + a decoded property) if that's preferred.Scope
Data layer only (
roborock/data/b01_q10/+ tests) — no trait/transport files; rebased onto current main (post-#859). Tests cover the ss07-divergent decodes, the from_dict path, and unmapped-code behavior; the one existing assertion touched (test_status.pyfault == 0) now readsfault is YXFault.NONE, consistent with its neighbors.Closes #855.