Skip to content

Commit 70ec12f

Browse files
committed
fix: Encode a01 values as json strings
Update the a01 internal values to be json strings inside the dictionary. This matches the old API behavior.
1 parent 4c4051e commit 70ec12f

File tree

2 files changed

+34
-9
lines changed

2 files changed

+34
-9
lines changed

roborock/protocols/a01_protocol.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@ def encode_mqtt_payload(
2626
| dict[RoborockDyadDataProtocol | RoborockZeoProtocol, Any],
2727
) -> RoborockMessage:
2828
"""Encode payload for A01 commands over MQTT."""
29-
dps_data = {"dps": data}
29+
# The A01 protocol generally expects values to be encoded as strings.
30+
# We use json.dumps for non-string types to ensure valid JSON formatting
31+
# (e.g. [1, 2] -> "[1, 2]", True -> "true", 123 -> "123").
32+
dps_data = {"dps": {key: json.dumps(value) for key, value in data.items()}}
3033
payload = pad(json.dumps(dps_data).encode("utf-8"), AES.block_size)
3134
return RoborockMessage(
3235
protocol=RoborockMessageProtocol.RPC_REQUEST,

tests/protocols/test_a01_protocol.py

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
from typing import Any
55

66
import pytest
7+
from Crypto.Cipher import AES
8+
from Crypto.Util.Padding import unpad
79

810
from roborock.exceptions import RoborockException
911
from roborock.protocols.a01_protocol import decode_rpc_response, encode_mqtt_payload
@@ -33,8 +35,9 @@ def test_encode_mqtt_payload_basic():
3335
assert len(result.payload) % 16 == 0 # Should be padded to AES block size
3436

3537
# Decode the payload to verify structure
38+
# With general stringification, numbers are converted to strings: 42 -> "42"
3639
decoded_data = decode_rpc_response(result)
37-
assert decoded_data == {200: {"test": "data", "number": 42}}
40+
assert decoded_data == {200: '{"test": "data", "number": 42}'}
3841

3942

4043
def test_encode_mqtt_payload_empty_data():
@@ -52,6 +55,21 @@ def test_encode_mqtt_payload_empty_data():
5255
assert decoded_data == {}
5356

5457

58+
def test_encode_mqtt_payload_list_conversion():
59+
"""Test that lists are converted to string representation (Fix validity)."""
60+
# This verifies the fix where lists must be encoded as strings
61+
data: dict[RoborockDyadDataProtocol | RoborockZeoProtocol, Any] = {RoborockDyadDataProtocol.ID_QUERY: [101, 102]}
62+
63+
result = encode_mqtt_payload(data)
64+
65+
# Decode manually to check the raw JSON structure
66+
decoded_json = json.loads(unpad(result.payload, AES.block_size).decode())
67+
68+
# ID_QUERY (10000) should be a string "[101, 102]", not a list [101, 102]
69+
assert decoded_json["dps"]["10000"] == "[101, 102]"
70+
assert isinstance(decoded_json["dps"]["10000"], str)
71+
72+
5573
def test_encode_mqtt_payload_complex_data():
5674
"""Test encoding with complex nested data."""
5775
data: dict[RoborockDyadDataProtocol | RoborockZeoProtocol, Any] = {
@@ -74,13 +92,17 @@ def test_encode_mqtt_payload_complex_data():
7492
# Decode the payload to verify structure
7593
decoded_data = decode_rpc_response(result)
7694
assert decoded_data == {
77-
201: {
78-
"nested": {"deep": {"value": 123}},
79-
"list": [1, 2, 3, "test"],
80-
"boolean": True,
81-
"null": None,
82-
},
83-
204: "simple_value",
95+
201: json.dumps(
96+
{
97+
"nested": {"deep": {"value": 123}},
98+
# Note: The list inside the dictionary is NOT converted because
99+
# our fix only targets top-level list values in the dps map
100+
"list": [1, 2, 3, "test"],
101+
"boolean": True,
102+
"null": None,
103+
}
104+
),
105+
204: '"simple_value"',
84106
}
85107

86108

0 commit comments

Comments
 (0)