6 Commits

Author SHA1 Message Date
Edward Firmo
88cf4af2a7 Add validation with arduino framework
Just to make sure we don't break support to that framework, as we might want to migrate back in the future or some user might wanna use that.
2023-11-01 22:03:21 +01:00
Edward Firmo
fce2c5e4be Set framework esp-idf by default 2023-11-01 21:29:06 +01:00
Edward Firmo
b105d83b12 Persistent http client 2023-11-01 21:22:58 +01:00
Edward Firmo
25cf9f1bb9 Update nspanel_esphome_addon_upload_tft.yaml 2023-11-01 13:31:41 +01:00
Edward Firmo
88f287aa0d Upload TFT ESP-IDF - Cleaning logs 2023-11-01 10:04:42 +01:00
Edward Firmo
34142c510f Upload TFT for ESP-IDF
Still pending some clean-up, but I would say this is a working version.
2023-11-01 09:35:51 +01:00
4 changed files with 98 additions and 96 deletions

View File

@@ -35,3 +35,8 @@ jobs:
uses: esphome/build-action@v1.8.0
with:
yaml_file: "./.test/esphome_advanced_climate_heat.yaml"
- name: Build core+advanced+climate_heat+arduino
uses: esphome/build-action@v1.8.0
with:
yaml_file: "./.test/esphome_advanced_climate_heat_arduino.yaml"

View File

@@ -0,0 +1,15 @@
substitutions:
device_name: nspanel
wifi_ssid: "nspanel"
wifi_password: "NSPanel_HA_Blueprint"
nextion_update_url: "https://github.com/Blackymas/NSPanel_HA_Blueprint/dummy"
packages:
core_package: !include ../nspanel_esphome.yaml # Core package
advanced_package: !include ../nspanel_esphome_advanced.yaml
addon_climate_heat: !include ../nspanel_esphome_addon_climate_heat.yaml
#addon_climate_cold: !include ../nspanel_esphome_addon_climate_cold.yaml
esp32:
framework:
type: arduino

View File

