12
12
import zigpy .profiles
13
13
import zigpy .zcl .foundation
14
14
15
- from zigpy .zdo .types import ZDOCmd , ZDOHeader , CLUSTERS as ZDO_CLUSTERS
16
-
17
15
from zigpy .zcl import clusters
18
16
from zigpy .types import (
19
17
ExtendedPanId ,
20
18
deserialize as list_deserialize ,
21
19
Struct as ZigpyStruct ,
22
20
)
21
+ from zigpy .zdo .types import ZDOCmd , ZDOHeader , CLUSTERS as ZDO_CLUSTERS
23
22
from zigpy .exceptions import DeliveryError
24
23
25
- import zigpy_znp .config as conf
26
24
import zigpy_znp .types as t
25
+ import zigpy_znp .config as conf
27
26
import zigpy_znp .commands as c
28
27
29
- from zigpy_znp .exceptions import InvalidCommandResponse
30
-
31
28
from zigpy_znp .api import ZNP
32
29
from zigpy_znp .znp .nib import parse_nib
30
+ from zigpy_znp .exceptions import InvalidCommandResponse
33
31
from zigpy_znp .types .nvids import NwkNvIds
34
32
35
33
@@ -148,7 +146,7 @@ def __init__(self, config: conf.ConfigType):
148
146
149
147
self ._znp = None
150
148
151
- # It's easier to deal with this if it's never None
149
+ # It's simpler to work with Task objects if they're never actually None
152
150
self ._reconnect_task = asyncio .Future ()
153
151
self ._reconnect_task .cancel ()
154
152
@@ -194,6 +192,7 @@ def _receive_zdo_message(
194
192
message = t .serialize_list ([t .uint8_t (tsn )] + zdo_args )
195
193
196
194
LOGGER .debug ("Pretending we received a ZDO message: %s" , message )
195
+
197
196
self .handle_message (
198
197
sender = sender ,
199
198
profile = zigpy .profiles .zha .PROFILE_ID ,
@@ -317,7 +316,7 @@ async def _register_endpoint(
317
316
endpoint ,
318
317
profile_id = zigpy .profiles .zha .PROFILE_ID ,
319
318
device_id = zigpy .profiles .zha .DeviceType .CONFIGURATION_TOOL ,
320
- device_version = 0x00 ,
319
+ device_version = 0b0000 ,
321
320
latency_req = c .af .LatencyReq .NoLatencyReqs ,
322
321
input_clusters = [],
323
322
output_clusters = [],
@@ -328,7 +327,7 @@ async def _register_endpoint(
328
327
ProfileId = profile_id ,
329
328
DeviceId = device_id ,
330
329
DeviceVersion = device_version ,
331
- LatencyReq = latency_req ,
330
+ LatencyReq = latency_req , # completely ignored by Z-Stack
332
331
InputClusters = input_clusters ,
333
332
OutputClusters = output_clusters ,
334
333
),
@@ -427,25 +426,18 @@ async def startup(self, auto_form=False):
427
426
c .AF .Delete .Req (Endpoint = endpoint ), RspStatus = t .Status .SUCCESS
428
427
)
429
428
429
+ # We really need only a single endpoint
430
430
await self ._register_endpoint (
431
431
endpoint = 1 ,
432
432
profile_id = zigpy .profiles .zha .PROFILE_ID ,
433
- input_clusters = [clusters .general .Ota .cluster_id ],
434
- )
435
-
436
- await self ._register_endpoint (
437
- endpoint = 2 ,
438
433
device_id = zigpy .profiles .zha .DeviceType .IAS_CONTROL ,
434
+ input_clusters = [clusters .general .Ota .cluster_id ],
439
435
output_clusters = [
440
436
clusters .security .IasZone .cluster_id ,
441
437
clusters .security .IasWd .cluster_id ,
442
438
],
443
439
)
444
440
445
- await self ._register_endpoint (
446
- endpoint = 100 , profile_id = zigpy .profiles .zll .PROFILE_ID , device_id = 0x0005
447
- )
448
-
449
441
nib = parse_nib (await self ._znp .nvram_read (NwkNvIds .NIB ))
450
442
LOGGER .debug ("Parsed NIB: %s" , nib )
451
443
@@ -680,6 +672,11 @@ async def _send_request(
680
672
dst_addr , dst_ep , src_ep , cluster , sequence , options , radius , data
681
673
)
682
674
675
+ # Zigpy just sets src == dst, which doesn't work for devices with many endpoints
676
+ # We use endpoint 1 for everything.
677
+ if dst_ep != ZDO_ENDPOINT :
678
+ src_ep = 1
679
+
683
680
request = c .AF .DataRequestExt .Req (
684
681
DstAddrModeAddress = dst_addr ,
685
682
DstEndpoint = dst_ep ,
0 commit comments