mirror of
https://github.com/esphome/esphome.git
synced 2026-08-22 22:26:21 +00:00
[nextion] Reconnect stale HTTP connection during TFT upload (#17824)
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user