Skip to content

Commit b05c9b4

Browse files
authored
Do multiple ping attempts when discovering a node (#600)
1 parent d03cf0c commit b05c9b4

File tree

2 files changed

+18
-11
lines changed

2 files changed

+18
-11
lines changed

matter_server/server/device_controller.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -710,7 +710,7 @@ async def subscribe_attribute(
710710
)
711711

712712
@api_command(APICommand.PING_NODE)
713-
async def ping_node(self, node_id: int) -> NodePingResult:
713+
async def ping_node(self, node_id: int, attempts: int = 1) -> NodePingResult:
714714
"""Ping node on the currently known IP-adress(es)."""
715715
result: NodePingResult = {}
716716
node = self._nodes.get(node_id)
@@ -741,7 +741,7 @@ async def _do_ping(ip_address: str) -> None:
741741
else:
742742
clean_ip = ip_address
743743
node_logger.debug("Pinging address %s", clean_ip)
744-
result[clean_ip] = await ping_ip(ip_address, timeout)
744+
result[clean_ip] = await ping_ip(ip_address, timeout, attempts=attempts)
745745

746746
ip_addresses = await self.get_node_ip_addresses(
747747
node_id, prefer_cache=False, scoped=True
@@ -1058,7 +1058,7 @@ async def _setup_node(self, node_id: int) -> None:
10581058
# Ping the node to rule out stale mdns reports and to prevent that we
10591059
# send an unreachable node to the sdk which is very slow with resolving it.
10601060
# This will also precache the ip addresses of the node for later use.
1061-
ping_result = await self.ping_node(node_id)
1061+
ping_result = await self.ping_node(node_id, attempts=3)
10621062
if not any(ping_result.values()):
10631063
LOGGER.warning(
10641064
"Skip set-up for node %s because it does not appear to be reachable...",

matter_server/server/helpers/utils.py

+15-8
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
PLATFORM_MAC = platform.system() == "Darwin"
99

1010

11-
async def ping_ip(ip_address: str, timeout: int = 2) -> bool:
11+
async def ping_ip(ip_address: str, timeout: int = 2, attempts: int = 1) -> bool:
1212
"""Ping given (IPv4 or IPv6) IP-address."""
1313
is_ipv6 = ":" in ip_address
1414
if is_ipv6 and PLATFORM_MAC:
@@ -18,13 +18,20 @@ async def ping_ip(ip_address: str, timeout: int = 2) -> bool:
1818
cmd = f"ping6 -c 1 -W {timeout} {ip_address}"
1919
else:
2020
cmd = f"ping -c 1 -W {timeout} {ip_address}"
21-
try:
22-
# we add an additional timeout here as safeguard and to account for the fact
23-
# that macos does not seem to have timeout on ping6
24-
async with async_timeout.timeout(timeout + 2):
25-
return (await check_output(cmd))[0] == 0
26-
except asyncio.TimeoutError:
27-
return False
21+
while attempts:
22+
attempts -= 1
23+
try:
24+
# we add an additional timeout here as safeguard and to account for the fact
25+
# that macos does not seem to have timeout on ping6
26+
async with async_timeout.timeout(timeout + 2):
27+
success = (await check_output(cmd))[0] == 0
28+
if success or not attempts:
29+
return success
30+
except asyncio.TimeoutError:
31+
pass
32+
# sleep between attempts
33+
await asyncio.sleep(10)
34+
return False
2835

2936

3037
async def check_output(shell_cmd: str) -> tuple[int | None, bytes]:

0 commit comments

Comments
 (0)