@@ -116,14 +116,45 @@ class ProductFeatures(StrEnum):
116
116
NEW_DEFAULT_FEATURES = [ProductFeatures .REMOTE_BACK , ProductFeatures .CLEANMODE_MAXPLUS ]
117
117
118
118
119
- PEARL_FEATURES = NEW_DEFAULT_FEATURES + SINGLE_LINE_CAMERA_FEATURES + [ProductFeatures .MOP_SPIN_MODULE ]
119
+ PEARL_FEATURES = SINGLE_LINE_CAMERA_FEATURES + [ProductFeatures . CLEANMODE_MAXPLUS , ProductFeatures .MOP_SPIN_MODULE ]
120
120
PEARL_PLUS_FEATURES = NEW_DEFAULT_FEATURES + RGB_CAMERA_FEATURES + [ProductFeatures .MOP_SPIN_MODULE ]
121
121
ULTRON_FEATURES = NEW_DEFAULT_FEATURES + DUAL_LINE_CAMERA_FEATURES + [ProductFeatures .MOP_SHAKE_MODULE ]
122
122
ULTRONSV_FEATURES = NEW_DEFAULT_FEATURES + RGB_CAMERA_FEATURES + [ProductFeatures .MOP_SHAKE_MODULE ]
123
- TANOSS_FEATURES = NEW_DEFAULT_FEATURES + [ ProductFeatures .MOP_SHAKE_MODULE ]
124
- TOPAZSPOWER_FEATURES = NEW_DEFAULT_FEATURES + [ ProductFeatures .MOP_SHAKE_MODULE ]
123
+ TANOSS_FEATURES = [ ProductFeatures . REMOTE_BACK , ProductFeatures .MOP_SHAKE_MODULE ]
124
+ TOPAZSPOWER_FEATURES = [ ProductFeatures . CLEANMODE_MAXPLUS , ProductFeatures .MOP_SHAKE_MODULE ]
125
125
126
- product_feature_map = {
126
+ PRODUCTS_WITHOUT_CUSTOM_CLEAN : set [RoborockProductNickname ] = {
127
+ RoborockProductNickname .TANOS ,
128
+ RoborockProductNickname .RUBYPLUS ,
129
+ RoborockProductNickname .RUBYSC ,
130
+ RoborockProductNickname .RUBYSE ,
131
+ }
132
+ PRODUCTS_WITHOUT_DEFAULT_3D_MAP : set [RoborockProductNickname ] = {
133
+ RoborockProductNickname .TANOS ,
134
+ RoborockProductNickname .TANOSSPLUS ,
135
+ RoborockProductNickname .TANOSE ,
136
+ RoborockProductNickname .TANOSV ,
137
+ RoborockProductNickname .RUBYPLUS ,
138
+ RoborockProductNickname .RUBYSC ,
139
+ RoborockProductNickname .RUBYSE ,
140
+ }
141
+ PRODUCTS_WITHOUT_PURE_CLEAN_MOP : set [RoborockProductNickname ] = {
142
+ RoborockProductNickname .TANOS ,
143
+ RoborockProductNickname .TANOSE ,
144
+ RoborockProductNickname .TANOSV ,
145
+ RoborockProductNickname .TANOSSLITE ,
146
+ RoborockProductNickname .TANOSSE ,
147
+ RoborockProductNickname .TANOSSC ,
148
+ RoborockProductNickname .ULTRONLITE ,
149
+ RoborockProductNickname .ULTRONE ,
150
+ RoborockProductNickname .RUBYPLUS ,
151
+ RoborockProductNickname .RUBYSLITE ,
152
+ RoborockProductNickname .RUBYSC ,
153
+ RoborockProductNickname .RUBYSE ,
154
+ }
155
+
156
+ # Base map containing the initial, unconditional features for each product.
157
+ _BASE_PRODUCT_FEATURE_MAP : dict [RoborockProductNickname , list [ProductFeatures ]] = {
127
158
RoborockProductNickname .PEARL : PEARL_FEATURES ,
128
159
RoborockProductNickname .PEARLS : PEARL_FEATURES ,
129
160
RoborockProductNickname .PEARLPLUS : PEARL_PLUS_FEATURES ,
@@ -139,7 +170,8 @@ class ProductFeatures(StrEnum):
139
170
RoborockProductNickname .PEARLSLITE : PEARL_FEATURES ,
140
171
RoborockProductNickname .PEARLE : PEARL_FEATURES ,
141
172
RoborockProductNickname .PEARLELITE : PEARL_FEATURES ,
142
- RoborockProductNickname .VIVIANC : PEARL_PLUS_FEATURES ,
173
+ RoborockProductNickname .VIVIANC : [ProductFeatures .CLEANMODE_MAXPLUS , ProductFeatures .MOP_SPIN_MODULE ]
174
+ + SINGLE_LINE_CAMERA_FEATURES ,
143
175
RoborockProductNickname .CORALPRO : PEARL_PLUS_FEATURES ,
144
176
RoborockProductNickname .ULTRONLITE : SINGLE_LINE_CAMERA_FEATURES
145
177
+ [ProductFeatures .CLEANMODE_NONE_PURECLEANMOP_WITH_MAXPLUS , ProductFeatures .MOP_ELECTRONIC_MODULE ],
@@ -150,7 +182,7 @@ class ProductFeatures(StrEnum):
150
182
],
151
183
RoborockProductNickname .ULTRONSPLUS : ULTRON_FEATURES ,
152
184
RoborockProductNickname .VERDELITE : ULTRONSV_FEATURES ,
153
- RoborockProductNickname .TOPAZS : NEW_DEFAULT_FEATURES + [ ProductFeatures .MOP_SHAKE_MODULE ],
185
+ RoborockProductNickname .TOPAZS : [ ProductFeatures . REMOTE_BACK , ProductFeatures .MOP_SHAKE_MODULE ],
154
186
RoborockProductNickname .TOPAZSPLUS : NEW_DEFAULT_FEATURES
155
187
+ DUAL_LINE_CAMERA_FEATURES
156
188
+ [ProductFeatures .MOP_SHAKE_MODULE ],
@@ -173,6 +205,16 @@ class ProductFeatures(StrEnum):
173
205
RoborockProductNickname .RUBYSLITE : [ProductFeatures .MOP_ELECTRONIC_MODULE ],
174
206
}
175
207
208
+ PRODUCT_FEATURE_MAP : dict [RoborockProductNickname , list [ProductFeatures ]] = {
209
+ product : (
210
+ features
211
+ + ([ProductFeatures .DEFAULT_CLEANMODECUSTOM ] if product not in PRODUCTS_WITHOUT_CUSTOM_CLEAN else [])
212
+ + ([ProductFeatures .DEFAULT_MAP3D ] if product not in PRODUCTS_WITHOUT_DEFAULT_3D_MAP else [])
213
+ + ([ProductFeatures .CLEANMODE_PURECLEANMOP ] if product not in PRODUCTS_WITHOUT_PURE_CLEAN_MOP else [])
214
+ )
215
+ for product , features in _BASE_PRODUCT_FEATURE_MAP .items ()
216
+ }
217
+
176
218
177
219
@dataclass
178
220
class DeviceFeatures :
@@ -424,6 +466,9 @@ class DeviceFeatures:
424
466
metadata = {"product_features" : [ProductFeatures .MOP_SHAKE_MODULE , ProductFeatures .MOP_SPIN_MODULE ]}
425
467
)
426
468
is_mop_shake_module_supported : bool = field (metadata = {"product_features" : [ProductFeatures .MOP_SHAKE_MODULE ]})
469
+ is_customized_clean_supported : bool = field (
470
+ metadata = {"product_features" : [ProductFeatures .MOP_SHAKE_MODULE , ProductFeatures .MOP_SPIN_MODULE ]}
471
+ )
427
472
428
473
@classmethod
429
474
def from_feature_flags (
@@ -493,7 +538,7 @@ def from_feature_flags(
493
538
kwargs [f .name ] = product_nickname not in blacklist
494
539
elif (product_features := f .metadata .get ("product_features" )) is not None :
495
540
if product_nickname is not None :
496
- available_features = product_feature_map .get (product_nickname , [])
541
+ available_features = PRODUCT_FEATURE_MAP .get (product_nickname , [])
497
542
if any (feat in available_features for feat in product_features ): # type: ignore
498
543
kwargs [f .name ] = True
499
544
0 commit comments