@@ -285,13 +285,13 @@ async def interview_node(self, node_id: int) -> None:
285
285
286
286
LOGGER .debug ("Interviewing node: %s" , node_id )
287
287
try :
288
- await self ._call_sdk ( self . chip_controller . ResolveNode , nodeid = node_id )
288
+ await self ._resolve_node ( node_id = node_id )
289
289
read_response : Attribute .AsyncReadTransaction .ReadResponse = (
290
290
await self .chip_controller .Read (
291
291
nodeid = node_id , attributes = "*" , events = "*" , fabricFiltered = False
292
292
)
293
293
)
294
- except ChipStackError as err :
294
+ except ( ChipStackError , NodeNotResolving ) as err :
295
295
raise NodeInterviewFailed (f"Failed to interview node { node_id } " ) from err
296
296
297
297
is_new_node = node_id not in self ._nodes
@@ -406,12 +406,9 @@ async def subscribe_node(self, node_id: int) -> None:
406
406
node_logger .debug ("Setting up subscriptions..." )
407
407
408
408
node = cast (MatterNodeData , self ._nodes [node_id ])
409
-
410
- try :
411
- await self ._call_sdk (self .chip_controller .ResolveNode , nodeid = node_id )
412
- except ChipStackError as err :
413
- node .available = False
414
- raise NodeNotResolving (f"Failed to resolve node { node_id } " ) from err
409
+ node .available = False
410
+ await self ._resolve_node (node_id = node_id )
411
+ node .available = True
415
412
416
413
# we follow the pattern of apple and google here and
417
414
# just do a wildcard subscription for all clusters and properties
@@ -421,7 +418,7 @@ async def subscribe_node(self, node_id: int) -> None:
421
418
sub : Attribute .SubscriptionTransaction = await self .chip_controller .Read (
422
419
nodeid = node_id ,
423
420
attributes = "*" ,
424
- events = [("*" , 0 )],
421
+ events = [("*" , 1 )],
425
422
reportInterval = (0 , 120 ),
426
423
fabricFiltered = False ,
427
424
)
@@ -632,3 +629,32 @@ def _parse_attributes_from_read_result(
632
629
)
633
630
result [attribute_path ] = attr_value
634
631
return result
632
+
633
+ async def _resolve_node (
634
+ self , node_id : int , retries : int = 3 , allow_pase : bool = False
635
+ ) -> None :
636
+ """Resolve a Node on the network."""
637
+ if self .chip_controller is None :
638
+ raise RuntimeError ("Device Controller not initialized." )
639
+ try :
640
+ if allow_pase :
641
+ # last attempt allows PASE connection (last resort)
642
+ LOGGER .debug (
643
+ "Attempting to resolve node %s (with PASE connection)" , node_id
644
+ )
645
+ await self ._call_sdk (
646
+ self .chip_controller .GetConnectedDeviceSync ,
647
+ nodeid = node_id ,
648
+ allowPASE = True ,
649
+ )
650
+ return
651
+ LOGGER .debug ("Resolving node %s" , node_id )
652
+ await self ._call_sdk (self .chip_controller .ResolveNode , nodeid = node_id )
653
+ except (ChipStackError , TimeoutError ) as err :
654
+ if not retries :
655
+ # when we're out of retries, raise NodeNotResolving
656
+ raise NodeNotResolving (f"Unable to resolve Node { node_id } " ) from err
657
+ await self ._resolve_node (
658
+ node_id = node_id , retries = retries - 1 , allow_pase = retries - 1 == 0
659
+ )
660
+ await asyncio .sleep (2 )
0 commit comments