@@ -105,9 +105,18 @@ class ResponseMessage:
105105 data : dict [str , Any ]
106106 """The data of the response."""
107107
108+ api_error : RoborockException | None = None
109+ """The API error message of the response if any."""
110+
108111
109112def decode_rpc_response (message : RoborockMessage ) -> ResponseMessage :
110- """Decode a V1 RPC_RESPONSE message."""
113+ """Decode a V1 RPC_RESPONSE message.
114+
115+ This will raise a RoborockException if the message cannot be parsed. A
116+ response object will be returned even if there is an error in the
117+ response, as long as we can extract the request ID. This is so we can
118+ associate an API response with a request even if there was an error.
119+ """
111120 if not message .payload :
112121 return ResponseMessage (request_id = message .seq , data = {})
113122 try :
@@ -133,19 +142,28 @@ def decode_rpc_response(message: RoborockMessage) -> ResponseMessage:
133142 ) from e
134143
135144 request_id : int | None = data_point_response .get ("id" )
145+ exc : RoborockException | None = None
136146 if error := data_point_response .get ("error" ):
137- raise RoborockException (f"Error in message: { error } " )
138-
147+ exc = RoborockException (error )
139148 if not (result := data_point_response .get ("result" )):
140- raise RoborockException (f"Invalid V1 message format: missing 'result' in data point for { message .payload !r} " )
141- _LOGGER .debug ("Decoded V1 message result: %s" , result )
142- if isinstance (result , list ) and result :
143- result = result [0 ]
144- if isinstance (result , str ) and result == "ok" :
145- result = {}
146- if not isinstance (result , dict ):
147- raise RoborockException (f"Invalid V1 message format: 'result' should be a dictionary for { message .payload !r} " )
148- return ResponseMessage (request_id = request_id , data = result )
149+ exc = RoborockException (f"Invalid V1 message format: missing 'result' in data point for { message .payload !r} " )
150+ else :
151+ _LOGGER .debug ("Decoded V1 message result: %s" , result )
152+ if isinstance (result , list ) and result :
153+ result = result [0 ]
154+ if isinstance (result , str ):
155+ if result == "unknown_method" :
156+ exc = RoborockException ("The method called is not recognized by the device." )
157+ elif result != "ok" :
158+ exc = RoborockException (f"Unexpected API Result: { result } " )
159+ result = {}
160+ if not isinstance (result , (dict , list , int )):
161+ exc = RoborockException (
162+ f"Invalid V1 message format: 'result' should be a dictionary for { message .payload !r} "
163+ )
164+ if not request_id and exc :
165+ raise exc
166+ return ResponseMessage (request_id = request_id , data = result , api_error = exc )
149167
150168
151169@dataclass
0 commit comments