@@ -83,8 +83,6 @@ script:
bool is_updating_ = false;
size_t transfer_buffer_size_ = 0;
uint8_t *transfer_buffer_{nullptr};
bool upload_first_chunk_sent_ = false;
int content_length_ = 0;
@@ -176,6 +174,8 @@ script:
};
#ifdef ARDUINO // arduino # To do: Move to Nextion component on ESPHome
size_t transfer_buffer_size_ = 0;
uint8_t *transfer_buffer_{nullptr};
auto upload_by_chunks_arduino = [&](HTTPClient *http, const std::string &url, int range_start) -> int
{
static const char *const TAG = "script.upload_tft.upload_by_chunks_arduino";
@@ -440,72 +440,90 @@ script:
return upload_end_(true);
};
#elif defined(ESP_PLATFORM) // esp-idf # To do: Move to Nextion component on ESPHome
auto upload_by_chunks_esp_idf = [&](const std::string &url, int range_start) -> int // Is this function needed or should it be merged into the parent?
{
static const char *const TAG = "script.upload_tft.upload_by_chunks_esp_idf";
ESP_LOGD(TAG, "url: %s", url.c_str());
ESP_LOGD(TAG, "range_start: %i", range_start);
ESP_LOGD(TAG, "transfer_buffer_size_: %i", transfer_buffer_size_);
ESP_LOGD(TAG, "tft_size_: %i", tft_size_);
int range_end;
if (range_start == 0 && transfer_buffer_size_ > 16384) {
range_end = 16384 - 1;
} else {
range_end = range_start + transfer_buffer_size_ - 1;
auto upload_range_esp_idf_ = [&](const std::string &url, int range_start) -> int {
static const char *const TAG = "script.upload_tft.upload_range_esp_idf_";
ESP_LOGVV(TAG, "url: %s", url.c_str());
ESP_LOGVV(TAG, "range_start: %i", range_start);
uint range_size_ = tft_size_ - range_start;
ESP_LOGVV(TAG, "range_size_: %i", range_size_);
if (range_size_ <= 0) {
ESP_LOGE(TAG, "Invalid range");
return -1;
}
ESP_LOGVV(TAG, "tft_size_: %i", tft_size_);
ESP_LOGV(TAG, "Available heap: %u", esp_get_free_heap_size());
if (range_end > tft_size_)
range_end = tft_size_;
ESP_LOGD(TAG, "range_end: %i", range_end);
int range = range_end - range_start;
ESP_LOGD(TAG, "range size: %i", range);
int range_end = (range_start == 0) ? std::min(tft_size_, 16383) : tft_size_;
ESP_LOGVV(TAG, "range_end: %i", range_end);
esp_http_client_config_t config = {
.url = url.c_str(),
};
esp_http_client_handle_t client = esp_http_client_init(&config);
char range_header[64];
sprintf(range_header, "bytes=%d-%d", range_start, range_end);
ESP_LOGV(TAG, "Requesting range: %s", range_header);
esp_http_client_set_header(client, "Range", range_header);
ESP_LOGVV(TAG, "Available heap: %u", esp_get_free_heap_size());
ESP_LOGV(TAG, "Opening http connetion");
esp_err_t err;
if ((err = esp_http_client_open(client, 0)) != ESP_OK) {
ESP_LOGE(TAG, "Failed to open HTTP connection: %s", esp_err_to_name(err));
free(transfer_buffer_);
esp_http_client_cleanup(client);
return -1;
}
//char range_header[64];
//sprintf(range_header, "bytes=%d-%d", range_start, range_end);
//ESP_LOGD(TAG, "Requesting range: %s", range_header);
//esp_http_client_set_header(client, "Range", range_header);
ESP_LOGV(TAG, "Fetch content length");
int content_length = esp_http_client_fetch_headers(client);
ESP_LOGD(TAG, "content_length = %d", content_length);
ESP_LOGV(TAG, "content_length = %d", content_length);
int total_read_len = 0, read_len;
ESP_LOGD(TAG, "Allocate buffer");
ESP_LOGV(TAG, "Allocate buffer");
uint8_t* buffer = new uint8_t[4096];
std::string recv_string;
if (buffer == nullptr) {
ESP_LOGE(TAG, "Failed to allocate memory for buffer");
ESP_LOGD(TAG, "Available heap: %u", esp_get_free_heap_size());
ESP_LOGV(TAG, "Available heap: %u", esp_get_free_heap_size());
} else {
ESP_LOGI(TAG, "Memory for buffer allocated successfully");
ESP_LOGD(TAG, "Available heap: %u", esp_get_free_heap_size());
ESP_LOGV(TAG, "Memory for buffer allocated successfully");
while (true) {
ESP_LOGD(TAG, "Available heap: %u", esp_get_free_heap_size());
App.feed_wdt();
ESP_LOGVV(TAG, "Available heap: %u", esp_get_free_heap_size());
int read_len = esp_http_client_read(client, reinterpret_cast<char*>(buffer), 4096);
ESP_LOGVV(TAG, "Read %d bytes from HTTP client, writing to UART", read_len);
if (read_len > 0) {
ESP_LOGI(TAG, "Read %d bytes from HTTP client, writing to UART", read_len);
tf_uart->write_array(buffer, read_len);
ESP_LOGI(TAG, "Write to UART successful");
ESP_LOGVV(TAG, "Write to UART successful");
recv_ret_string_(recv_string, 5000, true);
if (recv_string[0] != 0x05) { // 0x05 == "ok"
content_length_ -= read_len;
ESP_LOGD(TAG, "Uploaded %0.2f %%, remaining %d bytes",
100.0 * (tft_size_ - content_length_) / tft_size_,
content_length_);
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;
for (int j = 0; j < 4; ++j) {
result += static_cast<uint8_t>(recv_string[j + 1]) << (8 * j);
}
if (result > 0) {
ESP_LOGI(TAG, "Nextion reported new range %d", result);
content_length_ = tft_size_ - result;
// Deallocate the buffer when done
delete[] buffer;
ESP_LOGVV(TAG, "Memory for buffer deallocated");
esp_http_client_cleanup(client);
esp_http_client_close(client);
return result;
}
}
recv_string.clear();
} else if (read_len == 0) {
ESP_LOGI(TAG, "End of HTTP response reached");
ESP_LOGV(TAG, "End of HTTP response reached");
break; // Exit the loop if there is no more data to read
} else {
ESP_LOGE(TAG, "Failed to read from HTTP client, error code: %d", read_len);
@@ -515,8 +533,10 @@ script:
// Deallocate the buffer when done
delete[] buffer;
ESP_LOGI(TAG, "Memory for buffer deallocated");
ESP_LOGVV(TAG, "Memory for buffer deallocated");
}
esp_http_client_cleanup(client);
esp_http_client_close(client);
return range_end + 1;
};
auto upload_tft_ = [&](const std::string &url, unsigned int update_baud_rate_) -> bool {
@@ -526,12 +546,12 @@ script:
ESP_LOGD(TAG, "baud_rate: %i", update_baud_rate_);
if (is_updating_) {
ESP_LOGD(TAG, "Currently updating");
ESP_LOGW(TAG, "Currently updating");
return upload_end_(false);
}
if (!network::is_connected()) {
ESP_LOGD(TAG, "Network is not connected");
ESP_LOGE(TAG, "Network is not connected");
return upload_end_(false);
}
@@ -541,8 +561,8 @@ script:
is_updating_ = true;
// Define the configuration for the HTTP client
ESP_LOGD(TAG, "Establishing connection to HTTP server");
ESP_LOGD(TAG, "Available heap: %u", esp_get_free_heap_size());
ESP_LOGV(TAG, "Establishing connection to HTTP server");
ESP_LOGVV(TAG, "Available heap: %u", esp_get_free_heap_size());
esp_http_client_config_t config = {
.url = url.c_str(),
.method = HTTP_METHOD_HEAD,
@@ -550,8 +570,8 @@ script:
};
// Initialize the HTTP client with the configuration
ESP_LOGD(TAG, "Initializing HTTP client");
ESP_LOGD(TAG, "Available heap: %u", esp_get_free_heap_size());
ESP_LOGV(TAG, "Initializing HTTP client");
ESP_LOGV(TAG, "Available heap: %u", esp_get_free_heap_size());
esp_http_client_handle_t http = esp_http_client_init(&config);
if (!http) {
ESP_LOGE(TAG, "Failed to initialize HTTP client.");
@@ -559,8 +579,8 @@ script:
}
// Perform the HTTP request
ESP_LOGD(TAG, "Check if the client could connect");
ESP_LOGD(TAG, "Available heap: %u", esp_get_free_heap_size());
ESP_LOGV(TAG, "Check if the client could connect");
ESP_LOGV(TAG, "Available heap: %u", esp_get_free_heap_size());
esp_err_t err = esp_http_client_perform(http);
if (err != ESP_OK) {
ESP_LOGE(TAG, "HTTP request failed: %s", esp_err_to_name(err));
@@ -570,7 +590,7 @@ script:
// Check the HTTP Status Code
int status_code = esp_http_client_get_status_code(http);
ESP_LOGD(TAG, "HTTP Status Code: %d", status_code);
ESP_LOGV(TAG, "HTTP Status Code: %d", status_code);
size_t tft_file_size = esp_http_client_get_content_length(http);
ESP_LOGD(TAG, "TFT file size: %zu", tft_file_size);
@@ -616,72 +636,34 @@ script:
format_hex_pretty(reinterpret_cast<const uint8_t *>(response.data()), response.size()).c_str());
if (response.find(0x05) != std::string::npos) {
ESP_LOGD(TAG, "Preparation for tft update done");
ESP_LOGV(TAG, "Preparation for tft update done");
} else {
ESP_LOGD(TAG, "Preparation for tft update failed %d \"%s\"", response[0], response.c_str());
ESP_LOGE(TAG, "Preparation for tft update failed %d \"%s\"", response[0], response.c_str());
esp_http_client_cleanup(http);
return upload_end_(false);
}
// Nextion wants 4096 bytes at a time. Make chunk_size a multiple of 4096
uint32_t chunk_size = 8192;
if (esp_get_free_heap_size() > 81920) { // Ensure some FreeHeap to other things and limit chunk size
chunk_size = esp_get_free_heap_size() - 65536;
chunk_size = int(chunk_size / 4096) * 4096;
chunk_size = chunk_size > ${upload_tft_chunk_size_max} ? ${upload_tft_chunk_size_max} : chunk_size;
} else if (esp_get_free_heap_size() < 32768) {
chunk_size = 4096;
}
ESP_LOGD(TAG, "Updating tft from \"%s\" with a file size of %d, Heap Size %d",
url.c_str(), content_length_, esp_get_free_heap_size());
if (transfer_buffer_ == nullptr) {
ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
ESP_LOGD(TAG, "Allocating buffer size %d, Heap size is %u", chunk_size, esp_get_free_heap_size());
transfer_buffer_ = allocator.allocate(chunk_size);
if (transfer_buffer_ == nullptr) { // Try a smaller size
ESP_LOGD(TAG, "Could not allocate buffer size: %d trying 4096 instead", chunk_size);
chunk_size = 4096;
ESP_LOGD(TAG, "Allocating %d buffer", chunk_size);
transfer_buffer_ = allocator.allocate(chunk_size);
if (!transfer_buffer_) {
esp_http_client_cleanup(http);
return upload_end_(false);
}
}
transfer_buffer_size_ = chunk_size;
}
ESP_LOGD(TAG, "Updating tft from \"%s\" with a file size of %d using %zu chunksize, Heap Size %d",
url.c_str(), content_length_, transfer_buffer_size_, esp_get_free_heap_size());
ESP_LOGD(TAG, "Starting transfer by chunks loop");
ESP_LOGV(TAG, "Starting transfer by chunks loop");
int result = 0;
while (content_length_ > 0) {
result = upload_by_chunks_esp_idf(url.c_str(), result);
result = upload_range_esp_idf_(url.c_str(), result);
if (result < 0) {
ESP_LOGD(TAG, "Error updating Nextion!");
ESP_LOGE(TAG, "Error updating Nextion!");
esp_http_client_cleanup(http);
return upload_end_(false);
}
App.feed_wdt();
ESP_LOGD(TAG, "Heap Size %d, Bytes left %d", esp_get_free_heap_size(), content_length_);
ESP_LOGV(TAG, "Heap Size %d, Bytes left %d", esp_get_free_heap_size(), content_length_);
}
//int result = 0;
//while (content_length_ > 0) {
// result = upload_by_chunks_esp_idf(http, url, result);
// if (result < 0) {
// ESP_LOGD(TAG, "Error updating Nextion!");
// esp_http_client_cleanup(http);
// return upload_end_(false);
// }
// App.feed_wdt();
// ESP_LOGD(TAG, "Heap Size %d, Bytes left %d", esp_get_free_heap_size(), content_length_);
//}
is_updating_ = false;
ESP_LOGD(TAG, "Successfully updated Nextion!");
ESP_LOGD(TAG, "Close HTTP connection");
esp_http_client_close(http);
esp_http_client_cleanup(http);
return upload_end_(true);
};

View File

@@ -48,8 +48,8 @@ esphome:
##### TYPE OF ESP BOARD #####
esp32:
board: esp32dev
# framework:
# type: esp-idf
framework:
type: esp-idf
##### WIFI SETUP #####
wifi: