refactor #2
| @ -1,4 +1,4 @@ | |||||||
| idf_component_register(SRCS "HTTPS_client.c" "Mesh_network_handler.c" "Mesh_network.c" "Mesh_OTA.c" | idf_component_register(SRCS "Mesh_OTA_Util.c" "Mesh_Network.c" "Mesh_Network_Handler.c" "HTTPS_Client.c" "Mesh_OTA_Partition_Access.c" "Mesh_OTA_Globals.c" "Mesh_OTA.c" | ||||||
|                     INCLUDE_DIRS "include"  |                     INCLUDE_DIRS "include"  | ||||||
|                     REQUIRES nvs_flash |                     REQUIRES nvs_flash | ||||||
|                     esp_http_client |                     esp_http_client | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| #include "HTTPS_client.h" | #include "HTTPS_Client.h" | ||||||
| 
 | 
 | ||||||
| static const char *TAG = "https_client"; | static const char *TAG = "https_client"; | ||||||
| 
 | 
 | ||||||
| @ -1,5 +1,5 @@ | |||||||
| 
 | 
 | ||||||
| #include "Mesh_OTA.h" | #include "Mesh_Network.h" | ||||||
| 
 | 
 | ||||||
| static const char *LOG_TAG = "mesh_network"; | static const char *LOG_TAG = "mesh_network"; | ||||||
| static uint8_t tx_buf[CONFIG_MESH_MESSAGE_SIZE] = { 0, }; | static uint8_t tx_buf[CONFIG_MESH_MESSAGE_SIZE] = { 0, }; | ||||||
| @ -1,5 +1,5 @@ | |||||||
| 
 | 
 | ||||||
| #include "Mesh_OTA.h" | #include "Mesh_Network.h" | ||||||
| 
 | 
 | ||||||
| static const char *LOG_TAG = "mesh_network_handler"; | static const char *LOG_TAG = "mesh_network_handler"; | ||||||
| 
 | 
 | ||||||
| @ -1,16 +1,10 @@ | |||||||
| #include "Mesh_OTA.h" | #include "Mesh_OTA.h" | ||||||
|  | #include "Mesh_OTA_Util.h" | ||||||
|  | #include "Mesh_OTA_Globals.h" | ||||||
|  | #include "Mesh_OTA_Access.h" | ||||||
|  |  | ||||||
| static const char *LOG_TAG = "mesh_ota"; | static const char *LOG_TAG = "mesh_ota"; | ||||||
|  |  | ||||||
| xQueueHandle queueNodes; //nodes that should be checked for ota update (contains children and parent) |  | ||||||
| xQueueHandle queueMessageOTA; //mesh ota controll messages like "OTA_Version_Response" "OTA_ACK" |  | ||||||
|  |  | ||||||
| SemaphoreHandle_t bsStartStopServerWorker; //binary semaphore |  | ||||||
| SemaphoreHandle_t bsOTAProcess; //binary semaphore |  | ||||||
|  |  | ||||||
| const esp_partition_t* pOTAPartition; //pointer to ota partition |  | ||||||
| bool bWantReboot; //flag to signal pending reboot |  | ||||||
|  |  | ||||||
| esp_err_t errMeshOTAInitialize() | esp_err_t errMeshOTAInitialize() | ||||||
| { | { | ||||||
|     esp_err_t err = ESP_OK; |     esp_err_t err = ESP_OK; | ||||||
| @ -105,75 +99,6 @@ esp_err_t errMeshOTAInitialize() | |||||||
|     return err; |     return err; | ||||||
| } | } | ||||||
|  |  | ||||||
| void vAddNodeToPossibleUpdatableQueue(uint8_t* pu8MAC) |  | ||||||
| { |  | ||||||
|     //send payload to node queues |  | ||||||
|     mesh_addr_t addrNode; |  | ||||||
|     memcpy(&addrNode.addr, (uint8_t *)pu8MAC, 6); //copy MAC |  | ||||||
|  |  | ||||||
|     if (xQueueSend(queueNodes, &addrNode, portMAX_DELAY) != pdPASS) |  | ||||||
|         { |  | ||||||
|             ESP_LOGE(LOG_TAG, "Unable to push node into node queue"); |  | ||||||
|         } |  | ||||||
|     else |  | ||||||
|         { |  | ||||||
|             ESP_LOGI(LOG_TAG, "added node \"%x:%x:%x:%x:%x:%x\" to possible updatable queue", addrNode.addr[0], addrNode.addr[1], addrNode.addr[2], addrNode.addr[3], addrNode.addr[4], addrNode.addr[5]); |  | ||||||
|         } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void vAddOtaMessageToQueue(MESH_PACKET_t* puMeshPacket) |  | ||||||
| { |  | ||||||
|     //send ota packet to packet queue |  | ||||||
|     if (xQueueSend(queueMessageOTA, puMeshPacket, portMAX_DELAY) != pdPASS) |  | ||||||
|         { |  | ||||||
|             ESP_LOGE(LOG_TAG, "Unable to push ota packet into packet queue"); |  | ||||||
|         } |  | ||||||
|     else |  | ||||||
|         { |  | ||||||
|             switch (puMeshPacket->type) |  | ||||||
|                 { |  | ||||||
|                 case OTA_Abort: |  | ||||||
|                     ESP_LOGI(LOG_TAG, "added ota message to queue: OTA_Abort from 0x%x", puMeshPacket->meshSenderAddr.addr[5]); |  | ||||||
|                     break; |  | ||||||
|                 case OTA_Version_Request: |  | ||||||
|                     ESP_LOGI(LOG_TAG, "added ota message to queue: OTA_Version_Request from 0x%x", puMeshPacket->meshSenderAddr.addr[5]); |  | ||||||
|                     break; |  | ||||||
|  |  | ||||||
|                 case OTA_Version_Response: |  | ||||||
|                     ESP_LOGI(LOG_TAG, "added ota message to queue: OTA_Version Response from 0x%x", puMeshPacket->meshSenderAddr.addr[5]); |  | ||||||
|                     break; |  | ||||||
|                 default: |  | ||||||
|                     break; |  | ||||||
|                 } |  | ||||||
|         } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void vChangeStateOfServerWorker(bool bState) //allow access via function ptn to networl_handler |  | ||||||
| { |  | ||||||
|     static bool bLastState = false; |  | ||||||
|  |  | ||||||
|     if(bState != bLastState) //change only if necessary |  | ||||||
|         { |  | ||||||
|             ESP_LOGI(LOG_TAG, "server worker change handler"); |  | ||||||
|  |  | ||||||
|             if(bState == true) |  | ||||||
|                 { |  | ||||||
|                     if (xSemaphoreGive(bsStartStopServerWorker)  != pdTRUE) |  | ||||||
|                         { |  | ||||||
|                             ESP_LOGE(LOG_TAG, "Unable to give mutex to activate the server worker"); |  | ||||||
|                         } |  | ||||||
|                 } |  | ||||||
|             else |  | ||||||
|                 { |  | ||||||
|                     if (xSemaphoreTake(bsStartStopServerWorker,( TickType_t ) 10 )  != pdTRUE) |  | ||||||
|                         { |  | ||||||
|                             ESP_LOGE(LOG_TAG, "Unable to obtain mutex to deactivate the server worker"); |  | ||||||
|                         } |  | ||||||
|                 } |  | ||||||
|             bLastState = bState; |  | ||||||
|         } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void vTaskServerWorker(void *arg) | void vTaskServerWorker(void *arg) | ||||||
| { | { | ||||||
|     esp_err_t err; |     esp_err_t err; | ||||||
| @ -272,84 +197,6 @@ void vTaskOTAWorker(void *arg) | |||||||
|         } |         } | ||||||
| } | } | ||||||
|  |  | ||||||
| esp_err_t errOTAHTTPS(bool* pbNewOTAImage) |  | ||||||
| { |  | ||||||
|     esp_err_t err = ESP_OK; |  | ||||||
|     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 |  | ||||||
|     uint32_t u32OTABytesWritten = 0U; //counter unsed for progress log |  | ||||||
|  |  | ||||||
|     ERROR_CHECK(errHTTPSClientRetrieveData(u8OTABuffer, &u32BufferLenght, &u32BytesRead)); //read first bytes if image, including the version |  | ||||||
|  |  | ||||||
|     ERROR_CHECK(errExtractVersionNumber(u8OTABuffer, &u32BytesRead, pcRemoteVersionNumber)); //extract version numbers |  | ||||||
|  |  | ||||||
|     if(err == ESP_OK) //check if version number is found |  | ||||||
|         { |  | ||||||
|             xSemaphoreTake(bsOTAProcess, portMAX_DELAY); //wait for binary semaphore that allows to start the OTA process |  | ||||||
|  |  | ||||||
|             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 metadata of partition |  | ||||||
|  |  | ||||||
|             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"); |  | ||||||
|  |  | ||||||
|                     ERROR_CHECK(errFindImageStart(u8OTABuffer, &u32BufferLenght, &u32StartOffset)); //get image start offset |  | ||||||
|  |  | ||||||
|                     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 download via HTTPS"); |  | ||||||
|                             do |  | ||||||
|                                 { |  | ||||||
|                                     vPrintOTAProgress(&(pOTAPartition->size), &u32OTABytesWritten, Receiver); |  | ||||||
|                                     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 |  | ||||||
|                                             ERROR_CHECK(errHTTPSClientRetrieveData(u8OTABuffer, &u32BufferLenght, &u32BytesRead)); //download next data segment |  | ||||||
|                                             u32OTABytesWritten = u32OTABytesWritten + u32BytesRead; //update counter |  | ||||||
|                                         } |  | ||||||
|                                 } |  | ||||||
|                             while ((u32BytesRead > 0) && (err == ESP_OK) && (u32OTABytesWritten <= pOTAPartition->size)); //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(pOTAPartition)); //set new image as boot |  | ||||||
|                             if(err == ESP_OK) |  | ||||||
|                                 { |  | ||||||
|                                     *pbNewOTAImage = true; //image validated |  | ||||||
|                                 } |  | ||||||
|                         } |  | ||||||
|                     else |  | ||||||
|                         { |  | ||||||
|                             //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 |  | ||||||
|                         } |  | ||||||
|                 } |  | ||||||
|             else |  | ||||||
|                 { |  | ||||||
|                     ESP_LOGI(LOG_TAG, "server image is NOT newer --> OTA update NOT required"); |  | ||||||
|                 } |  | ||||||
|             xSemaphoreGive(bsOTAProcess); //free binary semaphore, this allows other tasks to start the OTA process |  | ||||||
|         } //end version number extracted |  | ||||||
|     return err; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| esp_err_t errOTAMeshSlave(bool* pbNewOTAImage) | esp_err_t errOTAMeshSlave(bool* pbNewOTAImage) | ||||||
| { | { | ||||||
| @ -476,481 +323,3 @@ esp_err_t errOTAMeshMaster(bool* pbNewOTAImage, mesh_addr_t* pMeshNodeAddr) | |||||||
|         } |         } | ||||||
|     return err; |     return err; | ||||||
| } | } | ||||||
|  |  | ||||||
| bool bNewerVersion(const char* pu8Local, const  char* pu8Remote) |  | ||||||
| { |  | ||||||
|     /* |  | ||||||
|      * Return true if remote version is newer (higher) than local version |  | ||||||
|     */ |  | ||||||
|     char u8LocalTmp[12]; //local version |  | ||||||
|     char u8RemoteTmp[12]; //remote version |  | ||||||
|     char* pu8saveptrLocal; //context for strok_r |  | ||||||
|     char* pu8saveptrRemote; //context for strok_r |  | ||||||
|     bool bReturn = false; //flag to stop loop |  | ||||||
|     uint8_t u8Index = 0; //numbers counter in version string |  | ||||||
|  |  | ||||||
|     strncpy(u8LocalTmp, pu8Local, 12); //copy in tmp |  | ||||||
|     strncpy(u8RemoteTmp, pu8Remote, 12); //copy in tmp |  | ||||||
|  |  | ||||||
|     char* pu8TokenLocal = strtok_r(u8LocalTmp, ".", &pu8saveptrLocal); //split tokens |  | ||||||
|     char* pu8TokenRemote = strtok_r(u8RemoteTmp, ".", &pu8saveptrRemote); //split tokens |  | ||||||
|  |  | ||||||
|     while( (u8Index <= 2) && (bReturn == false)) //loop through tokens |  | ||||||
|         { |  | ||||||
|             u8Index++; |  | ||||||
|             if(atoi(pu8TokenLocal) < atoi(pu8TokenRemote)) |  | ||||||
|                 { |  | ||||||
|                     bReturn = true; //version number difference --> stop loop |  | ||||||
|                 } |  | ||||||
|             pu8TokenLocal = strtok_r(NULL, ".", &pu8saveptrLocal); //split tokens |  | ||||||
|             pu8TokenRemote = strtok_r(NULL, ".", &pu8saveptrRemote); //split tokens |  | ||||||
|         } |  | ||||||
|     return bReturn; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| esp_err_t errFindImageStart(const char* pu8Data, uint32_t* pu32DataLenght, uint32_t* pu32StartOffset) |  | ||||||
| { |  | ||||||
|     /* |  | ||||||
|     Offset  value |  | ||||||
|     0      = 0xE9 (first byte in image --> magic byte) |  | ||||||
|     48     = first digit of version number |  | ||||||
|     */ |  | ||||||
|  |  | ||||||
|     esp_err_t errReturn = ESP_OK; |  | ||||||
|     bool bImageStartOffsetFound = false; |  | ||||||
|     uint32_t u32DataIndex = 0; |  | ||||||
|     uint32_t u32FirstDotOffset = 0; |  | ||||||
|     uint32_t u32SecondDotOffset = 0; |  | ||||||
|     uint8_t u8FirstDotIndex = 0; |  | ||||||
|     uint8_t u8SecondDotIndex = 0; |  | ||||||
|  |  | ||||||
|     *pu32StartOffset = 0U; //reset offset to zero |  | ||||||
|  |  | ||||||
|     while((u32DataIndex < *pu32DataLenght) &&  (bImageStartOffsetFound == false)) |  | ||||||
|         { |  | ||||||
|             //search for magic byte |  | ||||||
|             if(pu8Data[u32DataIndex] == 0xe9) |  | ||||||
|                 { |  | ||||||
|                     //magic byte found |  | ||||||
|                     while ((u8FirstDotIndex < 3) && (u32FirstDotOffset == 0)) |  | ||||||
|                         { |  | ||||||
|                             //search first dot in version number |  | ||||||
|                             if((u32DataIndex+49+u8FirstDotIndex) < *pu32DataLenght) |  | ||||||
|                                 { |  | ||||||
|                                     if((pu8Data[(u32DataIndex+49+u8FirstDotIndex)] == 0x2e)) |  | ||||||
|                                         { |  | ||||||
|                                             //first dot found |  | ||||||
|                                             u32FirstDotOffset = (u32DataIndex+49+u8FirstDotIndex); |  | ||||||
|                                         } |  | ||||||
|                                 } |  | ||||||
|                             u8FirstDotIndex++; |  | ||||||
|                         } |  | ||||||
|  |  | ||||||
|                     while ((u8SecondDotIndex < 3) && (u32SecondDotOffset == 0) && (u32FirstDotOffset != 0)) |  | ||||||
|                         { |  | ||||||
|                             //search first dot in version number |  | ||||||
|                             if((u32FirstDotOffset+(u8SecondDotIndex+2)) < *pu32DataLenght) |  | ||||||
|                                 { |  | ||||||
|                                     if((pu8Data[(u32FirstDotOffset+(u8SecondDotIndex+2))] == 0x2e)) |  | ||||||
|                                         { |  | ||||||
|                                             //second dot found |  | ||||||
|                                             u32SecondDotOffset = (u32FirstDotOffset+(u8SecondDotIndex+2)); |  | ||||||
|                                         } |  | ||||||
|                                 } |  | ||||||
|                             u8SecondDotIndex++; |  | ||||||
|                         } |  | ||||||
|  |  | ||||||
|                     if((u32FirstDotOffset != 0) && (u32SecondDotOffset != 0)) |  | ||||||
|                         { |  | ||||||
|                             //image start found based on magic byte and version number systax |  | ||||||
|                             *pu32StartOffset = u32DataIndex; //store image start offset |  | ||||||
|                             bImageStartOffsetFound = true; |  | ||||||
|                         } |  | ||||||
|                     else |  | ||||||
|                         { |  | ||||||
|                             // this is propably not the magic byte --> reset |  | ||||||
|                             u32FirstDotOffset = 0; |  | ||||||
|                             u32SecondDotOffset = 0; |  | ||||||
|                             u8FirstDotIndex = 0; |  | ||||||
|                             u8SecondDotIndex = 0; |  | ||||||
|                         } |  | ||||||
|                 } |  | ||||||
|             u32DataIndex++; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|     if(bImageStartOffsetFound == false) |  | ||||||
|         { |  | ||||||
|             errReturn = ESP_ERR_NOT_FOUND; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|     return errReturn; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| esp_err_t errExtractVersionNumber(const char* pu8Data, uint32_t* pu32DataLenght, char* pc8RemoteVersionNumber) |  | ||||||
| { |  | ||||||
|     uint32_t u32StartOffset; |  | ||||||
|     esp_err_t err = ESP_OK; |  | ||||||
|  |  | ||||||
|     strcpy(pc8RemoteVersionNumber, "999.999.999"); //init value |  | ||||||
|     err = errFindImageStart(pu8Data, pu32DataLenght, &u32StartOffset); //get image start offset |  | ||||||
|  |  | ||||||
|     if(err == ESP_OK) |  | ||||||
|         { |  | ||||||
|             //image found |  | ||||||
|             strncpy(pc8RemoteVersionNumber, pu8Data+(u32StartOffset+48), 11); //copy version number |  | ||||||
|             pc8RemoteVersionNumber[12] = '\0'; |  | ||||||
|         } |  | ||||||
|     return err; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void vPrintOTAProgress(const uint32_t* const pu32TotalImageSize, const uint32_t* const pu32BytesWritten, OTA_MESH_ROLE_t eRole) |  | ||||||
| { |  | ||||||
|     uint32_t u32Percentage = 0U; |  | ||||||
|     static uint32_t u32LastPercentage = 0U; |  | ||||||
|  |  | ||||||
|     if((*pu32BytesWritten) >= (*pu32TotalImageSize)) |  | ||||||
|         { |  | ||||||
|             u32Percentage = 100; |  | ||||||
|         } |  | ||||||
|     else |  | ||||||
|         { |  | ||||||
|             u32Percentage = (uint32_t) (((float) (*pu32BytesWritten)/(float) (*pu32TotalImageSize)) * 100.0); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|     if((u32Percentage-u32LastPercentage) >= OTA_PROGRESS_LOG_INTERVAL) |  | ||||||
|         { |  | ||||||
|             if(eRole == Transmitter) |  | ||||||
|                 { |  | ||||||
|                     ESP_LOGI(LOG_TAG, "Transmitting OTA update: %i %%", u32Percentage); |  | ||||||
|                 } |  | ||||||
|  |  | ||||||
|             if(eRole == Receiver) |  | ||||||
|                 { |  | ||||||
|                     ESP_LOGI(LOG_TAG, "Receiving OTA update: %i %%", u32Percentage); |  | ||||||
|                 } |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|             u32LastPercentage = u32Percentage; |  | ||||||
|         } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void vAddAllNeighboursToQueue(void) |  | ||||||
| { |  | ||||||
|     esp_err_t err = ESP_OK; |  | ||||||
|  |  | ||||||
|     mesh_addr_t addrParent;  //addr of parent node |  | ||||||
|     mesh_addr_t childrenAddr[CONFIG_MESH_ROUTE_TABLE_SIZE]; //array of children attached to this node |  | ||||||
|     uint16_t u16ChildrenSize = 0U; //number of children attached to this node |  | ||||||
|  |  | ||||||
|     err = errGetParentNode(&addrParent); |  | ||||||
|  |  | ||||||
|     if(err == ESP_OK) |  | ||||||
|         { |  | ||||||
|             vAddNodeToPossibleUpdatableQueue(addrParent.addr); |  | ||||||
|             ESP_LOGI(LOG_TAG, "added parent"); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|     err = ESP_OK; //reset error code |  | ||||||
|  |  | ||||||
|     ERROR_CHECK(errGetChildren(childrenAddr, &u16ChildrenSize)); //get all children |  | ||||||
|  |  | ||||||
|     for (uint16_t u16Index = 0; ((u16Index < u16ChildrenSize) && (err == ESP_OK)); u16Index++) |  | ||||||
|         { |  | ||||||
|             vAddNodeToPossibleUpdatableQueue(childrenAddr[u16Index].addr); |  | ||||||
|             ESP_LOGI(LOG_TAG, "added child"); |  | ||||||
|         } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| esp_err_t errSendOTAVersionResponse(mesh_addr_t* pMeshReceiverAddr) |  | ||||||
| { |  | ||||||
|     esp_err_t err = ESP_OK; |  | ||||||
|     MESH_PACKET_t packet; |  | ||||||
|     packet.type = OTA_Version_Response; |  | ||||||
|  |  | ||||||
|     const esp_partition_t* pBootPartition; //pointer to boot partition (that will booted after reset) |  | ||||||
|     esp_app_desc_t bootPartitionDesc; //Metadata 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 |  | ||||||
|     memcpy(&packet.au8Payload, &bootPartitionDesc.version, 12); //copy local version to OTA_Version_Response packet |  | ||||||
|  |  | ||||||
|     ESP_LOGI(LOG_TAG, "Send OTA_Version_Response to 0x%x", pMeshReceiverAddr->addr[5]); |  | ||||||
|  |  | ||||||
|     err = errSendMeshPacket(pMeshReceiverAddr, &packet); |  | ||||||
|     return err; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void vClearOtaMessageQueue(mesh_addr_t* pMeshNodeAddr) |  | ||||||
| { |  | ||||||
|     MESH_PACKET_t sMeshPacket; //packet for sending and receiving |  | ||||||
|     for (uint32_t u32Index = 0; (u32Index < QUEUE_MESSAGE_OTA_SIZE); u32Index++) //loop through all OTA messages |  | ||||||
|         { |  | ||||||
|             if (xQueueReceive(queueMessageOTA, &sMeshPacket, 0) == pdTRUE) |  | ||||||
|                 { |  | ||||||
|                     if(!(bCheckMACEquality(sMeshPacket.meshSenderAddr.addr, pMeshNodeAddr->addr))) |  | ||||||
|                         { |  | ||||||
|                             //received OTA message is NOT from pMeshNodeAddr --> keep it in queue |  | ||||||
|                             vAddOtaMessageToQueue(&sMeshPacket); |  | ||||||
|                         } |  | ||||||
|                     else |  | ||||||
|                         { |  | ||||||
|                             ESP_LOGI(LOG_TAG, "Removed type %i from node 0x%x", sMeshPacket.type, pMeshNodeAddr->addr[5]); |  | ||||||
|                         } |  | ||||||
|                 } |  | ||||||
|         }//end OTA message loop |  | ||||||
| } |  | ||||||
|  |  | ||||||
| esp_err_t errSendOTAVersionRequest(mesh_addr_t* pMeshReceiverAddr) |  | ||||||
| { |  | ||||||
|     esp_err_t err = ESP_OK; |  | ||||||
|     MESH_PACKET_t packet; |  | ||||||
|     packet.type = OTA_Version_Request; |  | ||||||
|  |  | ||||||
|     const esp_partition_t* pBootPartition; //pointer to boot partition (that will booted after reset) |  | ||||||
|     esp_app_desc_t bootPartitionDesc; //Metadata 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 |  | ||||||
|     memcpy(&packet.au8Payload, &bootPartitionDesc.version, 12); //copy local version to OTA_Version_Request packet |  | ||||||
|     err = errSendMeshPacket(pMeshReceiverAddr, &packet); |  | ||||||
|     return err; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| esp_err_t errOTAMeshTransmit(mesh_addr_t* pMeshNodeAddr) |  | ||||||
| { |  | ||||||
|     esp_err_t err = ESP_OK; |  | ||||||
|     const esp_partition_t* pBootPartition; //pointer to boot partition (that will booted after reset) |  | ||||||
|     MESH_PACKET_t sMeshPacket; //packet for sending and receiving |  | ||||||
|     // uint32_t u32Index = 0U; //index for partition read offset |  | ||||||
|     bool bAbort = false; //abort the OTA process |  | ||||||
|     bool bNodeIsResponding = false; //remote node is still active |  | ||||||
|     uint32_t u32OTABytesWritten = 0U; |  | ||||||
|     uint32_t u32SegmentCounter = 0U; |  | ||||||
|  |  | ||||||
|     pBootPartition = esp_ota_get_boot_partition(); //get boot partition (that will booted after reset), not the running partition |  | ||||||
|  |  | ||||||
|     //loop through partition to read in segmensts until end or error or abort called |  | ||||||
|     while( ((OTA_MESH_SEGMENT_SIZE * u32SegmentCounter) < pBootPartition->size) && (err == ESP_OK) && (bAbort == false)) |  | ||||||
|         { |  | ||||||
|             bNodeIsResponding = false; //reset to default |  | ||||||
|  |  | ||||||
|             // read partition with offset based in index |  | ||||||
|             ERROR_CHECK(esp_partition_read(pBootPartition, (OTA_MESH_SEGMENT_SIZE * u32SegmentCounter), sMeshPacket.au8Payload, OTA_MESH_SEGMENT_SIZE)); |  | ||||||
|             u32OTABytesWritten = ((u32SegmentCounter+1) * OTA_MESH_SEGMENT_SIZE); |  | ||||||
|             vPrintOTAProgress(&(pBootPartition->size), &u32OTABytesWritten, Transmitter); |  | ||||||
|  |  | ||||||
|             if(err == ESP_OK) |  | ||||||
|                 { |  | ||||||
|                     //no error while read --> send OTA_DATA packet |  | ||||||
|                     sMeshPacket.type = OTA_Data; |  | ||||||
|  |  | ||||||
|                     if((OTA_MESH_SEGMENT_SIZE * (u32SegmentCounter+1)) >= pBootPartition->size) //check if last segment |  | ||||||
|                         { |  | ||||||
|                             //last partition image segment --> send OTA_Complete |  | ||||||
|                             ESP_LOGI(LOG_TAG, "OTA-TX: last segment--> send Complete"); |  | ||||||
|                             sMeshPacket.type = OTA_Complete; |  | ||||||
|                         } |  | ||||||
|                     //ESP_LOGI(LOG_TAG, "OTA-TX: send packet"); |  | ||||||
|                     err = errSendMeshPacket(pMeshNodeAddr, &sMeshPacket); |  | ||||||
|                 } |  | ||||||
|             else |  | ||||||
|                 { |  | ||||||
|                     // error while read --> send OTA_ABORT and abort this OTA process |  | ||||||
|                     sMeshPacket.type = OTA_Abort; |  | ||||||
|                     bAbort = true; |  | ||||||
|                     ESP_LOGI(LOG_TAG, "OTA-TX: error while read --> send ABORT"); |  | ||||||
|                     errSendMeshPacket(pMeshNodeAddr, &sMeshPacket); |  | ||||||
|                 } |  | ||||||
|  |  | ||||||
|             // loop through all OTA messages or until abort is called or error |  | ||||||
|             for (uint32_t u32Index = 0; ((u32Index < QUEUE_MESSAGE_OTA_SIZE) && (bAbort == false) && (err == ESP_OK)); u32Index++) //loop through all OTA messages |  | ||||||
|                 { |  | ||||||
|                     // if(uxQueueSpacesAvailable(queueMessageOTA) < QUEUE_MESSAGE_OTA_SIZE) |  | ||||||
|                     //   { |  | ||||||
|                     //queue not empty |  | ||||||
|                     if (xQueueReceive(queueMessageOTA, &sMeshPacket, ((OTA_MESH_TIMEOUT) / portTICK_PERIOD_MS)) != pdTRUE) |  | ||||||
|                         { |  | ||||||
|                             ESP_LOGE(LOG_TAG, "Unable to receive OTA Messages from queue"); |  | ||||||
|                             err = ESP_FAIL; |  | ||||||
|                         } |  | ||||||
|  |  | ||||||
|                     if((err == ESP_OK) && (bCheckMACEquality(sMeshPacket.meshSenderAddr.addr, pMeshNodeAddr->addr))) //if OTA_Version_Request |  | ||||||
|                         { |  | ||||||
|                             //packet from node received |  | ||||||
|                             switch (sMeshPacket.type) |  | ||||||
|                                 { |  | ||||||
|                                 case OTA_ACK: //increase index for next round |  | ||||||
|                                     u32Index++; |  | ||||||
|                                     bNodeIsResponding = true; |  | ||||||
|                                     u32Index = QUEUE_MESSAGE_OTA_SIZE;//this will end the loop through all OTA messages |  | ||||||
|                                     break; |  | ||||||
|                                 case OTA_Abort: //abort this OTA process |  | ||||||
|                                     bAbort = true; |  | ||||||
|                                     bNodeIsResponding = true; |  | ||||||
|                                     break; |  | ||||||
|                                 default: |  | ||||||
|                                     //receives wrong OTA message type from node --> back to queue |  | ||||||
|                                     //vAddOtaMessageToQueue(&sMeshPacket); |  | ||||||
|                                     break; |  | ||||||
|                                 } |  | ||||||
|                         } |  | ||||||
|                     else if (err == ESP_OK) |  | ||||||
|                         { |  | ||||||
|                             //received from wrong node --> back to queue |  | ||||||
|                             vAddOtaMessageToQueue(&sMeshPacket); |  | ||||||
|                         } |  | ||||||
|                     /* |  | ||||||
|                     } |  | ||||||
|                     else |  | ||||||
|                     { |  | ||||||
|                         // OTA Message queue is empty --> wait some time |  | ||||||
|                         ESP_LOGI(LOG_TAG, "OTA-TX: ota message queue empty --> wait"); |  | ||||||
|                         vTaskDelay( (OTA_MESH_TIMEOUT) / portTICK_PERIOD_MS); |  | ||||||
|                     } |  | ||||||
|                     */ |  | ||||||
|  |  | ||||||
|                 }//end OTA message loop |  | ||||||
|  |  | ||||||
|             if(bNodeIsResponding == false) |  | ||||||
|                 { |  | ||||||
|                     //no abort was called but node didn’t responded |  | ||||||
|                     ESP_LOGE(LOG_TAG, "OTA-TX: no abort was called but node didn’t responded --> error"); |  | ||||||
|                     bAbort = true; |  | ||||||
|                     err = ESP_FAIL; //this OTA process failed with error |  | ||||||
|                 } |  | ||||||
|             u32SegmentCounter++; |  | ||||||
|         }//end of partition segment loop |  | ||||||
|         vClearOtaMessageQueue(pMeshNodeAddr); |  | ||||||
|     return err; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| esp_err_t errOTAMeshReceive(bool* pbNewOTAImage, mesh_addr_t* pMeshNodeAddr) |  | ||||||
| { |  | ||||||
|     esp_err_t err = ESP_OK; |  | ||||||
|     MESH_PACKET_t sMeshPacket; //packet for sending and receiving |  | ||||||
|     bool bComplete = false; //complete the OTA process |  | ||||||
|     bool bAbort = false; //abort the OTA process |  | ||||||
|     bool bNodeIsResponding = false; //remote node is still active |  | ||||||
|     uint32_t u32OTABytesWritten = 0U; //counter unsed for progress log |  | ||||||
|     static esp_ota_handle_t otaHandle; //OTA process handle |  | ||||||
|     *pbNewOTAImage = false; |  | ||||||
|     uint32_t u32SegmentCounter = 0U; |  | ||||||
|  |  | ||||||
|     ERROR_CHECK(esp_ota_begin(pOTAPartition, OTA_SIZE_UNKNOWN, &otaHandle)); //start ota update process |  | ||||||
|  |  | ||||||
|     //partition segement loop through partition to read in segmensts until end or error or abort called |  | ||||||
|     while((bComplete == false) && (err == ESP_OK) && (bAbort == false) && (u32OTABytesWritten <= pOTAPartition->size)) |  | ||||||
|         { |  | ||||||
|             bNodeIsResponding = false; //reset to default |  | ||||||
|  |  | ||||||
|             // loop through all OTA messages or until abort is called |  | ||||||
|             for (uint32_t u32Index = 0; ((u32Index < QUEUE_MESSAGE_OTA_SIZE) && (bAbort == false)); u32Index++) //loop through all OTA messages |  | ||||||
|                 { |  | ||||||
|                     //if(uxQueueSpacesAvailable(queueMessageOTA) < QUEUE_MESSAGE_OTA_SIZE) |  | ||||||
|                     //   { |  | ||||||
|                     //queue not empty |  | ||||||
|                     if (xQueueReceive(queueMessageOTA, &sMeshPacket, ((OTA_MESH_TIMEOUT) / portTICK_PERIOD_MS)) != pdTRUE) |  | ||||||
|                         { |  | ||||||
|                             ESP_LOGE(LOG_TAG, "Unable to receive OTA Messages from queue"); |  | ||||||
|                             err = ESP_FAIL; |  | ||||||
|                         } |  | ||||||
|  |  | ||||||
|                     if((err == ESP_OK) && (bCheckMACEquality(sMeshPacket.meshSenderAddr.addr, pMeshNodeAddr->addr))) //if OTA_Version_Request |  | ||||||
|                         { |  | ||||||
|                             //packet from node received |  | ||||||
|                             switch (sMeshPacket.type) |  | ||||||
|                                 { |  | ||||||
|                                 case OTA_Complete: //signal end of this OTA process, fall through because same behavior as OTA_Data |  | ||||||
|                                     bComplete = true; |  | ||||||
|                                     ESP_LOGI(LOG_TAG, "OTA-RX: rec Complete --> last segment"); |  | ||||||
|                                 //fall through |  | ||||||
|                                 case OTA_Data: //data segement received |  | ||||||
|                                     bNodeIsResponding = true; |  | ||||||
|                                     ERROR_CHECK(esp_ota_write(otaHandle, sMeshPacket.au8Payload, OTA_MESH_SEGMENT_SIZE)); |  | ||||||
|                                     u32OTABytesWritten = ((u32SegmentCounter+1) * OTA_MESH_SEGMENT_SIZE); |  | ||||||
|                                     vPrintOTAProgress(&(pOTAPartition->size), &u32OTABytesWritten, Receiver); |  | ||||||
|                                     u32Index = QUEUE_MESSAGE_OTA_SIZE; //this will end the loop through all OTA messages |  | ||||||
|                                     break; |  | ||||||
|                                 case OTA_Abort: //abort this OTA process |  | ||||||
|                                     bAbort = true; |  | ||||||
|                                     bNodeIsResponding = true; |  | ||||||
|                                     ESP_LOGI(LOG_TAG, "OTA-RX: rec Abort"); |  | ||||||
|                                     //this will end the loop through all OTA messages |  | ||||||
|                                     break; |  | ||||||
|                                 default: |  | ||||||
|                                     //receives wrong OTA message type from node --> back to queue |  | ||||||
|                                     //vAddOtaMessageToQueue(&sMeshPacket); |  | ||||||
|                                     break; |  | ||||||
|                                 } |  | ||||||
|                         } |  | ||||||
|                     else if (err == ESP_OK) |  | ||||||
|                         { |  | ||||||
|                             //received from wrong node --> back to queue |  | ||||||
|                             vAddOtaMessageToQueue(&sMeshPacket); |  | ||||||
|                         } |  | ||||||
|  |  | ||||||
|                     /*  } |  | ||||||
|                     else |  | ||||||
|                       { |  | ||||||
|                           ESP_LOGI(LOG_TAG, "OTA-RX: ota message queue empty --> wait"); |  | ||||||
|                           // OTA Message queue is empty --> wait some time |  | ||||||
|                           vTaskDelay( (OTA_MESH_TIMEOUT) / portTICK_PERIOD_MS); |  | ||||||
|                       } |  | ||||||
|                       */ |  | ||||||
|  |  | ||||||
|                 }//end of OTA message loop |  | ||||||
|  |  | ||||||
|             if(bNodeIsResponding == false) |  | ||||||
|                 { |  | ||||||
|                     //no abort was called but node didn’t responded --> error |  | ||||||
|                     ESP_LOGI(LOG_TAG, "OTA-RX: no abort was called but node didn’t responded --> error"); |  | ||||||
|                     bAbort = true; //this will stop the partition segement loop |  | ||||||
|                     err = ESP_FAIL; //this OTA process failed with error |  | ||||||
|                 } |  | ||||||
|             else |  | ||||||
|                 { |  | ||||||
|                     //node has responded with OTA_DATA or OTA_Complete or OTA_ABORT |  | ||||||
|                     if(err == ESP_OK) |  | ||||||
|                         { |  | ||||||
|  |  | ||||||
|                             if(bAbort == false) |  | ||||||
|                                 { |  | ||||||
|                                     //no error while ota write --> send OTA_ACK packet |  | ||||||
|                                     //ESP_LOGI(LOG_TAG, "OTA-RX: no error while ota write --> send OTA_ACK packet"); |  | ||||||
|                                     sMeshPacket.type = OTA_ACK; |  | ||||||
|                                     err = errSendMeshPacket(pMeshNodeAddr, &sMeshPacket); |  | ||||||
|                                 } |  | ||||||
|                         } |  | ||||||
|                     else |  | ||||||
|                         { |  | ||||||
|                             // error while read --> send OTA_ABORT and abort this OTA process |  | ||||||
|                             sMeshPacket.type = OTA_Abort; |  | ||||||
|                             bAbort = true; |  | ||||||
|                             ESP_LOGI(LOG_TAG, "OTA-RX: abort --> send ABORT"); |  | ||||||
|                             errSendMeshPacket(pMeshNodeAddr, &sMeshPacket); |  | ||||||
|                         } |  | ||||||
|                 } |  | ||||||
|             u32SegmentCounter++; |  | ||||||
|         }//end of partition segement loop |  | ||||||
|  |  | ||||||
|     if(bComplete == true) |  | ||||||
|         { |  | ||||||
|             //all OTA segments received --> validate |  | ||||||
|             ESP_LOGI(LOG_TAG, "OTA-RX: validate image "); |  | ||||||
|             ERROR_CHECK(esp_ota_end(otaHandle)); |  | ||||||
|             ERROR_CHECK(esp_ota_set_boot_partition(pOTAPartition)); |  | ||||||
|             if(err == ESP_OK) |  | ||||||
|                 { |  | ||||||
|                     //successfully updated OTA partition |  | ||||||
|                     *pbNewOTAImage = true; |  | ||||||
|                 } |  | ||||||
|         } |  | ||||||
|     else |  | ||||||
|         { |  | ||||||
|             //not all OTA segments received --> abort this OTA process |  | ||||||
|             ERROR_CHECK(esp_ota_abort(otaHandle)); |  | ||||||
|         } |  | ||||||
|         vClearOtaMessageQueue(pMeshNodeAddr); |  | ||||||
|     return err; |  | ||||||
| } |  | ||||||
|  | |||||||
							
								
								
									
										10
									
								
								components/mesh_ota/Mesh_OTA_Globals.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								components/mesh_ota/Mesh_OTA_Globals.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,10 @@ | |||||||
|  | #include "Mesh_OTA_Globals.h" | ||||||
|  |  | ||||||
|  | xQueueHandle queueNodes; //nodes that should be checked for ota update (contains children and parent) | ||||||
|  | xQueueHandle queueMessageOTA; //mesh ota controll messages like "OTA_Version_Response" "OTA_ACK" | ||||||
|  |  | ||||||
|  | SemaphoreHandle_t bsStartStopServerWorker; //binary semaphore | ||||||
|  | SemaphoreHandle_t bsOTAProcess; //binary semaphore | ||||||
|  |  | ||||||
|  | const esp_partition_t* pOTAPartition; //pointer to ota partition | ||||||
|  | bool bWantReboot; //flag to signal pending reboot | ||||||
							
								
								
									
										323
									
								
								components/mesh_ota/Mesh_OTA_Partition_Access.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										323
									
								
								components/mesh_ota/Mesh_OTA_Partition_Access.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,323 @@ | |||||||
|  | #include "Mesh_OTA.h" | ||||||
|  | #include "Mesh_OTA_Util.h" | ||||||
|  | #include "Mesh_OTA_Globals.h" | ||||||
|  | #include "Mesh_OTA_Access.h" | ||||||
|  |  | ||||||
|  | static const char *LOG_TAG = "mesh_ota_access"; | ||||||
|  |  | ||||||
|  | esp_err_t errOTAMeshTransmit(mesh_addr_t* pMeshNodeAddr) | ||||||
|  | { | ||||||
|  |     esp_err_t err = ESP_OK; | ||||||
|  |     const esp_partition_t* pBootPartition; //pointer to boot partition (that will booted after reset) | ||||||
|  |     MESH_PACKET_t sMeshPacket; //packet for sending and receiving | ||||||
|  |     // uint32_t u32Index = 0U; //index for partition read offset | ||||||
|  |     bool bAbort = false; //abort the OTA process | ||||||
|  |     bool bNodeIsResponding = false; //remote node is still active | ||||||
|  |     uint32_t u32OTABytesWritten = 0U; | ||||||
|  |     uint32_t u32SegmentCounter = 0U; | ||||||
|  |  | ||||||
|  |     pBootPartition = esp_ota_get_boot_partition(); //get boot partition (that will booted after reset), not the running partition | ||||||
|  |  | ||||||
|  |     //loop through partition to read in segmensts until end or error or abort called | ||||||
|  |     while( ((OTA_MESH_SEGMENT_SIZE * u32SegmentCounter) < pBootPartition->size) && (err == ESP_OK) && (bAbort == false)) | ||||||
|  |         { | ||||||
|  |             bNodeIsResponding = false; //reset to default | ||||||
|  |  | ||||||
|  |             // read partition with offset based in index | ||||||
|  |             ERROR_CHECK(esp_partition_read(pBootPartition, (OTA_MESH_SEGMENT_SIZE * u32SegmentCounter), sMeshPacket.au8Payload, OTA_MESH_SEGMENT_SIZE)); | ||||||
|  |             u32OTABytesWritten = ((u32SegmentCounter+1) * OTA_MESH_SEGMENT_SIZE); | ||||||
|  |             vPrintOTAProgress(&(pBootPartition->size), &u32OTABytesWritten, Transmitter); | ||||||
|  |  | ||||||
|  |             if(err == ESP_OK) | ||||||
|  |                 { | ||||||
|  |                     //no error while read --> send OTA_DATA packet | ||||||
|  |                     sMeshPacket.type = OTA_Data; | ||||||
|  |  | ||||||
|  |                     if((OTA_MESH_SEGMENT_SIZE * (u32SegmentCounter+1)) >= pBootPartition->size) //check if last segment | ||||||
|  |                         { | ||||||
|  |                             //last partition image segment --> send OTA_Complete | ||||||
|  |                             ESP_LOGI(LOG_TAG, "OTA-TX: last segment--> send Complete"); | ||||||
|  |                             sMeshPacket.type = OTA_Complete; | ||||||
|  |                         } | ||||||
|  |                     //ESP_LOGI(LOG_TAG, "OTA-TX: send packet"); | ||||||
|  |                     err = errSendMeshPacket(pMeshNodeAddr, &sMeshPacket); | ||||||
|  |                 } | ||||||
|  |             else | ||||||
|  |                 { | ||||||
|  |                     // error while read --> send OTA_ABORT and abort this OTA process | ||||||
|  |                     sMeshPacket.type = OTA_Abort; | ||||||
|  |                     bAbort = true; | ||||||
|  |                     ESP_LOGI(LOG_TAG, "OTA-TX: error while read --> send ABORT"); | ||||||
|  |                     errSendMeshPacket(pMeshNodeAddr, &sMeshPacket); | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |             // loop through all OTA messages or until abort is called or error | ||||||
|  |             for (uint32_t u32Index = 0; ((u32Index < QUEUE_MESSAGE_OTA_SIZE) && (bAbort == false) && (err == ESP_OK)); u32Index++) //loop through all OTA messages | ||||||
|  |                 { | ||||||
|  |                     // if(uxQueueSpacesAvailable(queueMessageOTA) < QUEUE_MESSAGE_OTA_SIZE) | ||||||
|  |                     //   { | ||||||
|  |                     //queue not empty | ||||||
|  |                     if (xQueueReceive(queueMessageOTA, &sMeshPacket, ((OTA_MESH_TIMEOUT) / portTICK_PERIOD_MS)) != pdTRUE) | ||||||
|  |                         { | ||||||
|  |                             ESP_LOGE(LOG_TAG, "Unable to receive OTA Messages from queue"); | ||||||
|  |                             err = ESP_FAIL; | ||||||
|  |                         } | ||||||
|  |  | ||||||
|  |                     if((err == ESP_OK) && (bCheckMACEquality(sMeshPacket.meshSenderAddr.addr, pMeshNodeAddr->addr))) //if OTA_Version_Request | ||||||
|  |                         { | ||||||
|  |                             //packet from node received | ||||||
|  |                             switch (sMeshPacket.type) | ||||||
|  |                                 { | ||||||
|  |                                 case OTA_ACK: //increase index for next round | ||||||
|  |                                     u32Index++; | ||||||
|  |                                     bNodeIsResponding = true; | ||||||
|  |                                     u32Index = QUEUE_MESSAGE_OTA_SIZE;//this will end the loop through all OTA messages | ||||||
|  |                                     break; | ||||||
|  |                                 case OTA_Abort: //abort this OTA process | ||||||
|  |                                     bAbort = true; | ||||||
|  |                                     bNodeIsResponding = true; | ||||||
|  |                                     break; | ||||||
|  |                                 default: | ||||||
|  |                                     //receives wrong OTA message type from node --> back to queue | ||||||
|  |                                     //vAddOtaMessageToQueue(&sMeshPacket); | ||||||
|  |                                     break; | ||||||
|  |                                 } | ||||||
|  |                         } | ||||||
|  |                     else if (err == ESP_OK) | ||||||
|  |                         { | ||||||
|  |                             //received from wrong node --> back to queue | ||||||
|  |                             vAddOtaMessageToQueue(&sMeshPacket); | ||||||
|  |                         } | ||||||
|  |                     /* | ||||||
|  |                     } | ||||||
|  |                     else | ||||||
|  |                     { | ||||||
|  |                         // OTA Message queue is empty --> wait some time | ||||||
|  |                         ESP_LOGI(LOG_TAG, "OTA-TX: ota message queue empty --> wait"); | ||||||
|  |                         vTaskDelay( (OTA_MESH_TIMEOUT) / portTICK_PERIOD_MS); | ||||||
|  |                     } | ||||||
|  |                     */ | ||||||
|  |  | ||||||
|  |                 }//end OTA message loop | ||||||
|  |  | ||||||
|  |             if(bNodeIsResponding == false) | ||||||
|  |                 { | ||||||
|  |                     //no abort was called but node didn’t responded | ||||||
|  |                     ESP_LOGE(LOG_TAG, "OTA-TX: no abort was called but node didn’t responded --> error"); | ||||||
|  |                     bAbort = true; | ||||||
|  |                     err = ESP_FAIL; //this OTA process failed with error | ||||||
|  |                 } | ||||||
|  |             u32SegmentCounter++; | ||||||
|  |         }//end of partition segment loop | ||||||
|  |     vClearOtaMessageQueue(pMeshNodeAddr); | ||||||
|  |     return err; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | esp_err_t errOTAMeshReceive(bool* pbNewOTAImage, mesh_addr_t* pMeshNodeAddr) | ||||||
|  | { | ||||||
|  |     esp_err_t err = ESP_OK; | ||||||
|  |     MESH_PACKET_t sMeshPacket; //packet for sending and receiving | ||||||
|  |     bool bComplete = false; //complete the OTA process | ||||||
|  |     bool bAbort = false; //abort the OTA process | ||||||
|  |     bool bNodeIsResponding = false; //remote node is still active | ||||||
|  |     uint32_t u32OTABytesWritten = 0U; //counter unsed for progress log | ||||||
|  |     static esp_ota_handle_t otaHandle; //OTA process handle | ||||||
|  |     *pbNewOTAImage = false; | ||||||
|  |     uint32_t u32SegmentCounter = 0U; | ||||||
|  |  | ||||||
|  |     ERROR_CHECK(esp_ota_begin(pOTAPartition, OTA_SIZE_UNKNOWN, &otaHandle)); //start ota update process | ||||||
|  |  | ||||||
|  |     //partition segement loop through partition to read in segmensts until end or error or abort called | ||||||
|  |     while((bComplete == false) && (err == ESP_OK) && (bAbort == false) && (u32OTABytesWritten <= pOTAPartition->size)) | ||||||
|  |         { | ||||||
|  |             bNodeIsResponding = false; //reset to default | ||||||
|  |  | ||||||
|  |             // loop through all OTA messages or until abort is called | ||||||
|  |             for (uint32_t u32Index = 0; ((u32Index < QUEUE_MESSAGE_OTA_SIZE) && (bAbort == false)); u32Index++) //loop through all OTA messages | ||||||
|  |                 { | ||||||
|  |                     //if(uxQueueSpacesAvailable(queueMessageOTA) < QUEUE_MESSAGE_OTA_SIZE) | ||||||
|  |                     //   { | ||||||
|  |                     //queue not empty | ||||||
|  |                     if (xQueueReceive(queueMessageOTA, &sMeshPacket, ((OTA_MESH_TIMEOUT) / portTICK_PERIOD_MS)) != pdTRUE) | ||||||
|  |                         { | ||||||
|  |                             ESP_LOGE(LOG_TAG, "Unable to receive OTA Messages from queue"); | ||||||
|  |                             err = ESP_FAIL; | ||||||
|  |                         } | ||||||
|  |  | ||||||
|  |                     if((err == ESP_OK) && (bCheckMACEquality(sMeshPacket.meshSenderAddr.addr, pMeshNodeAddr->addr))) //if OTA_Version_Request | ||||||
|  |                         { | ||||||
|  |                             //packet from node received | ||||||
|  |                             switch (sMeshPacket.type) | ||||||
|  |                                 { | ||||||
|  |                                 case OTA_Complete: //signal end of this OTA process, fall through because same behavior as OTA_Data | ||||||
|  |                                     bComplete = true; | ||||||
|  |                                     ESP_LOGI(LOG_TAG, "OTA-RX: rec Complete --> last segment"); | ||||||
|  |                                 //fall through | ||||||
|  |                                 case OTA_Data: //data segement received | ||||||
|  |                                     bNodeIsResponding = true; | ||||||
|  |                                     ERROR_CHECK(esp_ota_write(otaHandle, sMeshPacket.au8Payload, OTA_MESH_SEGMENT_SIZE)); | ||||||
|  |                                     u32OTABytesWritten = ((u32SegmentCounter+1) * OTA_MESH_SEGMENT_SIZE); | ||||||
|  |                                     vPrintOTAProgress(&(pOTAPartition->size), &u32OTABytesWritten, Receiver); | ||||||
|  |                                     u32Index = QUEUE_MESSAGE_OTA_SIZE; //this will end the loop through all OTA messages | ||||||
|  |                                     break; | ||||||
|  |                                 case OTA_Abort: //abort this OTA process | ||||||
|  |                                     bAbort = true; | ||||||
|  |                                     bNodeIsResponding = true; | ||||||
|  |                                     ESP_LOGI(LOG_TAG, "OTA-RX: rec Abort"); | ||||||
|  |                                     //this will end the loop through all OTA messages | ||||||
|  |                                     break; | ||||||
|  |                                 default: | ||||||
|  |                                     //receives wrong OTA message type from node --> back to queue | ||||||
|  |                                     //vAddOtaMessageToQueue(&sMeshPacket); | ||||||
|  |                                     break; | ||||||
|  |                                 } | ||||||
|  |                         } | ||||||
|  |                     else if (err == ESP_OK) | ||||||
|  |                         { | ||||||
|  |                             //received from wrong node --> back to queue | ||||||
|  |                             vAddOtaMessageToQueue(&sMeshPacket); | ||||||
|  |                         } | ||||||
|  |  | ||||||
|  |                     /*  } | ||||||
|  |                     else | ||||||
|  |                       { | ||||||
|  |                           ESP_LOGI(LOG_TAG, "OTA-RX: ota message queue empty --> wait"); | ||||||
|  |                           // OTA Message queue is empty --> wait some time | ||||||
|  |                           vTaskDelay( (OTA_MESH_TIMEOUT) / portTICK_PERIOD_MS); | ||||||
|  |                       } | ||||||
|  |                       */ | ||||||
|  |  | ||||||
|  |                 }//end of OTA message loop | ||||||
|  |  | ||||||
|  |             if(bNodeIsResponding == false) | ||||||
|  |                 { | ||||||
|  |                     //no abort was called but node didn’t responded --> error | ||||||
|  |                     ESP_LOGI(LOG_TAG, "OTA-RX: no abort was called but node didn’t responded --> error"); | ||||||
|  |                     bAbort = true; //this will stop the partition segement loop | ||||||
|  |                     err = ESP_FAIL; //this OTA process failed with error | ||||||
|  |                 } | ||||||
|  |             else | ||||||
|  |                 { | ||||||
|  |                     //node has responded with OTA_DATA or OTA_Complete or OTA_ABORT | ||||||
|  |                     if(err == ESP_OK) | ||||||
|  |                         { | ||||||
|  |  | ||||||
|  |                             if(bAbort == false) | ||||||
|  |                                 { | ||||||
|  |                                     //no error while ota write --> send OTA_ACK packet | ||||||
|  |                                     //ESP_LOGI(LOG_TAG, "OTA-RX: no error while ota write --> send OTA_ACK packet"); | ||||||
|  |                                     sMeshPacket.type = OTA_ACK; | ||||||
|  |                                     err = errSendMeshPacket(pMeshNodeAddr, &sMeshPacket); | ||||||
|  |                                 } | ||||||
|  |                         } | ||||||
|  |                     else | ||||||
|  |                         { | ||||||
|  |                             // error while read --> send OTA_ABORT and abort this OTA process | ||||||
|  |                             sMeshPacket.type = OTA_Abort; | ||||||
|  |                             bAbort = true; | ||||||
|  |                             ESP_LOGI(LOG_TAG, "OTA-RX: abort --> send ABORT"); | ||||||
|  |                             errSendMeshPacket(pMeshNodeAddr, &sMeshPacket); | ||||||
|  |                         } | ||||||
|  |                 } | ||||||
|  |             u32SegmentCounter++; | ||||||
|  |         }//end of partition segement loop | ||||||
|  |  | ||||||
|  |     if(bComplete == true) | ||||||
|  |         { | ||||||
|  |             //all OTA segments received --> validate | ||||||
|  |             ESP_LOGI(LOG_TAG, "OTA-RX: validate image "); | ||||||
|  |             ERROR_CHECK(esp_ota_end(otaHandle)); | ||||||
|  |             ERROR_CHECK(esp_ota_set_boot_partition(pOTAPartition)); | ||||||
|  |             if(err == ESP_OK) | ||||||
|  |                 { | ||||||
|  |                     //successfully updated OTA partition | ||||||
|  |                     *pbNewOTAImage = true; | ||||||
|  |                 } | ||||||
|  |         } | ||||||
|  |     else | ||||||
|  |         { | ||||||
|  |             //not all OTA segments received --> abort this OTA process | ||||||
|  |             ERROR_CHECK(esp_ota_abort(otaHandle)); | ||||||
|  |         } | ||||||
|  |     vClearOtaMessageQueue(pMeshNodeAddr); | ||||||
|  |     return err; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | esp_err_t errOTAHTTPS(bool* pbNewOTAImage) | ||||||
|  | { | ||||||
|  |     esp_err_t err = ESP_OK; | ||||||
|  |     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 | ||||||
|  |     uint32_t u32OTABytesWritten = 0U; //counter unsed for progress log | ||||||
|  |  | ||||||
|  |     ERROR_CHECK(errHTTPSClientRetrieveData(u8OTABuffer, &u32BufferLenght, &u32BytesRead)); //read first bytes if image, including the version | ||||||
|  |  | ||||||
|  |     ERROR_CHECK(errExtractVersionNumber(u8OTABuffer, &u32BytesRead, pcRemoteVersionNumber)); //extract version numbers | ||||||
|  |  | ||||||
|  |     if(err == ESP_OK) //check if version number is found | ||||||
|  |         { | ||||||
|  |             xSemaphoreTake(bsOTAProcess, portMAX_DELAY); //wait for binary semaphore that allows to start the OTA process | ||||||
|  |  | ||||||
|  |             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 metadata of partition | ||||||
|  |  | ||||||
|  |             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"); | ||||||
|  |  | ||||||
|  |                     ERROR_CHECK(errFindImageStart(u8OTABuffer, &u32BufferLenght, &u32StartOffset)); //get image start offset | ||||||
|  |  | ||||||
|  |                     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 download via HTTPS"); | ||||||
|  |                             do | ||||||
|  |                                 { | ||||||
|  |                                     vPrintOTAProgress(&(pOTAPartition->size), &u32OTABytesWritten, Receiver); | ||||||
|  |                                     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 | ||||||
|  |                                             ERROR_CHECK(errHTTPSClientRetrieveData(u8OTABuffer, &u32BufferLenght, &u32BytesRead)); //download next data segment | ||||||
|  |                                             u32OTABytesWritten = u32OTABytesWritten + u32BytesRead; //update counter | ||||||
|  |                                         } | ||||||
|  |                                 } | ||||||
|  |                             while ((u32BytesRead > 0) && (err == ESP_OK) && (u32OTABytesWritten <= pOTAPartition->size)); //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(pOTAPartition)); //set new image as boot | ||||||
|  |                             if(err == ESP_OK) | ||||||
|  |                                 { | ||||||
|  |                                     *pbNewOTAImage = true; //image validated | ||||||
|  |                                 } | ||||||
|  |                         } | ||||||
|  |                     else | ||||||
|  |                         { | ||||||
|  |                             //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 | ||||||
|  |                         } | ||||||
|  |                 } | ||||||
|  |             else | ||||||
|  |                 { | ||||||
|  |                     ESP_LOGI(LOG_TAG, "server image is NOT newer --> OTA update NOT required"); | ||||||
|  |                 } | ||||||
|  |             xSemaphoreGive(bsOTAProcess); //free binary semaphore, this allows other tasks to start the OTA process | ||||||
|  |         } //end version number extracted | ||||||
|  |     return err; | ||||||
|  | } | ||||||
							
								
								
									
										314
									
								
								components/mesh_ota/Mesh_OTA_Util.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										314
									
								
								components/mesh_ota/Mesh_OTA_Util.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,314 @@ | |||||||
|  | #include "Mesh_OTA_Util.h" | ||||||
|  | #include "Mesh_OTA_Globals.h" | ||||||
|  |  | ||||||
|  | static const char *LOG_TAG = "mesh_ota"; | ||||||
|  |  | ||||||
|  | void vAddNodeToPossibleUpdatableQueue(uint8_t* pu8MAC) | ||||||
|  | { | ||||||
|  |     //send payload to node queues | ||||||
|  |     mesh_addr_t addrNode; | ||||||
|  |     memcpy(&addrNode.addr, (uint8_t *)pu8MAC, 6); //copy MAC | ||||||
|  |  | ||||||
|  |     if (xQueueSend(queueNodes, &addrNode, portMAX_DELAY) != pdPASS) | ||||||
|  |         { | ||||||
|  |             ESP_LOGE(LOG_TAG, "Unable to push node into node queue"); | ||||||
|  |         } | ||||||
|  |     else | ||||||
|  |         { | ||||||
|  |             ESP_LOGI(LOG_TAG, "added node \"%x:%x:%x:%x:%x:%x\" to possible updatable queue", addrNode.addr[0], addrNode.addr[1], addrNode.addr[2], addrNode.addr[3], addrNode.addr[4], addrNode.addr[5]); | ||||||
|  |         } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void vAddOtaMessageToQueue(MESH_PACKET_t* puMeshPacket) | ||||||
|  | { | ||||||
|  |     //send ota packet to packet queue | ||||||
|  |     if (xQueueSend(queueMessageOTA, puMeshPacket, portMAX_DELAY) != pdPASS) | ||||||
|  |         { | ||||||
|  |             ESP_LOGE(LOG_TAG, "Unable to push ota packet into packet queue"); | ||||||
|  |         } | ||||||
|  |     else | ||||||
|  |         { | ||||||
|  |             switch (puMeshPacket->type) | ||||||
|  |                 { | ||||||
|  |                 case OTA_Abort: | ||||||
|  |                     ESP_LOGI(LOG_TAG, "added ota message to queue: OTA_Abort from 0x%x", puMeshPacket->meshSenderAddr.addr[5]); | ||||||
|  |                     break; | ||||||
|  |                 case OTA_Version_Request: | ||||||
|  |                     ESP_LOGI(LOG_TAG, "added ota message to queue: OTA_Version_Request from 0x%x", puMeshPacket->meshSenderAddr.addr[5]); | ||||||
|  |                     break; | ||||||
|  |  | ||||||
|  |                 case OTA_Version_Response: | ||||||
|  |                     ESP_LOGI(LOG_TAG, "added ota message to queue: OTA_Version Response from 0x%x", puMeshPacket->meshSenderAddr.addr[5]); | ||||||
|  |                     break; | ||||||
|  |                 default: | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|  |         } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void vChangeStateOfServerWorker(bool bState) //allow access via function ptn to networl_handler | ||||||
|  | { | ||||||
|  |     static bool bLastState = false; | ||||||
|  |  | ||||||
|  |     if(bState != bLastState) //change only if necessary | ||||||
|  |         { | ||||||
|  |             ESP_LOGI(LOG_TAG, "server worker change handler"); | ||||||
|  |  | ||||||
|  |             if(bState == true) | ||||||
|  |                 { | ||||||
|  |                     if (xSemaphoreGive(bsStartStopServerWorker)  != pdTRUE) | ||||||
|  |                         { | ||||||
|  |                             ESP_LOGE(LOG_TAG, "Unable to give mutex to activate the server worker"); | ||||||
|  |                         } | ||||||
|  |                 } | ||||||
|  |             else | ||||||
|  |                 { | ||||||
|  |                     if (xSemaphoreTake(bsStartStopServerWorker,( TickType_t ) 10 )  != pdTRUE) | ||||||
|  |                         { | ||||||
|  |                             ESP_LOGE(LOG_TAG, "Unable to obtain mutex to deactivate the server worker"); | ||||||
|  |                         } | ||||||
|  |                 } | ||||||
|  |             bLastState = bState; | ||||||
|  |         } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool bNewerVersion(const char* pu8Local, const  char* pu8Remote) | ||||||
|  | { | ||||||
|  |     /* | ||||||
|  |      * Return true if remote version is newer (higher) than local version | ||||||
|  |     */ | ||||||
|  |     char u8LocalTmp[12]; //local version | ||||||
|  |     char u8RemoteTmp[12]; //remote version | ||||||
|  |     char* pu8saveptrLocal; //context for strok_r | ||||||
|  |     char* pu8saveptrRemote; //context for strok_r | ||||||
|  |     bool bReturn = false; //flag to stop loop | ||||||
|  |     uint8_t u8Index = 0; //numbers counter in version string | ||||||
|  |  | ||||||
|  |     strncpy(u8LocalTmp, pu8Local, 12); //copy in tmp | ||||||
|  |     strncpy(u8RemoteTmp, pu8Remote, 12); //copy in tmp | ||||||
|  |  | ||||||
|  |     char* pu8TokenLocal = strtok_r(u8LocalTmp, ".", &pu8saveptrLocal); //split tokens | ||||||
|  |     char* pu8TokenRemote = strtok_r(u8RemoteTmp, ".", &pu8saveptrRemote); //split tokens | ||||||
|  |  | ||||||
|  |     while( (u8Index <= 2) && (bReturn == false)) //loop through tokens | ||||||
|  |         { | ||||||
|  |             u8Index++; | ||||||
|  |             if(atoi(pu8TokenLocal) < atoi(pu8TokenRemote)) | ||||||
|  |                 { | ||||||
|  |                     bReturn = true; //version number difference --> stop loop | ||||||
|  |                 } | ||||||
|  |             pu8TokenLocal = strtok_r(NULL, ".", &pu8saveptrLocal); //split tokens | ||||||
|  |             pu8TokenRemote = strtok_r(NULL, ".", &pu8saveptrRemote); //split tokens | ||||||
|  |         } | ||||||
|  |     return bReturn; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | esp_err_t errFindImageStart(const char* pu8Data, uint32_t* pu32DataLenght, uint32_t* pu32StartOffset) | ||||||
|  | { | ||||||
|  |     /* | ||||||
|  |     Offset  value | ||||||
|  |     0      = 0xE9 (first byte in image --> magic byte) | ||||||
|  |     48     = first digit of version number | ||||||
|  |     */ | ||||||
|  |  | ||||||
|  |     esp_err_t errReturn = ESP_OK; | ||||||
|  |     bool bImageStartOffsetFound = false; | ||||||
|  |     uint32_t u32DataIndex = 0; | ||||||
|  |     uint32_t u32FirstDotOffset = 0; | ||||||
|  |     uint32_t u32SecondDotOffset = 0; | ||||||
|  |     uint8_t u8FirstDotIndex = 0; | ||||||
|  |     uint8_t u8SecondDotIndex = 0; | ||||||
|  |  | ||||||
|  |     *pu32StartOffset = 0U; //reset offset to zero | ||||||
|  |  | ||||||
|  |     while((u32DataIndex < *pu32DataLenght) &&  (bImageStartOffsetFound == false)) | ||||||
|  |         { | ||||||
|  |             //search for magic byte | ||||||
|  |             if(pu8Data[u32DataIndex] == 0xe9) | ||||||
|  |                 { | ||||||
|  |                     //magic byte found | ||||||
|  |                     while ((u8FirstDotIndex < 3) && (u32FirstDotOffset == 0)) | ||||||
|  |                         { | ||||||
|  |                             //search first dot in version number | ||||||
|  |                             if((u32DataIndex+49+u8FirstDotIndex) < *pu32DataLenght) | ||||||
|  |                                 { | ||||||
|  |                                     if((pu8Data[(u32DataIndex+49+u8FirstDotIndex)] == 0x2e)) | ||||||
|  |                                         { | ||||||
|  |                                             //first dot found | ||||||
|  |                                             u32FirstDotOffset = (u32DataIndex+49+u8FirstDotIndex); | ||||||
|  |                                         } | ||||||
|  |                                 } | ||||||
|  |                             u8FirstDotIndex++; | ||||||
|  |                         } | ||||||
|  |  | ||||||
|  |                     while ((u8SecondDotIndex < 3) && (u32SecondDotOffset == 0) && (u32FirstDotOffset != 0)) | ||||||
|  |                         { | ||||||
|  |                             //search first dot in version number | ||||||
|  |                             if((u32FirstDotOffset+(u8SecondDotIndex+2)) < *pu32DataLenght) | ||||||
|  |                                 { | ||||||
|  |                                     if((pu8Data[(u32FirstDotOffset+(u8SecondDotIndex+2))] == 0x2e)) | ||||||
|  |                                         { | ||||||
|  |                                             //second dot found | ||||||
|  |                                             u32SecondDotOffset = (u32FirstDotOffset+(u8SecondDotIndex+2)); | ||||||
|  |                                         } | ||||||
|  |                                 } | ||||||
|  |                             u8SecondDotIndex++; | ||||||
|  |                         } | ||||||
|  |  | ||||||
|  |                     if((u32FirstDotOffset != 0) && (u32SecondDotOffset != 0)) | ||||||
|  |                         { | ||||||
|  |                             //image start found based on magic byte and version number systax | ||||||
|  |                             *pu32StartOffset = u32DataIndex; //store image start offset | ||||||
|  |                             bImageStartOffsetFound = true; | ||||||
|  |                         } | ||||||
|  |                     else | ||||||
|  |                         { | ||||||
|  |                             // this is propably not the magic byte --> reset | ||||||
|  |                             u32FirstDotOffset = 0; | ||||||
|  |                             u32SecondDotOffset = 0; | ||||||
|  |                             u8FirstDotIndex = 0; | ||||||
|  |                             u8SecondDotIndex = 0; | ||||||
|  |                         } | ||||||
|  |                 } | ||||||
|  |             u32DataIndex++; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |     if(bImageStartOffsetFound == false) | ||||||
|  |         { | ||||||
|  |             errReturn = ESP_ERR_NOT_FOUND; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |     return errReturn; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | esp_err_t errExtractVersionNumber(const char* pu8Data, uint32_t* pu32DataLenght, char* pc8RemoteVersionNumber) | ||||||
|  | { | ||||||
|  |     uint32_t u32StartOffset; | ||||||
|  |     esp_err_t err = ESP_OK; | ||||||
|  |  | ||||||
|  |     strcpy(pc8RemoteVersionNumber, "999.999.999"); //init value | ||||||
|  |     err = errFindImageStart(pu8Data, pu32DataLenght, &u32StartOffset); //get image start offset | ||||||
|  |  | ||||||
|  |     if(err == ESP_OK) | ||||||
|  |         { | ||||||
|  |             //image found | ||||||
|  |             strncpy(pc8RemoteVersionNumber, pu8Data+(u32StartOffset+48), 11); //copy version number | ||||||
|  |             pc8RemoteVersionNumber[12] = '\0'; | ||||||
|  |         } | ||||||
|  |     return err; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void vPrintOTAProgress(const uint32_t* const pu32TotalImageSize, const uint32_t* const pu32BytesWritten, OTA_MESH_ROLE_t eRole) | ||||||
|  | { | ||||||
|  |     uint32_t u32Percentage = 0U; | ||||||
|  |     static uint32_t u32LastPercentage = 0U; | ||||||
|  |  | ||||||
|  |     if((*pu32BytesWritten) >= (*pu32TotalImageSize)) | ||||||
|  |         { | ||||||
|  |             u32Percentage = 100; | ||||||
|  |         } | ||||||
|  |     else | ||||||
|  |         { | ||||||
|  |             u32Percentage = (uint32_t) (((float) (*pu32BytesWritten)/(float) (*pu32TotalImageSize)) * 100.0); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |     if((u32Percentage-u32LastPercentage) >= OTA_PROGRESS_LOG_INTERVAL) | ||||||
|  |         { | ||||||
|  |             if(eRole == Transmitter) | ||||||
|  |                 { | ||||||
|  |                     ESP_LOGI(LOG_TAG, "Transmitting OTA update: %i %%", u32Percentage); | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |             if(eRole == Receiver) | ||||||
|  |                 { | ||||||
|  |                     ESP_LOGI(LOG_TAG, "Receiving OTA update: %i %%", u32Percentage); | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |             u32LastPercentage = u32Percentage; | ||||||
|  |         } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void vAddAllNeighboursToQueue(void) | ||||||
|  | { | ||||||
|  |     esp_err_t err = ESP_OK; | ||||||
|  |  | ||||||
|  |     mesh_addr_t addrParent;  //addr of parent node | ||||||
|  |     mesh_addr_t childrenAddr[CONFIG_MESH_ROUTE_TABLE_SIZE]; //array of children attached to this node | ||||||
|  |     uint16_t u16ChildrenSize = 0U; //number of children attached to this node | ||||||
|  |  | ||||||
|  |     err = errGetParentNode(&addrParent); | ||||||
|  |  | ||||||
|  |     if(err == ESP_OK) | ||||||
|  |         { | ||||||
|  |             vAddNodeToPossibleUpdatableQueue(addrParent.addr); | ||||||
|  |             ESP_LOGI(LOG_TAG, "added parent"); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |     err = ESP_OK; //reset error code | ||||||
|  |  | ||||||
|  |     ERROR_CHECK(errGetChildren(childrenAddr, &u16ChildrenSize)); //get all children | ||||||
|  |  | ||||||
|  |     for (uint16_t u16Index = 0; ((u16Index < u16ChildrenSize) && (err == ESP_OK)); u16Index++) | ||||||
|  |         { | ||||||
|  |             vAddNodeToPossibleUpdatableQueue(childrenAddr[u16Index].addr); | ||||||
|  |             ESP_LOGI(LOG_TAG, "added child"); | ||||||
|  |         } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | esp_err_t errSendOTAVersionResponse(mesh_addr_t* pMeshReceiverAddr) | ||||||
|  | { | ||||||
|  |     esp_err_t err = ESP_OK; | ||||||
|  |     MESH_PACKET_t packet; | ||||||
|  |     packet.type = OTA_Version_Response; | ||||||
|  |  | ||||||
|  |     const esp_partition_t* pBootPartition; //pointer to boot partition (that will booted after reset) | ||||||
|  |     esp_app_desc_t bootPartitionDesc; //Metadata 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 | ||||||
|  |     memcpy(&packet.au8Payload, &bootPartitionDesc.version, 12); //copy local version to OTA_Version_Response packet | ||||||
|  |  | ||||||
|  |     ESP_LOGI(LOG_TAG, "Send OTA_Version_Response to 0x%x", pMeshReceiverAddr->addr[5]); | ||||||
|  |  | ||||||
|  |     err = errSendMeshPacket(pMeshReceiverAddr, &packet); | ||||||
|  |     return err; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void vClearOtaMessageQueue(mesh_addr_t* pMeshNodeAddr) | ||||||
|  | { | ||||||
|  |     MESH_PACKET_t sMeshPacket; //packet for sending and receiving | ||||||
|  |     for (uint32_t u32Index = 0; (u32Index < QUEUE_MESSAGE_OTA_SIZE); u32Index++) //loop through all OTA messages | ||||||
|  |         { | ||||||
|  |             if (xQueueReceive(queueMessageOTA, &sMeshPacket, 0) == pdTRUE) | ||||||
|  |                 { | ||||||
|  |                     if(!(bCheckMACEquality(sMeshPacket.meshSenderAddr.addr, pMeshNodeAddr->addr))) | ||||||
|  |                         { | ||||||
|  |                             //received OTA message is NOT from pMeshNodeAddr --> keep it in queue | ||||||
|  |                             vAddOtaMessageToQueue(&sMeshPacket); | ||||||
|  |                         } | ||||||
|  |                     else | ||||||
|  |                         { | ||||||
|  |                             ESP_LOGI(LOG_TAG, "Removed type %i from node 0x%x", sMeshPacket.type, pMeshNodeAddr->addr[5]); | ||||||
|  |                         } | ||||||
|  |                 } | ||||||
|  |         }//end OTA message loop | ||||||
|  | } | ||||||
|  |  | ||||||
|  | esp_err_t errSendOTAVersionRequest(mesh_addr_t* pMeshReceiverAddr) | ||||||
|  | { | ||||||
|  |     esp_err_t err = ESP_OK; | ||||||
|  |     MESH_PACKET_t packet; | ||||||
|  |     packet.type = OTA_Version_Request; | ||||||
|  |  | ||||||
|  |     const esp_partition_t* pBootPartition; //pointer to boot partition (that will booted after reset) | ||||||
|  |     esp_app_desc_t bootPartitionDesc; //Metadata 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 | ||||||
|  |     memcpy(&packet.au8Payload, &bootPartitionDesc.version, 12); //copy local version to OTA_Version_Request packet | ||||||
|  |     err = errSendMeshPacket(pMeshReceiverAddr, &packet); | ||||||
|  |     return err; | ||||||
|  | } | ||||||
|  |  | ||||||
| @ -5,19 +5,10 @@ | |||||||
| #include <stdlib.h> | #include <stdlib.h> | ||||||
| #include "freertos/FreeRTOS.h" | #include "freertos/FreeRTOS.h" | ||||||
| #include "freertos/task.h" | #include "freertos/task.h" | ||||||
| #include "esp_wifi.h" |  | ||||||
| #include "esp_event.h" | #include "esp_event.h" | ||||||
| #include "esp_log.h" | #include "esp_log.h" | ||||||
| #include "esp_system.h" | #include "esp_system.h" | ||||||
| #include "nvs_flash.h" |  | ||||||
| #include "esp_netif.h" | #include "esp_netif.h" | ||||||
| 
 |  | ||||||
| #include "lwip/err.h" |  | ||||||
| #include "lwip/sockets.h" |  | ||||||
| #include "lwip/sys.h" |  | ||||||
| #include "lwip/netdb.h" |  | ||||||
| #include "lwip/dns.h" |  | ||||||
| 
 |  | ||||||
| #include "mbedtls/platform.h" | #include "mbedtls/platform.h" | ||||||
| #include "mbedtls/net_sockets.h" | #include "mbedtls/net_sockets.h" | ||||||
| #include "mbedtls/esp_debug.h" | #include "mbedtls/esp_debug.h" | ||||||
| @ -8,7 +8,7 @@ | |||||||
| #include "esp_log.h" | #include "esp_log.h" | ||||||
| #include "esp_mesh.h" | #include "esp_mesh.h" | ||||||
| #include "esp_mesh_internal.h" | #include "esp_mesh_internal.h" | ||||||
| #include <stdlib.h> | #include "nvs_flash.h" | ||||||
| 
 | 
 | ||||||
| #ifndef CONFIG_MESH_MESSAGE_SIZE | #ifndef CONFIG_MESH_MESSAGE_SIZE | ||||||
| #define CONFIG_MESH_MESSAGE_SIZE 1500 | #define CONFIG_MESH_MESSAGE_SIZE 1500 | ||||||
| @ -67,6 +67,15 @@ struct meshPacket | |||||||
| 
 | 
 | ||||||
| typedef struct meshPacket MESH_PACKET_t; | typedef struct meshPacket MESH_PACKET_t; | ||||||
| 
 | 
 | ||||||
|  | #define ERROR_CHECK(x) if (err == ESP_OK)                                                               \ | ||||||
|  |     {                                                                                                   \ | ||||||
|  |         err = (x);                                                                                      \ | ||||||
|  |         if (err != ESP_OK)                                                                              \ | ||||||
|  |             {                                                                                           \ | ||||||
|  |                 ESP_LOGE(LOG_TAG,  "%s failed with error: 0x%x -> %s", #x,  err, esp_err_to_name(err)); \ | ||||||
|  |             }                                                                                           \ | ||||||
|  |     }                                                                                                   \ | ||||||
|  | 
 | ||||||
| extern bool bIsMeshConnected; | extern bool bIsMeshConnected; | ||||||
| extern int32_t i32MeshLayer; | extern int32_t i32MeshLayer; | ||||||
| extern mesh_addr_t meshParentAddr; | extern mesh_addr_t meshParentAddr; | ||||||
| @ -1,20 +1,14 @@ | |||||||
| #ifndef H_MESH_OTA | #ifndef H_MESH_OTA | ||||||
| #define H_MESH_OTA | #define H_MESH_OTA | ||||||
|  |  | ||||||
| #include <string.h> |  | ||||||
| #include "esp_wifi.h" |  | ||||||
| #include "esp_system.h" | #include "esp_system.h" | ||||||
| #include "esp_event.h" | #include "esp_event.h" | ||||||
| #include "esp_log.h" | #include "esp_log.h" | ||||||
| #include "esp_mesh.h" |  | ||||||
| #include "esp_mesh_internal.h" |  | ||||||
| #include "nvs_flash.h" |  | ||||||
| #include "driver/gpio.h" |  | ||||||
| #include "esp_ota_ops.h" | #include "esp_ota_ops.h" | ||||||
| #include "esp_partition.h" | #include "esp_partition.h" | ||||||
|  |  | ||||||
| #include "Mesh_network.h" | #include "Mesh_Network.h" | ||||||
| #include "HTTPS_client.h" | #include "HTTPS_Client.h" | ||||||
|  |  | ||||||
| #define ERASE_NVS //erase non volatile storage if full | #define ERASE_NVS //erase non volatile storage if full | ||||||
| #define QUEUE_NODES_SIZE 10 | #define QUEUE_NODES_SIZE 10 | ||||||
| @ -34,42 +28,15 @@ | |||||||
|             }                                                                                           \ |             }                                                                                           \ | ||||||
|     }                                                                                                   \ |     }                                                                                                   \ | ||||||
|  |  | ||||||
| enum otaMeshRole |  | ||||||
| { |  | ||||||
|     Transmitter, |  | ||||||
|     Receiver |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| typedef  enum otaMeshRole OTA_MESH_ROLE_t; |  | ||||||
|  |  | ||||||
| esp_err_t errMeshOTAInitialize(); | esp_err_t errMeshOTAInitialize(); | ||||||
|  |  | ||||||
| esp_err_t errOTAHTTPS(bool* pbNewOTAImage); |  | ||||||
| esp_err_t errOTAMeshSlave(bool* pbNewOTAImage); | esp_err_t errOTAMeshSlave(bool* pbNewOTAImage); | ||||||
| esp_err_t errOTAMeshMaster(bool* pbNewOTAImage, mesh_addr_t* pMeshNodeAddr); | esp_err_t errOTAMeshMaster(bool* pbNewOTAImage, mesh_addr_t* pMeshNodeAddr); | ||||||
| esp_err_t errOTAMeshTransmit(mesh_addr_t* pMeshNodeAddr); |  | ||||||
| esp_err_t errOTAMeshReceive(bool* pbNewOTAImage, mesh_addr_t* pMeshNodeAddr); |  | ||||||
|  |  | ||||||
|  |  | ||||||
| //helper functions |  | ||||||
| bool bNewerVersion(const char* pu8Local, const char* pu8Remote); |  | ||||||
| esp_err_t errExtractVersionNumber(const  char* pu8Data, uint32_t* pu32DataLenght, char* pc8RemoteVersionNumber); |  | ||||||
| esp_err_t errFindImageStart(const  char* pu8Data, uint32_t* pu32DataLenght, uint32_t* pu32StartOffset); |  | ||||||
| void vPrintOTAProgress(const uint32_t* const pu32TotalImageSize, const uint32_t* const pu32BytesWritten, OTA_MESH_ROLE_t eRole); |  | ||||||
| void vAddAllNeighboursToQueue(void); |  | ||||||
| esp_err_t errSendOTAVersionResponse(mesh_addr_t* meshReceiverAddr); |  | ||||||
| esp_err_t errSendOTAVersionRequest(mesh_addr_t* meshReceiverAddr); |  | ||||||
| void vClearOtaMessageQueue(mesh_addr_t* pMeshNodeAddr); |  | ||||||
|  |  | ||||||
| //Handler |  | ||||||
| void vAddNodeToPossibleUpdatableQueue(uint8_t* pu8MAC); |  | ||||||
| void vAddOtaMessageToQueue(MESH_PACKET_t* puMeshPacket); |  | ||||||
| void vChangeStateOfServerWorker(bool state); |  | ||||||
|  |  | ||||||
| //Tasks | //Tasks | ||||||
| void vTaskServerWorker(void *arg); | void vTaskServerWorker(void *arg); | ||||||
| void vTaskOTAWorker(void *arg); | void vTaskOTAWorker(void *arg); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| #endif /* H_MESH_OTA */ | #endif /* H_MESH_OTA */ | ||||||
|  | |||||||
							
								
								
									
										28
									
								
								components/mesh_ota/include/Mesh_OTA_Access.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								components/mesh_ota/include/Mesh_OTA_Access.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,28 @@ | |||||||
|  | #ifndef H_MESH_OTA_ACCESS | ||||||
|  | #define H_MESH_OTA_ACCESS | ||||||
|  |  | ||||||
|  | #include "esp_system.h" | ||||||
|  | #include "esp_event.h" | ||||||
|  | #include "esp_log.h" | ||||||
|  | #include "nvs_flash.h" | ||||||
|  | #include "esp_ota_ops.h" | ||||||
|  | #include "esp_partition.h" | ||||||
|  |  | ||||||
|  | #include "Mesh_Network.h" | ||||||
|  | #include "HTTPS_Client.h" | ||||||
|  |  | ||||||
|  | #define ERROR_CHECK(x) if (err == ESP_OK)                                                               \ | ||||||
|  |     {                                                                                                   \ | ||||||
|  |         err = (x);                                                                                      \ | ||||||
|  |         if (err != ESP_OK)                                                                              \ | ||||||
|  |             {                                                                                           \ | ||||||
|  |                 ESP_LOGE(LOG_TAG,  "%s failed with error: 0x%x -> %s", #x,  err, esp_err_to_name(err)); \ | ||||||
|  |             }                                                                                           \ | ||||||
|  |     }                                                                                                   \ | ||||||
|  |  | ||||||
|  | esp_err_t errOTAMeshTransmit(mesh_addr_t* pMeshNodeAddr); | ||||||
|  | esp_err_t errOTAMeshReceive(bool* pbNewOTAImage, mesh_addr_t* pMeshNodeAddr); | ||||||
|  |  | ||||||
|  | esp_err_t errOTAHTTPS(bool* pbNewOTAImage); | ||||||
|  |  | ||||||
|  | #endif /* H_MESH_OTA_ACCESS */ | ||||||
							
								
								
									
										19
									
								
								components/mesh_ota/include/Mesh_OTA_Globals.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								components/mesh_ota/include/Mesh_OTA_Globals.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | |||||||
|  | #ifndef H_MESH_OTA_GLOBALS | ||||||
|  | #define H_MESH_OTA_GLOBALS | ||||||
|  |  | ||||||
|  | #include "esp_system.h" | ||||||
|  | #include "esp_partition.h" | ||||||
|  |  | ||||||
|  | #include "Mesh_Network.h" | ||||||
|  | #include "HTTPS_Client.h" | ||||||
|  |  | ||||||
|  | extern xQueueHandle queueNodes; //nodes that should be checked for ota update (contains children and parent) | ||||||
|  | extern xQueueHandle queueMessageOTA; //mesh ota controll messages like "OTA_Version_Response" "OTA_ACK" | ||||||
|  |  | ||||||
|  | extern SemaphoreHandle_t bsStartStopServerWorker; //binary semaphore | ||||||
|  | extern SemaphoreHandle_t bsOTAProcess; //binary semaphore | ||||||
|  |  | ||||||
|  | extern const esp_partition_t* pOTAPartition; //pointer to ota partition | ||||||
|  | extern bool bWantReboot; //flag to signal pending reboot | ||||||
|  |  | ||||||
|  | #endif /* H_MESH_OTA_GLOBALS */ | ||||||
							
								
								
									
										35
									
								
								components/mesh_ota/include/Mesh_OTA_Util.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								components/mesh_ota/include/Mesh_OTA_Util.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,35 @@ | |||||||
|  | #ifndef H_MESH_OTA_UTIL | ||||||
|  | #define H_MESH_OTA_UTIL | ||||||
|  |  | ||||||
|  | #include "esp_system.h" | ||||||
|  | #include "esp_event.h" | ||||||
|  | #include "esp_log.h" | ||||||
|  |  | ||||||
|  | #include "Mesh_Network.h" | ||||||
|  | #include "HTTPS_Client.h" | ||||||
|  | #include "Mesh_OTA.h" | ||||||
|  |  | ||||||
|  | enum otaMeshRole | ||||||
|  | { | ||||||
|  |     Transmitter, | ||||||
|  |     Receiver | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | typedef  enum otaMeshRole OTA_MESH_ROLE_t; | ||||||
|  |  | ||||||
|  | //helper functions | ||||||
|  | bool bNewerVersion(const char* pu8Local, const char* pu8Remote); | ||||||
|  | esp_err_t errExtractVersionNumber(const  char* pu8Data, uint32_t* pu32DataLenght, char* pc8RemoteVersionNumber); | ||||||
|  | esp_err_t errFindImageStart(const  char* pu8Data, uint32_t* pu32DataLenght, uint32_t* pu32StartOffset); | ||||||
|  | void vPrintOTAProgress(const uint32_t* const pu32TotalImageSize, const uint32_t* const pu32BytesWritten, OTA_MESH_ROLE_t eRole); | ||||||
|  | void vAddAllNeighboursToQueue(void); | ||||||
|  | esp_err_t errSendOTAVersionResponse(mesh_addr_t* meshReceiverAddr); | ||||||
|  | esp_err_t errSendOTAVersionRequest(mesh_addr_t* meshReceiverAddr); | ||||||
|  | void vClearOtaMessageQueue(mesh_addr_t* pMeshNodeAddr); | ||||||
|  |  | ||||||
|  | //Handler | ||||||
|  | void vAddNodeToPossibleUpdatableQueue(uint8_t* pu8MAC); | ||||||
|  | void vAddOtaMessageToQueue(MESH_PACKET_t* puMeshPacket); | ||||||
|  | void vChangeStateOfServerWorker(bool state); | ||||||
|  |  | ||||||
|  | #endif /* H_MESH_OTA_UTIL */ | ||||||
| @ -183,4 +183,4 @@ void vTaskReceiveData(void *arg) | |||||||
|                 } |                 } | ||||||
|             vTaskDelay(200 / portTICK_PERIOD_MS); |             vTaskDelay(200 / portTICK_PERIOD_MS); | ||||||
|         } |         } | ||||||
| } | } | ||||||
|  | |||||||
| @ -11,6 +11,7 @@ | |||||||
|  |  | ||||||
| #include "Mesh_OTA.h" | #include "Mesh_OTA.h" | ||||||
|  |  | ||||||
|  |  | ||||||
| #define GPIO_BOOT_BTN   0 //GPIO0 (Boot BTN) | #define GPIO_BOOT_BTN   0 //GPIO0 (Boot BTN) | ||||||
| #define GPIO_LED        2 //GPIO2 (internal blue LED in DevKit V1.0) | #define GPIO_LED        2 //GPIO2 (internal blue LED in DevKit V1.0) | ||||||
|  |  | ||||||
|  | |||||||
							
								
								
									
										18
									
								
								main/Main.c
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								main/Main.c
									
									
									
									
									
								
							| @ -1,15 +1,9 @@ | |||||||
|  | #include <stdio.h> | ||||||
| #include <string.h> | #include "sdkconfig.h" | ||||||
| #include "esp_wifi.h" | #include "freertos/FreeRTOS.h" | ||||||
|  | #include "freertos/task.h" | ||||||
| #include "esp_system.h" | #include "esp_system.h" | ||||||
| #include "esp_event.h" | #include "esp_spi_flash.h" | ||||||
| #include "esp_log.h" |  | ||||||
| #include "esp_mesh.h" |  | ||||||
| #include "esp_mesh_internal.h" |  | ||||||
| #include "nvs_flash.h" |  | ||||||
| #include "driver/gpio.h" |  | ||||||
| #include "esp_ota_ops.h" |  | ||||||
| #include "esp_partition.h" |  | ||||||
|  |  | ||||||
| #include "Mesh_OTA.h" | #include "Mesh_OTA.h" | ||||||
| #include "Blinky_LED.h" | #include "Blinky_LED.h" | ||||||
| @ -19,7 +13,7 @@ static const char *LOG_TAG = "esp_main"; | |||||||
| void app_main(void) | void app_main(void) | ||||||
| { | { | ||||||
|     esp_err_t err = ESP_OK; |     esp_err_t err = ESP_OK; | ||||||
|     ESP_LOGI(LOG_TAG, "hardcoded: 0.0.1"); |     ESP_LOGI(LOG_TAG, "hardcoded version: 0.0.1"); | ||||||
|  |  | ||||||
|     ESP_LOGI(LOG_TAG, "start mesh network"); |     ESP_LOGI(LOG_TAG, "start mesh network"); | ||||||
|     err = errMeshNetworkInitialize(); |     err = errMeshNetworkInitialize(); | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user