From 397b164eeec7e8688a71817a559268b036fc2d80 Mon Sep 17 00:00:00 2001 From: Ryan Malloy Date: Mon, 2 Feb 2026 19:45:01 -0700 Subject: [PATCH] Add ready probe to esp32_connect for reliable startup The boot event fires early in app_main before the UART command handler task is fully initialised. This means the first command after connect can get lost, causing transient ping timeouts. Now esp32_connect retries a ping (up to 5 attempts, 1s timeout each) after the boot-event wait, so it only returns "connected" when the firmware is actually responsive. --- src/mcbluetooth_esp32/tools/connection.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/mcbluetooth_esp32/tools/connection.py b/src/mcbluetooth_esp32/tools/connection.py index 993e88b..15fab26 100644 --- a/src/mcbluetooth_esp32/tools/connection.py +++ b/src/mcbluetooth_esp32/tools/connection.py @@ -8,7 +8,7 @@ from typing import Any from fastmcp import FastMCP from ..protocol import CMD_GET_INFO, CMD_GET_STATUS, CMD_PING, CMD_RESET, Status -from ..serial_client import NotConnected, get_client, init_client +from ..serial_client import CommandTimeout, NotConnected, get_client, init_client def register_tools(mcp: FastMCP) -> None: @@ -51,11 +51,25 @@ def register_tools(mcp: FastMCP) -> None: except TimeoutError: pass + # Ready probe: retry ping until the firmware's command handler is up. + # The boot event fires early in app_main, before the UART command + # task is fully initialised, so the first command can get lost. + ready = False + for attempt in range(5): + try: + resp = await client.send_command(CMD_PING, timeout=1.0) + if resp.status == Status.OK: + ready = True + break + except (CommandTimeout, NotConnected): + await asyncio.sleep(0.3) + return { "connected": True, "port": port, "baudrate": baudrate, "boot_event": boot_received, + "ready": ready, } @mcp.tool()