roborock.data.code_mappings

  1import logging
  2from collections import namedtuple
  3from enum import Enum, IntEnum, StrEnum
  4from typing import Any, Self
  5
  6_LOGGER = logging.getLogger(__name__)
  7completed_warnings = set()
  8
  9
 10class RoborockEnum(IntEnum):
 11    """Roborock Enum for codes with int values"""
 12
 13    @property
 14    def name(self) -> str:
 15        return super().name.lower()
 16
 17    @classmethod
 18    def _missing_(cls: type[Self], key) -> Self:
 19        if hasattr(cls, "unknown"):
 20            warning = f"Missing {cls.__name__} code: {key} - defaulting to 'unknown'"
 21            if warning not in completed_warnings:
 22                completed_warnings.add(warning)
 23                _LOGGER.warning(warning)
 24            return cls.unknown  # type: ignore
 25        default_value = next(item for item in cls)
 26        warning = f"Missing {cls.__name__} code: {key} - defaulting to {default_value}"
 27        if warning not in completed_warnings:
 28            completed_warnings.add(warning)
 29            _LOGGER.warning(warning)
 30        return default_value
 31
 32    @classmethod
 33    def as_dict(cls: type[Self]):
 34        return {i.name: i.value for i in cls if i.name != "missing"}
 35
 36    @classmethod
 37    def as_enum_dict(cls: type[Self]):
 38        return {i.value: i for i in cls if i.name != "missing"}
 39
 40    @classmethod
 41    def values(cls: type[Self]) -> list[int]:
 42        return list(cls.as_dict().values())
 43
 44    @classmethod
 45    def keys(cls: type[Self]) -> list[str]:
 46        return list(cls.as_dict().keys())
 47
 48    @classmethod
 49    def items(cls: type[Self]):
 50        return cls.as_dict().items()
 51
 52
 53class RoborockModeEnum(StrEnum):
 54    """A custom StrEnum that also stores an integer code for each member."""
 55
 56    code: int
 57    """The integer code associated with the enum member."""
 58
 59    def __new__(cls, value: str, code: int) -> Self:
 60        """Creates a new enum member."""
 61        member = str.__new__(cls, value)
 62        member._value_ = value
 63        member.code = code
 64        return member
 65
 66    @classmethod
 67    def from_code(cls, code: int) -> Self:
 68        for member in cls:
 69            if member.code == code:
 70                return member
 71        message = f"{code} is not a valid code for {cls.__name__}"
 72        if message not in completed_warnings:
 73            completed_warnings.add(message)
 74            _LOGGER.warning(message)
 75        raise ValueError(message)
 76
 77    @classmethod
 78    def from_code_optional(cls, code: int) -> Self | None:
 79        """Gracefully return None if the code does not exist."""
 80        try:
 81            return cls.from_code(code)
 82        except ValueError:
 83            return None
 84
 85    @classmethod
 86    def from_value(cls, value: str) -> Self:
 87        """Find enum member by string value (case-insensitive)."""
 88        for member in cls:
 89            if member.value.lower() == value.lower():
 90                return member
 91        raise ValueError(f"{value} is not a valid value for {cls.__name__}")
 92
 93    @classmethod
 94    def from_name(cls, name: str) -> Self:
 95        """Find enum member by name (case-insensitive)."""
 96        for member in cls:
 97            if member.name.lower() == name.lower():
 98                return member
 99        raise ValueError(f"{name} is not a valid name for {cls.__name__}")
