Skip to content

Commit db93cb1

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 db93cb1

File tree

11 files changed

+109
-151
lines changed

11 files changed

+109
-151
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: 23 additions & 49 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,7 +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:
235+
if not self._register.node_is_registered(mac):
236236
if self._register.scan_completed:
237237
return
238238

@@ -248,7 +248,7 @@ async def node_awake_message(self, response: PlugwiseResponse) -> None:
248248
or self._discover_sed_tasks[mac].done()
249249
):
250250
self._discover_sed_tasks[mac] = create_task(
251-
self._discover_battery_powered_node(address, mac)
251+
self._discover_battery_powered_node(mac)
252252
)
253253
else:
254254
_LOGGER.debug("duplicate maintenance awake discovery for %s", mac)
@@ -280,15 +280,15 @@ async def node_rejoin_message(self, response: PlugwiseResponse) -> bool:
280280
f"Invalid response message type ({response.__class__.__name__}) received, expected NodeRejoinResponse"
281281
)
282282
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:
283+
if not self._register.node_is_registered(mac):
284+
if self._register.update_node_registration(mac) is None:
285285
raise NodeError(f"Failed to obtain address for node {mac}")
286286

287287
if self._nodes.get(mac) is None:
288288
task = self._discover_sed_tasks.get(mac)
289289
if task is None or task.done():
290290
self._discover_sed_tasks[mac] = create_task(
291-
self._discover_battery_powered_node(address, mac)
291+
self._discover_battery_powered_node(mac)
292292
)
293293
else:
294294
_LOGGER.debug("duplicate awake discovery for %s", mac)
@@ -335,7 +335,7 @@ async def discover_network_coordinator(self, load: bool = False) -> bool:
335335
return False
336336

337337
if await self._discover_node(
338-
-1, self._controller.mac_coordinator, None, ping_first=False
338+
self._controller.mac_coordinator, None, ping_first=False
339339
):
340340
if load:
341341
return await self._load_node(self._controller.mac_coordinator)
@@ -349,7 +349,6 @@ async def discover_network_coordinator(self, load: bool = False) -> bool:
349349
async def _create_node_object(
350350
self,
351351
mac: str,
352-
address: int,
353352
node_type: NodeType,
354353
) -> None:
355354
"""Create node object and update network registry."""
@@ -361,7 +360,6 @@ async def _create_node_object(
361360
return
362361
node = get_plugwise_node(
363362
mac,
364-
address,
365363
self._controller,
366364
self._notify_node_event_subscribers,
367365
node_type,
@@ -371,7 +369,7 @@ async def _create_node_object(
371369
return
372370
self._nodes[mac] = node
373371
_LOGGER.debug("%s node %s added", node.__class__.__name__, mac)
374-
await self._register.update_network_registration(address, mac, node_type)
372+
await self._register.update_network_nodetype(mac, node_type)
375373

376374
if self._cache_enabled:
377375
_LOGGER.debug(
@@ -385,16 +383,13 @@ async def _create_node_object(
385383

386384
async def _discover_battery_powered_node(
387385
self,
388-
address: int,
389386
mac: str,
390387
) -> bool:
391388
"""Discover a battery powered node and add it to list of nodes.
392389
393390
Return True if discovery succeeded.
394391
"""
395-
if not await self._discover_node(
396-
address, mac, node_type=None, ping_first=False
397-
):
392+
if not await self._discover_node(mac, node_type=None, ping_first=False):
398393
return False
399394
if await self._load_node(mac):
400395
await self._notify_node_event_subscribers(NodeEvent.AWAKE, mac)
@@ -403,7 +398,6 @@ async def _discover_battery_powered_node(
403398

404399
async def _discover_node(
405400
self,
406-
address: int,
407401
mac: str,
408402
node_type: NodeType | None,
409403
ping_first: bool = True,
@@ -420,16 +414,18 @@ async def _discover_node(
420414
return True
421415

422416
if node_type is not None:
423-
await self._create_node_object(mac, address, node_type)
417+
await self._create_node_object(mac, node_type)
424418
await self._notify_node_event_subscribers(NodeEvent.DISCOVERED, mac)
425419
return True
426420

427421
# Node type is unknown, so we need to discover it first
428422
_LOGGER.debug("Starting the discovery of node %s with unknown NodeType", mac)
429423
node_info, node_ping = await self._controller.get_node_details(mac, ping_first)
430424
if node_info is None:
425+
_LOGGER.debug("Node %s with unknown NodeType not responding", mac)
426+
self._registry_stragglers.append(mac)
431427
return False
432-
await self._create_node_object(mac, address, node_info.node_type)
428+
await self._create_node_object(mac, node_info.node_type)
433429

434430
# Forward received NodeInfoResponse message to node
435431
await self._nodes[mac].message_for_node(node_info)
@@ -438,41 +434,16 @@ async def _discover_node(
438434
await self._notify_node_event_subscribers(NodeEvent.DISCOVERED, mac)
439435
return True
440436

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-
464437
async def _discover_stragglers(self) -> None:
465438
"""Repeat Discovery of Nodes with unknown NodeType."""
466439
while len(self._registry_stragglers) > 0:
467440
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
441+
for mac in self._registry_stragglers:
442+
if not await self._discover_node(mac, None):
443+
self._registry_stragglers.remove(mac)
473444
_LOGGER.debug(
474445
"Total %s nodes unreachable having unknown NodeType",
475-
str(len(stragglers)),
446+
str(len(self._registry_stragglers)),
476447
)
477448

478449
async def _load_node(self, mac: str) -> bool:
@@ -526,19 +497,22 @@ async def _unload_discovered_nodes(self) -> None:
526497
# region - Network instance
527498
async def start(self) -> None:
528499
"""Start and activate network."""
529-
self._register.quick_scan_finished(self._discover_registered_nodes)
530-
self._register.full_scan_finished(self._discover_registered_nodes)
500+
self._register.start_node_discover(self._discover_node)
531501
await self._register.start()
532502
self._subscribe_to_protocol_events()
533503
await self._subscribe_to_node_events()
534504
self._is_running = True
505+
if len(self._registry_stragglers) > 0 and (
506+
self._discover_stragglers_task is None
507+
or self._discover_stragglers_task.done()
508+
):
509+
self._discover_stragglers_task = create_task(self._discover_stragglers())
535510

536511
async def discover_nodes(self, load: bool = True) -> bool:
537512
"""Discover nodes."""
538513
await self.discover_network_coordinator(load=load)
539514
if not self._is_running:
540515
await self.start()
541-
await self._discover_registered_nodes()
542516
if load and not await self._load_discovered_nodes():
543517
self._load_stragglers_task = create_task(self._load_stragglers())
544518
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)