4 #ifdef USE_NEXTION_TFT_UPLOAD 13 #include <esp_heap_caps.h> 18 static const char *
const TAG =
"nextion.upload.arduino";
27 range_end = 16384 - 1;
36 #if USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 7, 0) 37 http->setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
38 #elif USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 6, 0) 39 http->setFollowRedirects(
true);
41 #if USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 6, 0) 42 http->setRedirectLimit(3);
46 char range_header[64];
47 sprintf(range_header,
"bytes=%d-%d", range_start, range_end);
49 ESP_LOGD(TAG,
"Requesting range: %s", range_header);
53 bool begin_status =
false;
56 begin_status = http->begin(this->
tft_url_.c_str());
64 ESP_LOGD(TAG,
"upload_by_chunks_: connection failed");
69 http->addHeader(
"Range", range_header);
72 if (code == 200 || code == 206) {
75 ESP_LOGW(TAG,
"HTTP Request failed; URL: %s; Error: %s, retries(%d/5)", this->
tft_url_.c_str(),
76 HTTPClient::errorToString(code).c_str(), tries);
86 std::string recv_string;
89 int range = range_end - range_start;
91 while (fetched < range) {
92 size = http->getStreamPtr()->available();
98 int c = http->getStreamPtr()->readBytes(
103 ESP_LOGN(TAG,
"Fetched %d of %d bytes", fetched, this->
content_length_);
107 for (
int i = 0; i < range; i += 4096) {
112 ESP_LOGD(TAG,
"Uploaded %0.2f %%; %d bytes remaining",
121 if (recv_string[0] != 0x05) {
122 ESP_LOGD(TAG,
"recv_string [%s]",
123 format_hex_pretty(reinterpret_cast<const uint8_t *>(recv_string.data()), recv_string.size()).c_str());
127 if (recv_string[0] == 0x08 && recv_string.size() == 5) {
129 for (
int j = 0; j < 4; ++j) {
130 result +=
static_cast<uint8_t
>(recv_string[j + 1]) << (8 * j);
133 ESP_LOGD(TAG,
"Nextion reported new range %d", result);
141 return range_end + 1;
145 ESP_LOGD(TAG,
"Nextion TFT upload requested");
146 ESP_LOGD(TAG,
"URL: %s", this->
tft_url_.c_str());
149 ESP_LOGD(TAG,
"Currently updating");
154 ESP_LOGD(TAG,
"network is not connected");
161 http.setTimeout(15000);
162 bool begin_status =
false;
164 begin_status = http.begin(this->
tft_url_.c_str());
167 #if USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 7, 0) 168 http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
169 #elif USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 6, 0) 170 http.setFollowRedirects(
true);
172 #if USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 6, 0) 173 http.setRedirectLimit(3);
180 ESP_LOGD(TAG,
"Connection failed");
185 ESP_LOGD(TAG,
"Connected");
188 http.addHeader(
"Range",
"bytes=0-255");
189 const char *header_names[] = {
"Content-Range"};
190 http.collectHeaders(header_names, 1);
191 ESP_LOGD(TAG,
"Requesting URL: %s", this->
tft_url_.c_str());
196 int code = http.GET();
200 while (code != 200 && code != 206 && tries <= 5) {
201 ESP_LOGW(TAG,
"HTTP Request failed; URL: %s; Error: %s, retrying (%d/5)", this->
tft_url_.c_str(),
202 HTTPClient::errorToString(code).c_str(), tries);
210 if ((code != 200 && code != 206) || tries > 5) {
214 String content_range_string = http.header(
"Content-Range");
215 content_range_string.remove(0, 12);
221 ESP_LOGE(TAG,
"Failed to get file size");
225 ESP_LOGD(TAG,
"Updating Nextion %s...", this->
device_model_.c_str());
250 std::string response;
251 ESP_LOGD(TAG,
"Waiting for upgrade response");
255 ESP_LOGD(TAG,
"Upgrade response is [%s] - %zu bytes",
256 format_hex_pretty(reinterpret_cast<const uint8_t *>(response.data()), response.size()).c_str(),
259 for (
size_t i = 0; i < response.length(); i++) {
260 ESP_LOGD(TAG,
"Available %d : 0x%02X", i, response[i]);
263 if (response.find(0x05) != std::string::npos) {
264 ESP_LOGD(TAG,
"preparation for tft update done");
266 ESP_LOGD(TAG,
"preparation for tft update failed %d \"%s\"", response[0], response.c_str());
272 uint32_t chunk_size = 8192;
273 if (heap_caps_get_free_size(MALLOC_CAP_SPIRAM) > 0) {
276 if (ESP.getFreeHeap() > 81920) {
277 chunk_size = ESP.getFreeHeap() - 65536;
278 chunk_size = int(chunk_size / 4096) * 4096;
279 chunk_size = chunk_size > 65536 ? 65536 : chunk_size;
280 }
else if (ESP.getFreeHeap() < 32768) {
286 uint32_t chunk_size = ESP.getFreeHeap() < 16384 ? 4096 : 8192;
292 ESP_LOGD(TAG,
"Allocating buffer size %d, Heap size is %u", chunk_size, ESP.getFreeHeap());
294 if (this->transfer_buffer_ ==
nullptr) {
295 ESP_LOGD(TAG,
"Could not allocate buffer size: %d trying 4096 instead", chunk_size);
297 ESP_LOGD(TAG,
"Allocating %d buffer", chunk_size);
298 this->transfer_buffer_ = allocator.
allocate(chunk_size);
300 if (!this->transfer_buffer_)
308 ESP_LOGD(TAG,
"Updating tft from \"%s\" with a file size of %d using %zu chunksize, Heap Size %d",
315 ESP_LOGD(TAG,
"Error updating Nextion!");
320 ESP_LOGD(TAG,
"Heap Size %d, Bytes left %d", ESP.getFreeHeap(), this->
content_length_);
322 ESP_LOGD(TAG,
"Successfully updated Nextion!");
329 ESP_LOGD(TAG,
"Restarting Nextion");
333 ESP_LOGD(TAG,
"Restarting esphome");
341 if (this->
tft_url_.compare(0, 6,
"https:") == 0) {
361 #endif // USE_NEXTION_TFT_UPLOAD 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)
WiFiClient * get_wifi_client_()
An STL allocator that uses SPI RAM.
void deallocate(T *p, size_t n)
int upload_by_chunks_(HTTPClient *http, int range_start)
will request chunk_size chunks from the web server and send each to the nextion
bool send_command_(const std::string &command)
Manually send a raw command to the display and don't wait for an acknowledgement packet.
BearSSL::WiFiClientSecure * wifi_client_secure_
bool upload_end_(bool successful)
Ends the upload process, restart Nextion and, if successful, restarts ESP.
bool is_connected()
Return whether the node is connected to the network (through wifi, eth, ...)
bool read_byte(uint8_t *data)
Application App
Global storage of Application pointer - only one Application can exist.
uint8_t * transfer_buffer_
void set_backlight_brightness(float brightness)
Set the brightness of the backlight.
std::string device_model_
void soft_reset()
Softreset the Nextion.
bool upload_tft()
Upload the tft file and soft reset Nextion.
bool upload_first_chunk_sent_
WiFiClient * wifi_client_
This is a workaround until we can figure out a way to get the tflite-micro idf component code availab...
size_t transfer_buffer_size_
uint16_t recv_ret_string_(std::string &response, uint32_t timeout, bool recv_flag)
void IRAM_ATTR HOT delay(uint32_t ms)