100
101    @classmethod
102    def from_any_optional(cls, value: str | int) -> Self | None:
103        """Resolve a string or int to an enum member.
104
105        Tries to look up by enum name, string value, or integer code
106        and returns None if no match is found.
107        """
108        # Try enum name lookup (e.g. "SEEK")
109        try:
110            return cls.from_name(str(value))
111        except ValueError:
112            pass
113        # Try DP string value lookup (e.g. "dpSeek")
114        try:
115            return cls.from_value(str(value))
116        except ValueError:
117            pass
118        # Try integer code lookup (e.g. "11")
119        try:
120            return cls.from_code(int(value))
121        except (ValueError, TypeError):
122            pass
123        return None
124
125    @classmethod
126    def keys(cls) -> list[str]:
127        """Returns a list of all member values."""
128        return [member.value for member in cls]
129
130    def __eq__(self, other: Any) -> bool:
131        if isinstance(other, str):
132            return self.value == other or self.name == other
133        if isinstance(other, int):
134            return self.code == other
135        return super().__eq__(other)
136
137    def __hash__(self) -> int:
138        """Hash a RoborockModeEnum.
139
140        It is critical that you do not mix RoborockModeEnums with raw strings or ints in hashed situations
141        (i.e. sets or keys in dictionaries)
142        """
143        return hash((self.code, self._value_))
144
145
146ProductInfo = namedtuple("ProductInfo", ["nickname", "short_models"])
147
148
149class RoborockProductNickname(Enum):
150    # Coral Series
151    CORAL = ProductInfo(nickname="Coral", short_models=("a20", "a21"))
152    CORALPRO = ProductInfo(nickname="CoralPro", short_models=("a143", "a144"))
153
154    # Pearl Series
155    PEARL = ProductInfo(nickname="Pearl", short_models=("a74", "a75"))
156    PEARLC = ProductInfo(nickname="PearlC", short_models=("a103", "a104"))
157    PEARLE = ProductInfo(nickname="PearlE", short_models=("a167", "a168"))
158    PEARLELITE = ProductInfo(nickname="PearlELite", short_models=("a169", "a170"))
159    PEARLPLUS = ProductInfo(nickname="PearlPlus", short_models=("a86", "a87"))
160    PEARLPLUSS = ProductInfo(nickname="PearlPlusS", short_models=("a116", "a117", "a136"))
161    PEARLS = ProductInfo(nickname="PearlS", short_models=("a100", "a101"))
162    PEARLSLITE = ProductInfo(nickname="PearlSLite", short_models=("a122", "a123"))
163
164    # Ruby Series
165    RUBYPLUS = ProductInfo(nickname="RubyPlus", short_models=("t4", "s4"))
166    RUBYSC = ProductInfo(nickname="RubySC", short_models=("p5", "a08"))
167    RUBYSE = ProductInfo(nickname="RubySE", short_models=("a19",))
168    RUBYSLITE = ProductInfo(nickname="RubySLite", short_models=("p6", "s5e", "a05"))
169
170    # Tanos Series
171    TANOS = ProductInfo(nickname="Tanos", short_models=("t6", "s6"))
172    TANOSE = ProductInfo(nickname="TanosE", short_models=("t7", "a11"))
173    TANOSS = ProductInfo(nickname="TanosS", short_models=("a14", "a15"))
174    TANOSSC = ProductInfo(nickname="TanosSC", short_models=("a39", "a40"))
175    TANOSSE = ProductInfo(nickname="TanosSE", short_models=("a33", "a34"))
176    TANOSSMAX = ProductInfo(nickname="TanosSMax", short_models=("a52",))
177    TANOSSLITE = ProductInfo(nickname="TanosSLite", short_models=("a37", "a38"))
178    TANOSSPLUS = ProductInfo(nickname="TanosSPlus", short_models=("a23", "a24"))
179    TANOSV = ProductInfo(nickname="TanosV", short_models=("t7p", "a09", "a10"))
180
181    # Topaz Series
182    TOPAZS = ProductInfo(nickname="TopazS", short_models=("a29", "a30", "a76"))
183    TOPAZSC = ProductInfo(nickname="TopazSC", short_models=("a64", "a65"))
184    TOPAZSPLUS = ProductInfo(nickname="TopazSPlus", short_models=("a46", "a47", "a66"))
185    TOPAZSPOWER = ProductInfo(nickname="TopazSPower", short_models=("a62",))
186    TOPAZSV = ProductInfo(nickname="TopazSV", short_models=("a26", "a27"))
187
188    # Ultron Series
189    ULTRON = ProductInfo(nickname="Ultron", short_models=("a50", "a51"))
190    ULTRONE = ProductInfo(nickname="UltronE", short_models=("a72", "a84"))
191    ULTRONLITE = ProductInfo(nickname="UltronLite", short_models=("a73", "a85"))
192    ULTRONSC = ProductInfo(nickname="UltronSC", short_models=("a94", "a95"))
193    ULTRONSE = ProductInfo(nickname="UltronSE", short_models=("a124", "a125", "a139", "a140"))
194    ULTRONSPLUS = ProductInfo(nickname="UltronSPlus", short_models=("a68", "a69", "a70"))
195    ULTRONSV = ProductInfo(nickname="UltronSV", short_models=("a96", "a97"))
196
197    # Verdelite Series
198    VERDELITE = ProductInfo(nickname="Verdelite", short_models=("a146", "a147"))
199
200    # Vivian Series
201    VIVIAN = ProductInfo(nickname="Vivian", short_models=("a134", "a135", "a155", "a156"))
202    VIVIANC = ProductInfo(nickname="VivianC", short_models=("a158", "a159"))
203
204
205SHORT_MODEL_TO_ENUM = {model: product for product in RoborockProductNickname for model in product.value.short_models}
206
207
208class RoborockCategory(Enum):
209    """Describes the category of the device."""
210
211    WET_DRY_VAC = "roborock.wetdryvac"
212    VACUUM = "robot.vacuum.cleaner"
213    WASHING_MACHINE = "roborock.wm"
214    MOWER = "roborock.mower"
215    UNKNOWN = "UNKNOWN"
216
217    @classmethod
218    def _missing_(cls, value):
219        _LOGGER.warning("Missing code %s from category", value)
220        return RoborockCategory.UNKNOWN
completed_warnings = set()
class RoborockEnum(enum.IntEnum):
11class RoborockEnum(IntEnum):
12    """Roborock Enum for codes with int values"""
13
14    @property
15    def name(self) -> str:
16        return super().name.lower()
17
18    @classmethod
19    def _missing_(cls: type[Self], key) -> Self:
20        if hasattr(cls, "unknown"):
21            warning = f"Missing {cls.__name__} code: {key} - defaulting to 'unknown'"
22            if warning not in completed_warnings:
23                completed_warnings.add(warning)
24                _LOGGER.warning(warning)
25            return cls.unknown  # type: ignore
26        default_value = next(item for item in cls)
27        warning = f"Missing {cls.__name__} code: {key} - defaulting to {default_value}"
28        if warning not in completed_warnings:
29            completed_warnings.add(warning)
30            _LOGGER.warning(warning)
31        return default_value
32
33    @classmethod
34    def as_dict(cls: type[Self]):
35        return {i.name: i.value for i in cls if i.name != "missing"}
36
37    @classmethod
38    def as_enum_dict(cls: type[Self]):
39        return {i.value: i for i in cls if i.name != "missing"}
40
41    @classmethod
42    def values(cls: type[Self]) -> list[int]:
43        return list(cls.as_dict().values())
44
45    @classmethod
46    def keys(cls: type[Self]) -> list[str]:
47        return list(cls.as_dict().keys())
48
49    @classmethod
50    def items(cls: type[Self]):
51        return cls.as_dict().items()

