44import functools
55import logging
66
7+ from zigpy .exceptions import DeliveryError
78from zigpy .types import LVList
89
910from . import uart
@@ -35,14 +36,14 @@ class ModemStatus(t.uint8_t, t.UndefinedEnum):
3536 'queued_at' : (0x09 , (t .FrameId , t .ATCommand , t .Bytes ), 0x88 ),
3637 'remote_at' : (0x17 , (t .FrameId , t .EUI64 , t .NWK , t .uint8_t , t .ATCommand , t .Bytes ), 0x97 ),
3738 'tx' : (0x10 , (), None ),
38- 'tx_explicit' : (0x11 , (t .FrameId , t .EUI64 , t .NWK , t .uint8_t , t .uint8_t , t .uint16_t , t .uint16_t , t .uint8_t , t .uint8_t , t .Bytes ), None ),
39+ 'tx_explicit' : (0x11 , (t .FrameId , t .EUI64 , t .NWK , t .uint8_t , t .uint8_t , t .uint16_t , t .uint16_t , t .uint8_t , t .uint8_t , t .Bytes ), 0x8b ),
3940 'create_source_route' : (0x21 , (t .FrameId , t .EUI64 , t .NWK , t .uint8_t , LVList (t .NWK )), None ),
4041 'register_joining_device' : (0x24 , (), None ),
4142}
4243COMMAND_RESPONSES = {
4344 'at_response' : (0x88 , (t .FrameId , t .ATCommand , t .uint8_t , t .Bytes ), None ),
4445 'modem_status' : (0x8A , (ModemStatus , ), None ),
45- 'tx_status' : (0x8B , (t .FrameId , t .NWK , t .uint8_t , t .uint8_t , t .uint8_t ), None ),
46+ 'tx_status' : (0x8B , (t .FrameId , t .NWK , t .uint8_t , t .TXStatus , t .DiscoveryStatus ), None ),
4647 'route_information' : (0x8D , (), None ),
4748 'rx' : (0x90 , (), None ),
4849 'explicit_rx_indicator' : (0x91 , (t .EUI64 , t .NWK , t .uint8_t , t .uint8_t , t .uint16_t , t .uint16_t , t .uint8_t , t .Bytes ), None ),
@@ -269,15 +270,15 @@ def frame_received(self, data):
269270 LOGGER .debug ("Frame received: %s" , command )
270271 data , rest = t .deserialize (data [1 :], COMMAND_RESPONSES [command ][1 ])
271272 try :
272- getattr (self , '_handle_%s' % (command , ))(data )
273+ getattr (self , '_handle_%s' % (command , ))(* data )
273274 except AttributeError :
274275 LOGGER .error ("No '%s' handler. Data: %s" , command ,
275276 binascii .hexlify (data ))
276277
277- def _handle_at_response (self , data ):
278- fut , = self ._awaiting .pop (data [ 0 ] )
278+ def _handle_at_response (self , frame_id , cmd , status , value ):
279+ fut , = self ._awaiting .pop (frame_id )
279280 try :
280- status = ATCommandResult (data [ 2 ] )
281+ status = ATCommandResult (status )
281282 except ValueError :
282283 status = ATCommandResult .ERROR
283284
@@ -286,25 +287,26 @@ def _handle_at_response(self, data):
286287 RuntimeError ("AT Command response: {}" .format (status .name )))
287288 return
288289
289- response_type = AT_COMMANDS [data [ 1 ] .decode ('ascii' )]
290- if response_type is None or len (data [ 3 ] ) == 0 :
290+ response_type = AT_COMMANDS [cmd .decode ('ascii' )]
291+ if response_type is None or len (value ) == 0 :
291292 fut .set_result (None )
292293 return
293294
294- response , remains = response_type .deserialize (data [ 3 ] )
295+ response , remains = response_type .deserialize (value )
295296 fut .set_result (response )
296297
297- def _handle_remote_at_response (self , data ):
298+ def _handle_remote_at_response (self , frame_id , ieee , nwk , cmd , status , value ):
298299 """Remote AT command response."""
299- LOGGER .debug ("Remote AT command response: %s" , data )
300- return self ._handle_at_response ((data [0 ], data [3 ], data [4 ], data [5 ]))
300+ LOGGER .debug ("Remote AT command response from: %s" ,
301+ (frame_id , ieee , nwk , cmd , status , value ))
302+ return self ._handle_at_response (frame_id , cmd , status , value )
301303
302- def _handle_many_to_one_rri (self , data ):
303- LOGGER .debug ("_handle_many_to_one_rri: %s" , data )
304+ def _handle_many_to_one_rri (self , ieee , nwk , reserved ):
305+ LOGGER .debug ("_handle_many_to_one_rri: %s" , ( ieee , nwk , reserved ) )
304306
305- def _handle_modem_status (self , data ):
306- LOGGER .debug ("Handle modem status frame: %s" , data )
307- status = data [ 0 ]
307+ def _handle_modem_status (self , status ):
308+ LOGGER .debug ("Handle modem status frame: %s" , status )
309+ status = status
308310 if status == ModemStatus .COORDINATOR_STARTED :
309311 self .coordinator_started_event .set ()
310312 elif status in (ModemStatus .HARDWARE_RESET , ModemStatus .WATCHDOG_TIMER_RESET ):
@@ -316,16 +318,38 @@ def _handle_modem_status(self, data):
316318 if self ._app :
317319 self ._app .handle_modem_status (status )
318320
319- def _handle_explicit_rx_indicator (self , data ):
320- LOGGER .debug ("_handle_explicit_rx: opts=%s" , data [6 ])
321- self ._app .handle_rx (* data )
321+ def _handle_explicit_rx_indicator (self , ieee , nwk , src_ep ,
322+ dst_ep , cluster , profile , rx_opts , data ):
323+ LOGGER .debug ("_handle_explicit_rx: %s" ,
324+ (ieee , nwk , dst_ep , cluster , rx_opts ,
325+ binascii .hexlify (data )))
326+ self ._app .handle_rx (ieee , nwk , src_ep , dst_ep , cluster ,
327+ profile , rx_opts , data )
322328
323- def _handle_route_record_indicator (self , data ):
329+ def _handle_route_record_indicator (self , ieee , src , rx_opts , hops ):
324330 """Handle Route Record indicator from a device."""
325- LOGGER .debug ("_handle_route_record_indicator: %s" , data )
331+ LOGGER .debug ("_handle_route_record_indicator: %s" ,
332+ (ieee , src , rx_opts , hops ))
326333
327- def _handle_tx_status (self , data ):
328- LOGGER .debug ("tx_status: %s" , data )
334+ def _handle_tx_status (self , frame_id , nwk , tries , tx_status , dsc_status ):
335+ LOGGER .debug (
336+ ("tx_explicit to 0x%04x: %s after %i tries. Discovery Status: %s,"
337+ " Frame #%i" ), nwk , tx_status , tries , dsc_status , frame_id )
338+ try :
339+ fut , = self ._awaiting .pop (frame_id )
340+ except KeyError :
341+ LOGGER .debug ("unexpected tx_status report received" )
342+ return
343+
344+ try :
345+ if tx_status in (t .TXStatus .SUCCESS ,
346+ t .TXStatus .BROADCAST_APS_TX_ATTEMPT ):
347+ fut .set_result (tx_status )
348+ else :
349+ fut .set_exception (
350+ DeliveryError ('%s' % (tx_status , )))
351+ except asyncio .InvalidStateError as ex :
352+ LOGGER .debug ("duplicate tx_status for %s nwk? State: %s" , nwk , ex )
329353
330354 def set_application (self , app ):
331355 self ._app = app
0 commit comments