Skip to content

feat: add MopDryerTrait for controlling the dock mop dryer - #952

Open
dschuld wants to merge 2 commits into
Python-roborock:mainfrom
dschuld:feature/dryer-trait
Open

feat: add MopDryerTrait for controlling the dock mop dryer#952
dschuld wants to merge 2 commits into
Python-roborock:mainfrom
dschuld:feature/dryer-trait

Conversation

@dschuld

@dschuld dschuld commented Sep 11, 2026

Copy link
Copy Markdown

Summary

A switch trait for starting and stopping a mop drying cycle on docks that support
drying, via APP_SET_DRYER_STATUS.

dry_status is already readable. It was annotated with dps metadata in #740 and is
consumed by Home Assistant through is_field_supported(StatusV2, StatusField.DRY_STATUS). But there is no trait behind the write side, so callers have to fall back to a raw command.

mop_dryer = device.v1_properties.mop_dryer
if mop_dryer is not None:
    await mop_dryer.enable()   # start drying
    mop_dryer.is_on            # True
    await mop_dryer.disable()  # stop

The trait is created in the special-case block in discover_features() alongside
WashTowelModeTrait and ObstaclePhotoTrait, since it takes a constructor argument.
It is gated on dock_features.is_dryable.

Background

#262 asked for this in Dec 2024 and was closed by the reporter with:

solved with app_set_dryer_status with param status:1

APP_SET_DRYER_SETTING configures the dry duration; APP_SET_DRYER_STATUS starts and
stops the cycle. That finding never made it into the library. I've confirmed the
command works against my own dock.

Open Issues / Design Choices

1. Where the state comes from. Unlike the other switch traits, the dryer has no query
command of its own. If a cycle is running is reported as dry_status on StatusV2.
So this trait holds the status trait, reads is_on from it, and overrides refresh() to
delegate, leaving V1TraitMixin's command/converter unused.

That is a deliberate deviation from the pattern documented in the module docstring
("subclass V1TraitMixin and a RoborockBase dataclass… you must define a command
class variable"). I would like to point this out here rather than have it found in review.
The alternative is a self-contained trait backed by APP_GET_DRYER_SETTING with a new
DryerSetting dataclass, which would also expose the dry-duration setting. I didn't go
that way because I have no sample of that response and didn't want to guess at the wire
format. I am happy to capture it from my dock and rework this if this approach is preferred.

Testing

50 new tests in tests/devices/traits/v1/test_mop_dryer.py:

  • trait is created for all dock types where is_dryable is true, and absent for all where
    it is false (parametrized over the full RoborockDockTypeCode enum)
  • is_on mapping for dry_status of None / 0 / 1
  • enable() / disable() send APP_SET_DRYER_STATUS with the right params and apply the
    optimistic update
  • refresh() delegates to the status trait

100% line and branch coverage on the new module.

AI assistance disclosure

This contribution was prepared with Claude Code assistance. I reviewed the submitted changes and test results and take responsibility for the contribution.

Closes #905

Adds a switch trait for starting and stopping a mop drying cycle via
APP_SET_DRYER_STATUS, gated on the dock being able to dry.

The dryer has no dedicated query command: whether a cycle is running is
reported as dry_status on the device status. The trait therefore holds
the status trait, reads is_on from it, and refreshes through it, applying
the commanded value optimistically like the other switch traits.

Named MopDryerTrait rather than DryerTrait to stay clear of the Zeo
washer/dryer appliance support, which has its own dryer concepts.
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.

Add a trait for controlling the dock mop dryer

1 participant