Roborock Enum for codes with int values

name: str
14    @property
15    def name(self) -> str:
16        return super().name.lower()

The name of the Enum member.

@classmethod
def as_dict(cls: type[typing.Self]):
33    @classmethod
34    def as_dict(cls: type[Self]):
35        return {i.name: i.value for i in cls if i.name != "missing"}
@classmethod
def as_enum_dict(cls: type[typing.Self]):
37    @classmethod
38    def as_enum_dict(cls: type[Self]):
39        return {i.value: i for i in cls if i.name != "missing"}
@classmethod
def values(cls: type[typing.Self]) -> list[int]:
41    @classmethod
42    def values(cls: type[Self]) -> list[int]:
43        return list(cls.as_dict().values())
@classmethod
def keys(cls: type[typing.Self]) -> list[str]:
45    @classmethod
46    def keys(cls: type[Self]) -> list[str]:
47        return list(cls.as_dict().keys())
@classmethod
def items(cls: type[typing.Self]):
49    @classmethod
50    def items(cls: type[Self]):
51        return cls.as_dict().items()
class RoborockModeEnum(enum.StrEnum):
 54class RoborockModeEnum(StrEnum):
 55    """A custom StrEnum that also stores an integer code for each member."""
 56
 57    code: int
 58    """The integer code associated with the enum member."""
 59
 60    def __new__(cls, value: str, code: int) -> Self:
 61        """Creates a new enum member."""
 62        member = str.__new__(cls, value)
 63        member._value_ = value
 64        member.code = code
 65        return member
 66
 67    @classmethod
 68    def from_code(cls, code: int) -> Self:
 69        for member in cls:
 70            if member.code == code:
 71                return member
 72        message = f"{code} is not a valid code for {cls.__name__}"
 73        if message not in completed_warnings:
 74            completed_warnings.add(message)
 75            _LOGGER.warning(message)
 76        raise ValueError(message)
 77
 78    @classmethod
 79    def from_code_optional(cls, code: int) -> Self | None:
 80        """Gracefully return None if the code does not exist."""
 81        try:
 82            return cls.from_code(code)
 83        except ValueError:
 84            return None
 85
 86    @classmethod
 87    def from_value(cls, value: str) -> Self:
 88        """Find enum member by string value (case-insensitive)."""
 89        for member in cls:
 90            if member.value.lower() == value.lower():
 91                return member
 92        raise ValueError(f"{value} is not a valid value for {cls.__name__}")
 93
 94    @classmethod
 95    def from_name(cls, name: str) -> Self:
 96        """Find enum member by name (case-insensitive)."""
 97        for member in cls:
 98            if member.name.lower() == name.lower():
 99                return member
100        raise ValueError(f"{name} is not a valid name for {cls.__name__}")
101
102    @classmethod
103    def from_any_optional(cls, value: str | int) -> Self | None:
104        """Resolve a string or int to an enum member.
105
106        Tries to look up by enum name, string value, or integer code
107        and returns None if no match is found.
108        """
109        # Try enum name lookup (e.g. "SEEK")
110        try:
111            return cls.from_name(str(value))
112        except ValueError:
113            pass
114        # Try DP string value lookup (e.g. "dpSeek")
115        try:
116            return cls.from_value(str(value))
117        except ValueError:
118            pass
119        # Try integer code lookup (e.g. "11")
120        try:
121            return cls.from_code(int(value))
122        except (ValueError, TypeError):
123            pass
124        return None
125
126    @classmethod
127    def keys(cls) -> list[str]:
128        """Returns a list of all member values."""
129        return [member.value for member in cls]
130
131    def __eq__(self, other: Any) -> bool:
132        if isinstance(other, str):
133            return self.value == other or self.name == other
134        if isinstance(other, int):
135            return self.code == other
136        return super().__eq__(other)
137
138    def __hash__(self) -> int:
139        """Hash a RoborockModeEnum.
140
141        It is critical that you do not mix RoborockModeEnums with raw strings or ints in hashed situations
142        (i.e. sets or keys in dictionaries)
143        """
144        return hash((self.code, self._value_))

A custom StrEnum that also stores an integer code for each member.

code: int

The integer code associated with the enum member.

