@@ -92,22 +92,21 @@ async def request(
92
92
93
93
class RoborockClient :
94
94
95
- def __init__ (self , endpoint : str , device_localkey : dict [str , str ], prefixed = False ) -> None :
95
+ def __init__ (self , endpoint : str , device_localkey : dict [str , str ]) -> None :
96
96
self .device_localkey = device_localkey
97
97
self ._seq = 1
98
98
self ._random = 4711
99
99
self ._id_counter = 10000
100
100
self ._salt = "TXdfu$jyZ#TZHsg4"
101
- self ._endpoint = base64 . b64encode ( md5bin ( endpoint )[ 8 : 14 ]). decode ()
101
+ self ._endpoint = endpoint
102
102
self ._nonce = secrets .token_bytes (16 )
103
- self ._prefixed = prefixed
104
103
self ._waiting_queue : dict [int , RoborockQueue ] = {}
105
104
self ._status_listeners : list [Callable [[str , str ], None ]] = []
106
105
107
106
def _decode_msg (self , msg : bytes , local_key : str ) -> dict [str , Any ]:
108
- if self . _prefixed :
107
+ if msg [ 4 : 7 ] == "1.0" . encode () :
109
108
msg = msg [4 :]
110
- if msg [0 :3 ] != "1.0" .encode ():
109
+ elif msg [0 :3 ] != "1.0" .encode ():
111
110
raise RoborockException (f"Unknown protocol version { msg [0 :3 ]} " )
112
111
if len (msg ) == 17 :
113
112
[version , _seq , _random , timestamp , protocol ] = struct .unpack (
@@ -118,31 +117,27 @@ def _decode_msg(self, msg: bytes, local_key: str) -> dict[str, Any]:
118
117
"timestamp" : timestamp ,
119
118
"protocol" : protocol ,
120
119
}
121
- # crc32 = binascii.crc32(msg[0: len(msg) - 4])
122
120
[version , _seq , _random , timestamp , protocol , payload_len ] = struct .unpack (
123
121
"!3sIIIHH" , msg [0 :19 ]
124
122
)
125
- if not payload_len :
126
- return {
127
- "version" : version ,
128
- "timestamp" : timestamp ,
129
- "protocol" : protocol ,
130
- }
131
- [payload , expected_crc32 ] = struct .unpack_from (f"!{ payload_len } sI" , msg , 19 )
132
- # if crc32 != expected_crc32:
133
- # raise RoborockException(f"Wrong CRC32 {crc32}, expected {expected_crc32}")
123
+ extra_len = len (msg ) - 23 - payload_len
124
+ [payload , expected_crc32 , extra ] = struct .unpack_from (f"!{ payload_len } sI{ extra_len } s" , msg , 19 )
125
+ if not extra_len :
126
+ crc32 = binascii .crc32 (msg [0 : 19 + payload_len ])
127
+ if crc32 != expected_crc32 :
128
+ raise RoborockException (f"Wrong CRC32 { crc32 } , expected { expected_crc32 } " )
134
129
135
130
aes_key = md5bin (encode_timestamp (timestamp ) + local_key + self ._salt )
136
131
decipher = AES .new (aes_key , AES .MODE_ECB )
137
- decrypted_payload = unpad (decipher .decrypt (payload ), AES .block_size )
132
+ decrypted_payload = unpad (decipher .decrypt (payload ), AES .block_size ) if payload else extra
138
133
return {
139
134
"version" : version ,
140
135
"timestamp" : timestamp ,
141
136
"protocol" : protocol ,
142
- "payload" : decrypted_payload ,
137
+ "payload" : decrypted_payload
143
138
}
144
139
145
- def _encode_msg (self , device_id , protocol , timestamp , payload , prefix = '' ) -> bytes :
140
+ def _encode_msg (self , device_id , protocol , timestamp , payload , prefix = None ) -> bytes :
146
141
local_key = self .device_localkey [device_id ]
147
142
aes_key = md5bin (encode_timestamp (timestamp ) + local_key + self ._salt )
148
143
cipher = AES .new (aes_key , AES .MODE_ECB )
@@ -157,13 +152,13 @@ def _encode_msg(self, device_id, protocol, timestamp, payload, prefix='') -> byt
157
152
encrypted_len ,
158
153
encrypted
159
154
]
160
- if self . _prefixed :
155
+ if prefix :
161
156
values = [prefix ] + values
162
157
msg = struct .pack (
163
- f"!{ 'I' if self . _prefixed else '' } 3sIIIHH{ encrypted_len } s" ,
158
+ f"!{ 'I' if prefix else '' } 3sIIIHH{ encrypted_len } s" ,
164
159
* values
165
160
)
166
- crc32 = binascii .crc32 (msg [4 :] if self . _prefixed else msg )
161
+ crc32 = binascii .crc32 (msg [4 :] if prefix else msg )
167
162
msg += struct .pack ("!I" , crc32 )
168
163
return msg
169
164
@@ -258,7 +253,7 @@ def _get_payload(
258
253
if secured :
259
254
inner ["security" ] = {
260
255
"endpoint" : self ._endpoint ,
261
- "nonce" : "39344139463753454b4851444f4a4442" ,
256
+ "nonce" : self . _nonce . hex (). upper () ,
262
257
}
263
258
payload = bytes (
264
259
json .dumps (
0 commit comments