From 0707f383a69cbfc9c9d6365e1f43893ef16204ac Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Wed, 17 Dec 2025 17:45:17 +0100 Subject: [PATCH] [nextion] Use ESP-IDF for ESP32 Arduino (#9429) Co-authored-by: J. Nick Koston Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> --- esphome/components/nextion/__init__.py | 6 +- esphome/components/nextion/display.py | 5 +- esphome/components/nextion/nextion.h | 41 ++++------- .../nextion/nextion_upload_arduino.cpp | 73 ++++++++----------- ...pload_idf.cpp => nextion_upload_esp32.cpp} | 55 ++++++++------ 5 files changed, 84 insertions(+), 96 deletions(-) rename esphome/components/nextion/{nextion_upload_idf.cpp => nextion_upload_esp32.cpp} (90%) diff --git a/esphome/components/nextion/__init__.py b/esphome/components/nextion/__init__.py index 8adc49d68c1..38f449dc038 100644 --- a/esphome/components/nextion/__init__.py +++ b/esphome/components/nextion/__init__.py @@ -13,14 +13,16 @@ CONF_SEND_TO_NEXTION = "send_to_nextion" FILTER_SOURCE_FILES = filter_source_files_from_platform( { - "nextion_upload_arduino.cpp": { + "nextion_upload_esp32.cpp": { PlatformFramework.ESP32_ARDUINO, + PlatformFramework.ESP32_IDF, + }, + "nextion_upload_arduino.cpp": { PlatformFramework.ESP8266_ARDUINO, PlatformFramework.RP2040_ARDUINO, PlatformFramework.BK72XX_ARDUINO, PlatformFramework.RTL87XX_ARDUINO, PlatformFramework.LN882X_ARDUINO, }, - "nextion_upload_idf.cpp": {PlatformFramework.ESP32_IDF}, } ) diff --git a/esphome/components/nextion/display.py b/esphome/components/nextion/display.py index ed6cd930277..b95df55a61a 100644 --- a/esphome/components/nextion/display.py +++ b/esphome/components/nextion/display.py @@ -154,14 +154,11 @@ async def to_code(config): cg.add_define("USE_NEXTION_TFT_UPLOAD") cg.add(var.set_tft_url(config[CONF_TFT_URL])) if CORE.is_esp32: - if CORE.using_arduino: - cg.add_library("NetworkClientSecure", None) - cg.add_library("HTTPClient", None) esp32.add_idf_sdkconfig_option("CONFIG_ESP_TLS_INSECURE", True) esp32.add_idf_sdkconfig_option( "CONFIG_ESP_TLS_SKIP_SERVER_CERT_VERIFY", True ) - elif CORE.is_esp8266 and CORE.using_arduino: + elif CORE.is_esp8266: cg.add_library("ESP8266HTTPClient", None) if CONF_TOUCH_SLEEP_TIMEOUT in config: diff --git a/esphome/components/nextion/nextion.h b/esphome/components/nextion/nextion.h index 7e8f563a96c..f4fc50ee7d4 100644 --- a/esphome/components/nextion/nextion.h +++ b/esphome/components/nextion/nextion.h @@ -13,17 +13,12 @@ #include "esphome/components/display/display_color_utils.h" #ifdef USE_NEXTION_TFT_UPLOAD -#ifdef USE_ARDUINO #ifdef USE_ESP32 -#include -#endif // USE_ESP32 -#ifdef USE_ESP8266 +#include +#elif defined(USE_ESP8266) #include #include -#endif // USE_ESP8266 -#elif defined(USE_ESP_IDF) -#include -#endif // ARDUINO vs USE_ESP_IDF +#endif // USE_ESP32 vs USE_ESP8266 #endif // USE_NEXTION_TFT_UPLOAD namespace esphome { @@ -1078,7 +1073,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe #ifdef USE_NEXTION_TFT_UPLOAD /** - * Set the tft file URL. https seems problematic with Arduino.. + * Set the tft file URL. */ void set_tft_url(const std::string &tft_url) { this->tft_url_ = tft_url; } @@ -1422,16 +1417,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe uint32_t original_baud_rate_ = 0; bool upload_first_chunk_sent_ = false; -#ifdef USE_ARDUINO - /** - * will request chunk_size chunks from the web server - * and send each to the nextion - * @param HTTPClient http_client HTTP client handler. - * @param int range_start Position of next byte to transfer. - * @return position of last byte transferred, -1 for failure. - */ - int upload_by_chunks_(HTTPClient &http_client, uint32_t &range_start); -#elif defined(USE_ESP_IDF) +#ifdef USE_ESP32 /** * will request 4096 bytes chunks from the web server * and send each to Nextion @@ -1440,7 +1426,16 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * @return position of last byte transferred, -1 for failure. */ int upload_by_chunks_(esp_http_client_handle_t http_client, uint32_t &range_start); -#endif // USE_ARDUINO vs USE_ESP_IDF +#else + /** + * will request chunk_size chunks from the web server + * and send each to the nextion + * @param HTTPClient http_client HTTP client handler. + * @param int range_start Position of next byte to transfer. + * @return position of last byte transferred, -1 for failure. + */ + int upload_by_chunks_(HTTPClient &http_client, uint32_t &range_start); +#endif // USE_ESP32 vs others /** * Ends the upload process, restart Nextion and, if successful, @@ -1450,12 +1445,6 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe */ bool upload_end_(bool successful); - /** - * Returns the ESP Free Heap memory. This is framework independent. - * @return Free Heap in bytes. - */ - uint32_t get_free_heap_(); - #endif // USE_NEXTION_TFT_UPLOAD bool check_connect_(); diff --git a/esphome/components/nextion/nextion_upload_arduino.cpp b/esphome/components/nextion/nextion_upload_arduino.cpp index baea9387293..dfbb5a497ec 100644 --- a/esphome/components/nextion/nextion_upload_arduino.cpp +++ b/esphome/components/nextion/nextion_upload_arduino.cpp @@ -1,7 +1,7 @@ #include "nextion.h" #ifdef USE_NEXTION_TFT_UPLOAD -#ifdef USE_ARDUINO +#ifndef USE_ESP32 #include #include "esphome/components/network/util.h" @@ -10,10 +10,6 @@ #include "esphome/core/log.h" #include "esphome/core/util.h" -#ifdef USE_ESP32 -#include -#endif - namespace esphome { namespace nextion { static const char *const TAG = "nextion.upload.arduino"; @@ -21,23 +17,17 @@ static const char *const TAG = "nextion.upload.arduino"; // Followed guide // https://unofficialnextion.com/t/nextion-upload-protocol-v1-2-the-fast-one/1044/2 -inline uint32_t Nextion::get_free_heap_() { -#if defined(USE_ESP32) - return heap_caps_get_free_size(MALLOC_CAP_INTERNAL); -#elif defined(USE_ESP8266) - return EspClass::getFreeHeap(); -#endif // USE_ESP32 vs USE_ESP8266 -} - int Nextion::upload_by_chunks_(HTTPClient &http_client, uint32_t &range_start) { uint32_t range_size = this->tft_size_ - range_start; - ESP_LOGV(TAG, "Heap: %" PRIu32, this->get_free_heap_()); + ESP_LOGV(TAG, "Heap: %" PRIu32, EspClass::getFreeHeap()); uint32_t range_end = ((upload_first_chunk_sent_ or this->tft_size_ < 4096) ? this->tft_size_ : 4096) - 1; ESP_LOGD(TAG, "Range start: %" PRIu32, range_start); if (range_size <= 0 or range_end <= range_start) { - ESP_LOGD(TAG, "Range end: %" PRIu32, range_end); - ESP_LOGD(TAG, "Range size: %" PRIu32, range_size); ESP_LOGE(TAG, "Invalid range"); + ESP_LOGD(TAG, + "Range end: %" PRIu32 "\n" + "Range size: %" PRIu32, + range_end, range_size); return -1; } @@ -95,14 +85,8 @@ int Nextion::upload_by_chunks_(HTTPClient &http_client, uint32_t &range_start) { this->recv_ret_string_(recv_string, upload_first_chunk_sent_ ? 500 : 5000, true); this->content_length_ -= read_len; const float upload_percentage = 100.0f * (this->tft_size_ - this->content_length_) / this->tft_size_; -#if defined(USE_ESP32) && defined(USE_PSRAM) - ESP_LOGD(TAG, "Upload: %0.2f%% (%" PRIu32 " left, heap: %" PRIu32 "+%" PRIu32 ")", upload_percentage, - this->content_length_, static_cast(heap_caps_get_free_size(MALLOC_CAP_INTERNAL)), - static_cast(heap_caps_get_free_size(MALLOC_CAP_SPIRAM))); -#else ESP_LOGD(TAG, "Upload: %0.2f%% (%" PRIu32 " left, heap: %" PRIu32 ")", upload_percentage, this->content_length_, - this->get_free_heap_()); -#endif + EspClass::getFreeHeap()); upload_first_chunk_sent_ = true; if (recv_string[0] == 0x08 && recv_string.size() == 5) { // handle partial upload request ESP_LOGD(TAG, "Recv: [%s]", @@ -148,9 +132,11 @@ int Nextion::upload_by_chunks_(HTTPClient &http_client, uint32_t &range_start) { } bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) { - ESP_LOGD(TAG, "TFT upload requested"); - ESP_LOGD(TAG, "Exit reparse: %s", YESNO(exit_reparse)); - ESP_LOGD(TAG, "URL: %s", this->tft_url_.c_str()); + ESP_LOGD(TAG, + "TFT upload requested\n" + "Exit reparse: %s\n" + "URL: %s", + YESNO(exit_reparse), this->tft_url_.c_str()); if (this->connection_state_.is_updating_) { ESP_LOGW(TAG, "Upload in progress"); @@ -180,15 +166,14 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) { ESP_LOGD(TAG, "Baud rate: %" PRIu32, baud_rate); // Define the configuration for the HTTP client - ESP_LOGV(TAG, "Init HTTP client"); - ESP_LOGV(TAG, "Heap: %" PRIu32, this->get_free_heap_()); + ESP_LOGV(TAG, + "Init HTTP client\n" + "Heap: %" PRIu32, + EspClass::getFreeHeap()); HTTPClient http_client; http_client.setTimeout(15000); // Yes 15 seconds.... Helps 8266s along bool begin_status = false; -#ifdef USE_ESP32 - begin_status = http_client.begin(this->tft_url_.c_str()); -#endif #ifdef USE_ESP8266 #if USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 7, 0) http_client.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS); @@ -256,22 +241,24 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) { this->send_command_("sleep=0"); this->send_command_("dim=100"); delay(250); // NOLINT - ESP_LOGV(TAG, "Heap: %" PRIu32, this->get_free_heap_()); + ESP_LOGV(TAG, "Heap: %" PRIu32, EspClass::getFreeHeap()); App.feed_wdt(); char command[128]; // Tells the Nextion the content length of the tft file and baud rate it will be sent at // Once the Nextion accepts the command it will wait until the file is successfully uploaded // If it fails for any reason a power cycle of the display will be needed - sprintf(command, "whmi-wris %d,%d,1", this->content_length_, baud_rate); + snprintf(command, sizeof(command), "whmi-wris %" PRIu32 ",%" PRIu32 ",1", this->content_length_, baud_rate); // Clear serial receive buffer ESP_LOGV(TAG, "Clear RX buffer"); this->reset_(false); delay(250); // NOLINT - ESP_LOGV(TAG, "Heap: %" PRIu32, this->get_free_heap_()); - ESP_LOGV(TAG, "Upload cmd: %s", command); + ESP_LOGV(TAG, + "Heap: %" PRIu32 "\n" + "Upload cmd: %s", + EspClass::getFreeHeap(), command); this->send_command_(command); if (baud_rate != this->original_baud_rate_) { @@ -290,7 +277,7 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) { ESP_LOGD(TAG, "Upload resp: [%s] %zu B", format_hex_pretty(reinterpret_cast(response.data()), response.size()).c_str(), response.length()); - ESP_LOGV(TAG, "Heap: %" PRIu32, this->get_free_heap_()); + ESP_LOGV(TAG, "Heap: %" PRIu32, EspClass::getFreeHeap()); if (response.find(0x05) != std::string::npos) { ESP_LOGV(TAG, "Upload prep done"); @@ -302,10 +289,12 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) { return this->upload_end_(false); } - ESP_LOGD(TAG, "Upload TFT:"); - ESP_LOGD(TAG, " URL: %s", this->tft_url_.c_str()); - ESP_LOGD(TAG, " Size: %d bytes", this->content_length_); - ESP_LOGD(TAG, " Heap: %" PRIu32, this->get_free_heap_()); + ESP_LOGD(TAG, + "Upload TFT:\n" + " URL: %s\n" + " Size: %d bytes\n" + " Heap: %" PRIu32, + this->tft_url_.c_str(), this->content_length_, EspClass::getFreeHeap()); // Proceed with the content download as before @@ -322,7 +311,7 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) { return this->upload_end_(false); } App.feed_wdt(); - ESP_LOGV(TAG, "Heap: %" PRIu32 " left: %" PRIu32, this->get_free_heap_(), this->content_length_); + ESP_LOGV(TAG, "Heap: %" PRIu32 " left: %" PRIu32, EspClass::getFreeHeap(), this->content_length_); } ESP_LOGD(TAG, "Upload complete"); @@ -356,5 +345,5 @@ WiFiClient *Nextion::get_wifi_client_() { } // namespace nextion } // namespace esphome -#endif // USE_ARDUINO +#endif // NOT USE_ESP32 #endif // USE_NEXTION_TFT_UPLOAD diff --git a/esphome/components/nextion/nextion_upload_idf.cpp b/esphome/components/nextion/nextion_upload_esp32.cpp similarity index 90% rename from esphome/components/nextion/nextion_upload_idf.cpp rename to esphome/components/nextion/nextion_upload_esp32.cpp index 942e3dd6c31..29a7e3c8d70 100644 --- a/esphome/components/nextion/nextion_upload_idf.cpp +++ b/esphome/components/nextion/nextion_upload_esp32.cpp @@ -1,7 +1,7 @@ #include "nextion.h" #ifdef USE_NEXTION_TFT_UPLOAD -#ifdef USE_ESP_IDF +#ifdef USE_ESP32 #include #include @@ -14,7 +14,7 @@ namespace esphome { namespace nextion { -static const char *const TAG = "nextion.upload.idf"; +static const char *const TAG = "nextion.upload.esp32"; // Followed guide // https://unofficialnextion.com/t/nextion-upload-protocol-v1-2-the-fast-one/1044/2 @@ -25,8 +25,10 @@ int Nextion::upload_by_chunks_(esp_http_client_handle_t http_client, uint32_t &r uint32_t range_end = ((upload_first_chunk_sent_ or this->tft_size_ < 4096) ? this->tft_size_ : 4096) - 1; ESP_LOGD(TAG, "Range start: %" PRIu32, range_start); if (range_size <= 0 or range_end <= range_start) { - ESP_LOGD(TAG, "Range end: %" PRIu32, range_end); - ESP_LOGD(TAG, "Range size: %" PRIu32, range_size); + ESP_LOGD(TAG, + "Range end: %" PRIu32 "\n" + "Range size: %" PRIu32, + range_end, range_size); ESP_LOGE(TAG, "Invalid range"); return -1; } @@ -151,9 +153,11 @@ int Nextion::upload_by_chunks_(esp_http_client_handle_t http_client, uint32_t &r } bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) { - ESP_LOGD(TAG, "TFT upload requested"); - ESP_LOGD(TAG, "Exit reparse: %s", YESNO(exit_reparse)); - ESP_LOGD(TAG, "URL: %s", this->tft_url_.c_str()); + ESP_LOGD(TAG, + "TFT upload requested\n" + "Exit reparse: %s\n" + "URL: %s", + YESNO(exit_reparse), this->tft_url_.c_str()); if (this->connection_state_.is_updating_) { ESP_LOGW(TAG, "Upload in progress"); @@ -183,8 +187,10 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) { ESP_LOGD(TAG, "Baud rate: %" PRIu32, baud_rate); // Define the configuration for the HTTP client - ESP_LOGV(TAG, "Init HTTP client"); - ESP_LOGV(TAG, "Heap: %" PRIu32, esp_get_free_heap_size()); + ESP_LOGV(TAG, + "Init HTTP client\n" + "Heap: %" PRIu32, + esp_get_free_heap_size()); esp_http_client_config_t config = { .url = this->tft_url_.c_str(), .cert_pem = nullptr, @@ -208,8 +214,10 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) { } // Perform the HTTP request - ESP_LOGV(TAG, "Check connection"); - ESP_LOGV(TAG, "Heap: %" PRIu32, esp_get_free_heap_size()); + ESP_LOGV(TAG, + "Check connection\n" + "Heap: %" PRIu32, + esp_get_free_heap_size()); err = esp_http_client_perform(http_client); if (err != ESP_OK) { ESP_LOGE(TAG, "HTTP failed: %s", esp_err_to_name(err)); @@ -218,8 +226,10 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) { } // Check the HTTP Status Code - ESP_LOGV(TAG, "Check status"); - ESP_LOGV(TAG, "Heap: %" PRIu32, esp_get_free_heap_size()); + ESP_LOGV(TAG, + "Check status\n" + "Heap: %" PRIu32, + esp_get_free_heap_size()); int status_code = esp_http_client_get_status_code(http_client); if (status_code != 200 && status_code != 206) { return this->upload_end_(false); @@ -255,7 +265,7 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) { // Tells the Nextion the content length of the tft file and baud rate it will be sent at // Once the Nextion accepts the command it will wait until the file is successfully uploaded // If it fails for any reason a power cycle of the display will be needed - sprintf(command, "whmi-wris %" PRIu32 ",%" PRIu32 ",1", this->content_length_, baud_rate); + snprintf(command, sizeof(command), "whmi-wris %" PRIu32 ",%" PRIu32 ",1", this->content_length_, baud_rate); // Clear serial receive buffer ESP_LOGV(TAG, "Clear RX buffer"); @@ -300,10 +310,12 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) { return this->upload_end_(false); } - ESP_LOGD(TAG, "Uploading TFT:"); - ESP_LOGD(TAG, " URL: %s", this->tft_url_.c_str()); - ESP_LOGD(TAG, " Size: %" PRIu32 " bytes", this->content_length_); - ESP_LOGD(TAG, " Heap: %" PRIu32, esp_get_free_heap_size()); + ESP_LOGD(TAG, + "Uploading TFT:\n" + " URL: %s\n" + " Size: %" PRIu32 " bytes\n" + " Heap: %" PRIu32, + this->tft_url_.c_str(), this->content_length_, esp_get_free_heap_size()); // Proceed with the content download as before @@ -324,9 +336,8 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) { ESP_LOGV(TAG, "Heap: %" PRIu32 " left: %" PRIu32, esp_get_free_heap_size(), this->content_length_); } - ESP_LOGD(TAG, "TFT upload complete"); - - ESP_LOGD(TAG, "Close HTTP"); + ESP_LOGD(TAG, "TFT upload complete\n" + "Close HTTP"); esp_http_client_close(http_client); esp_http_client_cleanup(http_client); ESP_LOGV(TAG, "Connection closed"); @@ -336,5 +347,5 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) { } // namespace nextion } // namespace esphome -#endif // USE_ESP_IDF +#endif // USE_ESP32 #endif // USE_NEXTION_TFT_UPLOAD