[nextion] Add configurable HTTP parameters for TFT upload (#14234)

Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
Edward Firmo
2026-03-09 02:29:41 +01:00
committed by GitHub
parent 6ba5c9a705
commit cac751e9e8
11 changed files with 132 additions and 23 deletions
@@ -27,6 +27,9 @@ CONF_PRECISION = "precision"
CONF_SKIP_CONNECTION_HANDSHAKE = "skip_connection_handshake"
CONF_START_UP_PAGE = "start_up_page"
CONF_STARTUP_OVERRIDE_MS = "startup_override_ms"
CONF_TFT_UPLOAD_HTTP_RETRIES = "tft_upload_http_retries"
CONF_TFT_UPLOAD_HTTP_TIMEOUT = "tft_upload_http_timeout"
CONF_TFT_UPLOAD_WATCHDOG_TIMEOUT = "tft_upload_watchdog_timeout"
CONF_TFT_URL = "tft_url"
CONF_TOUCH_SLEEP_TIMEOUT = "touch_sleep_timeout"
CONF_VARIABLE_NAME = "variable_name"
+62 -4
View File
@@ -33,15 +33,24 @@ from .base_component import (
CONF_SKIP_CONNECTION_HANDSHAKE,
CONF_START_UP_PAGE,
CONF_STARTUP_OVERRIDE_MS,
CONF_TFT_UPLOAD_HTTP_RETRIES,
CONF_TFT_UPLOAD_HTTP_TIMEOUT,
CONF_TFT_UPLOAD_WATCHDOG_TIMEOUT,
CONF_TFT_URL,
CONF_TOUCH_SLEEP_TIMEOUT,
CONF_WAKE_UP_PAGE,
)
CODEOWNERS = ["@senexcrenshaw", "@edwardtfn"]
DEPENDENCIES = ["uart"]
AUTO_LOAD = ["binary_sensor", "switch", "sensor", "text_sensor"]
def AUTO_LOAD() -> list[str]:
base = ["binary_sensor", "switch", "sensor", "text_sensor"]
if CORE.is_esp32:
base.append("watchdog")
return base
NextionSetBrightnessAction = nextion_ns.class_(
"NextionSetBrightnessAction", automation.Action
@@ -55,7 +64,24 @@ BufferOverflowTrigger = nextion_ns.class_(
"BufferOverflowTrigger", automation.Trigger.template()
)
CONFIG_SCHEMA = (
def _validate_tft_upload(config):
has_tft_url = CONF_TFT_URL in config
for conf_key in (
CONF_TFT_UPLOAD_HTTP_TIMEOUT,
CONF_TFT_UPLOAD_HTTP_RETRIES,
CONF_TFT_UPLOAD_WATCHDOG_TIMEOUT,
):
if conf_key in config and not has_tft_url:
raise cv.Invalid(f"{conf_key} requires {CONF_TFT_URL} to be set")
if CONF_TFT_UPLOAD_WATCHDOG_TIMEOUT in config and not CORE.is_esp32:
raise cv.Invalid(
f"{CONF_TFT_UPLOAD_WATCHDOG_TIMEOUT} is only available on ESP32"
)
return config
CONFIG_SCHEMA = cv.All(
display.BASIC_DISPLAY_SCHEMA.extend(
{
cv.GenerateID(): cv.declare_id(Nextion),
@@ -115,6 +141,14 @@ CONFIG_SCHEMA = (
),
),
cv.Optional(CONF_START_UP_PAGE): cv.uint8_t,
cv.Optional(CONF_TFT_UPLOAD_HTTP_RETRIES): cv.int_range(min=1, max=255),
cv.Optional(CONF_TFT_UPLOAD_HTTP_TIMEOUT): cv.All(
cv.positive_time_period_milliseconds,
cv.Range(max=TimePeriod(milliseconds=65535)),
),
cv.Optional(
CONF_TFT_UPLOAD_WATCHDOG_TIMEOUT
): cv.positive_time_period_milliseconds,
cv.Optional(CONF_TFT_URL): cv.url,
cv.Optional(CONF_TOUCH_SLEEP_TIMEOUT): cv.Any(
0, cv.int_range(min=3, max=65535)
@@ -123,7 +157,8 @@ CONFIG_SCHEMA = (
}
)
.extend(cv.polling_component_schema("5s"))
.extend(uart.UART_DEVICE_SCHEMA)
.extend(uart.UART_DEVICE_SCHEMA),
_validate_tft_upload,
)
@@ -176,6 +211,29 @@ async def to_code(config):
if CONF_TFT_URL in config:
cg.add_define("USE_NEXTION_TFT_UPLOAD")
cg.add(var.set_tft_url(config[CONF_TFT_URL]))
# TFT upload HTTP timeout (default: 4.5s)
if CONF_TFT_UPLOAD_HTTP_TIMEOUT in config:
cg.add(
var.set_tft_upload_http_timeout(
config[CONF_TFT_UPLOAD_HTTP_TIMEOUT].total_milliseconds
)
)
# TFT upload HTTP retries (default: 5)
if CONF_TFT_UPLOAD_HTTP_RETRIES in config:
cg.add(
var.set_tft_upload_http_retries(config[CONF_TFT_UPLOAD_HTTP_RETRIES])
)
# TFT upload watchdog timeout (default: 0 = no adjustment)
if CONF_TFT_UPLOAD_WATCHDOG_TIMEOUT in config:
cg.add(
var.set_tft_upload_watchdog_timeout(
config[CONF_TFT_UPLOAD_WATCHDOG_TIMEOUT].total_milliseconds
)
)
if CORE.is_esp32:
# Re-enable ESP-IDF's HTTP client (excluded by default to save compile time)
esp32.include_builtin_idf_component("esp_http_client")
+12
View File
@@ -191,6 +191,18 @@ void Nextion::dump_config() {
#ifdef USE_NEXTION_MAX_QUEUE_SIZE
ESP_LOGCONFIG(TAG, " Max queue size: %zu", this->max_queue_size_);
#endif
#ifdef USE_NEXTION_TFT_UPLOAD
ESP_LOGCONFIG(TAG,
" TFT URL: %s\n"
" TFT upload HTTP timeout: %" PRIu16 "ms\n"
" TFT upload HTTP retries: %u",
this->tft_url_.c_str(), this->tft_upload_http_timeout_, this->tft_upload_http_retries_);
#ifdef USE_ESP32
if (this->tft_upload_watchdog_timeout_ > 0) {
ESP_LOGCONFIG(TAG, " TFT upload WDT timeout: %" PRIu32 "ms", this->tft_upload_watchdog_timeout_);
}
#endif // USE_ESP32
#endif // USE_NEXTION_TFT_UPLOAD
}
void Nextion::update() {
+31
View File
@@ -1071,6 +1071,33 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe
bool send_command_printf(const char *format, ...) __attribute__((format(printf, 2, 3)));
#ifdef USE_NEXTION_TFT_UPLOAD
/**
* @brief Set the HTTP timeout for TFT upload requests.
* @param timeout_ms Timeout in milliseconds. Defaults to 4500ms (4.5s).
*/
void set_tft_upload_http_timeout(uint16_t timeout_ms) { this->tft_upload_http_timeout_ = timeout_ms; }
#ifdef USE_ESP32
/**
* @brief Set the watchdog timeout during TFT upload.
*
* The system watchdog timeout is temporarily adjusted to this value
* during the entire TFT transfer process and restored to the original
* value after the transfer completes (whether successful or not).
*
* A value of 0 means no watchdog adjustment (default).
*
* @param timeout_ms Watchdog timeout in milliseconds. 0 = no adjustment.
*/
void set_tft_upload_watchdog_timeout(uint32_t timeout_ms) { this->tft_upload_watchdog_timeout_ = timeout_ms; }
#endif // USE_ESP32
/**
* @brief Set the number of HTTP retries for TFT upload requests.
* @param retries Number of retries. Defaults to 5. Range: 1-255.
*/
void set_tft_upload_http_retries(uint8_t retries) { this->tft_upload_http_retries_ = retries; }
/**
* Set the tft file URL.
*/
@@ -1439,8 +1466,12 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe
int tft_size_ = 0;
uint32_t original_baud_rate_ = 0;
bool upload_first_chunk_sent_ = false;
uint16_t tft_upload_http_timeout_{4500}; ///< HTTP timeout in ms (default: 4.5s)
uint8_t tft_upload_http_retries_{5}; ///< HTTP retry count (default: 5)
#ifdef USE_ESP32
uint32_t tft_upload_watchdog_timeout_{0}; ///< WDT timeout in ms (0 = no adjustment)
/**
* will request 4096 bytes chunks from the web server
* and send each to Nextion
@@ -166,7 +166,7 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) {
// Define the configuration for the HTTP client
ESP_LOGV(TAG, "Init HTTP client, heap: %" PRIu32, EspClass::getFreeHeap());
HTTPClient http_client;
http_client.setTimeout(15000); // Yes 15 seconds.... Helps 8266s along
http_client.setTimeout(this->tft_upload_http_timeout_);
bool begin_status = false;
#ifdef USE_ESP8266
@@ -192,15 +192,15 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) {
http_client.collectHeaders(header_names, 1);
ESP_LOGD(TAG, "URL: %s", this->tft_url_.c_str());
http_client.setReuse(true);
// try up to 5 times. DNS sometimes needs a second try or so
int tries = 1;
int code = http_client.GET();
delay(100); // NOLINT
App.feed_wdt();
while (code != 200 && code != 206 && tries <= 5) {
ESP_LOGW(TAG, "HTTP fail: URL: %s; Error: %s, retry %d/5", this->tft_url_.c_str(),
HTTPClient::errorToString(code).c_str(), tries);
while (code != 200 && code != 206 && tries <= this->tft_upload_http_retries_) {
ESP_LOGW(TAG, "HTTP fail: URL: %s; Error: %s, retry %d/%u", this->tft_url_.c_str(),
HTTPClient::errorToString(code).c_str(), tries, this->tft_upload_http_retries_);
delay(250); // NOLINT
App.feed_wdt();
@@ -7,6 +7,7 @@
#include <esp_http_client.h>
#include <cinttypes>
#include "esphome/components/network/util.h"
#include "esphome/components/watchdog/watchdog.h"
#include "esphome/core/application.h"
#include "esphome/core/defines.h"
#include "esphome/core/helpers.h"
@@ -68,7 +69,7 @@ int Nextion::upload_by_chunks_(esp_http_client_handle_t http_client, uint32_t &r
int partial_read_len = 0;
uint8_t retries = 0;
// Attempt to read the chunk with retries.
while (retries < 5 && read_len < buffer_size) {
while (retries < this->tft_upload_http_retries_ && read_len < buffer_size) {
partial_read_len =
esp_http_client_read(http_client, reinterpret_cast<char *>(buffer) + read_len, buffer_size - read_len);
if (partial_read_len > 0) {
@@ -167,6 +168,9 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) {
return false;
}
// Temporarily adjust watchdog timeout for the duration of the TFT upload
watchdog::WatchdogManager wdm(this->tft_upload_watchdog_timeout_);
this->connection_state_.is_updating_ = true;
if (exit_reparse) {
@@ -190,7 +194,7 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) {
.url = this->tft_url_.c_str(),
.cert_pem = nullptr,
.method = HTTP_METHOD_HEAD,
.timeout_ms = 15000,
.timeout_ms = static_cast<int>(this->tft_upload_http_timeout_),
.disable_auto_redirect = false,
.max_redirection_count = 10,
};
@@ -0,0 +1,5 @@
display:
- id: !extend main_lcd
tft_url: http://esphome.io/default35.tft
tft_upload_http_timeout: 20s
tft_upload_http_retries: 10
@@ -0,0 +1,3 @@
display:
- id: !extend main_lcd
tft_upload_watchdog_timeout: 30s
+2 -4
View File
@@ -1,7 +1,5 @@
packages:
uart: !include ../../test_build_components/common/uart/esp32-ard.yaml
base: !include common.yaml
display:
- id: !extend main_lcd
tft_url: http://esphome.io/default35.tft
tft_upload: !include common_tft_upload.yaml
tft_upload_watchdog: !include common_tft_upload_watchdog.yaml
+2 -4
View File
@@ -1,7 +1,5 @@
packages:
uart: !include ../../test_build_components/common/uart/esp32-idf.yaml
base: !include common.yaml
display:
- id: !extend main_lcd
tft_url: http://esphome.io/default35.tft
tft_upload: !include common_tft_upload.yaml
tft_upload_watchdog: !include common_tft_upload_watchdog.yaml
@@ -1,7 +1,4 @@
packages:
uart: !include ../../test_build_components/common/uart/esp8266-ard.yaml
base: !include common.yaml
display:
- id: !extend main_lcd
tft_url: http://esphome.io/default35.tft
tft_upload: !include common_tft_upload.yaml