Skip to content

Commit 8680692

Browse files
committed
chore: more debug logs and error handling
1 parent 80f9875 commit 8680692

File tree

2 files changed

+75
-5
lines changed

2 files changed

+75
-5
lines changed

roborock/devices/b01_channel.py

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,14 @@ async def send_decoded_command(
3333
3434
Note: B01 "set" commands may return a scalar (e.g. 0/"ok") rather than a dict.
3535
"""
36-
_LOGGER.debug("Sending MQTT command: %s", params)
3736
msg_id = str(get_next_int(100000000000, 999999999999))
37+
_LOGGER.debug(
38+
"Sending B01 MQTT command: dps=%s method=%s msg_id=%s params=%s",
39+
dps,
40+
command,
41+
msg_id,
42+
params,
43+
)
3844
roborock_message = encode_mqtt_payload(dps, command, params, msg_id)
3945
future: asyncio.Future[Any] = asyncio.get_running_loop().create_future()
4046

@@ -43,7 +49,13 @@ def find_response(response_message: RoborockMessage) -> None:
4349
try:
4450
decoded_dps = decode_rpc_response(response_message)
4551
except RoborockException as ex:
46-
_LOGGER.info("Failed to decode b01 message: %s: %s", response_message, ex)
52+
_LOGGER.debug(
53+
"Failed to decode B01 RPC response (expecting method=%s msg_id=%s): %s: %s",
54+
command,
55+
msg_id,
56+
response_message,
57+
ex,
58+
)
4759
return
4860

4961
for dps_value in decoded_dps.values():
@@ -60,11 +72,27 @@ def find_response(response_message: RoborockMessage) -> None:
6072

6173
if isinstance(inner, dict) and inner.get("msgId") == msg_id:
6274
_LOGGER.debug("Received query response: %s", inner)
75+
# Check for error code (0 = success, non-zero = error)
76+
code = inner.get("code", 0)
77+
if code != 0:
78+
error_msg = (
79+
f"B01 command failed with code {code} "
80+
f"(method={command}, msg_id={msg_id}, dps={dps}, params={params})"
81+
)
82+
_LOGGER.debug("B01 error response: %s", error_msg)
83+
if not future.done():
84+
future.set_exception(RoborockException(error_msg))
85+
return
6386
data = inner.get("data")
6487
# All get commands should be dicts
6588
if command.endswith(".get") and not isinstance(data, dict):
6689
if not future.done():
67-
future.set_exception(RoborockException("Unexpected data type for response"))
90+
future.set_exception(
91+
RoborockException(
92+
f"Unexpected data type for response "
93+
f"(method={command}, msg_id={msg_id}, dps={dps}, params={params})"
94+
)
95+
)
6896
return
6997
if not future.done():
7098
future.set_result(data)
@@ -76,9 +104,18 @@ def find_response(response_message: RoborockMessage) -> None:
76104
await mqtt_channel.publish(roborock_message)
77105
return await asyncio.wait_for(future, timeout=_TIMEOUT)
78106
except TimeoutError as ex:
79-
raise RoborockException(f"Command timed out after {_TIMEOUT}s") from ex
107+
raise RoborockException(
108+
f"B01 command timed out after {_TIMEOUT}s (method={command}, msg_id={msg_id}, dps={dps}, params={params})"
109+
) from ex
80110
except Exception as ex:
81-
_LOGGER.exception("Error sending decoded command: %s", ex)
111+
_LOGGER.exception(
112+
"Error sending B01 decoded command (method=%s msg_id=%s dps=%s params=%s): %s",
113+
command,
114+
msg_id,
115+
dps,
116+
params,
117+
ex,
118+
)
82119
raise
83120
finally:
84121
unsub()

tests/devices/traits/b01/test_init.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,39 @@ async def test_send_decoded_command_non_dict_response(fake_channel: FakeChannel)
172172
await send_decoded_command(fake_channel, 10000, "prop.get", []) # type: ignore[arg-type]
173173

174174

175+
async def test_send_decoded_command_error_code(fake_channel: FakeChannel):
176+
"""Test that non-zero error codes from device are properly handled."""
177+
msg_id = "999888777"
178+
error_code = 5001
179+
180+
dps_payload = {
181+
"dps": {
182+
"10000": json.dumps(
183+
{
184+
"msgId": msg_id,
185+
"code": error_code,
186+
"data": {},
187+
}
188+
)
189+
}
190+
}
191+
message = RoborockMessage(
192+
protocol=RoborockMessageProtocol.RPC_RESPONSE,
193+
payload=pad(
194+
json.dumps(dps_payload).encode(),
195+
AES.block_size,
196+
),
197+
version=b"B01",
198+
seq=2022,
199+
)
200+
201+
fake_channel.response_queue.append(message)
202+
203+
with patch("roborock.devices.b01_channel.get_next_int", return_value=int(msg_id)):
204+
with pytest.raises(RoborockException, match=f"B01 command failed with code {error_code}"):
205+
await send_decoded_command(fake_channel, 10000, "prop.get", []) # type: ignore[arg-type]
206+
207+
175208
async def test_q7_api_set_fan_speed(q7_api: Q7PropertiesApi, fake_channel: FakeChannel):
176209
"""Test setting fan speed."""
177210
msg_id = "12345"

0 commit comments

Comments
 (0)