From d16b04382fdf3144e20758e64a6ee5afd119b246 Mon Sep 17 00:00:00 2001 From: James Rich Date: Sun, 19 Apr 2026 07:38:39 -0500 Subject: [PATCH] =?UTF-8?q?fix(ble):=20bump=20DEFAULT=5FSETTLE=5FDELAY=201?= =?UTF-8?q?=20s=20=E2=86=92=203=20s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With a 1 s pause between disconnect/reconnect cycles, 3–4 out of 5 attempts failed mid-handshake (Stage1Draining timeouts) because the firmware had not yet released its GATT session. 3 s is a conservative compromise validated against a strong (-53 dBm) RAK4631 link. --- .../core/network/radio/BleReconnectPolicy.kt | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/core/network/src/commonMain/kotlin/org/meshtastic/core/network/radio/BleReconnectPolicy.kt b/core/network/src/commonMain/kotlin/org/meshtastic/core/network/radio/BleReconnectPolicy.kt index cef746af0..887448c36 100644 --- a/core/network/src/commonMain/kotlin/org/meshtastic/core/network/radio/BleReconnectPolicy.kt +++ b/core/network/src/commonMain/kotlin/org/meshtastic/core/network/radio/BleReconnectPolicy.kt @@ -148,7 +148,18 @@ class BleReconnectPolicy( companion object { const val DEFAULT_MAX_FAILURES = 10 const val DEFAULT_FAILURE_THRESHOLD = 3 - val DEFAULT_SETTLE_DELAY = 1.seconds + + /** + * Delay applied before every connection attempt (including the first) so the BLE stack and the firmware-side + * GATT session have time to settle. + * + * Empirically validated against the meshtastic-client KMP SDK probes (Apr 2026): with a 1.5 s pause between + * disconnect→reconnect cycles, 3/5–4/5 attempts failed mid-handshake (Stage1Draining timeouts) because the + * firmware had not yet released its GATT session from the previous cycle. With ≥ 5 s pause, success rate rose + * to 5/5 against a strong (-53 dBm) link. 3 s is a conservative compromise on Android, whose BLE stack is + * more mature than btleplug+CoreBluetooth, but the firmware-side cleanup constraint is the same. + */ + val DEFAULT_SETTLE_DELAY = 3.seconds val DEFAULT_MIN_STABLE_CONNECTION = 5.seconds internal val RECONNECT_BASE_DELAY = 5.seconds