4 #ifdef USE_NEXTION_TFT_UPLOAD 12 #include <esp_heap_caps.h> 13 #include <esp_http_client.h> 18 static const char *
const TAG =
"nextion.upload.idf";
24 ESP_LOGVV(TAG,
"url: %s", url.c_str());
25 uint range_size = this->
tft_size_ - range_start;
26 ESP_LOGVV(TAG,
"tft_size_: %i", this->
tft_size_);
27 ESP_LOGVV(TAG,
"Available heap: %" PRIu32, esp_get_free_heap_size());
28 int range_end = (range_start == 0) ? std::min(this->
tft_size_, 16383) : this->
tft_size_;
29 if (range_size <= 0 or range_end <= range_start) {
30 ESP_LOGE(TAG,
"Invalid range");
31 ESP_LOGD(TAG,
"Range start: %i", range_start);
32 ESP_LOGD(TAG,
"Range end: %i", range_end);
33 ESP_LOGD(TAG,
"Range size: %i", range_size);
37 esp_http_client_config_t config = {
40 .disable_auto_redirect =
false,
41 .max_redirection_count = 10,
43 esp_http_client_handle_t client = esp_http_client_init(&config);
45 char range_header[64];
46 sprintf(range_header,
"bytes=%d-%d", range_start, range_end);
47 ESP_LOGV(TAG,
"Requesting range: %s", range_header);
48 esp_http_client_set_header(client,
"Range", range_header);
49 ESP_LOGVV(TAG,
"Available heap: %" PRIu32, esp_get_free_heap_size());
51 ESP_LOGV(TAG,
"Opening http connetion");
53 if ((err = esp_http_client_open(client, 0)) != ESP_OK) {
54 ESP_LOGE(TAG,
"Failed to open HTTP connection: %s", esp_err_to_name(err));
55 esp_http_client_cleanup(client);
59 ESP_LOGV(TAG,
"Fetch content length");
60 int content_length = esp_http_client_fetch_headers(client);
61 ESP_LOGV(TAG,
"content_length = %d", content_length);
62 if (content_length <= 0) {
63 ESP_LOGE(TAG,
"Failed to get content length: %d", content_length);
64 esp_http_client_cleanup(client);
68 int total_read_len = 0, read_len;
70 ESP_LOGVV(TAG,
"Available heap: %" PRIu32, esp_get_free_heap_size());
71 ESP_LOGV(TAG,
"Allocate buffer");
72 uint8_t *buffer =
new uint8_t[4096];
73 std::string recv_string;
74 if (buffer ==
nullptr) {
75 ESP_LOGE(TAG,
"Failed to allocate memory for buffer");
76 ESP_LOGVV(TAG,
"Available heap: %" PRIu32, esp_get_free_heap_size());
78 ESP_LOGV(TAG,
"Memory for buffer allocated successfully");
82 ESP_LOGVV(TAG,
"Available heap: %" PRIu32, esp_get_free_heap_size());
83 int read_len = esp_http_client_read(client, reinterpret_cast<char *>(buffer), 4096);
84 ESP_LOGVV(TAG,
"Read %d bytes from HTTP client, writing to UART", read_len);
87 ESP_LOGVV(TAG,
"Write to UART successful");
90 ESP_LOGD(TAG,
"Uploaded %0.2f %%, remaining %d bytes, heap is %" PRIu32
" bytes",
92 esp_get_free_heap_size());
94 if (recv_string[0] == 0x08 && recv_string.size() == 5) {
96 TAG,
"recv_string [%s]",
97 format_hex_pretty(reinterpret_cast<const uint8_t *>(recv_string.data()), recv_string.size()).c_str());
99 for (
int j = 0; j < 4; ++j) {
100 result +=
static_cast<uint8_t
>(recv_string[j + 1]) << (8 * j);
103 ESP_LOGI(TAG,
"Nextion reported new range %" PRIu32, result);
106 ESP_LOGV(TAG,
"Deallocate buffer");
107 ESP_LOGVV(TAG,
"Available heap: %" PRIu32, esp_get_free_heap_size());
109 ESP_LOGVV(TAG,
"Memory for buffer deallocated");
110 ESP_LOGVV(TAG,
"Available heap: %" PRIu32, esp_get_free_heap_size());
111 ESP_LOGV(TAG,
"Close http client");
112 ESP_LOGVV(TAG,
"Available heap: %" PRIu32, esp_get_free_heap_size());
113 esp_http_client_close(client);
114 esp_http_client_cleanup(client);
115 ESP_LOGVV(TAG,
"Client closed");
116 ESP_LOGVV(TAG,
"Available heap: %" PRIu32, esp_get_free_heap_size());
119 }
else if (recv_string[0] != 0x05) {
121 TAG,
"Invalid response from Nextion: [%s]",
122 format_hex_pretty(reinterpret_cast<const uint8_t *>(recv_string.data()), recv_string.size()).c_str());
123 ESP_LOGV(TAG,
"Deallocate buffer");
124 ESP_LOGVV(TAG,
"Available heap: %" PRIu32, esp_get_free_heap_size());
126 ESP_LOGVV(TAG,
"Memory for buffer deallocated");
127 ESP_LOGVV(TAG,
"Available heap: %" PRIu32, esp_get_free_heap_size());
128 ESP_LOGV(TAG,
"Close http client");
129 ESP_LOGVV(TAG,
"Available heap: %" PRIu32, esp_get_free_heap_size());
130 esp_http_client_close(client);
131 esp_http_client_cleanup(client);
132 ESP_LOGVV(TAG,
"Client closed");
133 ESP_LOGVV(TAG,
"Available heap: %" PRIu32, esp_get_free_heap_size());
138 }
else if (read_len == 0) {
139 ESP_LOGV(TAG,
"End of HTTP response reached");
142 ESP_LOGE(TAG,
"Failed to read from HTTP client, error code: %d", read_len);
148 ESP_LOGV(TAG,
"Deallocate buffer");
149 ESP_LOGVV(TAG,
"Available heap: %" PRIu32, esp_get_free_heap_size());
151 ESP_LOGVV(TAG,
"Memory for buffer deallocated");
152 ESP_LOGVV(TAG,
"Available heap: %" PRIu32, esp_get_free_heap_size());
154 ESP_LOGV(TAG,
"Close http client");
155 ESP_LOGVV(TAG,
"Available heap: %" PRIu32, esp_get_free_heap_size());
156 esp_http_client_close(client);
157 esp_http_client_cleanup(client);
158 ESP_LOGVV(TAG,
"Client closed");
159 ESP_LOGVV(TAG,
"Available heap: %" PRIu32, esp_get_free_heap_size());
160 return range_end + 1;
164 ESP_LOGD(TAG,
"Nextion TFT upload requested");
165 ESP_LOGD(TAG,
"url: %s", this->
tft_url_.c_str());
168 ESP_LOGW(TAG,
"Currently updating");
173 ESP_LOGE(TAG,
"Network is not connected");
180 ESP_LOGV(TAG,
"Establishing connection to HTTP server");
181 ESP_LOGVV(TAG,
"Available heap: %" PRIu32, esp_get_free_heap_size());
182 esp_http_client_config_t config = {
185 .method = HTTP_METHOD_HEAD,
187 .disable_auto_redirect =
false,
188 .max_redirection_count = 10,
192 ESP_LOGV(TAG,
"Initializing HTTP client");
193 ESP_LOGVV(TAG,
"Available heap: %" PRIu32, esp_get_free_heap_size());
194 esp_http_client_handle_t http = esp_http_client_init(&config);
196 ESP_LOGE(TAG,
"Failed to initialize HTTP client.");
201 ESP_LOGV(TAG,
"Check if the client could connect");
202 ESP_LOGVV(TAG,
"Available heap: %" PRIu32, esp_get_free_heap_size());
203 esp_err_t err = esp_http_client_perform(http);
205 ESP_LOGE(TAG,
"HTTP request failed: %s", esp_err_to_name(err));
206 esp_http_client_cleanup(http);
211 ESP_LOGV(TAG,
"Check the HTTP Status Code");
212 ESP_LOGVV(TAG,
"Available heap: %" PRIu32, esp_get_free_heap_size());
213 int status_code = esp_http_client_get_status_code(http);
214 ESP_LOGV(TAG,
"HTTP Status Code: %d", status_code);
215 size_t tft_file_size = esp_http_client_get_content_length(http);
216 ESP_LOGD(TAG,
"TFT file size: %zu", tft_file_size);
218 ESP_LOGD(TAG,
"Close HTTP connection");
219 ESP_LOGVV(TAG,
"Available heap: %" PRIu32, esp_get_free_heap_size());
220 esp_http_client_close(http);
221 esp_http_client_cleanup(http);
222 ESP_LOGVV(TAG,
"Connection closed");
223 ESP_LOGVV(TAG,
"Available heap: %" PRIu32, esp_get_free_heap_size());
225 if (tft_file_size < 4096) {
226 ESP_LOGE(TAG,
"File size check failed. Size: %zu", tft_file_size);
229 ESP_LOGV(TAG,
"File size check passed. Proceeding...");
234 ESP_LOGD(TAG,
"Updating Nextion");
237 ESP_LOGV(TAG,
"Wake-up Nextion");
238 ESP_LOGVV(TAG,
"Available heap: %" PRIu32, esp_get_free_heap_size());
241 vTaskDelay(pdMS_TO_TICKS(250));
251 ESP_LOGV(TAG,
"Clear serial receive buffer");
252 ESP_LOGVV(TAG,
"Available heap: %" PRIu32, esp_get_free_heap_size());
258 ESP_LOGV(TAG,
"Send update instruction: %s", command);
259 ESP_LOGVV(TAG,
"Available heap: %" PRIu32, esp_get_free_heap_size());
262 std::string response;
263 ESP_LOGV(TAG,
"Waiting for upgrade response");
267 ESP_LOGD(TAG,
"Upgrade response is [%s] - %zu bytes",
268 format_hex_pretty(reinterpret_cast<const uint8_t *>(response.data()), response.size()).c_str(),
270 ESP_LOGVV(TAG,
"Available heap: %" PRIu32, esp_get_free_heap_size());
272 if (response.find(0x05) != std::string::npos) {
273 ESP_LOGV(TAG,
"Preparation for tft update done");
275 ESP_LOGE(TAG,
"Preparation for tft update failed %d \"%s\"", response[0], response.c_str());
279 ESP_LOGD(TAG,
"Updating tft from \"%s\" with a file size of %d, Heap Size %" PRIu32, this->
tft_url_.c_str(),
282 ESP_LOGV(TAG,
"Starting transfer by chunks loop");
283 ESP_LOGVV(TAG,
"Available heap: %" PRIu32, esp_get_free_heap_size());
288 ESP_LOGE(TAG,
"Error updating Nextion!");
292 ESP_LOGV(TAG,
"Heap Size %" PRIu32
", Bytes left %d", esp_get_free_heap_size(),
content_length_);
295 ESP_LOGD(TAG,
"Successfully updated Nextion!");
302 ESP_LOGD(TAG,
"Restarting Nextion");
304 vTaskDelay(pdMS_TO_TICKS(1500));
306 ESP_LOGD(TAG,
"Restarting ESPHome");
315 #endif // USE_NEXTION_TFT_UPLOAD 316 #endif // USE_ESP_IDF int upload_range(const std::string &url, int range_start)
will request 4096 bytes chunks from the web server and send each to Nextion
uint32_t get_baud_rate() const
std::string format_hex_pretty(const uint8_t *data, size_t length)
Format the byte array data of length len in pretty-printed, human-readable hex.
void write_array(const uint8_t *data, size_t len)
bool send_command_(const std::string &command)
Manually send a raw command to the display and don't wait for an acknowledgement packet.
bool is_connected()
Return whether the node is connected to the network (through wifi, eth, ...)
bool upload_end(bool successful)
Ends the upload process, restart Nextion and, if successful, restarts ESP.
bool read_byte(uint8_t *data)
Application App
Global storage of Application pointer - only one Application can exist.
void set_backlight_brightness(float brightness)
Set the brightness of the backlight.
void soft_reset()
Softreset the Nextion.
bool upload_tft()
Upload the tft file and soft reset Nextion.
This is a workaround until we can figure out a way to get the tflite-micro idf component code availab...
uint16_t recv_ret_string_(std::string &response, uint32_t timeout, bool recv_flag)