1212
1313from ..api import NodeEvent , NodeType , PlugwiseNode , StickEvent
1414from ..connection import StickController
15- from ..constants import ENERGY_NODE_TYPES , UTF8
15+ from ..constants import (
16+ ENERGY_NODE_TYPES ,
17+ NODE_RETRY_DISCOVER_INTERVAL ,
18+ NODE_RETRY_LOAD_INTERVAL ,
19+ UTF8 ,
20+ )
1621from ..exceptions import CacheError , MessageError , NodeError , StickError , StickTimeout
1722from ..helpers .util import validate_mac
1823from ..messages .requests import CircleMeasureIntervalRequest , NodePingRequest
@@ -72,6 +77,9 @@ def __init__(
7277 self ._unsubscribe_node_rejoin : Callable [[], None ] | None = None
7378
7479 self ._discover_sed_tasks : dict [str , Task [bool ]] = {}
80+ self ._registry_stragglers : dict [int , str ] = {}
81+ self ._discover_stragglers_task : Task [None ] | None = None
82+ self ._load_stragglers_task : Task [None ] | None = None
7583
7684 # region - Properties
7785
@@ -338,7 +346,7 @@ async def discover_network_coordinator(self, load: bool = False) -> bool:
338346 # endregion
339347
340348 # region - Nodes
341- def _create_node_object (
349+ async def _create_node_object (
342350 self ,
343351 mac : str ,
344352 address : int ,
@@ -363,7 +371,7 @@ def _create_node_object(
363371 return
364372 self ._nodes [mac ] = node
365373 _LOGGER .debug ("%s node %s added" , node .__class__ .__name__ , mac )
366- self ._register .update_network_registration (address , mac , node_type )
374+ await self ._register .update_network_registration (address , mac , node_type )
367375
368376 if self ._cache_enabled :
369377 _LOGGER .debug (
@@ -404,22 +412,24 @@ async def _discover_node(
404412
405413 Return True if discovery succeeded.
406414 """
407- _LOGGER .debug ("Start discovery of node %s " , mac )
415+ _LOGGER .debug (
416+ "Start discovery of node %s with NodeType %s" , mac , str (node_type )
417+ )
408418 if self ._nodes .get (mac ) is not None :
409419 _LOGGER .debug ("Skip discovery of already known node %s " , mac )
410420 return True
411421
412422 if node_type is not None :
413- self ._create_node_object (mac , address , node_type )
423+ await self ._create_node_object (mac , address , node_type )
414424 await self ._notify_node_event_subscribers (NodeEvent .DISCOVERED , mac )
415425 return True
416426
417427 # Node type is unknown, so we need to discover it first
418- _LOGGER .debug ("Starting the discovery of node %s" , mac )
428+ _LOGGER .debug ("Starting the discovery of node %s with unknown NodeType " , mac )
419429 node_info , node_ping = await self ._controller .get_node_details (mac , ping_first )
420430 if node_info is None :
421431 return False
422- self ._create_node_object (mac , address , node_info .node_type )
432+ await self ._create_node_object (mac , address , node_info .node_type )
423433
424434 # Forward received NodeInfoResponse message to node
425435 await self ._nodes [mac ].message_for_node (node_info )
@@ -431,15 +441,39 @@ async def _discover_node(
431441 async def _discover_registered_nodes (self ) -> None :
432442 """Discover nodes."""
433443 _LOGGER .debug ("Start discovery of registered nodes" )
434- counter = 0
444+ registered_counter = 0
435445 for address , registration in self ._register .registry .items ():
436446 mac , node_type = registration
437447 if mac != "" :
438448 if self ._nodes .get (mac ) is None :
439- await self ._discover_node (address , mac , node_type )
440- counter += 1
449+ if not await self ._discover_node (address , mac , node_type ):
450+ self ._registry_stragglers [address ] = mac
451+ registered_counter += 1
441452 await sleep (0 )
442- _LOGGER .debug ("Total %s registered node(s)" , str (counter ))
453+ if len (self ._registry_stragglers ) > 0 and (
454+ self ._discover_stragglers_task is None
455+ or self ._discover_stragglers_task .done ()
456+ ):
457+ self ._discover_stragglers_task = create_task (self ._discover_stragglers ())
458+ _LOGGER .debug (
459+ "Total %s online of %s registered node(s)" ,
460+ str (len (self ._nodes )),
461+ str (registered_counter ),
462+ )
463+
464+ async def _discover_stragglers (self ) -> None :
465+ """Repeat Discovery of Nodes with unknown NodeType."""
466+ while len (self ._registry_stragglers ) > 0 :
467+ await sleep (NODE_RETRY_DISCOVER_INTERVAL )
468+ stragglers : dict [int , str ] = {}
469+ for address , mac in self ._registry_stragglers .items ():
470+ if not await self ._discover_node (address , mac , None ):
471+ stragglers [address ] = mac
472+ self ._registry_stragglers = stragglers
473+ _LOGGER .debug (
474+ "Total %s nodes unreachable having unknown NodeType" ,
475+ str (len (stragglers )),
476+ )
443477
444478 async def _load_node (self , mac : str ) -> bool :
445479 """Load node."""
@@ -452,6 +486,12 @@ async def _load_node(self, mac: str) -> bool:
452486 return True
453487 return False
454488
489+ async def _load_stragglers (self ) -> None :
490+ """Retry failed load operation."""
491+ await sleep (NODE_RETRY_LOAD_INTERVAL )
492+ while not self ._load_discovered_nodes ():
493+ await sleep (NODE_RETRY_LOAD_INTERVAL )
494+
455495 async def _load_discovered_nodes (self ) -> bool :
456496 """Load all nodes currently discovered."""
457497 _LOGGER .debug ("_load_discovered_nodes | START | %s" , len (self ._nodes ))
@@ -499,10 +539,10 @@ async def discover_nodes(self, load: bool = True) -> bool:
499539 await self .discover_network_coordinator (load = load )
500540 if not self ._is_running :
501541 await self .start ()
502-
503542 await self ._discover_registered_nodes ()
504- if load :
505- return await self ._load_discovered_nodes ()
543+ if load and not await self ._load_discovered_nodes ():
544+ self ._load_stragglers_task = create_task (self ._load_stragglers ())
545+ return False
506546
507547 return True
508548
@@ -512,10 +552,22 @@ async def stop(self) -> None:
512552 for task in self ._discover_sed_tasks .values ():
513553 if not task .done ():
514554 task .cancel ()
555+ if (
556+ hasattr (self , "_load_stragglers_task" )
557+ and self ._load_stragglers_task
558+ and not self ._load_stragglers_task .done ()
559+ ):
560+ self ._load_stragglers_task .cancel ()
561+ if (
562+ hasattr (self , "_discover_stragglers_task" )
563+ and self ._discover_stragglers_task
564+ and not self ._discover_stragglers_task .done ()
565+ ):
566+ self ._discover_stragglers_task .cancel ()
515567 self ._is_running = False
516568 self ._unsubscribe_to_protocol_events ()
517569 await self ._unload_discovered_nodes ()
518- await self ._register .stop ()
570+ self ._register .stop ()
519571 _LOGGER .debug ("Stopping finished" )
520572
521573 # endregion
0 commit comments