[esphome][core] Give a lost OTA chunk ack time to be retransmitted

This commit is contained in:
J. Nick Koston
2026-09-08 15:39:00 +02:00
parent f91486305f
commit e9f25a55b0
2 changed files with 9 additions and 4 deletions
@@ -41,7 +41,10 @@ const noise::NoiseContext &ESPHomeOTAComponent::noise_context_() const {
#endif
static constexpr uint16_t OTA_BLOCK_SIZE = 8192;
static constexpr uint32_t OTA_SOCKET_TIMEOUT_HANDSHAKE = 20000; // milliseconds for initial handshake
static constexpr uint32_t OTA_SOCKET_TIMEOUT_DATA = 90000; // milliseconds for data transfer
// Milliseconds for data transfer. Outlasts lwIP retransmitting a lost chunk ack
// six times (1.5 + 3 + 6 + 12 + 24 + 48 s); the CLI waits longer (160 s) so the
// device is always free again before the CLI retries
static constexpr uint32_t OTA_SOCKET_TIMEOUT_DATA = 105000;
// Single-instance pointer — multi-port configs are rejected in final_validate.
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
+5 -3
View File
@@ -694,8 +694,10 @@ def perform_ota(
_LOGGER.info("Handshake complete")
# Timeout must match device-side OTA_SOCKET_TIMEOUT_DATA to prevent premature failures
sock.settimeout(90.0)
# Longer than the device's OTA_SOCKET_TIMEOUT_DATA (105 s) so a stalled
# session is gone before a retry, and long enough for lwIP to get a lost
# chunk ack through after six retransmissions
sock.settimeout(160.0)
if extended_proto:
send_check(sock, ota_type, "ota type")
@@ -854,7 +856,7 @@ def run_ota_impl_(
# clean up a half-open connection (its handshake watchdog runs at 20s);
# moving on to the next address family stays immediate. Known limitation:
# a silent mid-transfer drop with no reset can wedge the device until its
# 90s data timeout, which outlasts this budget; the retries target the
# 105s data timeout, which outlasts this budget; the retries target the
# common failures where the device resets or closes the link promptly.
total_attempts = len(res) + EXTRA_UPLOAD_ATTEMPTS
last_error = ""