1212import zigpy .profiles
1313import zigpy .zcl .foundation
1414
15- from zigpy .zdo .types import ZDOCmd , ZDOHeader , CLUSTERS as ZDO_CLUSTERS
16-
1715from zigpy .zcl import clusters
1816from zigpy .types import (
1917 ExtendedPanId ,
2018 deserialize as list_deserialize ,
2119 Struct as ZigpyStruct ,
2220)
21+ from zigpy .zdo .types import ZDOCmd , ZDOHeader , CLUSTERS as ZDO_CLUSTERS
2322from zigpy .exceptions import DeliveryError
2423
25- import zigpy_znp .config as conf
2624import zigpy_znp .types as t
25+ import zigpy_znp .config as conf
2726import zigpy_znp .commands as c
2827
29- from zigpy_znp .exceptions import InvalidCommandResponse
30-
3128from zigpy_znp .api import ZNP
3229from zigpy_znp .znp .nib import parse_nib
30+ from zigpy_znp .exceptions import InvalidCommandResponse
3331from zigpy_znp .types .nvids import NwkNvIds
3432
3533
@@ -148,7 +146,7 @@ def __init__(self, config: conf.ConfigType):
148146
149147 self ._znp = None
150148
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
152150 self ._reconnect_task = asyncio .Future ()
153151 self ._reconnect_task .cancel ()
154152
@@ -194,6 +192,7 @@ def _receive_zdo_message(
194192 message = t .serialize_list ([t .uint8_t (tsn )] + zdo_args )
195193
196194 LOGGER .debug ("Pretending we received a ZDO message: %s" , message )
195+
197196 self .handle_message (
198197 sender = sender ,
199198 profile = zigpy .profiles .zha .PROFILE_ID ,
@@ -317,7 +316,7 @@ async def _register_endpoint(
317316 endpoint ,
318317 profile_id = zigpy .profiles .zha .PROFILE_ID ,
319318 device_id = zigpy .profiles .zha .DeviceType .CONFIGURATION_TOOL ,
320- device_version = 0x00 ,
319+ device_version = 0b0000 ,
321320 latency_req = c .af .LatencyReq .NoLatencyReqs ,
322321 input_clusters = [],
323322 output_clusters = [],
@@ -328,7 +327,7 @@ async def _register_endpoint(
328327 ProfileId = profile_id ,
329328 DeviceId = device_id ,
330329 DeviceVersion = device_version ,
331- LatencyReq = latency_req ,
330+ LatencyReq = latency_req , # completely ignored by Z-Stack
332331 InputClusters = input_clusters ,
333332 OutputClusters = output_clusters ,
334333 ),
@@ -427,25 +426,18 @@ async def startup(self, auto_form=False):
427426 c .AF .Delete .Req (Endpoint = endpoint ), RspStatus = t .Status .SUCCESS
428427 )
429428
429+ # We really need only a single endpoint
430430 await self ._register_endpoint (
431431 endpoint = 1 ,
432432 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 ,
438433 device_id = zigpy .profiles .zha .DeviceType .IAS_CONTROL ,
434+ input_clusters = [clusters .general .Ota .cluster_id ],
439435 output_clusters = [
440436 clusters .security .IasZone .cluster_id ,
441437 clusters .security .IasWd .cluster_id ,
442438 ],
443439 )
444440
445- await self ._register_endpoint (
446- endpoint = 100 , profile_id = zigpy .profiles .zll .PROFILE_ID , device_id = 0x0005
447- )
448-
449441 nib = parse_nib (await self ._znp .nvram_read (NwkNvIds .NIB ))
450442 LOGGER .debug ("Parsed NIB: %s" , nib )
451443
@@ -680,6 +672,11 @@ async def _send_request(
680672 dst_addr , dst_ep , src_ep , cluster , sequence , options , radius , data
681673 )
682674
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+
683680 request = c .AF .DataRequestExt .Req (
684681 DstAddrModeAddress = dst_addr ,
685682 DstEndpoint = dst_ep ,
0 commit comments