Skip to content

Commit 4f85240

Browse files
committed
feat: add data subpackage
BREAKING CHANGE: you can no longer import .container or .code_mappings, instead import .data
1 parent a1dbf6c commit 4f85240

File tree

4 files changed

+768
-1017
lines changed

4 files changed

+768
-1017
lines changed

roborock/data/code_mappings.py

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
from __future__ import annotations
2+
3+
import logging
4+
from collections import namedtuple
5+
from enum import Enum, IntEnum, StrEnum
6+
7+
_LOGGER = logging.getLogger(__name__)
8+
completed_warnings = set()
9+
10+
11+
class 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[RoborockEnum], key) -> RoborockEnum:
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[RoborockEnum]):
35+
return {i.name: i.value for i in cls if i.name != "missing"}
36+
37+
@classmethod
38+
def as_enum_dict(cls: type[RoborockEnum]):
39+
return {i.value: i for i in cls if i.name != "missing"}
40+
41+
@classmethod
42+
def values(cls: type[RoborockEnum]) -> list[int]:
43+
return list(cls.as_dict().values())
44+
45+
@classmethod
46+
def keys(cls: type[RoborockEnum]) -> list[str]:
47+
return list(cls.as_dict().keys())
48+
49+
@classmethod
50+
def items(cls: type[RoborockEnum]):
51+
return cls.as_dict().items()
52+
53+
54+
class RoborockModeEnum(StrEnum):
55+
"""A custom StrEnum that also stores an integer code for each member."""
56+
57+
code: int
58+
59+
def __new__(cls, value: str, code: int) -> RoborockModeEnum:
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):
68+
for member in cls:
69+
if member.code == code:
70+
return member
71+
raise ValueError(f"{code} is not a valid code for {cls.__name__}")
72+
73+
74+
ProductInfo = namedtuple("ProductInfo", ["nickname", "short_models"])
75+
76+
77+
class RoborockProductNickname(Enum):
78+
# Coral Series
79+
CORAL = ProductInfo(nickname="Coral", short_models=("a20", "a21"))
80+
CORALPRO = ProductInfo(nickname="CoralPro", short_models=("a143", "a144"))
81+
82+
# Pearl Series
83+
PEARL = ProductInfo(nickname="Pearl", short_models=("a74", "a75"))
84+
PEARLC = ProductInfo(nickname="PearlC", short_models=("a103", "a104"))
85+
PEARLE = ProductInfo(nickname="PearlE", short_models=("a167", "a168"))
86+
PEARLELITE = ProductInfo(nickname="PearlELite", short_models=("a169", "a170"))
87+
PEARLPLUS = ProductInfo(nickname="PearlPlus", short_models=("a86", "a87"))
88+
PEARLPLUSS = ProductInfo(nickname="PearlPlusS", short_models=("a116", "a117", "a136"))
89+
PEARLS = ProductInfo(nickname="PearlS", short_models=("a100", "a101"))
90+
PEARLSLITE = ProductInfo(nickname="PearlSLite", short_models=("a122", "a123"))
91+
92+
# Ruby Series
93+
RUBYPLUS = ProductInfo(nickname="RubyPlus", short_models=("t4", "s4"))
94+
RUBYSC = ProductInfo(nickname="RubySC", short_models=("p5", "a08"))
95+
RUBYSE = ProductInfo(nickname="RubySE", short_models=("a19",))
96+
RUBYSLITE = ProductInfo(nickname="RubySLite", short_models=("p6", "s5e", "a05"))
97+
98+
# Tanos Series
99+
TANOS = ProductInfo(nickname="Tanos", short_models=("t6", "s6"))
100+
TANOSE = ProductInfo(nickname="TanosE", short_models=("t7", "a11"))
101+
TANOSS = ProductInfo(nickname="TanosS", short_models=("a14", "a15"))
102+
TANOSSC = ProductInfo(nickname="TanosSC", short_models=("a39", "a40"))
103+
TANOSSE = ProductInfo(nickname="TanosSE", short_models=("a33", "a34"))
104+
TANOSSMAX = ProductInfo(nickname="TanosSMax", short_models=("a52",))
105+
TANOSSLITE = ProductInfo(nickname="TanosSLite", short_models=("a37", "a38"))
106+
TANOSSPLUS = ProductInfo(nickname="TanosSPlus", short_models=("a23", "a24"))
107+
TANOSV = ProductInfo(nickname="TanosV", short_models=("t7p", "a09", "a10"))
108+
109+
# Topaz Series
110+
TOPAZS = ProductInfo(nickname="TopazS", short_models=("a29", "a30", "a76"))
111+
TOPAZSC = ProductInfo(nickname="TopazSC", short_models=("a64", "a65"))
112+
TOPAZSPLUS = ProductInfo(nickname="TopazSPlus", short_models=("a46", "a47", "a66"))
113+
TOPAZSPOWER = ProductInfo(nickname="TopazSPower", short_models=("a62",))
114+
TOPAZSV = ProductInfo(nickname="TopazSV", short_models=("a26", "a27"))
115+
116+
# Ultron Series
117+
ULTRON = ProductInfo(nickname="Ultron", short_models=("a50", "a51"))
118+
ULTRONE = ProductInfo(nickname="UltronE", short_models=("a72", "a84"))
119+
ULTRONLITE = ProductInfo(nickname="UltronLite", short_models=("a73", "a85"))
120+
ULTRONSC = ProductInfo(nickname="UltronSC", short_models=("a94", "a95"))
121+
ULTRONSE = ProductInfo(nickname="UltronSE", short_models=("a124", "a125", "a139", "a140"))
122+
ULTRONSPLUS = ProductInfo(nickname="UltronSPlus", short_models=("a68", "a69", "a70"))
123+
ULTRONSV = ProductInfo(nickname="UltronSV", short_models=("a96", "a97"))
124+
125+
# Verdelite Series
126+
VERDELITE = ProductInfo(nickname="Verdelite", short_models=("a146", "a147"))
127+
128+
# Vivian Series
129+
VIVIAN = ProductInfo(nickname="Vivian", short_models=("a134", "a135", "a155", "a156"))
130+
VIVIANC = ProductInfo(nickname="VivianC", short_models=("a158", "a159"))
131+
132+
133+
SHORT_MODEL_TO_ENUM = {model: product for product in RoborockProductNickname for model in product.value.short_models}
134+
135+
136+
class RoborockCategory(Enum):
137+
"""Describes the category of the device."""
138+
139+
WET_DRY_VAC = "roborock.wetdryvac"
140+
VACUUM = "robot.vacuum.cleaner"
141+
WASHING_MACHINE = "roborock.wm"
142+
UNKNOWN = "UNKNOWN"
143+
144+
def __missing__(self, key):
145+
_LOGGER.warning("Missing key %s from category", key)
146+
return RoborockCategory.UNKNOWN

0 commit comments

Comments
 (0)