@classmethod
def from_code(cls, code: int) -> Self:
67    @classmethod
68    def from_code(cls, code: int) -> Self:
69        for member in cls:
70            if member.code == code:
71                return member
72        message = f"{code} is not a valid code for {cls.__name__}"
73        if message not in completed_warnings:
74            completed_warnings.add(message)
75            _LOGGER.warning(message)
76        raise ValueError(message)
@classmethod
def from_code_optional(cls, code: int) -> Optional[Self]:
78    @classmethod
79    def from_code_optional(cls, code: int) -> Self | None:
80        """Gracefully return None if the code does not exist."""
81        try:
82            return cls.from_code(code)
83        except ValueError:
84            return None

Gracefully return None if the code does not exist.

@classmethod
def from_value(cls, value: str) -> Self:
86    @classmethod
87    def from_value(cls, value: str) -> Self:
88        """Find enum member by string value (case-insensitive)."""
89        for member in cls:
90            if member.value.lower() == value.lower():
91                return member
92        raise ValueError(f"{value} is not a valid value for {cls.__name__}")

Find enum member by string value (case-insensitive).

@classmethod
def from_name(cls, name: str) -> Self:
 94    @classmethod
 95    def from_name(cls, name: str) -> Self:
 96        """Find enum member by name (case-insensitive)."""
 97        for member in cls:
 98            if member.name.lower() == name.lower():
 99                return member
100        raise ValueError(f"{name} is not a valid name for {cls.__name__}")

Find enum member by name (case-insensitive).

@classmethod
def from_any_optional(cls, value: str | int) -> Optional[Self]:
102    @classmethod
103    def from_any_optional(cls, value: str | int) -> Self | None:
104        """Resolve a string or int to an enum member.
105
106        Tries to look up by enum name, string value, or integer code
107        and returns None if no match is found.
108        """
109        # Try enum name lookup (e.g. "SEEK")
110        try:
111            return cls.from_name(str(value))
112        except ValueError:
113            pass
114        # Try DP string value lookup (e.g. "dpSeek")
115        try:
116            return cls.from_value(str(value))
117        except ValueError:
118            pass
119        # Try integer code lookup (e.g. "11")
120        try:
121            return cls.from_code(int(value))
122        except (ValueError, TypeError):
123            pass
124        return None

Resolve a string or int to an enum member.

Tries to look up by enum name, string value, or integer code and returns None if no match is found.

@classmethod
def keys(cls) -> list[str]:
126    @classmethod
127    def keys(cls) -> list[str]:
128        """Returns a list of all member values."""
129        return [member.value for member in cls]

Returns a list of all member values.

class ProductInfo(builtins.tuple):

ProductInfo(nickname, short_models)

ProductInfo(nickname, short_models)

Create new instance of ProductInfo(nickname, short_models)

nickname

Alias for field number 0

short_models

Alias for field number 1

