Skip to content

Commit 150462a

Browse files
committed
New registry scanning / startup procedure.
CirclePlus registry address mapping (also called network_address or zigbee_address) is no longer propagated to the nodes as it is unused. CirclePlus registry address is no longer mapped, only MAC addresses are important for caching. MAC + NodeType are loaded from cache at startup an initiate the node loading process instantly. If empty (<4 nodes) inside cache, or disabled cache, the CirclePlus registry scan is executed with short delays If a node is found, it is loaded / initialized instantly
1 parent f0825a1 commit 150462a

File tree

11 files changed

+114
-160
lines changed

11 files changed

+114
-160
lines changed

plugwise_usb/api.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,6 @@ class NodeInfo:
145145
"""Node hardware information."""
146146

147147
mac: str
148-
zigbee_address: int
149148
is_battery_powered: bool = False
150149
features: tuple[NodeFeature, ...] = (NodeFeature.INFO,)
151150
firmware: datetime | None = None

plugwise_usb/network/__init__.py

Lines changed: 25 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ def __init__(
7777
self._unsubscribe_node_rejoin: Callable[[], None] | None = None
7878

7979
self._discover_sed_tasks: dict[str, Task[bool]] = {}
80-
self._registry_stragglers: dict[int, str] = {}
80+
self._registry_stragglers: list[str] = []
8181
self._discover_stragglers_task: Task[None] | None = None
8282
self._load_stragglers_task: Task[None] | None = None
8383

@@ -232,10 +232,7 @@ async def node_awake_message(self, response: PlugwiseResponse) -> None:
232232
self._awake_discovery[mac] = response.timestamp
233233
return
234234

235-
if (address := self._register.network_address(mac)) is None:
236-
if self._register.scan_completed:
237-
return
238-
235+
if not self._register.node_is_registered(mac):
239236
_LOGGER.debug(
240237
"Skip node awake message for %s because network registry address is unknown",
241238
mac,
@@ -248,7 +245,7 @@ async def node_awake_message(self, response: PlugwiseResponse) -> None:
248245
or self._discover_sed_tasks[mac].done()
249246
):
250247
self._discover_sed_tasks[mac] = create_task(
251-
self._discover_battery_powered_node(address, mac)
248+
self._discover_battery_powered_node(mac)
252249
)
253250
else:
254251
_LOGGER.debug("duplicate maintenance awake discovery for %s", mac)
@@ -280,15 +277,14 @@ async def node_rejoin_message(self, response: PlugwiseResponse) -> bool:
280277
f"Invalid response message type ({response.__class__.__name__}) received, expected NodeRejoinResponse"
281278
)
282279
mac = response.mac_decoded
283-
if (address := self._register.network_address(mac)) is None:
284-
if (address := self._register.update_node_registration(mac)) is None:
285-
raise NodeError(f"Failed to obtain address for node {mac}")
286-
287-
if self._nodes.get(mac) is None:
280+
if (
281+
self._register.update_node_registration(mac)
282+
and self._nodes.get(mac) is None
283+
):
288284
task = self._discover_sed_tasks.get(mac)
289285
if task is None or task.done():
290286
self._discover_sed_tasks[mac] = create_task(
291-
self._discover_battery_powered_node(address, mac)
287+
self._discover_battery_powered_node(mac)
292288
)
293289
else:
294290
_LOGGER.debug("duplicate awake discovery for %s", mac)
@@ -335,7 +331,7 @@ async def discover_network_coordinator(self, load: bool = False) -> bool:
335331
return False
336332

