roborock.devices.traits.v1.status

  1import logging
  2from functools import cached_property
  3from typing import Any
  4
  5from roborock import (
  6    CleanRoutes,
  7    StatusV2,
  8    VacuumModes,
  9    WaterModes,
 10    get_clean_modes,
 11    get_clean_routes,
 12    get_water_mode_mapping,
 13    get_water_modes,
 14)
 15from roborock.devices.traits.common import DpsDataConverter, TraitUpdateListener
 16from roborock.roborock_message import RoborockDataProtocol
 17from roborock.roborock_typing import RoborockCommand
 18
 19from . import common
 20from .device_features import DeviceFeaturesTrait
 21
 22_LOGGER = logging.getLogger(__name__)
 23
 24_DPS_CONVERTER = DpsDataConverter.from_dataclass(StatusV2)
 25
 26
 27class StatusTrait(StatusV2, common.V1TraitMixin, TraitUpdateListener):
 28    """Trait for managing the status of Roborock devices.
 29
 30    The StatusTrait gives you the access to the state of a Roborock vacuum.
 31    The various attribute options on state change per each device.
 32    Values like fan speed, mop mode, etc. have different options for every device
 33    and are dynamically determined.
 34
 35    Usage:
 36        Before accessing status properties, you should call `refresh()` to fetch
 37        the latest data from the device. You must pass in the device feature trait
 38        to this trait so that the dynamic attributes can be pre-determined.
 39
 40    The current dynamic attributes are:
 41    - Fan Speed
 42    - Water Mode
 43    - Mop Route
 44
 45    You should call the _options() version of the attribute to know which are supported for your device
 46    (i.e. fan_speed_options())
 47    Then you can call the _mapping to convert an int value to the actual Enum. (i.e. fan_speed_mapping())
 48    You can call the _name property to get the str value of the enum. (i.e. fan_speed_name)
 49
 50    """
 51
 52    command = RoborockCommand.GET_STATUS
 53    converter = common.DefaultConverter(StatusV2)
 54
 55    def __init__(self, device_feature_trait: DeviceFeaturesTrait, region: str | None = None) -> None:
 56        """Initialize the StatusTrait."""
 57        super().__init__()
 58        TraitUpdateListener.__init__(self, logger=_LOGGER)
 59        self._device_features_trait = device_feature_trait
 60        self._region = region
 61
 62    @cached_property
 63    def fan_speed_options(self) -> list[VacuumModes]:
 64        return get_clean_modes(self._device_features_trait)
 65
 66    @cached_property
 67    def fan_speed_mapping(self) -> dict[int, str]:
 68        return {fan.code: fan.value for fan in self.fan_speed_options}
 69
 70    @cached_property
 71    def water_mode_options(self) -> list[WaterModes]:
 72        return get_water_modes(self._device_features_trait)
 73
 74    @cached_property
 75    def water_mode_mapping(self) -> dict[int, str]:
 76        return get_water_mode_mapping(self._device_features_trait)
 77
 78    @cached_property
 79    def mop_route_options(self) -> list[CleanRoutes]:
 80        return get_clean_routes(self._device_features_trait, self._region or "us")
 81
 82    @cached_property
 83    def mop_route_mapping(self) -> dict[int, str]:
 84        return {route.code: route.value for route in self.mop_route_options}
 85
 86    @property
 87    def fan_speed_name(self) -> str | None:
 88        if self.fan_power is None:
 89            return None
 90        return self.fan_speed_mapping.get(self.fan_power)
 91
 92    @property
 93    def water_mode_name(self) -> str | None:
 94        if self.water_box_mode is None:
 95            return None
 96        return self.water_mode_mapping.get(self.water_box_mode)
 97
 98    @property
 99    def mop_route_name(self) -> str | None:
