diff --git a/main/CommandHandler.cpp b/main/CommandHandler.cpp index 9b53b2c7..2b26b5a7 100644 --- a/main/CommandHandler.cpp +++ b/main/CommandHandler.cpp @@ -989,6 +989,221 @@ 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; +} + +#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 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, applyOTA, renameFile, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; #define NUM_COMMAND_HANDLERS (sizeof(commandHandlers) / sizeof(commandHandlers[0])) @@ -1034,6 +1252,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 +1281,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/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 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