Skip to content

Commit

Permalink
Override Liveness timeout on shutdown (#771)
Browse files Browse the repository at this point in the history
Co-authored-by: Martin Hjelmare <[email protected]>
  • Loading branch information
agners and MartinHjelmare authored Jun 25, 2024
1 parent b21a6dd commit 08b1335
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 4 deletions.
39 changes: 35 additions & 4 deletions matter_server/server/device_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
NODE_SUBSCRIPTION_CEILING_BATTERY_POWERED = 600
NODE_RESUBSCRIBE_ATTEMPTS_UNAVAILABLE = 3
NODE_RESUBSCRIBE_TIMEOUT_OFFLINE = 30 * 60 * 1000
NODE_RESUBSCRIBE_FORCE_TIMEOUT = 5
NODE_PING_TIMEOUT = 10
NODE_PING_TIMEOUT_BATTERY_POWERED = 60
NODE_MDNS_BACKOFF = 610 # must be higher than (highest) sub ceiling
Expand Down Expand Up @@ -978,7 +979,10 @@ def event_callback(
self.event_history.append(node_event)

if isinstance(data.Data, Clusters.BasicInformation.Events.ShutDown):
self._node_unavailable(node_id)
# Force resubscription after a shutdown event. Otherwise we'd have to
# wait for up to NODE_SUBSCRIPTION_CEILING_BATTERY_POWERED minutes for
# the SDK to notice the device is gone.
self._node_unavailable(node_id, True)

self.server.signal_event(EventType.NODE_EVENT, node_event)

Expand Down Expand Up @@ -1359,15 +1363,41 @@ def _write_node_state(self, node_id: int, force: bool = False) -> None:
force=force,
)

def _node_unavailable(self, node_id: int) -> None:
def _node_unavailable(
self, node_id: int, force_resubscription: bool = False
) -> None:
"""Mark node as unavailable."""
# mark node as unavailable (if it wasn't already)
node = self._nodes[node_id]
if not node.available:
return
node.available = False
self.server.signal_event(EventType.NODE_UPDATED, node)
LOGGER.info("Marked node %s as unavailable", node_id)
node_logger = LOGGER.getChild(f"node_{node_id}")
node_logger.info("Marked node as unavailable")
if force_resubscription:
# Make sure the subscriptions are expiring very soon to trigger subscription
# resumption logic quickly. This is especially important for battery operated
# devices so subscription resumption logic kicks in quickly.
node_logger.info(
"Forcing subscription timeout in %ds", NODE_RESUBSCRIBE_FORCE_TIMEOUT
)
asyncio.create_task(
self._chip_device_controller.subscription_override_liveness_timeout(
node_id, NODE_RESUBSCRIBE_FORCE_TIMEOUT * 1000
)
)
# Clear the timeout soon after the scheduled timeout above. This causes the
# SDK to use the default liveness timeout again, which is what we want for
# the once resumed subscription.
self._loop.call_later(
NODE_RESUBSCRIBE_FORCE_TIMEOUT + 1,
lambda: asyncio.create_task(
self._chip_device_controller.subscription_override_liveness_timeout(
node_id, 0
)
),
)

async def _node_offline(self, node_id: int) -> None:
"""Mark node as offline."""
Expand All @@ -1379,7 +1409,8 @@ async def _node_offline(self, node_id: int) -> None:
return # nothing to do to
node.available = False
self.server.signal_event(EventType.NODE_UPDATED, node)
LOGGER.info("Marked node %s as offline", node_id)
node_logger = LOGGER.getChild(f"node_{node_id}")
node_logger.info("Marked node as offline")

async def _fallback_node_scanner(self) -> None:
"""Scan for operational nodes in the background that are missed by mdns."""
Expand Down
7 changes: 7 additions & 0 deletions matter_server/server/sdk.py
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,13 @@ async def shutdown_subscription(self, node_id: int) -> None:
if sub := self._subscriptions.pop(node_id, None):
await self._call_sdk(sub.Shutdown)

async def subscription_override_liveness_timeout(
self, node_id: int, liveness_timeout_ms: int
) -> None:
"""Override the liveness timeout for the subscription of the node."""
if sub := self._subscriptions.get(node_id):
await self._call_sdk(sub.OverrideLivenessTimeoutMs, liveness_timeout_ms)

def node_has_subscription(self, node_id: int) -> bool:
"""Check if a node has an active subscription."""
return node_id in self._subscriptions
Expand Down

0 comments on commit 08b1335

Please sign in to comment.