66from dataclasses import dataclass
77from enum import IntEnum , auto
88import functools
9+ import json
910from typing import TYPE_CHECKING , Any , TypeVar , final
1011
12+ from deebot_client .events import FirmwareEvent
1113from deebot_client .util import verify_required_class_variables_exists
1214
1315from .logging_filter import get_logger
1921
2022_LOGGER = get_logger (__name__ )
2123
24+ MessagePayloadType = str | bytes | bytearray | dict [str , Any ]
25+
2226
2327class HandlingState (IntEnum ):
2428 """Handling state enum."""
@@ -63,6 +67,15 @@ def wrapper(
6367 ) -> HandlingResult :
6468 try :
6569 response = func (cls , event_bus , data )
70+ # This happens if for some reason someone calls super() of an ABC where handle is not implemented
71+ if not response :
72+ _LOGGER .error (
73+ "Handler for message %s: %s returned no response. "
74+ "This is a bug should not happen. Please report it." ,
75+ cls .NAME ,
76+ data ,
77+ )
78+ return HandlingResult (HandlingState .ERROR )
6679 if response .state == HandlingState .ANALYSE :
6780 _LOGGER .debug ("Could not handle %s message: %s" , cls .NAME , data )
6881 return HandlingResult (HandlingState .ANALYSE_LOGGED , response .args )
@@ -88,7 +101,7 @@ def __init_subclass__(cls) -> None:
88101 @classmethod
89102 @abstractmethod
90103 def _handle (
91- cls , event_bus : EventBus , message : dict [ str , Any ] | str
104+ cls , event_bus : EventBus , message : MessagePayloadType
92105 ) -> HandlingResult :
93106 """Handle message and notify the correct event subscribers.
94107
@@ -98,9 +111,7 @@ def _handle(
98111 @classmethod
99112 @_handle_error_or_analyse
100113 @final
101- def handle (
102- cls , event_bus : EventBus , message : dict [str , Any ] | str
103- ) -> HandlingResult :
114+ def handle (cls , event_bus : EventBus , message : MessagePayloadType ) -> HandlingResult :
104115 """Handle message and notify the correct event subscribers.
105116
106117 :return: A message response
@@ -120,28 +131,33 @@ def _handle_str(cls, event_bus: EventBus, message: str) -> HandlingResult:
120131 """
121132
122133 @classmethod
123- # @_handle_error_or_analyse @edenhaus will make the decorator to work again
134+ @_handle_error_or_analyse
124135 @final
125136 def __handle_str (cls , event_bus : EventBus , message : str ) -> HandlingResult :
126137 return cls ._handle_str (event_bus , message )
127138
128139 @classmethod
129140 def _handle (
130- cls , event_bus : EventBus , message : dict [ str , Any ] | str
141+ cls , event_bus : EventBus , message : MessagePayloadType
131142 ) -> HandlingResult :
132143 """Handle message and notify the correct event subscribers.
133144
134145 :return: A message response
135146 """
136- # This basically means an XML message
137- if isinstance (message , str ):
138- return cls .__handle_str (event_bus , message )
147+ if isinstance (message , bytearray ):
148+ data = bytes (message ).decode ()
149+ elif isinstance (message , bytes ):
150+ data = message .decode ()
151+ elif isinstance (message , str ):
152+ data = message
153+ else :
154+ return super ()._handle (event_bus , message )
139155
140- return super (). _handle (event_bus , message )
156+ return cls . __handle_str (event_bus , data )
141157
142158
143- class MessageDict (Message , ABC ):
144- """Dict message."""
159+ class MessageDictOrJson (Message , ABC ):
160+ """Dict or json message."""
145161
146162 @classmethod
147163 @abstractmethod
@@ -163,19 +179,34 @@ def __handle_dict(
163179
164180 @classmethod
165181 def _handle (
166- cls , event_bus : EventBus , message : dict [ str , Any ] | str
182+ cls , event_bus : EventBus , message : MessagePayloadType
167183 ) -> HandlingResult :
168184 """Handle message and notify the correct event subscribers.
169185
170186 :return: A message response
171187 """
172- if isinstance (message , dict ):
173- return cls .__handle_dict (event_bus , message )
188+ data = message
189+ if not isinstance (message , dict ):
190+ try :
191+ data = json .loads (message )
192+ except Exception : # pylint: disable=broad-except
193+ _LOGGER .debug (
194+ "Could not decode message %s payload %s as JSON" ,
195+ cls .NAME ,
196+ message ,
197+ )
198+
199+ if isinstance (data , dict ):
200+ fw_version = data .get ("header" , {}).get ("fwVer" , None )
201+ if fw_version :
202+ event_bus .notify (FirmwareEvent (fw_version ))
203+
204+ return cls .__handle_dict (event_bus , data )
174205
175206 return super ()._handle (event_bus , message )
176207
177208
178- class MessageBody (MessageDict , ABC ):
209+ class MessageBody (MessageDictOrJson , ABC ):
179210 """Dict message with body attribute."""
180211
181212 @classmethod
0 commit comments