1+ from __future__ import annotations
2+
13import asyncio
24import logging
35
46import zigpy .zdo
57import zigpy .device
68import zigpy .zdo .types as zdo_t
9+ import zigpy .application
710
811import zigpy_znp .types as t
912import zigpy_znp .commands as c
13+ import zigpy_znp .zigbee .application as znp_app
1014
1115LOGGER = logging .getLogger (__name__ )
1216
@@ -40,31 +44,61 @@ def model(self):
4044
4145 return f"{ model } , Z-Stack { version } (build { self .application ._zstack_build_id } )"
4246
47+ def request (
48+ self ,
49+ profile ,
50+ cluster ,
51+ src_ep ,
52+ dst_ep ,
53+ sequence ,
54+ data ,
55+ expect_reply = True ,
56+ # Extend the default timeout
57+ timeout = 2 * zigpy .device .APS_REPLY_TIMEOUT ,
58+ use_ieee = False ,
59+ ):
60+ """
61+ Normal `zigpy.device.Device:request` except its default timeout is longer.
62+ """
63+
64+ return super ().request (
65+ profile ,
66+ cluster ,
67+ src_ep ,
68+ dst_ep ,
69+ sequence ,
70+ data ,
71+ expect_reply = expect_reply ,
72+ timeout = timeout ,
73+ use_ieee = use_ieee ,
74+ )
75+
4376
4477class ZNPZDOEndpoint (zigpy .zdo .ZDO ):
4578 @property
46- def app (self ):
79+ def app (self ) -> zigpy . application . ControllerApplication :
4780 return self .device .application
4881
49- async def async_handle_mgmt_permit_joining_req (
50- self ,
51- hdr : zdo_t .ZDOHeader ,
52- PermitDuration : t .uint8_t ,
53- TC_Significant : t .Bool ,
54- * ,
55- dst_addressing ,
82+ def _send_loopback_reply (
83+ self , command_id : zdo_t .ZDOCmd , * , tsn : t .uint8_t , ** kwargs
5684 ):
57- # Joins *must* be sent via a ZDO command. Otherwise, Z-Stack will not actually
58- # permit the coordinator to send the network key while routers will.
59- await self .app ._znp .request_callback_rsp (
60- request = c .ZDO .MgmtPermitJoinReq .Req (
61- AddrMode = t .AddrMode .NWK ,
62- Dst = 0x0000 ,
63- Duration = PermitDuration ,
64- TCSignificance = TC_Significant ,
65- ),
66- RspStatus = t .Status .SUCCESS ,
67- callback = c .ZDO .MgmtPermitJoinRsp .Callback (Src = 0x0000 , partial = True ),
85+ """
86+ Constructs and sends back a loopback ZDO response.
87+ """
88+
89+ message = t .uint8_t (tsn ).serialize () + self ._serialize (
90+ command_id , * kwargs .values ()
91+ )
92+
93+ LOGGER .debug ("Sending loopback reply %s (%s), tsn=%s" , command_id , kwargs , tsn )
94+
95+ self .app .handle_message (
96+ sender = self .app .zigpy_device ,
97+ profile = znp_app .ZDO_PROFILE ,
98+ cluster = command_id ,
99+ src_ep = znp_app .ZDO_ENDPOINT ,
100+ dst_ep = znp_app .ZDO_ENDPOINT ,
101+ message = message ,
68102 )
69103
70104 def handle_mgmt_nwk_update_req (
@@ -83,7 +117,7 @@ def handle_mgmt_nwk_update_req(
83117 async def async_handle_mgmt_nwk_update_req (
84118 self , hdr : zdo_t .ZDOHeader , NwkUpdate : zdo_t .NwkUpdate , * , dst_addressing
85119 ):
86- # Energy scans are handled properly by Z-Stack
120+ # Energy scans are handled properly by Z-Stack, no need to do anything
87121 if NwkUpdate .ScanDuration not in (
88122 zdo_t .NwkUpdate .CHANNEL_CHANGE_REQ ,
89123 zdo_t .NwkUpdate .CHANNEL_MASK_MANAGER_ADDR_CHANGE_REQ ,
@@ -97,6 +131,15 @@ async def async_handle_mgmt_nwk_update_req(
97131 == NwkUpdate .ScanChannels
98132 ):
99133 LOGGER .warning ("NWK update request is ignored when channel does not change" )
134+ self ._send_loopback_reply (
135+ zdo_t .ZDOCmd .Mgmt_NWK_Update_rsp ,
136+ Status = zdo_t .Status .SUCCESS ,
137+ ScannedChannels = t .Channels .NO_CHANNELS ,
138+ TotalTransmissions = 0 ,
139+ TransmissionFailures = 0 ,
140+ EnergyValues = [],
141+ tsn = hdr .tsn ,
142+ )
100143 return
101144
102145 await self .app ._znp .request (
@@ -128,3 +171,13 @@ async def async_handle_mgmt_nwk_update_req(
128171 f" { self .app .state .network_information .nwk_update_id } instead of being"
129172 f" set to { NwkUpdate .nwkUpdateId } "
130173 )
174+
175+ self ._send_loopback_reply (
176+ zdo_t .ZDOCmd .Mgmt_NWK_Update_rsp ,
177+ Status = zdo_t .Status .SUCCESS ,
178+ ScannedChannels = t .Channels .NO_CHANNELS ,
179+ TotalTransmissions = 0 ,
180+ TransmissionFailures = 0 ,
181+ EnergyValues = [],
182+ tsn = hdr .tsn ,
183+ )
0 commit comments