77from dataclasses import asdict , dataclass , field
88from datetime import timezone
99from enum import Enum
10- from typing import Any , NamedTuple
11-
12- from dacite import Config , from_dict
10+ from typing import Any , NamedTuple , get_args , get_origin
1311
1412from .code_mappings import (
1513 RoborockCategory ,
@@ -102,14 +100,70 @@ class RoborockBase:
102100 _ignore_keys = [] # type: ignore
103101 is_cached = False
104102
103+ @staticmethod
104+ def convert_to_class_obj (type , value ):
105+ try :
106+ class_type = eval (type )
107+ if get_origin (class_type ) is list :
108+ return_list = []
109+ cls_type = get_args (class_type )[0 ]
110+ for obj in value :
111+ if issubclass (cls_type , RoborockBase ):
112+ return_list .append (cls_type .from_dict (obj ))
113+ elif cls_type in {str , int , float }:
114+ return_list .append (cls_type (obj ))
115+ else :
116+ return_list .append (cls_type (** obj ))
117+ return return_list
118+ if issubclass (class_type , RoborockBase ):
119+ converted_value = class_type .from_dict (value )
120+ else :
121+ converted_value = class_type (value )
122+ return converted_value
123+ except NameError as err :
124+ _LOGGER .exception (err )
125+ except ValueError as err :
126+ _LOGGER .exception (err )
127+ except Exception as err :
128+ _LOGGER .exception (err )
129+ raise Exception ("Fail" )
130+
105131 @classmethod
106132 def from_dict (cls , data : dict [str , Any ]):
107133 if isinstance (data , dict ):
108134 ignore_keys = cls ._ignore_keys
109- try :
110- return from_dict (cls , decamelize_obj (data , ignore_keys ), config = Config (cast = [Enum ]))
111- except AttributeError as err :
112- raise RoborockException ("It seems like you have an outdated version of dacite." ) from err
135+ data = decamelize_obj (data , ignore_keys )
136+ cls_annotations : dict [str , str ] = {}
137+ for base in reversed (cls .__mro__ ):
138+ cls_annotations .update (getattr (base , "__annotations__" , {}))
139+ remove_keys = []
140+ for key , value in data .items ():
141+ if value == "None" or value is None :
142+ data [key ] = None
143+ continue
144+ if key not in cls_annotations :
145+ remove_keys .append (key )
146+ continue
147+ field_type : str = cls_annotations [key ]
148+ if "|" in field_type :
149+ # It's a union
150+ types = field_type .split ("|" )
151+ for type in types :
152+ if "None" in type or "Any" in type :
153+ continue
154+ try :
155+ data [key ] = RoborockBase .convert_to_class_obj (type , value )
156+ break
157+ except Exception :
158+ ...
159+ else :
160+ try :
161+ data [key ] = RoborockBase .convert_to_class_obj (field_type , value )
162+ except Exception :
163+ ...
164+ for key in remove_keys :
165+ del data [key ]
166+ return cls (** data )
113167
114168 def as_dict (self ) -> dict :
115169 return asdict (
@@ -185,6 +239,7 @@ class HomeDataProductSchema(RoborockBase):
185239 mode : Any | None = None
186240 type : Any | None = None
187241 product_property : Any | None = None
242+ property : Any | None = None
188243 desc : Any | None = None
189244
190245
@@ -195,7 +250,7 @@ class HomeDataProduct(RoborockBase):
195250 model : str
196251 category : RoborockCategory
197252 code : str | None = None
198- iconurl : str | None = None
253+ icon_url : str | None = None
199254 attribute : Any | None = None
200255 capability : int | None = None
201256 schema : list [HomeDataProductSchema ] | None = None
0 commit comments