From ad93421f36606c75e12a0f654eb290f1c41d5e5d Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Mon, 11 Jun 2018 18:57:45 +0200 Subject: [PATCH 1/5] Initial implementation of FS handling --- main/CommandHandler.cpp | 123 +++++++++++++++++++++++++++++++++++++++- main/sketch.ino.cpp | 17 ++++++ partitions.csv | 1 + 3 files changed, 139 insertions(+), 2 deletions(-) diff --git a/main/CommandHandler.cpp b/main/CommandHandler.cpp index 9b53b2c7..39b7a6d4 100644 --- a/main/CommandHandler.cpp +++ b/main/CommandHandler.cpp @@ -989,6 +989,119 @@ int setAnalogWrite(const uint8_t command[], uint8_t response[]) return 6; } +int writeFile(const uint8_t command[], uint8_t response[]) { + char filename[32 + 1]; + size_t len; + size_t offset; + + memcpy(&offset, &command[4], command[3]); + memcpy(&len, &command[5 + command[3]], command[4 + command[3]]); + + memset(filename, 0x00, sizeof(filename)); + memcpy(filename, &command[6 + command[3] + command[4 + command[3]]], command[5 + command[3] + command[4 + command[3]]]); + + FILE* f = fopen(filename, "ab+"); + if (f == NULL) { + return -1; + } + + fseek(f, offset, SEEK_SET); + const uint8_t* data = &command[7 + command[3] + command[4 + command[3]] + command[5 + command[3] + command[4 + command[3]]]]; + + int ret = fwrite(data, 1, len, f); + fclose(f); + + return ret; +} + +int readFile(const uint8_t command[], uint8_t response[]) { + char filename[32 + 1]; + size_t len; + size_t offset; + + memcpy(&offset, &command[4], command[3]); + memcpy(&len, &command[5 + command[3]], command[4 + command[3]]); + + memset(filename, 0x00, sizeof(filename)); + memcpy(filename, &command[6 + command[3] + command[4 + command[3]]], command[5 + command[3] + command[4 + command[3]]]); + + FILE* f = fopen(filename, "rb"); + if (f == NULL) { + return -1; + } + fseek(f, offset, SEEK_SET); + int ret = fread(&response[4], len, 1, f); + fclose(f); + + response[2] = 1; // number of parameters + response[3] = len; // parameter 1 length + + return len + 5; +} + +int deleteFile(const uint8_t command[], uint8_t response[]) { + char filename[32 + 1]; + size_t len; + size_t offset; + + memcpy(&offset, &command[4], command[3]); + memcpy(&len, &command[5 + command[3]], command[4 + command[3]]); + + memset(filename, 0x00, sizeof(filename)); + memcpy(filename, &command[6 + command[3] + command[4 + command[3]]], command[5 + command[3] + command[4 + command[3]]]); + + int ret = -1; + struct stat st; + if (stat(filename, &st) == 0) { + // Delete it if it exists + ret = unlink(filename); + } + return 0; +} + +int existsFile(const uint8_t command[], uint8_t response[]) { + char filename[32 + 1]; + size_t len; + size_t offset; + + memcpy(&offset, &command[4], command[3]); + memcpy(&len, &command[5 + command[3]], command[4 + command[3]]); + + memset(filename, 0x00, sizeof(filename)); + memcpy(filename, &command[6 + command[3] + command[4 + command[3]]], command[5 + command[3] + command[4 + command[3]]]); + + int ret = -1; + + struct stat st; + ret = stat(filename, &st); + if (ret != 0) { + st.st_size = -1; + } + memcpy(&response[4], &(st.st_size), sizeof(st.st_size)); + + response[2] = 1; // number of parameters + response[3] = sizeof(st.st_size); // parameter 1 length + + return 10; +} + +int downloadFile(const uint8_t command[], uint8_t response[]) { + char url[64 + 1]; + char filename[64 + 1]; + + memset(url, 0x00, sizeof(url)); + memset(filename, 0x00, sizeof(filename)); + + memcpy(url, &command[4], command[3]); + memcpy(filename, "/fs/", strlen("/fs/")); + memcpy(&filename[strlen("/fs/")], &command[5 + command[3]], command[4 + command[3]]); + + FILE* f = fopen(filename, "w"); + downloadAndSaveFile(url, filename, f); + fclose(f); + + return 0; +} typedef int (*CommandHandlerType)(const uint8_t command[], uint8_t response[]); @@ -1009,7 +1122,10 @@ const CommandHandlerType commandHandlers[] = { NULL, NULL, NULL, NULL, sendDataTcp, getDataBufTcp, insertDataBuf, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 0x50 -> 0x5f - setPinMode, setDigitalWrite, setAnalogWrite, + setPinMode, setDigitalWrite, setAnalogWrite, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + + // 0x60 -> 0x6f + writeFile, readFile, deleteFile, existsFile, downloadFile, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; #define NUM_COMMAND_HANDLERS (sizeof(commandHandlers) / sizeof(commandHandlers[0])) @@ -1034,6 +1150,9 @@ void CommandHandlerClass::begin() xTaskCreatePinnedToCore(CommandHandlerClass::gpio0Updater, "gpio0Updater", 8192, NULL, 1, NULL, 1); } +#define UDIV_UP(a, b) (((a) + (b) - 1) / (b)) +#define ALIGN_UP(a, b) (UDIV_UP(a, b) * (b)) + int CommandHandlerClass::handle(const uint8_t command[], uint8_t response[]) { int responseLength = 0; @@ -1060,7 +1179,7 @@ int CommandHandlerClass::handle(const uint8_t command[], uint8_t response[]) xSemaphoreGive(_updateGpio0PinSemaphore); - return responseLength; + return ALIGN_UP(responseLength, 4); } void CommandHandlerClass::gpio0Updater(void*) diff --git a/main/sketch.ino.cpp b/main/sketch.ino.cpp index 17889f8a..f1cefec9 100644 --- a/main/sketch.ino.cpp +++ b/main/sketch.ino.cpp @@ -21,8 +21,16 @@ extern "C" { #include + #include #include + + #include "esp_spiffs.h" + #include "esp_log.h" + #include + #include + #include + #include "esp_partition.h" } #include @@ -135,6 +143,15 @@ void setupWiFi() { esp_bt_controller_mem_release(ESP_BT_MODE_BTDM); SPIS.begin(); + esp_vfs_spiffs_conf_t conf = { + .base_path = "/fs", + .partition_label = "storage", + .max_files = 20, + .format_if_mount_failed = true + }; + + esp_err_t ret = esp_vfs_spiffs_register(&conf); + if (WiFi.status() == WL_NO_SHIELD) { while (1); // no shield } diff --git a/partitions.csv b/partitions.csv index 2f45debf..a549e0e3 100644 --- a/partitions.csv +++ b/partitions.csv @@ -4,3 +4,4 @@ nvs, data, nvs, 0x9000, 0x6000 phy_init, data, phy, 0xf000, 0x1000 certs, data, 0x04, 0x10000, 0x20000 factory, app, factory, 0x30000, 0x180000 +storage, data, spiffs, 0x1B0000,0x40000 From a56703448057d4f29e4fca6aa22b1486b98171ae Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Tue, 2 Oct 2018 16:42:34 +0200 Subject: [PATCH 2/5] Add downloadFile helper --- main/CommandHandler.h | 2 ++ main/http_client.c | 65 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 main/http_client.c diff --git a/main/CommandHandler.h b/main/CommandHandler.h index 28a47a43..9cef4619 100644 --- a/main/CommandHandler.h +++ b/main/CommandHandler.h @@ -45,4 +45,6 @@ class CommandHandlerClass { extern CommandHandlerClass CommandHandler; +extern "C" int downloadAndSaveFile(char* url, char* filename, FILE* f); + #endif diff --git a/main/http_client.c b/main/http_client.c new file mode 100644 index 00000000..002036dc --- /dev/null +++ b/main/http_client.c @@ -0,0 +1,65 @@ +// esp_http_client.c +#include +#include +#include "esp_log.h" +#include + +#include "esp_http_client.h" + +#define MAX_HTTP_RECV_BUFFER 128 + +static const char* TAG = "HTTP_HANDLER"; + +static esp_err_t _http_event_handler(esp_http_client_event_t *evt) +{ + switch(evt->event_id) { + case HTTP_EVENT_ERROR: + case HTTP_EVENT_ON_CONNECTED: + case HTTP_EVENT_HEADER_SENT: + case HTTP_EVENT_ON_FINISH: + case HTTP_EVENT_DISCONNECTED: + case HTTP_EVENT_ON_HEADER: + break; + case HTTP_EVENT_ON_DATA: + if (!esp_http_client_is_chunked_response(evt->client)) { + //fwrite((char*)evt->data, sizeof(uint8_t), evt->data_len, (FILE*)evt->user_data); + } + break; + } + return ESP_OK; +} + +int downloadAndSaveFile(char* url, char* filename, FILE* f) { + + char *buffer = (char*)malloc(MAX_HTTP_RECV_BUFFER); + if (buffer == NULL) { + return -1; + } + esp_http_client_config_t config = { + .url = url, + .event_handler = _http_event_handler, + .user_data = f, + }; + + esp_http_client_handle_t client = esp_http_client_init(&config); + esp_err_t err; + if ((err = esp_http_client_open(client, 0)) != ESP_OK) { + free(buffer); + return -1; + } + int content_length = esp_http_client_fetch_headers(client); + int total_read_len = 0, read_len; + while (total_read_len < content_length) { + read_len = esp_http_client_read(client, buffer, MAX_HTTP_RECV_BUFFER); + fwrite(buffer, sizeof(uint8_t), read_len, f); + if (read_len <= 0) { + break; + } + total_read_len += read_len; + } + esp_http_client_close(client); + esp_http_client_cleanup(client); + free(buffer); + + return 0; +} \ No newline at end of file From 072354249dd0ccfcc09e1e0b5a61d4b6faa26c8a Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Tue, 11 Dec 2018 17:11:57 +0100 Subject: [PATCH 3/5] Add OTA routine for UNO WiFi rev2 --- main/CommandHandler.cpp | 83 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 82 insertions(+), 1 deletion(-) diff --git a/main/CommandHandler.cpp b/main/CommandHandler.cpp index 39b7a6d4..ac3fdfc2 100644 --- a/main/CommandHandler.cpp +++ b/main/CommandHandler.cpp @@ -1059,6 +1059,87 @@ int deleteFile(const uint8_t command[], uint8_t response[]) { return 0; } +#include + +int applyOTA(const uint8_t command[], uint8_t response[]) { +#ifdef UNO_WIFI_REV2 + + const char* filename = "/fs/UPDATE.BIN"; + FILE* updateFile = fopen(filename, "rb"); + + // init uart and write update to 4809 + uart_config_t uart_config; + + uart_config.baud_rate = 115200; + uart_config.data_bits = UART_DATA_8_BITS; + uart_config.parity = UART_PARITY_DISABLE; + uart_config.stop_bits = UART_STOP_BITS_1; + uart_config.flow_ctrl = UART_HW_FLOWCTRL_DISABLE; + uart_config.rx_flow_ctrl_thresh = 122; + uart_config.use_ref_tick = true; + + uart_param_config(UART_NUM_1, &uart_config); + + uart_set_pin(UART_NUM_1, + 1, // tx + 3, // rx + UART_PIN_NO_CHANGE, // rts + UART_PIN_NO_CHANGE); //cts + + uart_driver_install(UART_NUM_1, 1024, 0, 20, NULL, 0); + + struct stat st; + stat(filename, &st); + + int retries = 0; + + size_t remaining = st.st_size % 1024; + for (int i=0; i= 100) { + goto exit; + } + } + // send remaining bytes (to reach page size) as 0xFF + for (int i=0; i 0x6f - writeFile, readFile, deleteFile, existsFile, downloadFile, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + writeFile, readFile, deleteFile, existsFile, downloadFile, applyOTA, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; #define NUM_COMMAND_HANDLERS (sizeof(commandHandlers) / sizeof(commandHandlers[0])) From abb02a3cdc6456261217c757e9ad298f836dc4e4 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 10 Jun 2020 11:14:14 +0200 Subject: [PATCH 4/5] Adding 'rename' operation necessary for using the WiFiNiNa for OTA --- main/CommandHandler.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/main/CommandHandler.cpp b/main/CommandHandler.cpp index ac3fdfc2..d752b17d 100644 --- a/main/CommandHandler.cpp +++ b/main/CommandHandler.cpp @@ -1140,6 +1140,21 @@ int applyOTA(const uint8_t command[], uint8_t response[]) { #endif } +int renameFile(const uint8_t command[], uint8_t response[]) { + char old_file_name[64 + 1]; + char new_file_name[64 + 1]; + + memset(old_file_name, 0x00, sizeof(old_file_name)); + memcpy(old_file_name, "/fs/", strlen("/fs/")); + memcpy(&old_file_name[strlen("/fs/")], &command[4], command[3]); + + memset(new_file_name, 0x00, sizeof(new_file_name)); + memcpy(new_file_name, "/fs/", strlen("/fs/")); + memcpy(&new_file_name[strlen("/fs/")], &command[5 + command[3]], command[4 + command[3]]); + + return rename(old_file_name, new_file_name); +} + int existsFile(const uint8_t command[], uint8_t response[]) { char filename[32 + 1]; size_t len; @@ -1206,7 +1221,7 @@ const CommandHandlerType commandHandlers[] = { setPinMode, setDigitalWrite, setAnalogWrite, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 0x60 -> 0x6f - writeFile, readFile, deleteFile, existsFile, downloadFile, applyOTA, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + writeFile, readFile, deleteFile, existsFile, downloadFile, applyOTA, renameFile, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; #define NUM_COMMAND_HANDLERS (sizeof(commandHandlers) / sizeof(commandHandlers[0])) From 65d6e1aacf679b5f0d3f1f42a064dc7987d1b50e Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 24 Jun 2020 09:47:51 +0200 Subject: [PATCH 5/5] Adding the errno code of the rename operation to the response message --- main/CommandHandler.cpp | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/main/CommandHandler.cpp b/main/CommandHandler.cpp index d752b17d..2b26b5a7 100644 --- a/main/CommandHandler.cpp +++ b/main/CommandHandler.cpp @@ -1141,18 +1141,24 @@ int applyOTA(const uint8_t command[], uint8_t response[]) { } int renameFile(const uint8_t command[], uint8_t response[]) { - char old_file_name[64 + 1]; - char new_file_name[64 + 1]; + char old_file_name[64 + 1] = {0}; + char new_file_name[64 + 1] = {0}; - memset(old_file_name, 0x00, sizeof(old_file_name)); - memcpy(old_file_name, "/fs/", strlen("/fs/")); - memcpy(&old_file_name[strlen("/fs/")], &command[4], command[3]); + strcpy(old_file_name, "/fs/"); + memcpy(&old_file_name[strlen(old_file_name)], &command[4], command[3]); - memset(new_file_name, 0x00, sizeof(new_file_name)); - memcpy(new_file_name, "/fs/", strlen("/fs/")); - memcpy(&new_file_name[strlen("/fs/")], &command[5 + command[3]], command[4 + command[3]]); + strcpy(new_file_name, "/fs/"); + memcpy(&new_file_name[strlen(new_file_name)], &command[5 + command[3]], command[4 + command[3]]); - return rename(old_file_name, new_file_name); + errno = 0; + rename(old_file_name, new_file_name); + + /* Set up the response packet containing the ERRNO error number */ + response[2] = 1; /* Number of parameters */ + response[3] = 1; /* Length of parameter 1 */ + response[4] = errno; /* The actual payload */ + + return 0; } int existsFile(const uint8_t command[], uint8_t response[]) {