class RoborockProductNickname(enum.Enum):
150class RoborockProductNickname(Enum):
151    # Coral Series
152    CORAL = ProductInfo(nickname="Coral", short_models=("a20", "a21"))
153    CORALPRO = ProductInfo(nickname="CoralPro", short_models=("a143", "a144"))
154
155    # Pearl Series
156    PEARL = ProductInfo(nickname="Pearl", short_models=("a74", "a75"))
157    PEARLC = ProductInfo(nickname="PearlC", short_models=("a103", "a104"))
158    PEARLE = ProductInfo(nickname="PearlE", short_models=("a167", "a168"))
159    PEARLELITE = ProductInfo(nickname="PearlELite", short_models=("a169", "a170"))
160    PEARLPLUS = ProductInfo(nickname="PearlPlus", short_models=("a86", "a87"))
161    PEARLPLUSS = ProductInfo(nickname="PearlPlusS", short_models=("a116", "a117", "a136"))
162    PEARLS = ProductInfo(nickname="PearlS", short_models=("a100", "a101"))
163    PEARLSLITE = ProductInfo(nickname="PearlSLite", short_models=("a122", "a123"))
164
165    # Ruby Series
166    RUBYPLUS = ProductInfo(nickname="RubyPlus", short_models=("t4", "s4"))
167    RUBYSC = ProductInfo(nickname="RubySC", short_models=("p5", "a08"))
168    RUBYSE = ProductInfo(nickname="RubySE", short_models=("a19",))
169    RUBYSLITE = ProductInfo(nickname="RubySLite", short_models=("p6", "s5e", "a05"))
170
171    # Tanos Series
172    TANOS = ProductInfo(nickname="Tanos", short_models=("t6", "s6"))
173    TANOSE = ProductInfo(nickname="TanosE", short_models=("t7", "a11"))
174    TANOSS = ProductInfo(nickname="TanosS", short_models=("a14", "a15"))
175    TANOSSC = ProductInfo(nickname="TanosSC", short_models=("a39", "a40"))
176    TANOSSE = ProductInfo(nickname="TanosSE", short_models=("a33", "a34"))
177    TANOSSMAX = ProductInfo(nickname="TanosSMax", short_models=("a52",))
178    TANOSSLITE = ProductInfo(nickname="TanosSLite", short_models=("a37", "a38"))
179    TANOSSPLUS = ProductInfo(nickname="TanosSPlus", short_models=("a23", "a24"))
180    TANOSV = ProductInfo(nickname="TanosV", short_models=("t7p", "a09", "a10"))
181
182    # Topaz Series
183    TOPAZS = ProductInfo(nickname="TopazS", short_models=("a29", "a30", "a76"))
184    TOPAZSC = ProductInfo(nickname="TopazSC", short_models=("a64", "a65"))
185    TOPAZSPLUS = ProductInfo(nickname="TopazSPlus", short_models=("a46", "a47", "a66"))
186    TOPAZSPOWER = ProductInfo(nickname="TopazSPower", short_models=("a62",))
187    TOPAZSV = ProductInfo(nickname="TopazSV", short_models=("a26", "a27"))
188
189    # Ultron Series
190    ULTRON = ProductInfo(nickname="Ultron", short_models=("a50", "a51"))
191    ULTRONE = ProductInfo(nickname="UltronE", short_models=("a72", "a84"))
192    ULTRONLITE = ProductInfo(nickname="UltronLite", short_models=("a73", "a85"))
193    ULTRONSC = ProductInfo(nickname="UltronSC", short_models=("a94", "a95"))
194    ULTRONSE = ProductInfo(nickname="UltronSE", short_models=("a124", "a125", "a139", "a140"))
195    ULTRONSPLUS = ProductInfo(nickname="UltronSPlus", short_models=("a68", "a69", "a70"))
196    ULTRONSV = ProductInfo(nickname="UltronSV", short_models=("a96", "a97"))
197
198    # Verdelite Series
199    VERDELITE = ProductInfo(nickname="Verdelite", short_models=("a146", "a147"))
200
201    # Vivian Series
202    VIVIAN = ProductInfo(nickname="Vivian", short_models=("a134", "a135", "a155", "a156"))
203    VIVIANC = ProductInfo(nickname="VivianC", short_models=("a158", "a159"))
CORAL = <RoborockProductNickname.CORAL: ProductInfo(nickname='Coral', short_models=('a20', 'a21'))>
CORALPRO = <RoborockProductNickname.CORALPRO: ProductInfo(nickname='CoralPro', short_models=('a143', 'a144'))>
PEARL = <RoborockProductNickname.PEARL: ProductInfo(nickname='Pearl', short_models=('a74', 'a75'))>
PEARLC = <RoborockProductNickname.PEARLC: ProductInfo(nickname='PearlC', short_models=('a103', 'a104'))>
PEARLE = <RoborockProductNickname.PEARLE: ProductInfo(nickname='PearlE', short_models=('a167', 'a168'))>
PEARLELITE = <RoborockProductNickname.PEARLELITE: ProductInfo(nickname='PearlELite', short_models=('a169', 'a170'))>
PEARLPLUS = <RoborockProductNickname.PEARLPLUS: ProductInfo(nickname='PearlPlus', short_models=('a86', 'a87'))>
PEARLPLUSS = <RoborockProductNickname.PEARLPLUSS: ProductInfo(nickname='PearlPlusS', short_models=('a116', 'a117', 'a136'))>
PEARLS = <RoborockProductNickname.PEARLS: ProductInfo(nickname='PearlS', short_models=('a100', 'a101'))>
PEARLSLITE = <RoborockProductNickname.PEARLSLITE: ProductInfo(nickname='PearlSLite', short_models=('a122', 'a123'))>
RUBYPLUS = <RoborockProductNickname.RUBYPLUS: ProductInfo(nickname='RubyPlus', short_models=('t4', 's4'))>
RUBYSC = <RoborockProductNickname.RUBYSC: ProductInfo(nickname='RubySC', short_models=('p5', 'a08'))>
RUBYSE = <RoborockProductNickname.RUBYSE: ProductInfo(nickname='RubySE', short_models=('a19',))>
RUBYSLITE = <RoborockProductNickname.RUBYSLITE: ProductInfo(nickname='RubySLite', short_models=('p6', 's5e', 'a05'))>
TANOS = <RoborockProductNickname.TANOS: ProductInfo(nickname='Tanos', short_models=('t6', 's6'))>
TANOSE = <RoborockProductNickname.TANOSE: ProductInfo(nickname='TanosE', short_models=('t7', 'a11'))>
TANOSS = <RoborockProductNickname.TANOSS: ProductInfo(nickname='TanosS', short_models=('a14', 'a15'))>
TANOSSC = <RoborockProductNickname.TANOSSC: ProductInfo(nickname='TanosSC', short_models=('a39', 'a40'))>
TANOSSE = <RoborockProductNickname.TANOSSE: ProductInfo(nickname='TanosSE', short_models=('a33', 'a34'))>
TANOSSMAX = <RoborockProductNickname.TANOSSMAX: ProductInfo(nickname='TanosSMax', short_models=('a52',))>
TANOSSLITE = <RoborockProductNickname.TANOSSLITE: ProductInfo(nickname='TanosSLite', short_models=('a37', 'a38'))>
TANOSSPLUS = <RoborockProductNickname.TANOSSPLUS: ProductInfo(nickname='TanosSPlus', short_models=('a23', 'a24'))>
TANOSV = <RoborockProductNickname.TANOSV: ProductInfo(nickname='TanosV', short_models=('t7p', 'a09', 'a10'))>
TOPAZS = <RoborockProductNickname.TOPAZS: ProductInfo(nickname='TopazS', short_models=('a29', 'a30', 'a76'))>
TOPAZSC = <RoborockProductNickname.TOPAZSC: ProductInfo(nickname='TopazSC', short_models=('a64', 'a65'))>
TOPAZSPLUS = <RoborockProductNickname.TOPAZSPLUS: ProductInfo(nickname='TopazSPlus', short_models=('a46', 'a47', 'a66'))>
TOPAZSPOWER = <RoborockProductNickname.TOPAZSPOWER: ProductInfo(nickname='TopazSPower', short_models=('a62',))>
TOPAZSV = <RoborockProductNickname.TOPAZSV: ProductInfo(nickname='TopazSV', short_models=('a26', 'a27'))>
ULTRON = <RoborockProductNickname.ULTRON: ProductInfo(nickname='Ultron', short_models=('a50', 'a51'))>
ULTRONE = <RoborockProductNickname.ULTRONE: ProductInfo(nickname='UltronE', short_models=('a72', 'a84'))>
ULTRONLITE = <RoborockProductNickname.ULTRONLITE: ProductInfo(nickname='UltronLite', short_models=('a73', 'a85'))>
ULTRONSC = <RoborockProductNickname.ULTRONSC: ProductInfo(nickname='UltronSC', short_models=('a94', 'a95'))>
ULTRONSE = <RoborockProductNickname.ULTRONSE: ProductInfo(nickname='UltronSE', short_models=('a124', 'a125', 'a139', 'a140'))>
ULTRONSPLUS = <RoborockProductNickname.ULTRONSPLUS: ProductInfo(nickname='UltronSPlus', short_models=('a68', 'a69', 'a70'))>
ULTRONSV = <RoborockProductNickname.ULTRONSV: ProductInfo(nickname='UltronSV', short_models=('a96', 'a97'))>
VERDELITE = <RoborockProductNickname.VERDELITE: ProductInfo(nickname='Verdelite', short_models=('a146', 'a147'))>
VIVIAN = <RoborockProductNickname.VIVIAN: ProductInfo(nickname='Vivian', short_models=('a134', 'a135', 'a155', 'a156'))>
VIVIANC = <RoborockProductNickname.VIVIANC: ProductInfo(nickname='VivianC', short_models=('a158', 'a159'))>
SHORT_MODEL_TO_ENUM = {'a20': <RoborockProductNickname.CORAL: ProductInfo(nickname='Coral', short_models=('a20', 'a21'))>, 'a21': <RoborockProductNickname.CORAL: ProductInfo(nickname='Coral', short_models=('a20', 'a21'))>, 'a143': <RoborockProductNickname.CORALPRO: ProductInfo(nickname='CoralPro', short_models=('a143', 'a144'))>, 'a144': <RoborockProductNickname.CORALPRO: ProductInfo(nickname='CoralPro', short_models=('a143', 'a144'))>, 'a74': <RoborockProductNickname.PEARL: ProductInfo(nickname='Pearl', short_models=('a74', 'a75'))>, 'a75': <RoborockProductNickname.PEARL: ProductInfo(nickname='Pearl', short_models=('a74', 'a75'))>, 'a103': <RoborockProductNickname.PEARLC: ProductInfo(nickname='PearlC', short_models=('a103', 'a104'))>, 'a104': <RoborockProductNickname.PEARLC: ProductInfo(nickname='PearlC', short_models=('a103', 'a104'))>, 'a167': <RoborockProductNickname.PEARLE: ProductInfo(nickname='PearlE', short_models=('a167', 'a168'))>, 'a168': <RoborockProductNickname.PEARLE: ProductInfo(nickname='PearlE', short_models=('a167', 'a168'))>, 'a169': <RoborockProductNickname.PEARLELITE: ProductInfo(nickname='PearlELite', short_models=('a169', 'a170'))>, 'a170': <RoborockProductNickname.PEARLELITE: ProductInfo(nickname='PearlELite', short_models=('a169', 'a170'))>, 'a86': <RoborockProductNickname.PEARLPLUS: ProductInfo(nickname='PearlPlus', short_models=('a86', 'a87'))>, 'a87': <RoborockProductNickname.PEARLPLUS: ProductInfo(nickname='PearlPlus', short_models=('a86', 'a87'))>, 'a116': <RoborockProductNickname.PEARLPLUSS: ProductInfo(nickname='PearlPlusS', short_models=('a116', 'a117', 'a136'))>, 'a117': <RoborockProductNickname.PEARLPLUSS: ProductInfo(nickname='PearlPlusS', short_models=('a116', 'a117', 'a136'))>, 'a136': <RoborockProductNickname.PEARLPLUSS: ProductInfo(nickname='PearlPlusS', short_models=('a116', 'a117', 'a136'))>, 'a100': <RoborockProductNickname.PEARLS: ProductInfo(nickname='PearlS', short_models=('a100', 'a101'))>, 'a101': <RoborockProductNickname.PEARLS: ProductInfo(nickname='PearlS', short_models=('a100', 'a101'))>, 'a122': <RoborockProductNickname.PEARLSLITE: ProductInfo(nickname='PearlSLite', short_models=('a122', 'a123'))>, 'a123': <RoborockProductNickname.PEARLSLITE: ProductInfo(nickname='PearlSLite', short_models=('a122', 'a123'))>, 't4': <RoborockProductNickname.RUBYPLUS: ProductInfo(nickname='RubyPlus', short_models=('t4', 's4'))>, 's4': <RoborockProductNickname.RUBYPLUS: ProductInfo(nickname='RubyPlus', short_models=('t4', 's4'))>, 'p5': <RoborockProductNickname.RUBYSC: ProductInfo(nickname='RubySC', short_models=('p5', 'a08'))>, 'a08': <RoborockProductNickname.RUBYSC: ProductInfo(nickname='RubySC', short_models=('p5', 'a08'))>, 'a19': <RoborockProductNickname.RUBYSE: ProductInfo(nickname='RubySE', short_models=('a19',))>, 'p6': <RoborockProductNickname.RUBYSLITE: ProductInfo(nickname='RubySLite', short_models=('p6', 's5e', 'a05'))>, 's5e': <RoborockProductNickname.RUBYSLITE: ProductInfo(nickname='RubySLite', short_models=('p6', 's5e', 'a05'))>, 'a05': <RoborockProductNickname.RUBYSLITE: ProductInfo(nickname='RubySLite', short_models=('p6', 's5e', 'a05'))>, 't6': <RoborockProductNickname.TANOS: ProductInfo(nickname='Tanos', short_models=('t6', 's6'))>, 's6': <RoborockProductNickname.TANOS: ProductInfo(nickname='Tanos', short_models=('t6', 's6'))>, 't7': <RoborockProductNickname.TANOSE: ProductInfo(nickname='TanosE', short_models=('t7', 'a11'))>, 'a11': <RoborockProductNickname.TANOSE: ProductInfo(nickname='TanosE', short_models=('t7', 'a11'))>, 'a14': <RoborockProductNickname.TANOSS: ProductInfo(nickname='TanosS', short_models=('a14', 'a15'))>, 'a15': <RoborockProductNickname.TANOSS: ProductInfo(nickname='TanosS', short_models=('a14', 'a15'))>, 'a39': <RoborockProductNickname.TANOSSC: ProductInfo(nickname='TanosSC', short_models=('a39', 'a40'))>, 'a40': <RoborockProductNickname.TANOSSC: ProductInfo(nickname='TanosSC', short_models=('a39', 'a40'))>, 'a33': <RoborockProductNickname.TANOSSE: ProductInfo(nickname='TanosSE', short_models=('a33', 'a34'))>, 'a34': <RoborockProductNickname.TANOSSE: ProductInfo(nickname='TanosSE', short_models=('a33', 'a34'))>, 'a52': <RoborockProductNickname.TANOSSMAX: ProductInfo(nickname='TanosSMax', short_models=('a52',))>, 'a37': <RoborockProductNickname.TANOSSLITE: ProductInfo(nickname='TanosSLite', short_models=('a37', 'a38'))>, 'a38': <RoborockProductNickname.TANOSSLITE: ProductInfo(nickname='TanosSLite', short_models=('a37', 'a38'))>, 'a23': <RoborockProductNickname.TANOSSPLUS: ProductInfo(nickname='TanosSPlus', short_models=('a23', 'a24'))>, 'a24': <RoborockProductNickname.TANOSSPLUS: ProductInfo(nickname='TanosSPlus', short_models=('a23', 'a24'))>, 't7p': <RoborockProductNickname.TANOSV: ProductInfo(nickname='TanosV', short_models=('t7p', 'a09', 'a10'))>, 'a09': <RoborockProductNickname.TANOSV: ProductInfo(nickname='TanosV', short_models=('t7p', 'a09', 'a10'))>, 'a10': <RoborockProductNickname.TANOSV: ProductInfo(nickname='TanosV', short_models=('t7p', 'a09', 'a10'))>, 'a29': <RoborockProductNickname.TOPAZS: ProductInfo(nickname='TopazS', short_models=('a29', 'a30', 'a76'))>, 'a30': <RoborockProductNickname.TOPAZS: ProductInfo(nickname='TopazS', short_models=('a29', 'a30', 'a76'))>, 'a76': <RoborockProductNickname.TOPAZS: ProductInfo(nickname='TopazS', short_models=('a29', 'a30', 'a76'))>, 'a64': <RoborockProductNickname.TOPAZSC: ProductInfo(nickname='TopazSC', short_models=('a64', 'a65'))>, 'a65': <RoborockProductNickname.TOPAZSC: ProductInfo(nickname='TopazSC', short_models=('a64', 'a65'))>, 'a46': <RoborockProductNickname.TOPAZSPLUS: ProductInfo(nickname='TopazSPlus', short_models=('a46', 'a47', 'a66'))>, 'a47': <RoborockProductNickname.TOPAZSPLUS: ProductInfo(nickname='TopazSPlus', short_models=('a46', 'a47', 'a66'))>, 'a66': <RoborockProductNickname.TOPAZSPLUS: ProductInfo(nickname='TopazSPlus', short_models=('a46', 'a47', 'a66'))>, 'a62': <RoborockProductNickname.TOPAZSPOWER: ProductInfo(nickname='TopazSPower', short_models=('a62',))>, 'a26': <RoborockProductNickname.TOPAZSV: ProductInfo(nickname='TopazSV', short_models=('a26', 'a27'))>, 'a27': <RoborockProductNickname.TOPAZSV: ProductInfo(nickname='TopazSV', short_models=('a26', 'a27'))>, 'a50': <RoborockProductNickname.ULTRON: ProductInfo(nickname='Ultron', short_models=('a50', 'a51'))>, 'a51': <RoborockProductNickname.ULTRON: ProductInfo(nickname='Ultron', short_models=('a50', 'a51'))>, 'a72': <RoborockProductNickname.ULTRONE: ProductInfo(nickname='UltronE', short_models=('a72', 'a84'))>, 'a84': <RoborockProductNickname.ULTRONE: ProductInfo(nickname='UltronE', short_models=('a72', 'a84'))>, 'a73': <RoborockProductNickname.ULTRONLITE: ProductInfo(nickname='UltronLite', short_models=('a73', 'a85'))>, 'a85': <RoborockProductNickname.ULTRONLITE: ProductInfo(nickname='UltronLite', short_models=('a73', 'a85'))>, 'a94': <RoborockProductNickname.ULTRONSC: ProductInfo(nickname='UltronSC', short_models=('a94', 'a95'))>, 'a95': <RoborockProductNickname.ULTRONSC: ProductInfo(nickname='UltronSC', short_models=('a94', 'a95'))>, 'a124': <RoborockProductNickname.ULTRONSE: ProductInfo(nickname='UltronSE', short_models=('a124', 'a125', 'a139', 'a140'))>, 'a125': <RoborockProductNickname.ULTRONSE: ProductInfo(nickname='UltronSE', short_models=('a124', 'a125', 'a139', 'a140'))>, 'a139': <RoborockProductNickname.ULTRONSE: ProductInfo(nickname='UltronSE', short_models=('a124', 'a125', 'a139', 'a140'))>, 'a140': <RoborockProductNickname.ULTRONSE: ProductInfo(nickname='UltronSE', short_models=('a124', 'a125', 'a139', 'a140'))>, 'a68': <RoborockProductNickname.ULTRONSPLUS: ProductInfo(nickname='UltronSPlus', short_models=('a68', 'a69', 'a70'))>, 'a69': <RoborockProductNickname.ULTRONSPLUS: ProductInfo(nickname='UltronSPlus', short_models=('a68', 'a69', 'a70'))>, 'a70': <RoborockProductNickname.ULTRONSPLUS: ProductInfo(nickname='UltronSPlus', short_models=('a68', 'a69', 'a70'))>, 'a96': <RoborockProductNickname.ULTRONSV: ProductInfo(nickname='UltronSV', short_models=('a96', 'a97'))>, 'a97': <RoborockProductNickname.ULTRONSV: ProductInfo(nickname='UltronSV', short_models=('a96', 'a97'))>, 'a146': <RoborockProductNickname.VERDELITE: ProductInfo(nickname='Verdelite', short_models=('a146', 'a147'))>, 'a147': <RoborockProductNickname.VERDELITE: ProductInfo(nickname='Verdelite', short_models=('a146', 'a147'))>, 'a134': <RoborockProductNickname.VIVIAN: ProductInfo(nickname='Vivian', short_models=('a134', 'a135', 'a155', 'a156'))>, 'a135': <RoborockProductNickname.VIVIAN: ProductInfo(nickname='Vivian', short_models=('a134', 'a135', 'a155', 'a156'))>, 'a155': <RoborockProductNickname.VIVIAN: ProductInfo(nickname='Vivian', short_models=('a134', 'a135', 'a155', 'a156'))>, 'a156': <RoborockProductNickname.VIVIAN: ProductInfo(nickname='Vivian', short_models=('a134', 'a135', 'a155', 'a156'))>, 'a158': <RoborockProductNickname.VIVIANC: ProductInfo(nickname='VivianC', short_models=('a158', 'a159'))>, 'a159': <RoborockProductNickname.VIVIANC: ProductInfo(nickname='VivianC', short_models=('a158', 'a159'))>}
class RoborockCategory(enum.Enum):
209class RoborockCategory(Enum):
210    """Describes the category of the device."""
211
212    WET_DRY_VAC = "roborock.wetdryvac"
213    VACUUM = "robot.vacuum.cleaner"
214    WASHING_MACHINE = "roborock.wm"
215    MOWER = "roborock.mower"
216    UNKNOWN = "UNKNOWN"
217
218    @classmethod
219    def _missing_(cls, value):
220        _LOGGER.warning("Missing code %s from category", value)
221        return RoborockCategory.UNKNOWN

Describes the category of the device.

WET_DRY_VAC = <RoborockCategory.WET_DRY_VAC: 'roborock.wetdryvac'>
VACUUM = <RoborockCategory.VACUUM: 'robot.vacuum.cleaner'>
WASHING_MACHINE = <RoborockCategory.WASHING_MACHINE: 'roborock.wm'>
MOWER = <RoborockCategory.MOWER: 'roborock.mower'>
UNKNOWN = <RoborockCategory.UNKNOWN: 'UNKNOWN'>