[nextion] Reconnect stale HTTP connection during TFT upload (#17824)

This commit is contained in:
Keith Burzinski
2026-07-31 23:05:45 -05:00
committed by GitHub
parent ce9b221be4
commit 1df2759db6
@@ -44,17 +44,60 @@ int Nextion::upload_by_chunks_(esp_http_client_handle_t http_client, uint32_t &r
ESP_LOGV(TAG, "Range: %s", range_header);
esp_http_client_set_header(http_client, "Range", range_header);
ESP_LOGV(TAG, "Open HTTP");
esp_err_t err = esp_http_client_open(http_client, 0);
if (err != ESP_OK) {
ESP_LOGE(TAG, "HTTP open failed: %s", esp_err_to_name(err));
return -1;
int chunk_size = -1;
int status_code = -1;
esp_err_t last_err = ESP_FAIL;
for (uint8_t attempt = 0; attempt < this->tft_upload_http_retries_; attempt++) {
status_code = -1;
last_err = esp_http_client_open(http_client, 0);
if (last_err == ESP_OK) {
ESP_LOGV(TAG, "Fetch length");
chunk_size = esp_http_client_fetch_headers(http_client);
ESP_LOGV(TAG, "Length: %d", chunk_size);
if (chunk_size >= 0) {
status_code = esp_http_client_get_status_code(http_client);
// Accept the requested range (206 with exact length) or a full-body 200
// only from offset 0; elsewhere a 200 replays the file and corrupts the display.
if (chunk_size > 0 &&
((status_code == 206 && chunk_size == static_cast<int>(range_end - range_start + 1)) ||
(status_code == 200 && range_start == 0 && chunk_size == static_cast<int>(this->tft_size_)))) {
break;
}
if (status_code == 200) {
if (range_start == 0) {
ESP_LOGE(TAG, "Unexpected length for 200 response: %d (expected %d)", chunk_size,
static_cast<int>(this->tft_size_));
} else {
// A server that ignored the range once will ignore it again
ESP_LOGE(TAG, "Server does not support range requests (got 200 at offset %" PRIu32 ")", range_start);
}
chunk_size = -1;
last_err = ESP_FAIL;
break;
}
ESP_LOGW(TAG, "Bad response: status %d, length %d (expected %" PRIu32 ")", status_code, chunk_size,
range_end - range_start + 1);
chunk_size = -1;
last_err = ESP_FAIL;
// A 4xx (except timeout/rate-limit) won't improve on retry
if (status_code >= 400 && status_code < 500 && status_code != 408 && status_code != 429) {
break;
}
} else {
ESP_LOGW(TAG, "Get length failed: %d", chunk_size);
last_err = ESP_FAIL;
}
} else {
ESP_LOGW(TAG, "HTTP open failed: %s", esp_err_to_name(last_err));
}
// The server may have dropped the keep-alive connection while the display
// was busy processing a chunk; close so the next attempt reconnects.
esp_http_client_close(http_client);
vTaskDelay(pdMS_TO_TICKS(2)); // NOLINT
App.feed_wdt();
}
ESP_LOGV(TAG, "Fetch length");
const int chunk_size = esp_http_client_fetch_headers(http_client);
ESP_LOGV(TAG, "Length: %d", chunk_size);
if (chunk_size <= 0) {
ESP_LOGE(TAG, "Get length failed: %d", chunk_size);
ESP_LOGE(TAG, "HTTP request failed, last status: %d, last error: %s", status_code, esp_err_to_name(last_err));
return -1;
}
@@ -164,6 +207,9 @@ int Nextion::upload_by_chunks_(esp_http_client_handle_t http_client, uint32_t &r
} else {
range_start = range_end + 1;
}
// The response body may be only partially read; close so the next
// range request starts on a clean connection.
esp_http_client_close(http_client);
// Deallocate buffer
allocator.deallocate(buffer, 4096);
buffer = nullptr;