3232 CONF_USE_THREAD ,
3333 CONFIG_SCHEMA ,
3434)
35- from bellows .exception import ControllerError , EzspError , StackAlreadyRunning
35+ from bellows .exception import (
36+ ControllerError ,
37+ EzspError ,
38+ InvalidCommandError ,
39+ StackAlreadyRunning ,
40+ )
3641import bellows .ezsp
3742from bellows .ezsp .xncp import FirmwareFeatures
3843import bellows .multicast
@@ -259,6 +264,29 @@ async def start_network(self):
259264 LOGGER .debug ("Setting adapter concurrency to %d" , max_concurrent_requests )
260265 self ._concurrent_requests_semaphore .max_concurrency = max_concurrent_requests
261266
267+ backup = self .backups .most_recent_backup ()
268+ if backup is not None :
269+ await self ._restore_route_table (backup .network_info .route_table )
270+
271+ async def _restore_route_table (self , route_table : dict [t .NWK , t .NWK ]) -> None :
272+ if FirmwareFeatures .RESTORE_ROUTE_TABLE not in self ._ezsp ._xncp_features :
273+ LOGGER .debug (
274+ "Firmware does not support writing route table, cannot restore"
275+ )
276+ return
277+
278+ LOGGER .debug ("Restoring route table: %s" , route_table )
279+
280+ for index , (dest , next_hop ) in enumerate (route_table .items ()):
281+ # We unconditionally restore route table entries
282+ await self ._ezsp .xncp_set_route_table_entry (
283+ index = index ,
284+ destination = dest ,
285+ next_hop = next_hop ,
286+ status = t .RouteRecordStatus .ACTIVE_AGE_2 ,
287+ cost = 0 , # unused
288+ )
289+
262290 async def load_network_info (self , * , load_devices = False ) -> None :
263291 ezsp = self ._ezsp
264292
@@ -336,6 +364,7 @@ async def load_network_info(self, *, load_devices=False) -> None:
336364 key_table = [],
337365 children = [],
338366 nwk_addresses = {},
367+ tx_power = nwk_params .radioTxPower ,
339368 stack_specific = stack_specific ,
340369 metadata = {
341370 "ezsp" : {
@@ -369,6 +398,31 @@ async def load_network_info(self, *, load_devices=False) -> None:
369398 async for nwk , eui64 in ezsp .read_address_table ():
370399 self .state .network_info .nwk_addresses [eui64 ] = nwk
371400
401+ if FirmwareFeatures .RESTORE_ROUTE_TABLE in ezsp ._xncp_features :
402+ (status , route_table_size ) = await ezsp .getConfigurationValue (
403+ t .EzspConfigId .CONFIG_ROUTE_TABLE_SIZE
404+ )
405+
406+ for index in range (route_table_size ):
407+ try :
408+ rsp = await ezsp .xncp_get_route_table_entry (index = index )
409+ except InvalidCommandError :
410+ break
411+
412+ if (
413+ rsp .status
414+ not in (
415+ t .RouteRecordStatus .ACTIVE_AGE_0 ,
416+ t .RouteRecordStatus .ACTIVE_AGE_1 ,
417+ t .RouteRecordStatus .ACTIVE_AGE_2 ,
418+ )
419+ or rsp .destination == 0xFFFF
420+ or rsp .next_hop == 0xFFFF
421+ ):
422+ continue
423+
424+ self .state .network_info .route_table [rsp .destination ] = rsp .next_hop
425+
372426 async def can_write_network_settings (
373427 self ,
374428 * ,
@@ -468,7 +522,7 @@ async def write_network_info(
468522 parameters = t .EmberNetworkParameters ()
469523 parameters .panId = t .EmberPanId (network_info .pan_id )
470524 parameters .extendedPanId = t .EUI64 (network_info .extended_pan_id )
471- parameters .radioTxPower = t .uint8_t (8 )
525+ parameters .radioTxPower = t .uint8_t (network_info . tx_power )
472526 parameters .radioChannel = t .uint8_t (network_info .channel )
473527 parameters .joinMethod = t .EmberJoinMethod .USE_MAC_ASSOCIATION
474528 parameters .nwkManagerId = t .EmberNodeId (network_info .nwk_manager_id )
@@ -495,6 +549,8 @@ async def write_network_info(
495549
496550 await self ._ensure_network_running ()
497551
552+ await self ._restore_route_table (network_info .route_table )
553+
498554 async def reset_network_info (self ):
499555 await self ._ezsp .factory_reset ()
500556
0 commit comments