Skip to content

Commit 29d3c06

Browse files
authored
Refactor device lookup. (#36)
Lookup devices by NWK, fallback to IEEE if it exists.
1 parent e8bb134 commit 29d3c06

File tree

4 files changed

+49
-7
lines changed

4 files changed

+49
-7
lines changed

tests/test_application.py

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,14 +76,41 @@ def test_rx_nwk_0000(app):
7676
assert app._handle_reply.call_count == 0
7777

7878

79-
def test_rx_unknown_device(app):
79+
def test_rx_unknown_device(app, device):
80+
"""Unknown NWK, but existing device."""
8081
app._handle_reply = mock.MagicMock()
8182
app.handle_message = mock.MagicMock()
8283
app.handle_join = mock.MagicMock()
83-
app.get_device = mock.MagicMock(side_effect=KeyError)
84+
dev = device(nwk=0x1234)
85+
app.devices[dev.ieee] = dev
86+
app.get_device = mock.MagicMock(side_effect=[KeyError, dev])
87+
app.deserialize = mock.MagicMock(side_effect=ValueError)
8488
app.handle_rx(
8589
b'\x01\x02\x03\x04\x05\x06\x07\x08',
86-
0x1234,
90+
0x3334,
91+
mock.sentinel.src_ep,
92+
mock.sentinel.dst_ep,
93+
mock.sentinel.cluster_id,
94+
mock.sentinel.profile_id,
95+
mock.sentinel.rxopts,
96+
b''
97+
)
98+
assert app.handle_join.call_count == 1
99+
assert app.get_device.call_count == 2
100+
assert app.handle_message.call_count == 0
101+
assert app._handle_reply.call_count == 0
102+
103+
104+
def test_rx_unknown_device_iee(app):
105+
"""Unknown NWK, and unknown IEEE."""
106+
app._handle_reply = mock.MagicMock()
107+
app.handle_message = mock.MagicMock()
108+
app.handle_join = mock.MagicMock()
109+
app.get_device = mock.MagicMock(side_effect=KeyError)
110+
app.deserialize = mock.MagicMock(side_effect=ValueError)
111+
app.handle_rx(
112+
b'\xff\xff\xff\xff\xff\xff\xff\xff',
113+
0x3334,
87114
mock.sentinel.src_ep,
88115
mock.sentinel.dst_ep,
89116
mock.sentinel.cluster_id,

zigpy_xbee/types.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,3 +155,7 @@ def __repr__(self):
155155

156156
def __str__(self):
157157
return '0x{:04x}'.format(self)
158+
159+
160+
UNKNOWN_IEEE = EUI64([uint8_t(0xff) for i in range(0, 8)])
161+
UNKNOWN_NWK = NWK(0xfffe)

zigpy_xbee/uart.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ def __init__(self, api, connected_future=None):
2222

2323
def send(self, data):
2424
"""Send data, taking care of escaping and framing"""
25+
LOGGER.debug("Sending: %s", data)
2526
checksum = bytes([self._checksum(data)])
2627
frame = self.START + self._escape(len(data).to_bytes(2, 'big') + data + checksum)
2728
self._transport.write(frame)

zigpy_xbee/zigbee/application.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,20 @@
33
import logging
44

55
import zigpy.application
6+
import zigpy.exceptions
67
import zigpy.types
78
import zigpy.util
9+
import zigpy.zdo.types
10+
11+
from zigpy_xbee.types import UNKNOWN_IEEE
812

913

1014
# how long coordinator would hold message for an end device in 10ms units
1115
CONF_CYCLIC_SLEEP_PERIOD = 0x0300
1216
# end device poll timeout = 3 * SN * SP * 10ms
1317
CONF_POLL_TIMEOUT = 0x029b
1418

19+
1520
LOGGER = logging.getLogger(__name__)
1621

1722

@@ -72,6 +77,7 @@ async def startup(self, auto_form=False):
7277
LOGGER.debug("Coordinator %s", 'enabled' if ce else 'disabled')
7378
except RuntimeError as exc:
7479
LOGGER.debug("sending CE command: %s", exc)
80+
self.add_device(self.ieee, self.nwk)
7581

7682
async def force_remove(self, dev):
7783
"""Forcibly remove device from NCP."""
@@ -174,11 +180,15 @@ def handle_rx(self, src_ieee, src_nwk, src_ep, dst_ep, cluster_id, profile_id, r
174180
self.handle_join(nwk, ieee, 0)
175181

176182
try:
177-
device = self.get_device(ieee=ember_ieee)
183+
device = self.get_device(nwk=src_nwk)
178184
except KeyError:
179-
LOGGER.debug("Received frame from unknown device: 0x%04x/%s",
180-
src_nwk, str(ember_ieee))
181-
return
185+
if ember_ieee != UNKNOWN_IEEE and ember_ieee in self.devices:
186+
self.handle_join(src_nwk, ember_ieee, 0)
187+
device = self.get_device(ieee=ember_ieee)
188+
else:
189+
LOGGER.debug("Received frame from unknown device: 0x%04x/%s",
190+
src_nwk, str(ember_ieee))
191+
return
182192

183193
if device.status == zigpy.device.Status.NEW and dst_ep != 0:
184194
# only allow ZDO responses while initializing device

0 commit comments

Comments
 (0)