100        if self.mop_mode is None:
101            return None
102        return self.mop_route_mapping.get(self.mop_mode)
103
104    def update_from_dps(self, decoded_dps: dict[RoborockDataProtocol, Any]) -> None:
105        """Update the trait from data protocol push message data.
106
107        This handles unsolicited status updates pushed by the device
108        via RoborockDataProtocol codes (e.g. STATE=121, BATTERY=122).
109        """
110        if _DPS_CONVERTER.update_from_dps(self, decoded_dps):
111            self._notify_update()
class StatusTrait(roborock.data.v1.v1_containers.StatusV2, roborock.devices.traits.v1.common.V1TraitMixin, roborock.devices.traits.common.TraitUpdateListener):
 28class StatusTrait(StatusV2, common.V1TraitMixin, TraitUpdateListener):
 29    """Trait for managing the status of Roborock devices.
 30
 31    The StatusTrait gives you the access to the state of a Roborock vacuum.
 32    The various attribute options on state change per each device.
 33    Values like fan speed, mop mode, etc. have different options for every device
 34    and are dynamically determined.
 35
 36    Usage:
 37        Before accessing status properties, you should call `refresh()` to fetch
 38        the latest data from the device. You must pass in the device feature trait
 39        to this trait so that the dynamic attributes can be pre-determined.
 40
 41    The current dynamic attributes are:
 42    - Fan Speed
 43    - Water Mode
 44    - Mop Route
 45
 46    You should call the _options() version of the attribute to know which are supported for your device
 47    (i.e. fan_speed_options())
 48    Then you can call the _mapping to convert an int value to the actual Enum. (i.e. fan_speed_mapping())
 49    You can call the _name property to get the str value of the enum. (i.e. fan_speed_name)
 50
 51    """
 52
 53    command = RoborockCommand.GET_STATUS
 54    converter = common.DefaultConverter(StatusV2)
 55
 56    def __init__(self, device_feature_trait: DeviceFeaturesTrait, region: str | None = None) -> None:
 57        """Initialize the StatusTrait."""
 58        super().__init__()
 59        TraitUpdateListener.__init__(self, logger=_LOGGER)
 60        self._device_features_trait = device_feature_trait
 61        self._region = region
 62
 63    @cached_property
 64    def fan_speed_options(self) -> list[VacuumModes]:
 65        return get_clean_modes(self._device_features_trait)
 66
 67    @cached_property
 68    def fan_speed_mapping(self) -> dict[int, str]:
 69        return {fan.code: fan.value for fan in self.fan_speed_options}
 70
 71    @cached_property
 72    def water_mode_options(self) -> list[WaterModes]:
 73        return get_water_modes(self._device_features_trait)
 74
 75    @cached_property
 76    def water_mode_mapping(self) -> dict[int, str]:
 77        return get_water_mode_mapping(self._device_features_trait)
 78
 79    @cached_property
 80    def mop_route_options(self) -> list[CleanRoutes]:
 81        return get_clean_routes(self._device_features_trait, self._region or "us")
 82
 83    @cached_property
 84    def mop_route_mapping(self) -> dict[int, str]:
 85        return {route.code: route.value for route in self.mop_route_options}
 86
 87    @property
 88    def fan_speed_name(self) -> str | None:
 89        if self.fan_power is None:
 90            return None
 91        return self.fan_speed_mapping.get(self.fan_power)
 92
 93    @property
 94    def water_mode_name(self) -> str | None:
 95        if self.water_box_mode is None:
 96            return None
 97        return self.water_mode_mapping.get(self.water_box_mode)
 98
 99    @property
100    def mop_route_name(self) -> str | None:
101        if self.mop_mode is None:
102            return None
103        return self.mop_route_mapping.get(self.mop_mode)
104
105    def update_from_dps(self, decoded_dps: dict[RoborockDataProtocol, Any]) -> None:
106        """Update the trait from data protocol push message data.
107
108        This handles unsolicited status updates pushed by the device
109        via RoborockDataProtocol codes (e.g. STATE=121, BATTERY=122).
110        """
111        if _DPS_CONVERTER.update_from_dps(self, decoded_dps):
112            self._notify_update()

Trait for managing the status of Roborock devices.