337333
if await self._discover_node(
338-
-1, self._controller.mac_coordinator, None, ping_first=False
334+
self._controller.mac_coordinator, None, ping_first=False
339335
):
340336
if load:
341337
return await self._load_node(self._controller.mac_coordinator)
@@ -349,7 +345,6 @@ async def discover_network_coordinator(self, load: bool = False) -> bool:
349345
async def _create_node_object(
350346
self,
351347
mac: str,
352-
address: int,
353348
node_type: NodeType,
354349
) -> None:
355350
"""Create node object and update network registry."""
@@ -361,7 +356,6 @@ async def _create_node_object(
361356
return
362357
node = get_plugwise_node(
363358
mac,
364-
address,
365359
self._controller,
366360
self._notify_node_event_subscribers,
367361
node_type,
@@ -371,7 +365,7 @@ async def _create_node_object(
371365
return
372366
self._nodes[mac] = node
373367
_LOGGER.debug("%s node %s added", node.__class__.__name__, mac)
374-
await self._register.update_network_registration(address, mac, node_type)
368+
await self._register.update_network_nodetype(mac, node_type)
375369

376370
if self._cache_enabled:
377371
_LOGGER.debug(
@@ -385,16 +379,13 @@ async def _create_node_object(
385379

386380
async def _discover_battery_powered_node(
387381
self,
388-
address: int,
389382
mac: str,
390383
) -> bool:
391384
"""Discover a battery powered node and add it to list of nodes.
392385
393386
Return True if discovery succeeded.
394387
"""
395-
if not await self._discover_node(
396-
address, mac, node_type=None, ping_first=False
397-
):
388+
if not await self._discover_node(mac, node_type=None, ping_first=False):
398389
return False
399390
if await self._load_node(mac):
400391
await self._notify_node_event_subscribers(NodeEvent.AWAKE, mac)
@@ -403,7 +394,6 @@ async def _discover_battery_powered_node(
403394

404395
async def _discover_node(
405396
self,
406-
address: int,
407397
mac: str,
408398
node_type: NodeType | None,
409399
ping_first: bool = True,
@@ -420,16 +410,18 @@ async def _discover_node(
420410
return True
421411

422412
if node_type is not None:
423-
await self._create_node_object(mac, address, node_type)
413+
await self._create_node_object(mac, node_type)
424414
await self._notify_node_event_subscribers(NodeEvent.DISCOVERED, mac)
425415
return True
426416

427417
# Node type is unknown, so we need to discover it first
428418
_LOGGER.debug("Starting the discovery of node %s with unknown NodeType", mac)
429419
node_info, node_ping = await self._controller.get_node_details(mac, ping_first)
430420
if node_info is None:
421+
_LOGGER.debug("Node %s with unknown NodeType not responding", mac)
422+
self._registry_stragglers.append(mac)
431423
return False
432-
await self._create_node_object(mac, address, node_info.node_type)
424+
await self._create_node_object(mac, node_info.node_type)
433425

434426
# Forward received NodeInfoResponse message to node
435427
await self._nodes[mac].message_for_node(node_info)
@@ -438,41 +430,16 @@ async def _discover_node(
438430
await self._notify_node_event_subscribers(NodeEvent.DISCOVERED, mac)
439431
return True
440432

441-
async def _discover_registered_nodes(self) -> None:
442-
"""Discover nodes."""
443-
_LOGGER.debug("Start discovery of registered nodes")
444-
registered_counter = 0
445-
for address, registration in self._register.registry.items():
446-
mac, node_type = registration
447-
if mac != "":
448-
if self._nodes.get(mac) is None:
449-
if not await self._discover_node(address, mac, node_type):
450-
self._registry_stragglers[address] = mac
451-
registered_counter += 1
452-
await sleep(0)
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-
464433
async def _discover_stragglers(self) -> None:
465434
"""Repeat Discovery of Nodes with unknown NodeType."""
466435
while len(self._registry_stragglers) > 0:
467436
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
437+
for mac in self._registry_stragglers:
438+
if not await self._discover_node(mac, None):
439+
self._registry_stragglers.remove(mac)
473440
_LOGGER.debug(
474441
"Total %s nodes unreachable having unknown NodeType",
475-
str(len(stragglers)),
442+
str(len(self._registry_stragglers)),
476443
)
477444

478445
async def _load_node(self, mac: str) -> bool:
@@ -526,19 +493,22 @@ async def _unload_discovered_nodes(self) -> None:
526493
# region - Network instance
527494
async def start(self) -> None:
528495
"""Start and activate network."""
529-
self._register.quick_scan_finished(self._discover_registered_nodes)
530-
self._register.full_scan_finished(self._discover_registered_nodes)
496+
self._register.start_node_discover(self._discover_node)
531497
await self._register.start()
532498
self._subscribe_to_protocol_events()
533499
await self._subscribe_to_node_events()
534500
self._is_running = True
501+
if len(self._registry_stragglers) > 0 and (
502+
self._discover_stragglers_task is None
503+
or self._discover_stragglers_task.done()
504+
):
505+
self._discover_stragglers_task = create_task(self._discover_stragglers())
535506

536507
async def discover_nodes(self, load: bool = True) -> bool:
537508
"""Discover nodes."""
538509
await self.discover_network_coordinator(load=load)
539510
if not self._is_running:
540511
await self.start()
541-
await self._discover_registered_nodes()
542512
if load and not await self._load_discovered_nodes():
543513
self._load_stragglers_task = create_task(self._load_stragglers())
544514
return False

plugwise_usb/network/cache.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,14 @@ async def update_nodetypes(self, mac: str, node_type: NodeType | None) -> None:
7777
def get_nodetype(self, mac: str) -> NodeType | None:
7878
"""Return NodeType from cache."""
7979
return self._nodetypes.get(mac)
80+
81+
async def prune_cache(self, registry: list(str)) -> None:
82+
"""Remove items from cache which are not found in registry scan."""
83+
_new_nodetypes: dict[str, NodeType] = {}
84+
for mac in registry:
85+
if mac == "":
86+
continue
87+
if (node_type := self.get_nodetype(mac)) is not None:
88+
_new_nodetypes[mac] = node_type
89+
self._nodetypes = _new_nodetypes
90+
await self.save_cache()

0 commit comments

Comments
 (0)