diff --git a/components/mesh_ota/HTTPS_client.c b/components/mesh_ota/HTTPS_client.c index d273704..6c390f6 100644 --- a/components/mesh_ota/HTTPS_client.c +++ b/components/mesh_ota/HTTPS_client.c @@ -22,47 +22,10 @@ https_client_ret_t https_clientInitialize() i32RetHTTPClient = https_clientInitEmbedTLS(); - if(i32RetHTTPClient == HTTPS_CLIENT_OK) + if (i32RetHTTPClient == HTTPS_CLIENT_ERROR_INIT_EMBEDTLS) { - i32RetHTTPClient = https_clientConnectToServer(); - } - - if(i32RetHTTPClient == HTTPS_CLIENT_OK) - { - i32RetHTTPClient = https_clientValidateServer(); - } - - if(i32RetHTTPClient == HTTPS_CLIENT_OK) - { - i32RetHTTPClient = https_clientSendRequest(); - } - - switch (i32RetHTTPClient) - { - case HTTPS_CLIENT_ERROR_INIT_EMBEDTLS: ESP_LOGE(TAG, "Unable to initialize EmbedTLS"); i32RetHTTPClient = HTTPS_CLIENT_ERROR; - break; - case HTTPS_CLIENT_ERROR_INIT_CONNECT_TWO_SERVER: - ESP_LOGE(TAG, "Unable to connect to server"); - i32RetHTTPClient = HTTPS_CLIENT_ERROR; - break; - case HTTPS_CLIENT_ERROR_INIT_VALIDATE_SERVER: - ESP_LOGE(TAG, "Unable to validate the server"); - i32RetHTTPClient = HTTPS_CLIENT_ERROR; - break; - case HTTPS_CLIENT_ERROR_INIT_SEND_REQUEST: - ESP_LOGE(TAG, "Unable to send request to server"); - i32RetHTTPClient = HTTPS_CLIENT_ERROR; - break; - case HTTPS_CLIENT_OK: - ESP_LOGI(TAG, "HTTPS Client successfully initialized"); - i32RetHTTPClient = HTTPS_CLIENT_OK; - break; - default: - i32RetHTTPClient = HTTPS_CLIENT_ERROR; - ESP_LOGE(TAG, "Unknown error while init https client"); - break; } return i32RetHTTPClient; } @@ -78,6 +41,7 @@ https_client_ret_t https_clientRetrieveData(char* pu8Data, uint32_t* pu32DataLen while (bRetriveData) { + mbedtls_ssl_conf_read_timeout(&sHTTPS_ClientConfig.conf, HTTPS_READ_TIMEOUT); //set timeout //Reading HTTP response i32RetRetrieveData = mbedtls_ssl_read(&sHTTPS_ClientConfig.ssl, (unsigned char *)(pu8Data+(*pu32BytesRead)), ((*pu32DataLenght)-(*pu32BytesRead))); @@ -105,13 +69,18 @@ https_client_ret_t https_clientRetrieveData(char* pu8Data, uint32_t* pu32DataLen pu32BytesRead = 0; } + if(i32RetRetrieveData == MBEDTLS_ERR_SSL_TIMEOUT ) + { + //timeout --> stop reading + bRetriveData = false; + } + if(i32RetRetrieveData == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { //connection is going to be closed i32RetHTTPClient = HTTPS_CLIENT_ERROR; bRetriveData = false; } - } return i32RetHTTPClient; } @@ -120,15 +89,6 @@ https_client_ret_t https_clientReset() { https_client_ret_t i32RetHTTPClient = HTTPS_CLIENT_OK; - i32RetHTTPClient = https_clientSendRequest(); - - return i32RetHTTPClient; -} - -https_client_ret_t https_clientDeinitialize() -{ - https_client_ret_t i32RetHTTPClient = HTTPS_CLIENT_OK; - i32RetHTTPClient = mbedtls_ssl_close_notify(&sHTTPS_ClientConfig.ssl); //close session if(i32RetHTTPClient != ESP_OK) @@ -250,7 +210,7 @@ https_client_ret_t https_clientConnectToServer() if(i32RetServerConnect == ESP_OK) { - mbedtls_ssl_set_bio(&sHTTPS_ClientConfig.ssl, &sHTTPS_ClientConfig.server_fd, mbedtls_net_send, mbedtls_net_recv, NULL); + mbedtls_ssl_set_bio(&sHTTPS_ClientConfig.ssl, &sHTTPS_ClientConfig.server_fd, mbedtls_net_send, mbedtls_net_recv, mbedtls_net_recv_timeout); //Performing the SSL/TLS handshake while ((i32RetServerConnect = mbedtls_ssl_handshake(&sHTTPS_ClientConfig.ssl)) != 0) diff --git a/components/mesh_ota/Mesh_OTA.c b/components/mesh_ota/Mesh_OTA.c index 5ec0713..212c905 100644 --- a/components/mesh_ota/Mesh_OTA.c +++ b/components/mesh_ota/Mesh_OTA.c @@ -8,6 +8,8 @@ xQueueHandle queueMessageOTA; //mesh ota controll messages like "OTA_Version_Res SemaphoreHandle_t bsStartStopServerWorker; //binary semaphore +const esp_partition_t* pOTAPartition; //pointer to ota partition + esp_err_t errMeshOTAInitialize() { esp_err_t err = ESP_OK; @@ -46,6 +48,17 @@ esp_err_t errMeshOTAInitialize() ERROR_CHECK(errMeshNetworkSetOTAMessageHandleHandle(vAddOTAControllMessageToQueue)); ERROR_CHECK(errMeshNetworkSetChangeStateOfServerWorkerHandle(vChangeStateOfServerWorker)); + if(err == ESP_OK) + { + pOTAPartition = esp_ota_get_next_update_partition(NULL); //get ota partition + + if(pOTAPartition == NULL) + { + err = ESP_FAIL; + ESP_LOGE(LOG_TAG, "unable to get next ota partition"); + } + } + if(err == ESP_OK) { xReturned = xTaskCreate(vTaskServerWorker, "vTaskServerWorker", 8192, NULL, 5, NULL); @@ -130,7 +143,7 @@ void vTaskServerWorker(void *arg) { esp_err_t err; bool bNewOTAImage = false; // true if a new ota image was downloaded and validated - // bool bFirstRun = true; + bool bFirstRun = true; while(true) { @@ -140,16 +153,18 @@ void vTaskServerWorker(void *arg) if (esp_mesh_is_root()) //check again that this node is the root node { - // if(bFirstRun == true) - // { + if(bFirstRun == true) + { ERROR_CHECK(https_clientInitialize()); - // bFirstRun = false; - //} + bFirstRun = false; + } + + ERROR_CHECK(https_clientConnectToServer()); + ERROR_CHECK(https_clientValidateServer()); + ERROR_CHECK(https_clientSendRequest()); ERROR_CHECK(errOTAHTTPS(&bNewOTAImage)); - https_clientDeinitialize(); - - // https_clientReset(); + https_clientReset(); if(bNewOTAImage == true) { @@ -167,85 +182,58 @@ void vTaskServerWorker(void *arg) esp_err_t errOTAHTTPS(bool* pbNewOTAImage) { esp_err_t err = ESP_OK; - char buffer[1024U]; - uint32_t u32BufferLenght = 1024U; - uint32_t u32BytesRead = 0; - char pcRemoteVersionNumber[12]; - const esp_partition_t * currentPartition; - const esp_partition_t * otaPartition; - static esp_ota_handle_t otaHandle; - uint32_t u32StartOffset; - //esp_app_desc_t otaPartitionDesc; - esp_app_desc_t curPartitionDesc; + char u8OTABuffer[OTA_HTTPS_SEGMENT_SIZE]; //store image segment from server before ota write + uint32_t u32BufferLenght = OTA_HTTPS_SEGMENT_SIZE; //size of buffer + uint32_t u32BytesRead = 0; //number of bytes that are read from server, <= u32BufferLenght + char pcRemoteVersionNumber[12]; //string for version number in server image + const esp_partition_t* pBootPartition; //pointer to boot partition (that will booted after reset) + static esp_ota_handle_t otaHandle; //OTA process handle + uint32_t u32StartOffset = 0U; //start offset for image (exclude the http response data) + esp_app_desc_t bootPartitionDesc; //Metadate from boot partition + pBootPartition = esp_ota_get_boot_partition(); //get boot partition (that will booted after reset), not the running partition + ERROR_CHECK(esp_ota_get_partition_description(pBootPartition, &bootPartitionDesc)); //get metadate of partition - currentPartition = esp_ota_get_boot_partition(); - ESP_LOGI(LOG_TAG, "Type: %d", (*currentPartition).subtype); - ESP_LOGI(LOG_TAG, "Start address: %d", (*currentPartition).address); - ESP_LOGI(LOG_TAG, "Size: %d", (*currentPartition).size); - ESP_LOGI(LOG_TAG, "Encrypted: %d", (*currentPartition).encrypted); + ERROR_CHECK(https_clientRetrieveData(u8OTABuffer, &u32BufferLenght, &u32BytesRead)); //read first bytes if image, including the version + ERROR_CHECK(errExtractVersionNumber(u8OTABuffer, &u32BytesRead, pcRemoteVersionNumber)); //extract version numbers - ERROR_CHECK(esp_ota_get_partition_description(currentPartition, &curPartitionDesc)); - //ESP_LOGI(LOG_TAG, "currentPartition project_name: %s", (curPartitionDesc).project_name); - //ESP_LOGI(LOG_TAG, "currentPartition version: %s", (curPartitionDesc).version); - //ESP_LOGI(LOG_TAG, "currentPartition Timestamp: %s %s", (curPartitionDesc).date, (curPartitionDesc).time); - - - - ERROR_CHECK(https_clientRetrieveData(buffer, &u32BufferLenght, &u32BytesRead)); //read first bytes if image, including the version - - //ESP_LOGI(LOG_TAG, "Data received: %i", u32BytesRead); - - ERROR_CHECK(errExtractVersionNumber(buffer, &u32BytesRead, pcRemoteVersionNumber)); - - if(err == ESP_OK) + if(err == ESP_OK) //check if version number is found { - if(bNewerVersion((curPartitionDesc).version, pcRemoteVersionNumber)) //compare local and remote version + if(bNewerVersion((bootPartitionDesc).version, pcRemoteVersionNumber)) //compare local and remote version { // server image is newer --> OTA update required ESP_LOGI(LOG_TAG, "server image is newer --> OTA update required"); - otaPartition = esp_ota_get_next_update_partition(currentPartition); - - if(otaPartition == NULL) - { - err = ESP_FAIL; - ESP_LOGE(LOG_TAG, "unable to get next ota partition"); - } - - ERROR_CHECK(errFindImageStart(buffer, &u32BufferLenght, &u32StartOffset)); //get image start offset - - //ESP_LOGI(LOG_TAG, "first byte offset: %i", u32StartOffset); - //ESP_LOGI(LOG_TAG, "first byte: %x", buffer[u32StartOffset]); + ERROR_CHECK(errFindImageStart(u8OTABuffer, &u32BufferLenght, &u32StartOffset)); //get image start offset //TODO lock ota mutex - ERROR_CHECK(esp_ota_begin(otaPartition, OTA_SIZE_UNKNOWN, &otaHandle)); - + ERROR_CHECK(esp_ota_begin(pOTAPartition, OTA_SIZE_UNKNOWN, &otaHandle)); //start ota update process if(err == ESP_OK) { //image download and ota partition write + ESP_LOGI(LOG_TAG, "start ota https download"); do { - ESP_LOGI(LOG_TAG, "OTA-Data written: %i", u32BytesRead); - ERROR_CHECK(esp_ota_write(otaHandle, (const void*) buffer+u32StartOffset, (u32BytesRead-u32StartOffset))); + //TODO progress log + ERROR_CHECK(esp_ota_write(otaHandle, (const void*) u8OTABuffer+u32StartOffset, (u32BytesRead-u32StartOffset))); if(err == ESP_OK) { //write was succsesfull u32StartOffset = 0U; //reset the offset for next download - https_clientRetrieveData(buffer, &u32BufferLenght, &u32BytesRead); //download next data segment + ERROR_CHECK(https_clientRetrieveData(u8OTABuffer, &u32BufferLenght, &u32BytesRead)); //download next data segment } } - while ((u32BytesRead > 0) && (err == ESP_OK)); + while ((u32BytesRead > 0) && (err == ESP_OK)); //loop until error or complete image downloaded } if(err == ESP_OK) { //no error occurred --> finish ota update process ERROR_CHECK(esp_ota_end(otaHandle)); //finish process - ERROR_CHECK(esp_ota_set_boot_partition(otaPartition)); //set new image as boot + ERROR_CHECK(esp_ota_set_boot_partition(pOTAPartition)); //set new image as boot if(err == ESP_OK) { *pbNewOTAImage = true; //image validated @@ -253,23 +241,17 @@ esp_err_t errOTAHTTPS(bool* pbNewOTAImage) } else { - // error occurred --> abort ota update process - ESP_LOGE(LOG_TAG, "abort ota process"); + //error occurred --> abort ota update process + ESP_LOGE(LOG_TAG, "abort ota process due to error 0x%x -> %s", err, esp_err_to_name(err)); ERROR_CHECK(esp_ota_abort(otaHandle)); *pbNewOTAImage = false; //ota update failed } - //TODO unlock ota mutex - } //end newer version on server } //end version number extracted - - - return err; } - /* * Return true if remote version is newer (higher) than local version */ @@ -403,9 +385,9 @@ esp_err_t esp_mesh_ota_send(mesh_addr_t* dest) static uint32_t u32index; - const esp_partition_t * currentPartition = esp_ota_get_boot_partition(); + const esp_partition_t * pBootPartition = esp_ota_get_boot_partition(); - if((*currentPartition).subtype == 0) + if((*pBootPartition).subtype == 0) { int data_read = 0; @@ -422,7 +404,7 @@ esp_err_t esp_mesh_ota_send(mesh_addr_t* dest) else { ESP_LOGI(MESH_TAG, "OTA-Data read: %i", u32index); - err = esp_partition_read(currentPartition, (1024*u32index), packet.au8Payload, 1024 ); + err = esp_partition_read(pBootPartition, (1024*u32index), packet.au8Payload, 1024 ); ESP_ERROR_CHECK(err); data_read = 1024; u32index++; @@ -438,7 +420,7 @@ esp_err_t esp_mesh_ota_send(mesh_addr_t* dest) } else { - ESP_LOGI(MESH_TAG, "Subtype: %d", (*currentPartition).subtype); + ESP_LOGI(MESH_TAG, "Subtype: %d", (*pBootPartition).subtype); } return err; } @@ -449,14 +431,14 @@ esp_err_t esp_mesh_ota_receive(mesh_addr_t* dest, struct ota_mesh_packet* packet static esp_ota_handle_t otaHandle; static uint32_t u32index; - const esp_partition_t * currentPartition = esp_ota_get_boot_partition(); - const esp_partition_t * otaPartition = esp_ota_get_next_update_partition(currentPartition); + const esp_partition_t * pBootPartition = esp_ota_get_boot_partition(); + const esp_partition_t * pOTAPartition = esp_ota_get_next_update_partition(pBootPartition); if(u32index == 0) { //first run - err = esp_ota_begin(otaPartition, OTA_SIZE_UNKNOWN, &otaHandle); + err = esp_ota_begin(pOTAPartition, OTA_SIZE_UNKNOWN, &otaHandle); ESP_ERROR_CHECK(err); } @@ -480,11 +462,11 @@ esp_err_t esp_mesh_ota_receive(mesh_addr_t* dest, struct ota_mesh_packet* packet err = esp_ota_end(otaHandle); ESP_ERROR_CHECK(err); esp_app_desc_t otaPartitionDesc; - err = esp_ota_get_partition_description(otaPartition, &otaPartitionDesc); + err = esp_ota_get_partition_description(pOTAPartition, &otaPartitionDesc); ESP_ERROR_CHECK(err); - ESP_LOGI(MESH_TAG, "otaPartition project_name: %s", (otaPartitionDesc).project_name); + ESP_LOGI(MESH_TAG, "pOTAPartition project_name: %s", (otaPartitionDesc).project_name); - err = esp_ota_set_boot_partition(otaPartition); + err = esp_ota_set_boot_partition(pOTAPartition); ESP_ERROR_CHECK(err); struct ota_mesh_packet retPacket; diff --git a/components/mesh_ota/include/HTTPS_client.h b/components/mesh_ota/include/HTTPS_client.h index 889363a..a1c464f 100644 --- a/components/mesh_ota/include/HTTPS_client.h +++ b/components/mesh_ota/include/HTTPS_client.h @@ -51,6 +51,8 @@ #define HTTPS_CLIENT_ERROR_INIT_VALIDATE_SERVER -4 #define HTTPS_CLIENT_ERROR_INIT_SEND_REQUEST -5 +#define HTTPS_READ_TIMEOUT 1000 //ms + struct HTTPS_Client { mbedtls_entropy_context entropy; @@ -65,9 +67,11 @@ typedef int32_t https_client_ret_t; typedef struct HTTPS_Client HTTPS_Client_t; https_client_ret_t https_clientInitialize(); +https_client_ret_t https_clientConnectToServer(); +https_client_ret_t https_clientValidateServer(); +https_client_ret_t https_clientSendRequest(); https_client_ret_t https_clientRetrieveData(char* pu8Data, uint32_t* pu32DataLenght, uint32_t* pu32BytesRead); https_client_ret_t https_clientReset(); -https_client_ret_t https_clientDeinitialize(); #endif /* H_HTTPS_CLIENT */ diff --git a/components/mesh_ota/include/Mesh_OTA.h b/components/mesh_ota/include/Mesh_OTA.h index fece273..c42f0bb 100644 --- a/components/mesh_ota/include/Mesh_OTA.h +++ b/components/mesh_ota/include/Mesh_OTA.h @@ -20,6 +20,7 @@ #define QUEUE_NODES_SIZE 10 #define QUEUE_MESSAGE_OTA_SIZE 10 #define SERVER_CHECK_INTERVAL 30 //in seconds +#define OTA_HTTPS_SEGMENT_SIZE 2048U #define ERROR_CHECK(x) if (err == ESP_OK) \ { \