Improve reliability of Nextion TFT uploads (Arduino) (#5683)

Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
This commit is contained in:
Edward Firmo 2023-11-28 06:25:20 +01:00 committed by GitHub
parent ad5f6b5687
commit 3940c6ac4e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -41,7 +41,7 @@ int Nextion::upload_by_chunks_(HTTPClient *http, int range_start) {
#if USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 6, 0) #if USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 6, 0)
http->setRedirectLimit(3); http->setRedirectLimit(3);
#endif #endif
#endif #endif // USE_ESP8266
char range_header[64]; char range_header[64];
sprintf(range_header, "bytes=%d-%d", range_start, range_end); sprintf(range_header, "bytes=%d-%d", range_start, range_end);
@ -62,6 +62,7 @@ int Nextion::upload_by_chunks_(HTTPClient *http, int range_start) {
++tries; ++tries;
if (!begin_status) { if (!begin_status) {
ESP_LOGD(TAG, "upload_by_chunks_: connection failed"); ESP_LOGD(TAG, "upload_by_chunks_: connection failed");
delay(500); // NOLINT
continue; continue;
} }
@ -84,10 +85,10 @@ int Nextion::upload_by_chunks_(HTTPClient *http, int range_start) {
std::string recv_string; std::string recv_string;
size_t size = 0; size_t size = 0;
int sent = 0; int fetched = 0;
int range = range_end - range_start; int range = range_end - range_start;
while (sent < range) { while (fetched < range) {
size = http->getStreamPtr()->available(); size = http->getStreamPtr()->available();
if (!size) { if (!size) {
App.feed_wdt(); App.feed_wdt();
@ -95,28 +96,38 @@ int Nextion::upload_by_chunks_(HTTPClient *http, int range_start) {
continue; continue;
} }
int c = http->getStreamPtr()->readBytes( int c = http->getStreamPtr()->readBytes(
&this->transfer_buffer_[sent], ((size > this->transfer_buffer_size_) ? this->transfer_buffer_size_ : size)); &this->transfer_buffer_[fetched], ((size > this->transfer_buffer_size_) ? this->transfer_buffer_size_ : size));
sent += c; fetched += c;
} }
http->end(); http->end();
ESP_LOGN(TAG, "this->content_length_ %d sent %d", this->content_length_, sent); ESP_LOGN(TAG, "Fetched %d of %d bytes", fetched, this->content_length_);
// upload fetched segments to the display in 4KB chunks
int write_len;
for (int i = 0; i < range; i += 4096) { for (int i = 0; i < range; i += 4096) {
this->write_array(&this->transfer_buffer_[i], 4096); App.feed_wdt();
this->content_length_ -= 4096; write_len = this->content_length_ < 4096 ? this->content_length_ : 4096;
ESP_LOGN(TAG, "this->content_length_ %d range %d range_end %d range_start %d", this->content_length_, range, this->write_array(&this->transfer_buffer_[i], write_len);
range_end, range_start); this->content_length_ -= write_len;
ESP_LOGD(TAG, "Uploaded %0.2f %%; %d bytes remaining",
100.0 * (this->tft_size_ - this->content_length_) / this->tft_size_, this->content_length_);
if (!this->upload_first_chunk_sent_) { if (!this->upload_first_chunk_sent_) {
this->upload_first_chunk_sent_ = true; this->upload_first_chunk_sent_ = true;
delay(500); // NOLINT delay(500); // NOLINT
App.feed_wdt();
} }
this->recv_ret_string_(recv_string, 2048, true); this->recv_ret_string_(recv_string, 4096, true);
if (recv_string[0] == 0x08) { if (recv_string[0] != 0x05) { // 0x05 == "ok"
ESP_LOGD(TAG, "recv_string [%s]",
format_hex_pretty(reinterpret_cast<const uint8_t *>(recv_string.data()), recv_string.size()).c_str());
}
// handle partial upload request
if (recv_string[0] == 0x08 && recv_string.size() == 5) {
uint32_t result = 0; uint32_t result = 0;
for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) {
result += static_cast<uint8_t>(recv_string[i + 1]) << (8 * i); result += static_cast<uint8_t>(recv_string[j + 1]) << (8 * j);
} }
if (result > 0) { if (result > 0) {
ESP_LOGD(TAG, "Nextion reported new range %d", result); ESP_LOGD(TAG, "Nextion reported new range %d", result);
@ -126,10 +137,14 @@ int Nextion::upload_by_chunks_(HTTPClient *http, int range_start) {
} }
recv_string.clear(); recv_string.clear();
} }
return range_end + 1; return range_end + 1;
} }
bool Nextion::upload_tft() { bool Nextion::upload_tft() {
ESP_LOGD(TAG, "Nextion TFT upload requested");
ESP_LOGD(TAG, "URL: %s", this->tft_url_.c_str());
if (this->is_updating_) { if (this->is_updating_) {
ESP_LOGD(TAG, "Currently updating"); ESP_LOGD(TAG, "Currently updating");
return false; return false;
@ -162,7 +177,7 @@ bool Nextion::upload_tft() {
if (!begin_status) { if (!begin_status) {
this->is_updating_ = false; this->is_updating_ = false;
ESP_LOGD(TAG, "connection failed"); ESP_LOGD(TAG, "Connection failed");
ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE); ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
allocator.deallocate(this->transfer_buffer_, this->transfer_buffer_size_); allocator.deallocate(this->transfer_buffer_, this->transfer_buffer_size_);
return false; return false;
@ -237,7 +252,9 @@ bool Nextion::upload_tft() {
this->recv_ret_string_(response, 2000, true); // This can take some time to return this->recv_ret_string_(response, 2000, true); // This can take some time to return
// The Nextion display will, if it's ready to accept data, send a 0x05 byte. // The Nextion display will, if it's ready to accept data, send a 0x05 byte.
ESP_LOGD(TAG, "Upgrade response is %s %zu", response.c_str(), response.length()); ESP_LOGD(TAG, "Upgrade response is [%s] - %zu bytes",
format_hex_pretty(reinterpret_cast<const uint8_t *>(response.data()), response.size()).c_str(),
response.length());
for (size_t i = 0; i < response.length(); i++) { for (size_t i = 0; i < response.length(); i++) {
ESP_LOGD(TAG, "Available %d : 0x%02X", i, response[i]); ESP_LOGD(TAG, "Available %d : 0x%02X", i, response[i]);
@ -256,17 +273,17 @@ bool Nextion::upload_tft() {
if (heap_caps_get_free_size(MALLOC_CAP_SPIRAM) > 0) { if (heap_caps_get_free_size(MALLOC_CAP_SPIRAM) > 0) {
chunk_size = this->content_length_; chunk_size = this->content_length_;
} else { } else {
if (ESP.getFreeHeap() > 40960) { // 32K to keep on hand if (ESP.getFreeHeap() > 81920) { // Ensure some FreeHeap to other things and limit chunk size
int chunk = int((ESP.getFreeHeap() - 32768) / 4096); chunk_size = ESP.getFreeHeap() - 65536;
chunk_size = chunk * 4096; chunk_size = int(chunk_size / 4096) * 4096;
chunk_size = chunk_size > 65536 ? 65536 : chunk_size; chunk_size = chunk_size > 65536 ? 65536 : chunk_size;
} else if (ESP.getFreeHeap() < 10240) { } else if (ESP.getFreeHeap() < 32768) {
chunk_size = 4096; chunk_size = 4096;
} }
} }
#else #else
// NOLINTNEXTLINE(readability-static-accessed-through-instance) // NOLINTNEXTLINE(readability-static-accessed-through-instance)
uint32_t chunk_size = ESP.getFreeHeap() < 10240 ? 4096 : 8192; uint32_t chunk_size = ESP.getFreeHeap() < 16384 ? 4096 : 8192;
#endif #endif
if (this->transfer_buffer_ == nullptr) { if (this->transfer_buffer_ == nullptr) {