Skip to content

Commit a92b40f

Browse files
authored
0.11.0 Release
2 parents 03c0093 + 96e909d commit a92b40f

File tree

3 files changed

+60
-17
lines changed

3 files changed

+60
-17
lines changed

tests/test_api.py

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""Test api module."""
22

33
import asyncio
4+
import binascii
45
import logging
56

67
import pytest
@@ -18,12 +19,18 @@
1819

1920

2021
@pytest.fixture
21-
def api(event_loop):
22+
def uart_gw():
23+
gw = MagicMock(auto_spec=uart.Gateway(MagicMock()))
24+
return gw
25+
26+
27+
@pytest.fixture
28+
def api(event_loop, uart_gw):
2229
controller = MagicMock(
2330
spec_set=zigpy_deconz.zigbee.application.ControllerApplication
2431
)
2532
api = deconz_api.Deconz(controller, {zigpy.config.CONF_DEVICE_PATH: "/dev/null"})
26-
api._uart = MagicMock()
33+
api._uart = uart_gw
2734
return api
2835

2936

@@ -192,18 +199,18 @@ def test_data_received_unk_status(api, monkeypatch):
192199
my_handler = MagicMock()
193200

194201
for cmd, cmd_opts in deconz_api.RX_COMMANDS.items():
195-
_, unsolicited = cmd_opts
202+
_, solicited = cmd_opts
196203
payload = b"\x01\x02\x03\x04"
197204
status = t.uint8_t(0xFE).serialize()
198205
data = cmd.serialize() + b"\x00" + status + b"\x00\x00" + payload
199206
setattr(api, "_handle_{}".format(cmd.name), my_handler)
200207
api._awaiting[0] = MagicMock()
201208
api.data_received(data)
202-
assert t.deserialize.call_count == 1
203-
assert t.deserialize.call_args[0][0] == payload
204-
if unsolicited:
209+
if solicited:
205210
assert my_handler.call_count == 0
211+
assert t.deserialize.call_count == 0
206212
else:
213+
assert t.deserialize.call_count == 1
207214
assert my_handler.call_count == 1
208215
t.deserialize.reset_mock()
209216
my_handler.reset_mock()
@@ -566,3 +573,30 @@ def test_tx_status(value, name):
566573
def test_handle_add_neighbour(api):
567574
"""Test handle_add_neighbour."""
568575
api._handle_add_neighbour((12, 1, 0x1234, sentinel.ieee, 0x80))
576+
577+
578+
@pytest.mark.parametrize("status", (0x00, 0x05))
579+
async def test_aps_data_req_deserialize_error(api, uart_gw, status, caplog):
580+
"""Test deserialization error."""
581+
582+
device_state = (
583+
deconz_api.DeviceState.APSDE_DATA_INDICATION
584+
| deconz_api.DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE
585+
| deconz_api.NetworkState.CONNECTED
586+
)
587+
api._handle_device_state_value(device_state)
588+
await asyncio.sleep(0)
589+
await asyncio.sleep(0)
590+
await asyncio.sleep(0)
591+
assert uart_gw.send.call_count == 1
592+
assert api._data_indication is True
593+
594+
api.data_received(
595+
uart_gw.send.call_args[0][0][0:2]
596+
+ bytes([status])
597+
+ binascii.unhexlify("0800010022")
598+
)
599+
await asyncio.sleep(0)
600+
await asyncio.sleep(0)
601+
await asyncio.sleep(0)
602+
assert api._data_indication is False

zigpy_deconz/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# coding: utf-8
22
MAJOR_VERSION = 0
3-
MINOR_VERSION = 10
3+
MINOR_VERSION = 11
44
PATCH_VERSION = "0"
55
__short_version__ = "{}.{}".format(MAJOR_VERSION, MINOR_VERSION)
66
__version__ = "{}.{}".format(__short_version__, PATCH_VERSION)

zigpy_deconz/api.py

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
import serial
1111
from zigpy.config import CONF_DEVICE_PATH
12+
import zigpy.exceptions
1213
from zigpy.types import APSStatus, Channels
1314

1415
from zigpy_deconz.exception import APIException, CommandError
@@ -332,21 +333,29 @@ def data_received(self, data):
332333
status = Status(data[2])
333334
except ValueError:
334335
status = data[2]
335-
try:
336-
data, _ = t.deserialize(data[5:], schema)
337-
except Exception as exc:
338-
LOGGER.warning("Failed to deserialize frame: %s", binascii.hexlify(data))
339-
if solicited and seq in self._awaiting:
340-
fut = self._awaiting.pop(seq)
341-
fut.set_exception(exc)
342-
return
336+
337+
fut = None
343338
if solicited and seq in self._awaiting:
344339
fut = self._awaiting.pop(seq)
345340
if status != Status.SUCCESS:
346341
fut.set_exception(
347342
CommandError(status, "%s, status: %s" % (command, status))
348343
)
349344
return
345+
346+
try:
347+
data, _ = t.deserialize(data[5:], schema)
348+
except Exception:
349+
LOGGER.warning("Failed to deserialize frame: %s", binascii.hexlify(data))
350+
if fut is not None:
351+
fut.set_exception(
352+
APIException(
353+
f"Failed to deserialize frame: {binascii.hexlify(data)}"
354+
)
355+
)
356+
return
357+
358+
if fut is not None:
350359
fut.set_result(data)
351360
getattr(self, "_handle_%s" % (command.name,))(data)
352361

@@ -465,7 +474,7 @@ async def _aps_data_indication(self):
465474
binascii.hexlify(r[8]),
466475
)
467476
return r
468-
except asyncio.TimeoutError:
477+
except (asyncio.TimeoutError, zigpy.exceptions.ZigbeeException):
469478
self._data_indication = False
470479

471480
def _handle_aps_data_indication(self, data):
@@ -527,7 +536,7 @@ async def _aps_data_confirm(self):
527536
r[5],
528537
)
529538
return r
530-
except asyncio.TimeoutError:
539+
except (asyncio.TimeoutError, zigpy.exceptions.ZigbeeException):
531540
self._data_confirm = False
532541

533542
def _handle_add_neighbour(self, data) -> None:

0 commit comments

Comments
 (0)