diff --git a/components/lua/modules/net/net.c b/components/lua/modules/net/net.c index 1cfd3fc4..3a7ff571 100644 --- a/components/lua/modules/net/net.c +++ b/components/lua/modules/net/net.c @@ -371,9 +371,21 @@ static int lnet_connected(lua_State* L) { } static int lnet_ota(lua_State *L) { + const char *server = luaL_optstring( L, 1, NULL ); + const char *project = luaL_optstring( L, 2, NULL ); driver_error_t *error; + int reboot = 1; + if (lua_gettop(L) > 2) { + luaL_checktype(L, 3, LUA_TBOOLEAN); + reboot = lua_toboolean( L, 3 ); + } + int check = 1; + if (lua_gettop(L) > 3) { + luaL_checktype(L, 4, LUA_TBOOLEAN); + check = lua_toboolean( L, 4 ); + } - if ((error = net_ota())) { + if ((error = net_ota(server, project, check, reboot))) { return luaL_driver_error(L, error); } diff --git a/components/sys/drivers/net.c b/components/sys/drivers/net.c index 3c566b92..e9cbc027 100644 --- a/components/sys/drivers/net.c +++ b/components/sys/drivers/net.c @@ -56,6 +56,8 @@ #include "esp_event.h" #include "esp_event_loop.h" #include "esp_ota_ops.h" +#include "esp_partition.h" +#include "esp_image_format.h" #include #if CONFIG_LUA_RTOS_LUA_USE_MDNS @@ -442,13 +444,14 @@ int wait_for_network(uint32_t timeout) { return 1; } -driver_error_t *net_ota() { +driver_error_t *net_ota(const char *server, const char *project, int verify, int reboot) { #if CONFIG_LUA_RTOS_USE_OTA driver_error_t *error; net_http_client_t client = HTTP_CLIENT_INITIALIZER; net_http_response_t response; esp_ota_handle_t update_handle = 0 ; uint8_t buffer[1024]; + esp_err_t err; const esp_partition_t *running = esp_ota_get_running_partition(); const esp_partition_t *update_partition = esp_ota_get_next_update_partition(NULL); @@ -460,14 +463,19 @@ driver_error_t *net_ota() { return error; } - printf("Connecting to https://%s ...\r\n", CONFIG_LUA_RTOS_OTA_SERVER_NAME); - if ((error = net_http_create_client(CONFIG_LUA_RTOS_OTA_SERVER_NAME, "443", &client))) { + printf("Connecting to https://%s ...\r\n", server ? server : CONFIG_LUA_RTOS_OTA_SERVER_NAME); + if ((error = net_http_create_client(server ? server : CONFIG_LUA_RTOS_OTA_SERVER_NAME, "443", &client))) { return error; } printf("Current firmware commit is %s\r\n", BUILD_COMMIT); - sprintf((char *)buffer, "/?firmware=%s&commit=%s", CONFIG_LUA_RTOS_FIRMWARE, BUILD_COMMIT); + if (NULL != project) { + snprintf((char *)buffer, sizeof(buffer), "/?firmware=%s&commit=%s&project=%s", CONFIG_LUA_RTOS_FIRMWARE, BUILD_COMMIT, project); + } + else { + snprintf((char *)buffer, sizeof(buffer), "/?firmware=%s&commit=%s", CONFIG_LUA_RTOS_FIRMWARE, BUILD_COMMIT); + } if ((error = net_http_get(&client, (const char *)buffer, "application/octet-stream", &response))) { net_http_destroy_client(&client); @@ -476,22 +484,24 @@ driver_error_t *net_ota() { if ((response.code == 200) && (response.size > 0)) { printf( - "Running partition is %s, at offset 0x%08x\r\n", + "Running from %s at offset 0x%08x\r\n", running->label, running->address ); printf( - "Writing partition is %s, at offset 0x%08x\r\n", - update_partition->label, update_partition->address + "Writing to %s at offset 0x%08x - capacity is %.2f MB\r\n", + update_partition->label, update_partition->address, + (((float)update_partition->size)/(1024.0*1024.0)) ); - esp_task_wdt_reset(); + float total = (float)response.size; - printf("Begin OTA update ...\r\n"); + esp_task_wdt_reset(); - esp_err_t err = esp_ota_begin(update_partition, OTA_SIZE_UNKNOWN, &update_handle); + printf("Starting OTA update, downloading partition image with %.2f MB\r\n", (total/(1024.0*1024.0)) ); + err = esp_ota_begin(update_partition, OTA_SIZE_UNKNOWN, &update_handle); if (err != ESP_OK) { - printf("Failed, error %d\r\n", err); + printf("OTA update failed, error %d\r\n", err); net_http_destroy_client(&client); return NULL; } @@ -506,48 +516,75 @@ driver_error_t *net_ota() { err = esp_ota_write(update_handle, buffer, response.len); if (err != ESP_OK) { - printf("\nChunk written unsuccessfully in partition (offset 0x%08x), error %d\r\n", address, err); + printf("\nError while writing chunk to 0x%08x, error %d\r\n", address, err); net_http_destroy_client(&client); return NULL; } else { int pct = (int)(((float)(address-update_partition->address))/total*100); if (0 == pct%10) esp_task_wdt_reset(); - printf("\rChunk written successfully in partition at offset 0x%08x", address); + printf("\rWriting chunk at 0x%08x... (%i %%)", address, pct); } address = address + response.len; } - printf("\nEnding OTA update ...\r\n"); + printf("\rWriting chunk at 0x%08x... (%i %%)\r\n", address, 100 ); + + esp_task_wdt_reset(); esp_task_wdt_reset(); if (esp_ota_end(update_handle) != ESP_OK) { - printf("Failed\r\n"); + printf("OTA transfer complete, update failed\r\n"); net_http_destroy_client(&client); return NULL; - } else { - printf("Changing boot partition ...\r\n"); - err = esp_ota_set_boot_partition(update_partition); - if (err != ESP_OK) { - printf("Failed, err %d\r\n", err); - } else { - printf("Updated\r\n"); - } } } else if (response.code == 470) { printf("Missing or bad arguments\r\n"); + net_http_destroy_client(&client); + return NULL; } else if (response.code == 471) { printf("No new firmware available\r\n"); + net_http_destroy_client(&client); + return NULL; + } else { + printf("Unexpected error, response code %i, size %i\r\n", response.code, response.size); + net_http_destroy_client(&client); + return NULL; } if ((error = net_http_destroy_client(&client))) { return error; } + if (0 != verify) { + esp_image_metadata_t data = { 0 }; + const esp_partition_pos_t partition_pos = { + .offset = update_partition->address, + .size = update_partition->size, + }; + err = esp_image_verify(ESP_IMAGE_VERIFY, &partition_pos, &data); + if (err != ESP_OK) { + printf("OTA update finished but the written image is not valid, error %d\r\n", err); + return NULL; + } + } + + printf("OTA update finished\r\n"); + + err = esp_ota_set_boot_partition(update_partition); + if (err != ESP_OK) { + printf("Changing the boot partition failed, error %d\r\n", err); + return NULL; + } else { + printf("Successfully changed boot partition\r\n"); + } + if (response.code == 200) { - printf("Restarting ...\r\n"); - esp_restart(); + if (0 != reboot) { + printf("Restarting ...\r\n"); + esp_restart(); + } } return NULL; diff --git a/components/sys/drivers/net.h b/components/sys/drivers/net.h index e1e3d5db..6bbb915d 100644 --- a/components/sys/drivers/net.h +++ b/components/sys/drivers/net.h @@ -213,7 +213,7 @@ int network_started(); driver_error_t *net_ping(const char *name, int count, int interval, int size, int timeout); driver_error_t *net_reconnect(); -driver_error_t *net_ota(); +driver_error_t *net_ota(const char *server, const char *project, int verify, int reboot); #endif