The StatusTrait gives you the access to the state of a Roborock vacuum. The various attribute options on state change per each device. Values like fan speed, mop mode, etc. have different options for every device and are dynamically determined.

Usage: Before accessing status properties, you should call refresh() to fetch the latest data from the device. You must pass in the device feature trait to this trait so that the dynamic attributes can be pre-determined.

The current dynamic attributes are:

  • Fan Speed
  • Water Mode
  • Mop Route

You should call the _options() version of the attribute to know which are supported for your device (i.e. fan_speed_options()) Then you can call the _mapping to convert an int value to the actual Enum. (i.e. fan_speed_mapping()) You can call the _name property to get the str value of the enum. (i.e. fan_speed_name)

StatusTrait( device_feature_trait: roborock.devices.traits.v1.device_features.DeviceFeaturesTrait, region: str | None = None)
56    def __init__(self, device_feature_trait: DeviceFeaturesTrait, region: str | None = None) -> None:
57        """Initialize the StatusTrait."""
58        super().__init__()
59        TraitUpdateListener.__init__(self, logger=_LOGGER)
60        self._device_features_trait = device_feature_trait
61        self._region = region

Initialize the StatusTrait.

command = <RoborockCommand.GET_STATUS: 'get_status'>

The RoborockCommand used to fetch the trait data from the device (internal only).

converter = DefaultConverter

The converter used to parse the response from the device (internal only).

fan_speed_options: list[roborock.data.v1.v1_clean_modes.VacuumModes]
63    @cached_property
64    def fan_speed_options(self) -> list[VacuumModes]:
65        return get_clean_modes(self._device_features_trait)
fan_speed_mapping: dict[int, str]
67    @cached_property
68    def fan_speed_mapping(self) -> dict[int, str]:
69        return {fan.code: fan.value for fan in self.fan_speed_options}
water_mode_options: list[roborock.data.v1.v1_clean_modes.WaterModes]
71    @cached_property
72    def water_mode_options(self) -> list[WaterModes]:
73        return get_water_modes(self._device_features_trait)
water_mode_mapping: dict[int, str]
75    @cached_property
76    def water_mode_mapping(self) -> dict[int, str]:
77        return get_water_mode_mapping(self._device_features_trait)
mop_route_options: list[roborock.data.v1.v1_clean_modes.CleanRoutes]
79    @cached_property
80    def mop_route_options(self) -> list[CleanRoutes]:
81        return get_clean_routes(self._device_features_trait, self._region or "us")
mop_route_mapping: dict[int, str]
83    @cached_property
84    def mop_route_mapping(self) -> dict[int, str]:
85        return {route.code: route.value for route in self.mop_route_options}
fan_speed_name: str | None
87    @property
88    def fan_speed_name(self) -> str | None:
89        if self.fan_power is None:
90            return None
91        return self.fan_speed_mapping.get(self.fan_power)
water_mode_name: str | None
93    @property
94    def water_mode_name(self) -> str | None:
95        if self.water_box_mode is None:
96            return None
97        return self.water_mode_mapping.get(self.water_box_mode)
mop_route_name: str | None
 99    @property
100    def mop_route_name(self) -> str | None:
101        if self.mop_mode is None:
102            return None
103        return self.mop_route_mapping.get(self.mop_mode)
def update_from_dps( self, decoded_dps: dict[roborock.roborock_message.RoborockDataProtocol, typing.Any]) -> None:
105    def update_from_dps(self, decoded_dps: dict[RoborockDataProtocol, Any]) -> None:
106        """Update the trait from data protocol push message data.
107
108        This handles unsolicited status updates pushed by the device
109        via RoborockDataProtocol codes (e.g. STATE=121, BATTERY=122).
110        """
111        if _DPS_CONVERTER.update_from_dps(self, decoded_dps):
112            self._notify_update()

Update the trait from data protocol push message data.

This handles unsolicited status updates pushed by the device via RoborockDataProtocol codes (e.g. STATE=121, BATTERY=122).