refactor #2
| @ -56,7 +56,7 @@ https_client_ret_t errHTTPSClientInitialize(void) | ||||
| * @brief receive a image segment from server | ||||
| * @param cpu8Data data buffer | ||||
| * @param cpcu32DataLenght desired byte amount | ||||
| * @param pu32BytesRead actual received byte amount  | ||||
| * @param pu32BytesRead actual received byte amount | ||||
| * @return HTTPS_Client error code | ||||
| * @author Hendrik Schutter | ||||
| * @date 20.01.2021 | ||||
|  | ||||
| @ -224,6 +224,15 @@ esp_err_t errMeshNetworkSetChangeStateOfServerWorkerHandle(void (*pChangeStateOf | ||||
|     return ESP_OK; | ||||
| } | ||||
|  | ||||
| /** | ||||
| * @fn esp_err_t errMeshNetworkSendMeshPacket(const mesh_addr_t* const cpcAddrDest, const MESH_PACKET_t* const cpcPacket) | ||||
| * @brief send packet to mesh node | ||||
| * @param cpcAddrDest address from mesh node | ||||
| * @param cpcPacket packet to send | ||||
| * @return ESP32 error code | ||||
| * @author Hendrik Schutter | ||||
| * @date 20.01.2021 | ||||
| */ | ||||
| esp_err_t errMeshNetworkSendMeshPacket(const mesh_addr_t* const cpcAddrDest, const MESH_PACKET_t* const cpcPacket) | ||||
| { | ||||
|     esp_err_t err; | ||||
| @ -240,11 +249,27 @@ esp_err_t errMeshNetworkSendMeshPacket(const mesh_addr_t* const cpcAddrDest, con | ||||
|     return err; | ||||
| } | ||||
|  | ||||
| bool bMeshNetworkIsRootNode() | ||||
| /** | ||||
| * @fn bool bMeshNetworkIsRootNode() | ||||
| * @brief return  true if this node is the root | ||||
| * @param void | ||||
| * @return boolean | ||||
| * @author Hendrik Schutter | ||||
| * @date 21.01.2021 | ||||
| */ | ||||
| bool bMeshNetworkIsRootNode(void) | ||||
| { | ||||
|     return esp_mesh_is_root(); | ||||
| } | ||||
|  | ||||
| /** | ||||
| * @fn bool bMeshNetworkIsNodeNeighbour(const mesh_addr_t* const cpcNode) | ||||
| * @brief return true if node is neighbour if this | ||||
| * @param cpcNode to check | ||||
| * @return boolean | ||||
| * @author Hendrik Schutter | ||||
| * @date 21.01.2021 | ||||
| */ | ||||
| bool bMeshNetworkIsNodeNeighbour(const mesh_addr_t* const cpcNode) | ||||
| { | ||||
|     esp_err_t err = ESP_OK; | ||||
| @ -280,7 +305,16 @@ bool bMeshNetworkIsNodeNeighbour(const mesh_addr_t* const cpcNode) | ||||
|     return bReturn; | ||||
| } | ||||
|  | ||||
| //returns true if MAC address is equal | ||||
|  | ||||
| /** | ||||
| * @fn bool bMeshNetworkCheckMACEquality(const uint8_t* const cpcu8aMAC, const uint8_t* const cpcu8bMAC) | ||||
| * @brief returns true if MAC address is equal | ||||
| * @param cpcu8aMAC first MAC | ||||
| * @param cpcu8bMAC second MAC | ||||
| * @return boolean | ||||
| * @author Hendrik Schutter | ||||
| * @date 21.01.2021 | ||||
| */ | ||||
| bool bMeshNetworkCheckMACEquality(const uint8_t* const cpcu8aMAC, const uint8_t* const cpcu8bMAC) | ||||
| { | ||||
|     bool bRet = true; | ||||
| @ -306,7 +340,15 @@ bool bMeshNetworkCheckMACEquality(const uint8_t* const cpcu8aMAC, const uint8_t* | ||||
|     return bRet; | ||||
| } | ||||
|  | ||||
| esp_err_t errMeshNetworkStartReceiveTask() | ||||
| /** | ||||
| * @fn esp_err_t errMeshNetworkStartReceiveTask() | ||||
| * @brief start the task to receive the mesh packets | ||||
| * @param void | ||||
| * @return ESP32 error code | ||||
| * @author Hendrik Schutter | ||||
| * @date 21.01.2021 | ||||
| */ | ||||
| esp_err_t errMeshNetworkStartReceiveTask(void) | ||||
| { | ||||
|     esp_err_t err = ESP_OK; | ||||
|     BaseType_t xReturned; | ||||
| @ -320,11 +362,28 @@ esp_err_t errMeshNetworkStartReceiveTask() | ||||
|     return err; | ||||
| } | ||||
|  | ||||
| /** | ||||
| * @fn vMeshNetworkGetOwnAddr(mesh_addr_t* const cpMeshOwnAddr) | ||||
| * @brief return own MAC addr | ||||
| * @param cpMeshOwnAddr pointer to own mac | ||||
| * @return void | ||||
| * @author Hendrik Schutter | ||||
| * @date 21.01.2021 | ||||
| */ | ||||
| void vMeshNetworkGetOwnAddr(mesh_addr_t* const cpMeshOwnAddr) | ||||
| { | ||||
|     memcpy(cpMeshOwnAddr->addr, u8ownMAC, 6); | ||||
| } | ||||
|  | ||||
| /** | ||||
| * @fn esp_err_t errMeshNetworkGetChildren(mesh_addr_t* const cpChildren, uint16_t* const cpu16ChildrenSize) | ||||
| * @brief get all connected children to node in array | ||||
| * @param cpChildren pointer to array | ||||
| * @param cpu16ChildrenSize pointer to size of array | ||||
| * @return ESP32 error code | ||||
| * @author Hendrik Schutter | ||||
| * @date 21.01.2021 | ||||
| */ | ||||
| esp_err_t errMeshNetworkGetChildren(mesh_addr_t* const cpChildren, uint16_t* const cpu16ChildrenSize) | ||||
| { | ||||
|     esp_err_t err = ESP_OK; | ||||
| @ -349,6 +408,14 @@ esp_err_t errMeshNetworkGetChildren(mesh_addr_t* const cpChildren, uint16_t* con | ||||
|     return err; | ||||
| } | ||||
|  | ||||
| /** | ||||
| * @fn void vMeshNetworkTaskReceiveMeshData(void *arg) | ||||
| * @brief Task to receive all mesh packets | ||||
| * @param arg | ||||
| * @return void | ||||
| * @author Hendrik Schutter | ||||
| * @date 21.01.2021 | ||||
| */ | ||||
| void vMeshNetworkTaskReceiveMeshData(void *arg) | ||||
| { | ||||
|     esp_err_t err; | ||||
| @ -398,6 +465,14 @@ void vMeshNetworkTaskReceiveMeshData(void *arg) | ||||
|         } //end while | ||||
| } | ||||
|  | ||||
| /** | ||||
| * @fn esp_err_t errMeshNetworkGetParentNode(mesh_addr_t* const cpMeshParentAddr) | ||||
| * @brief get parrent node if connected to it | ||||
| * @param cpMeshParentAddr pointer to parent node addrs | ||||
| * @return ESP32 error code | ||||
| * @author Hendrik Schutter | ||||
| * @date 21.01.2021 | ||||
| */ | ||||
| esp_err_t errMeshNetworkGetParentNode(mesh_addr_t* const cpMeshParentAddr) | ||||
| { | ||||
|     esp_err_t err = ESP_OK; | ||||
|  | ||||
| @ -1,3 +1,10 @@ | ||||
| /** | ||||
| * @file Mesh_OTA.c | ||||
| * @brief Start and implement OTA updates via HTTPS from server and other mesh nodes (bidirectional) | ||||
| * @author Hendrik Schutter | ||||
| * @date 21.01.2021 | ||||
| */ | ||||
|  | ||||
| #include "Mesh_OTA.h" | ||||
| #include "Mesh_OTA_Util.h" | ||||
| #include "Mesh_OTA_Globals.h" | ||||
| @ -5,7 +12,18 @@ | ||||
|  | ||||
| static const char *LOG_TAG = "mesh_ota"; | ||||
|  | ||||
| esp_err_t errMeshOTAInitialize() | ||||
| /** | ||||
| * @fn esp_err_t errMeshOTAInitialize(void) | ||||
| * @brief Starts Mesh OTA functionality | ||||
| * @param void | ||||
| * @return ESP32 error code | ||||
| * @author Hendrik Schutter | ||||
| * @date 21.01.2021 | ||||
| * | ||||
| * Initialize queues and tasks | ||||
| * Set callbacks | ||||
| */ | ||||
| esp_err_t errMeshOTAInitialize(void) | ||||
| { | ||||
|     esp_err_t err = ESP_OK; | ||||
|     BaseType_t xReturned; | ||||
| @ -15,7 +33,7 @@ esp_err_t errMeshOTAInitialize() | ||||
|     queueNodes = xQueueCreate(QUEUE_NODES_SIZE, sizeof(mesh_addr_t)); | ||||
|     if (queueNodes == 0)  // Queue not created | ||||
|         { | ||||
|             ESP_LOGE(LOG_TAG, "Unable to create Queue for Nodes"); | ||||
|             ESP_LOGE(LOG_TAG, "Unable to create queue for nodes"); | ||||
|             err = ESP_FAIL; | ||||
|         } | ||||
|  | ||||
| @ -25,7 +43,7 @@ esp_err_t errMeshOTAInitialize() | ||||
|             queueMessageOTA = xQueueCreate(QUEUE_MESSAGE_OTA_SIZE, sizeof(MESH_PACKET_t)); | ||||
|             if (queueMessageOTA == 0)  // Queue not created | ||||
|                 { | ||||
|                     ESP_LOGE(LOG_TAG, "Unable to create Queue for OTA Messages"); | ||||
|                     ESP_LOGE(LOG_TAG, "Unable to create queue for OTA messages"); | ||||
|                     err = ESP_FAIL; | ||||
|                 } | ||||
|         } | ||||
| @ -35,7 +53,7 @@ esp_err_t errMeshOTAInitialize() | ||||
|             bsStartStopServerWorker = xSemaphoreCreateBinary(); | ||||
|             if( bsStartStopServerWorker == NULL ) | ||||
|                 { | ||||
|                     ESP_LOGE(LOG_TAG, "Unable to create Mutex to represent state of Server worker"); | ||||
|                     ESP_LOGE(LOG_TAG, "Unable to create mutex to represent state of server worker"); | ||||
|                     err = ESP_FAIL; | ||||
|                 } | ||||
|         } | ||||
| @ -45,7 +63,7 @@ esp_err_t errMeshOTAInitialize() | ||||
|             bsOTAProcess = xSemaphoreCreateBinary(); | ||||
|             if( bsOTAProcess == NULL ) | ||||
|                 { | ||||
|                     ESP_LOGE(LOG_TAG, "Unable to create Mutex to grant access to OTA Process"); | ||||
|                     ESP_LOGE(LOG_TAG, "Unable to create mutex to grant access to OTA process"); | ||||
|                     err = ESP_FAIL; | ||||
|                 } | ||||
|         } | ||||
| @ -55,11 +73,12 @@ esp_err_t errMeshOTAInitialize() | ||||
|             xSemaphoreGive(bsOTAProcess);  //unlock binary semaphore | ||||
|             if( bsOTAProcess == NULL ) | ||||
|                 { | ||||
|                     ESP_LOGE(LOG_TAG, "Unable to unlock Mutex to grant access to OTA Process"); | ||||
|                     ESP_LOGE(LOG_TAG, "Unable to unlock mutex to grant access to OTA process"); | ||||
|                     err = ESP_FAIL; | ||||
|                 } | ||||
|         } | ||||
|  | ||||
|     //register callbacks in network | ||||
|     ERROR_CHECK(errMeshNetworkSetChildConnectedHandle(vMeshOtaUtilAddNodeToPossibleUpdatableQueue)); | ||||
|     ERROR_CHECK(errMeshNetworkSetOTAMessageHandleHandle(vMeshOtaUtilAddOtaMessageToQueue)); | ||||
|     ERROR_CHECK(errMeshNetworkSetChangeStateOfServerWorkerHandle(vMeshOtaUtilChangeStateOfServerWorker)); | ||||
| @ -99,9 +118,17 @@ esp_err_t errMeshOTAInitialize() | ||||
|     return err; | ||||
| } | ||||
|  | ||||
| /** | ||||
| * @fn void vMeshOtaTaskServerWorker(void *arg) | ||||
| * @brief Task for updating from server via HTTPS | ||||
| * @param arg | ||||
| * @return void | ||||
| * @author Hendrik Schutter | ||||
| * @date 21.01.2021 | ||||
| */ | ||||
| void vMeshOtaTaskServerWorker(void *arg) | ||||
| { | ||||
|     esp_err_t err; | ||||
|     esp_err_t err = ESP_OK; | ||||
|     bool bNewOTAImage; //true if a new ota image was downloaded and validated | ||||
|     bool bFirstRun = true; | ||||
|  | ||||
| @ -118,6 +145,7 @@ void vMeshOtaTaskServerWorker(void *arg) | ||||
|  | ||||
|                     if(bFirstRun == true) | ||||
|                         { | ||||
|                             //init on first run | ||||
|                             ERROR_CHECK(errHTTPSClientInitialize()); | ||||
|                             bFirstRun = false; | ||||
|                         } | ||||
| @ -141,6 +169,14 @@ void vMeshOtaTaskServerWorker(void *arg) | ||||
|         } | ||||
| } | ||||
|  | ||||
| /** | ||||
| * @fn void vMeshOtaTaskServerWorker(void *arg) | ||||
| * @brief Task for updating from nodes in mesh network | ||||
| * @param arg | ||||
| * @return void | ||||
| * @author Hendrik Schutter | ||||
| * @date 21.01.2021 | ||||
| */ | ||||
| void vMeshOtaTaskOTAWorker(void *arg) | ||||
| { | ||||
|     esp_err_t err = ESP_OK; | ||||
| @ -155,8 +191,6 @@ void vMeshOtaTaskOTAWorker(void *arg) | ||||
|             if((uxQueueSpacesAvailable(queueNodes) - QUEUE_NODES_SIZE) == 0) | ||||
|                 { | ||||
|                     //nodes queue is empty | ||||
|                     ESP_LOGI(LOG_TAG, "nodes queue is empty"); | ||||
|  | ||||
|                     if((bWantReboot == true) && (OTA_ALLOW_REBOOT == 1)) | ||||
|                         { | ||||
|                             ESP_LOGE(LOG_TAG, "ESP32 Reboot ..."); | ||||
| @ -169,8 +203,6 @@ void vMeshOtaTaskOTAWorker(void *arg) | ||||
|             else | ||||
|                 { | ||||
|                     //queue not empty | ||||
|                     ESP_LOGI(LOG_TAG, "nodes queue not empty: %i", (QUEUE_NODES_SIZE - uxQueueSpacesAvailable(queueNodes))); | ||||
|  | ||||
|                     if (xQueueReceive(queueNodes, &meshNodeAddr, ((100) / portTICK_PERIOD_MS)) != pdTRUE) | ||||
|                         { | ||||
|                             ESP_LOGE(LOG_TAG, "Unable to receive OTA Messages from Queue"); | ||||
| @ -188,7 +220,6 @@ void vMeshOtaTaskOTAWorker(void *arg) | ||||
|                         { | ||||
|                             vMeshOtaUtilClearNeighboursQueue(&meshNodeAddr); //remove this node from queue | ||||
|                         } | ||||
|  | ||||
|                 } | ||||
|  | ||||
|             if(bNewOTAImage == true) | ||||
| @ -196,18 +227,28 @@ void vMeshOtaTaskOTAWorker(void *arg) | ||||
|                     //set want reboot | ||||
|                     ESP_LOGI(LOG_TAG, "Updated successfully via Mesh, set pending reboot"); | ||||
|                     bWantReboot = true; | ||||
|  | ||||
|                     vMeshOtaUtilAddAllNeighboursToQueue(); //add all existing neighbours to queue | ||||
|                 } | ||||
|             vTaskDelay( (1000) / portTICK_PERIOD_MS); | ||||
|         } | ||||
| } | ||||
|  | ||||
| /** | ||||
| * @fn esp_err_t errMeshOtaSlaveEndpoint(bool* const cpbNewOTAImage) | ||||
| * @brief Endpoint for OTA process that is called from remote node | ||||
| * @param cpbNewOTAImage pointer to boolean to signal if a new image was successfully received  | ||||
| * @return ESP32 error code | ||||
| * @author Hendrik Schutter | ||||
| * @date 21.01.2021 | ||||
| * | ||||
| * Answers the OTA_Version_Request with OTA_Version_Response | ||||
| * calls errMeshOtaPartitionAccessMeshReceive OR errMeshOtaPartitionAccessMeshTransmit based on version number | ||||
| */ | ||||
| esp_err_t errMeshOtaSlaveEndpoint(bool* const cpbNewOTAImage) | ||||
| { | ||||
|     esp_err_t err = ESP_OK; | ||||
|     MESH_PACKET_t sOTAMessage; | ||||
|     const esp_partition_t* pBootPartition; //pointer to boot partition (that will booted after reset) | ||||
|     const esp_partition_t* cpBootPartition = NULL; //pointer to boot partition (that will booted after reset) | ||||
|     esp_app_desc_t bootPartitionDesc; //Metadate from boot partition | ||||
|     *cpbNewOTAImage = false; //set default false | ||||
|  | ||||
| @ -225,8 +266,8 @@ esp_err_t errMeshOtaSlaveEndpoint(bool* const cpbNewOTAImage) | ||||
|                 { | ||||
|                     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 | ||||
|                     cpBootPartition = esp_ota_get_boot_partition(); //get boot partition (that will booted after reset), not the running partition | ||||
|                     ERROR_CHECK(esp_ota_get_partition_description(cpBootPartition, &bootPartitionDesc)); //get metadata of partition | ||||
|  | ||||
|                     //send OTA_Version_Response to sender of OTA_Version_Request packet wirh version in payload | ||||
|                     ERROR_CHECK(errMeshOtaUtilSendOTAVersionResponse(&sOTAMessage.meshSenderAddr)); | ||||
| @ -252,11 +293,23 @@ esp_err_t errMeshOtaSlaveEndpoint(bool* const cpbNewOTAImage) | ||||
|     return err; | ||||
| } | ||||
|  | ||||
| /** | ||||
| * @fn esp_err_t errMeshOtaMasterEndpoint(bool* const cpbNewOTAImage, const mesh_addr_t* const cpcMeshNodeAddr) | ||||
| * @brief Endpoint for OTA process that calls remote node | ||||
| * @param cpbNewOTAImage pointer to boolean to signal if a new image was successfully received  | ||||
| * @param cpcMeshNodeAddr pointer to remote node addr | ||||
| * @return ESP32 error code | ||||
| * @author Hendrik Schutter | ||||
| * @date 21.01.2021 | ||||
| * | ||||
| * Sends the OTA_Version_Request to remote node | ||||
| * calls errMeshOtaPartitionAccessMeshReceive OR errMeshOtaPartitionAccessMeshTransmit based on version number received | ||||
| */ | ||||
| esp_err_t errMeshOtaMasterEndpoint(bool* const cpbNewOTAImage, const mesh_addr_t* const cpcMeshNodeAddr) | ||||
| { | ||||
|     esp_err_t err = ESP_OK; | ||||
|     MESH_PACKET_t sOTAMessage; | ||||
|     const esp_partition_t* pBootPartition; //pointer to boot partition (that will booted after reset) | ||||
|     const esp_partition_t* cpBootPartition = NULL; //pointer to boot partition (that will booted after reset) | ||||
|     esp_app_desc_t bootPartitionDesc; //Metadata from boot partition | ||||
|     bool bNodeIsConnected = false; | ||||
|     bool bNodeIsResponding = false; | ||||
| @ -268,7 +321,6 @@ esp_err_t errMeshOtaMasterEndpoint(bool* const cpbNewOTAImage, const mesh_addr_t | ||||
|             bNodeIsConnected = true; //node is one of the neighbours | ||||
|             xSemaphoreTake(bsOTAProcess, portMAX_DELAY); //wait for binary semaphore that allows to start the OTA process | ||||
|  | ||||
|             ESP_LOGI(LOG_TAG, "Mesh-Master: send Version_Request to 0x%x", cpcMeshNodeAddr->addr[5]); | ||||
|             ERROR_CHECK(errMeshOtaUtilSendOTAVersionRequest(cpcMeshNodeAddr)); //send OTA_VERSION_REQUEST with local version in payload | ||||
|  | ||||
|             for (uint32_t u32Index = 0; u32Index < QUEUE_MESSAGE_OTA_SIZE; u32Index++) //loop through all OTA messages | ||||
| @ -285,8 +337,8 @@ esp_err_t errMeshOtaMasterEndpoint(bool* const cpbNewOTAImage, const mesh_addr_t | ||||
|                             if((err == ESP_OK) && (sOTAMessage.type == OTA_Version_Response) && (bMeshNetworkCheckMACEquality(sOTAMessage.meshSenderAddr.addr, cpcMeshNodeAddr->addr))) //if OTA_Version_Request | ||||
|                                 { | ||||
|                                     bNodeIsResponding = true; | ||||
|                                     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 | ||||
|                                     cpBootPartition = esp_ota_get_boot_partition(); //get boot partition (that will booted after reset), not the running partition | ||||
|                                     ERROR_CHECK(esp_ota_get_partition_description(cpBootPartition, &bootPartitionDesc)); //get metadata of partition | ||||
|  | ||||
|                                     if((bMeshOtaUtilNewerVersion((bootPartitionDesc).version, (char*) sOTAMessage.au8Payload)) && (err == ESP_OK)) //compare local and remote version | ||||
|                                         { | ||||
| @ -313,7 +365,7 @@ esp_err_t errMeshOtaMasterEndpoint(bool* const cpbNewOTAImage, const mesh_addr_t | ||||
|                     else | ||||
|                         { | ||||
|                             // OTA Message queue is empty --> wait some time | ||||
|                             ESP_LOGI(LOG_TAG, "OTA-Master: OTA Message queue is empty --> wait some time"); | ||||
|                             ESP_LOGD(LOG_TAG, "OTA-Master: OTA Message queue is empty --> wait some time"); | ||||
|                             vTaskDelay( (1000/QUEUE_MESSAGE_OTA_SIZE) / portTICK_PERIOD_MS); | ||||
|                         } | ||||
|                 }//end loop | ||||
| @ -323,7 +375,7 @@ esp_err_t errMeshOtaMasterEndpoint(bool* const cpbNewOTAImage, const mesh_addr_t | ||||
|     if((bNodeIsResponding == false) && (bNodeIsConnected == true)) | ||||
|         { | ||||
|             //add node back to queue if connected and NOT responding | ||||
|             ESP_LOGI(LOG_TAG, "OTA-Master: connected and NOT responding --> add node back to queue "); | ||||
|             ESP_LOGD(LOG_TAG, "OTA-Master: connected and NOT responding --> add node back to queue "); | ||||
|             vMeshOtaUtilAddNodeToPossibleUpdatableQueue(cpcMeshNodeAddr->addr); | ||||
|         } | ||||
|     return err; | ||||
|  | ||||
| @ -1,3 +1,10 @@ | ||||
| /** | ||||
| * @file Mesh_OTA_Globals.c | ||||
| * @brief global variables unsed in Mesh_OTA | ||||
| * @author Hendrik Schutter | ||||
| * @date 21.01.2021 | ||||
| */ | ||||
|  | ||||
| #include "Mesh_OTA_Globals.h" | ||||
|  | ||||
| xQueueHandle queueNodes; //nodes that should be checked for ota update (contains children and parent) | ||||
|  | ||||
| @ -1,3 +1,13 @@ | ||||
| /** | ||||
| * @file Mesh_OTA_Partition_Access.c | ||||
| * @brief Write and read partition if requested from Mesh_OTA | ||||
| * @author Hendrik Schutter | ||||
| * @date 21.01.2021 | ||||
| * | ||||
| * Additional Infos: Write image via HTTPS | ||||
| *                   Receive or transmit via Mesh | ||||
| */ | ||||
|  | ||||
| #include "Mesh_OTA.h" | ||||
| #include "Mesh_OTA_Util.h" | ||||
| #include "Mesh_OTA_Globals.h" | ||||
| @ -5,6 +15,18 @@ | ||||
|  | ||||
| static const char *LOG_TAG = "mesh_ota_partition_access"; | ||||
|  | ||||
| /** | ||||
| * @fn esp_err_t errMeshOtaPartitionAccessHttps(bool* const cpbNewOTAImage) | ||||
| * @brief Downloads and writes the image from the server to partition | ||||
| * @param cpbNewOTAImage pointer to boolean to signal if a new image was successfully received | ||||
| * @return ESP32 error code | ||||
| * @author Hendrik Schutter | ||||
| * @date 21.01.2021 | ||||
| * | ||||
| * Checks if the image on server is newer | ||||
| * Downloads the image in segements | ||||
| * Handles OTA process | ||||
| */ | ||||
| esp_err_t errMeshOtaPartitionAccessHttps(bool* const cpbNewOTAImage) | ||||
| { | ||||
|     esp_err_t err = ESP_OK; | ||||
| @ -22,7 +44,8 @@ esp_err_t errMeshOtaPartitionAccessHttps(bool* const cpbNewOTAImage) | ||||
|  | ||||
|     ERROR_CHECK(errMeshOtaUtilExtractVersionNumber(u8OTABuffer, &u32BytesRead, pcRemoteVersionNumber)); //extract version numbers | ||||
|  | ||||
|     if(err == ESP_OK) //check if version number is found | ||||
|     //check if version number is found | ||||
|     if(err == ESP_OK)  | ||||
|         { | ||||
|             xSemaphoreTake(bsOTAProcess, portMAX_DELAY); //wait for binary semaphore that allows to start the OTA process | ||||
|  | ||||
| @ -35,8 +58,8 @@ esp_err_t errMeshOtaPartitionAccessHttps(bool* const cpbNewOTAImage) | ||||
|                     ESP_LOGI(LOG_TAG, "Server: image is newer --> OTA update required"); | ||||
|  | ||||
|                     ERROR_CHECK(errMeshOtaUtilFindImageStart(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 | ||||
| @ -54,7 +77,8 @@ esp_err_t errMeshOtaPartitionAccessHttps(bool* const cpbNewOTAImage) | ||||
|                                             u32OTABytesWritten = u32OTABytesWritten + u32BytesRead; //update counter | ||||
|                                         } | ||||
|                                 } | ||||
|                             while ((u32BytesRead > 0) && (err == ESP_OK) && (u32OTABytesWritten <= pOTAPartition->size)); //loop until error or complete image downloaded | ||||
|                             //loop until error or complete image downloaded | ||||
|                             while ((u32BytesRead > 0) && (err == ESP_OK) && (u32OTABytesWritten <= pOTAPartition->size)); | ||||
|                         } | ||||
|  | ||||
|                     if(err == ESP_OK) | ||||
| @ -70,7 +94,7 @@ esp_err_t errMeshOtaPartitionAccessHttps(bool* const cpbNewOTAImage) | ||||
|                     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)); | ||||
|                             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)); | ||||
|                             *cpbNewOTAImage = false; //ota update failed | ||||
|                         } | ||||
| @ -84,27 +108,39 @@ esp_err_t errMeshOtaPartitionAccessHttps(bool* const cpbNewOTAImage) | ||||
|     return err; | ||||
| } | ||||
|  | ||||
| /** | ||||
| * @fn esp_err_t errMeshOtaPartitionAccessMeshTransmit(const mesh_addr_t* const cpcMeshNodeAddr) | ||||
| * @brief Reads the local image and sends it to node | ||||
| * @param cpcMeshNodeAddr pointer to mesh node addr to send the image segments to | ||||
| * @return ESP32 error code | ||||
| * @author Hendrik Schutter | ||||
| * @date 21.01.2021 | ||||
| * | ||||
| * Reads the newest OTA image in segments | ||||
| * Sends the image to mesh node in segments | ||||
| * Handles OTA process | ||||
| */ | ||||
| esp_err_t errMeshOtaPartitionAccessMeshTransmit(const mesh_addr_t* const cpcMeshNodeAddr) | ||||
| { | ||||
|     esp_err_t err = ESP_OK; | ||||
|     const esp_partition_t* pBootPartition; //pointer to boot partition (that will booted after reset) | ||||
|     const esp_partition_t* pBootPartition = NULL; //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; | ||||
|     uint32_t u32OTABytesWritten = 0U; //counter of bytes unsed for progress log | ||||
|     uint32_t u32SegmentCounter = 0U; //counter of segments unsed for progress log | ||||
|  | ||||
|     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 | ||||
|             bNodeIsResponding = false; //reset to default for this loop | ||||
|  | ||||
|             // 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); | ||||
|             u32OTABytesWritten = ((u32SegmentCounter+1) * OTA_MESH_SEGMENT_SIZE); //calc bytes that are written in this ota process | ||||
|             vMeshOtaUtilPrintOTAProgress(&(pBootPartition->size), &u32OTABytesWritten, Transmitter); | ||||
|  | ||||
|             if(err == ESP_OK) | ||||
| @ -115,10 +151,9 @@ esp_err_t errMeshOtaPartitionAccessMeshTransmit(const mesh_addr_t* const cpcMesh | ||||
|                     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"); | ||||
|                             ESP_LOGD(LOG_TAG, "OTA-TX: last segment--> send Complete"); | ||||
|                             sMeshPacket.type = OTA_Complete; | ||||
|                         } | ||||
|                     //ESP_LOGI(LOG_TAG, "OTA-TX: send packet"); | ||||
|                     err = errMeshNetworkSendMeshPacket(cpcMeshNodeAddr, &sMeshPacket); | ||||
|                 } | ||||
|             else | ||||
| @ -126,39 +161,35 @@ esp_err_t errMeshOtaPartitionAccessMeshTransmit(const mesh_addr_t* const cpcMesh | ||||
|                     // 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"); | ||||
|                     ESP_LOGE(LOG_TAG, "OTA-TX: error while read --> send ABORT"); | ||||
|                     errMeshNetworkSendMeshPacket(cpcMeshNodeAddr, &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 | ||||
|                     //get OTA message from queue | ||||
|                     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) && (bMeshNetworkCheckMACEquality(sMeshPacket.meshSenderAddr.addr, cpcMeshNodeAddr->addr))) //if OTA_Version_Request | ||||
|                     //check if from correct node | ||||
|                     if((err == ESP_OK) && (bMeshNetworkCheckMACEquality(sMeshPacket.meshSenderAddr.addr, cpcMeshNodeAddr->addr)))  | ||||
|                         { | ||||
|                             //packet from node received | ||||
|                             //packet from node received --> handle it | ||||
|                             switch (sMeshPacket.type) | ||||
|                                 { | ||||
|                                 case OTA_ACK: //increase index for next round | ||||
|                                     u32Index++; | ||||
|                                 case OTA_ACK: //start next loop for segment | ||||
|                                     bNodeIsResponding = true; | ||||
|                                     u32Index = QUEUE_MESSAGE_OTA_SIZE;//this will end the loop through all OTA messages | ||||
|                                     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 | ||||
|                                     //vMeshOtaUtilAddOtaMessageToQueue(&sMeshPacket); | ||||
|                                     break; | ||||
|                                 } | ||||
|                         } | ||||
| @ -167,16 +198,6 @@ esp_err_t errMeshOtaPartitionAccessMeshTransmit(const mesh_addr_t* const cpcMesh | ||||
|                             //received from wrong node --> back to queue | ||||
|                             vMeshOtaUtilAddOtaMessageToQueue(&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) | ||||
| @ -188,10 +209,23 @@ esp_err_t errMeshOtaPartitionAccessMeshTransmit(const mesh_addr_t* const cpcMesh | ||||
|                 } | ||||
|             u32SegmentCounter++; | ||||
|         }//end of partition segment loop | ||||
|     vMeshOtaUtilClearOtaMessageQueue(cpcMeshNodeAddr); | ||||
|     vMeshOtaUtilClearOtaMessageQueue(cpcMeshNodeAddr); //remove all OTA messages from remote node | ||||
|     return err; | ||||
| } | ||||
|  | ||||
| /** | ||||
| * @fn esp_err_t errMeshOtaPartitionAccessMeshReceive(bool* const cpbNewOTAImage, const mesh_addr_t* const cpcMeshNodeAddr) | ||||
| * @brief Downloads and writes the image from the remote node  | ||||
| * @param cpbNewOTAImage pointer to boolean to signal if a new image was successfully received | ||||
| * @param cpcMeshNodeAddr pointer to mesh node addr to receive the image segments from | ||||
| * @return ESP32 error code | ||||
| * @author Hendrik Schutter | ||||
| * @date 21.01.2021 | ||||
| * | ||||
| * Receives the images segments from remote node | ||||
| * Writtes segments to OTA partition | ||||
| * Handles OTA process | ||||
| */ | ||||
| esp_err_t errMeshOtaPartitionAccessMeshReceive(bool* const cpbNewOTAImage, const mesh_addr_t* const cpcMeshNodeAddr) | ||||
| { | ||||
|     esp_err_t err = ESP_OK; | ||||
| @ -201,8 +235,8 @@ esp_err_t errMeshOtaPartitionAccessMeshReceive(bool* const cpbNewOTAImage, const | ||||
|     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 | ||||
|     *cpbNewOTAImage = false; | ||||
|     uint32_t u32SegmentCounter = 0U; | ||||
|     *cpbNewOTAImage = false; //set default to false | ||||
|     uint32_t u32SegmentCounter = 0U; //counter of segments unsed for progress log | ||||
|  | ||||
|     ERROR_CHECK(esp_ota_begin(pOTAPartition, OTA_SIZE_UNKNOWN, &otaHandle)); //start ota update process | ||||
|  | ||||
| @ -230,24 +264,21 @@ esp_err_t errMeshOtaPartitionAccessMeshReceive(bool* const cpbNewOTAImage, const | ||||
|                                 { | ||||
|                                 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 | ||||
|                                     //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); | ||||
|                                     vMeshOtaUtilPrintOTAProgress(&(pOTAPartition->size), &u32OTABytesWritten, Receiver); | ||||
|                                     u32OTABytesWritten = ((u32SegmentCounter+1) * OTA_MESH_SEGMENT_SIZE); //calc bytes that are written in this ota process | ||||
|                                     vMeshOtaUtilPrintOTAProgress(&(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"); | ||||
|                                     ESP_LOGE(LOG_TAG, "OTA-RX: receives abort --> abort this OTA process on this node"); | ||||
|                                     //this will end the loop through all OTA messages | ||||
|                                     break; | ||||
|                                 default: | ||||
|                                     //receives wrong OTA message type from node --> back to queue | ||||
|                                     //vMeshOtaUtilAddOtaMessageToQueue(&sMeshPacket); | ||||
|                                     break; | ||||
|                                 } | ||||
|                         } | ||||
| @ -256,16 +287,6 @@ esp_err_t errMeshOtaPartitionAccessMeshReceive(bool* const cpbNewOTAImage, const | ||||
|                             //received from wrong node --> back to queue | ||||
|                             vMeshOtaUtilAddOtaMessageToQueue(&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) | ||||
| @ -284,7 +305,6 @@ esp_err_t errMeshOtaPartitionAccessMeshReceive(bool* const cpbNewOTAImage, const | ||||
|                             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 = errMeshNetworkSendMeshPacket(cpcMeshNodeAddr, &sMeshPacket); | ||||
|                                 } | ||||
| @ -305,7 +325,7 @@ esp_err_t errMeshOtaPartitionAccessMeshReceive(bool* const cpbNewOTAImage, const | ||||
|         { | ||||
|             //all OTA segments received --> validate | ||||
|             ESP_LOGI(LOG_TAG, "OTA-RX: validate image "); | ||||
|             ERROR_CHECK(esp_ota_end(otaHandle)); | ||||
|             ERROR_CHECK(esp_ota_end(otaHandle)); //validate image | ||||
|             ERROR_CHECK(esp_ota_set_boot_partition(pOTAPartition)); | ||||
|             if(err == ESP_OK) | ||||
|                 { | ||||
|  | ||||
| @ -1,17 +1,32 @@ | ||||
| /** | ||||
| * @file Mesh_OTA_Util.c | ||||
| * @brief Utility and helper functions to perfrom mesh OTA updates | ||||
| * @author Hendrik Schutter | ||||
| * @date 21.01.2021 | ||||
| */ | ||||
|  | ||||
| #include "Mesh_OTA_Util.h" | ||||
| #include "Mesh_OTA_Globals.h" | ||||
|  | ||||
| static const char *LOG_TAG = "mesh_ota"; | ||||
|  | ||||
| /** | ||||
| * @fn bool bMeshOtaUtilNewerVersion(const char* cpu8Local, const char* cpu8Remote) | ||||
| * @brief compares to version strings | ||||
| * @param cpu8Local local image version string | ||||
| * @param cpu8Remote remote image version string | ||||
| * @return bool | ||||
| * @author Hendrik Schutter | ||||
| * @date 21.01.2021 | ||||
| * | ||||
| * Returns true if remote is newer | ||||
| */ | ||||
| bool bMeshOtaUtilNewerVersion(const char* cpu8Local, const char* cpu8Remote) | ||||
| { | ||||
|     /* | ||||
|      * 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 | ||||
|     char* pu8saveptrLocal = NULL; //context for strok_r | ||||
|     char* pu8saveptrRemote = NULL; //context for strok_r | ||||
|     bool bReturn = false; //flag to stop loop | ||||
|     uint8_t u8Index = 0; //numbers counter in version string | ||||
|  | ||||
| @ -34,6 +49,18 @@ bool bMeshOtaUtilNewerVersion(const char* cpu8Local, const char* cpu8Remote) | ||||
|     return bReturn; | ||||
| } | ||||
|  | ||||
| /** | ||||
| * @fn esp_err_t errMeshOtaUtilExtractVersionNumber(const char* cpu8Data, uint32_t* const cpcu32DataLenght, char* const pc8RemoteVersionNumber) | ||||
| * @brief extract version number from image data | ||||
| * @param cpu8Data image data buffer | ||||
| * @param cpcu32DataLenght pointer to lenght of image data | ||||
| * @param pc8RemoteVersionNumber pointer version number | ||||
| * @return ESP32 error code | ||||
| * @author Hendrik Schutters | ||||
| * @date 21.01.2021 | ||||
| * | ||||
| * Search version number in raw image data | ||||
| */ | ||||
| esp_err_t errMeshOtaUtilExtractVersionNumber(const char* cpu8Data, uint32_t* const cpcu32DataLenght, char* const pc8RemoteVersionNumber) | ||||
| { | ||||
|     uint32_t u32StartOffset; | ||||
| @ -51,14 +78,25 @@ esp_err_t errMeshOtaUtilExtractVersionNumber(const char* cpu8Data, uint32_t* con | ||||
|     return err; | ||||
| } | ||||
|  | ||||
| /** | ||||
| * @fn esp_err_t errMeshOtaUtilFindImageStart(const char* const cpu8Data, const uint32_t* const cpcu32DataLenght, uint32_t* const cpu32StartOffset) | ||||
| * @brief find start offset from image raw data | ||||
| * @param cpu8Data image data buffer | ||||
| * @param cpcu32DataLenght pointer to lenght of image data | ||||
| * @param cpu32StartOffset pointer to determined offset | ||||
| * @return ESP32 error code | ||||
| * @author Hendrik Schutter | ||||
| * @date 21.01.2021 | ||||
| * | ||||
| * Search offset in raw image data from server (exclude HTTP response) | ||||
| */ | ||||
| esp_err_t errMeshOtaUtilFindImageStart(const char* const cpu8Data, const uint32_t* const cpcu32DataLenght, uint32_t* const cpu32StartOffset) | ||||
| { | ||||
|     /* | ||||
|     Offset  value | ||||
|     0      = 0xE9 (first byte in image --> magic byte) | ||||
|     48     = first digit of version number | ||||
|     */ | ||||
|  | ||||
|      | ||||
|     // 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; | ||||
| @ -129,13 +167,21 @@ esp_err_t errMeshOtaUtilFindImageStart(const char* const cpu8Data, const uint32_ | ||||
|     return errReturn; | ||||
| } | ||||
|  | ||||
| /** | ||||
| * @fn esp_err_t errMeshOtaUtilSendOTAVersionRequest(const mesh_addr_t* const cpcMeshReceiverAddr) | ||||
| * @brief send OTA_Version_Request to node | ||||
| * @param cpcMeshReceiverAddr node addr | ||||
| * @return ESP32 error code | ||||
| * @author Hendrik Schutter | ||||
| * @date 21.01.2021 | ||||
| */ | ||||
| esp_err_t errMeshOtaUtilSendOTAVersionRequest(const mesh_addr_t* const cpcMeshReceiverAddr) | ||||
| { | ||||
|     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) | ||||
|     const esp_partition_t* pBootPartition = NULL; //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 | ||||
| @ -145,25 +191,43 @@ esp_err_t errMeshOtaUtilSendOTAVersionRequest(const mesh_addr_t* const cpcMeshRe | ||||
|     return err; | ||||
| } | ||||
|  | ||||
| /** | ||||
| * @fn esp_err_t errMeshOtaUtilSendOTAVersionResponse(const mesh_addr_t* const cpcMeshReceiverAddr) | ||||
| * @brief send OTA_Version_Response to node | ||||
| * @param cpcMeshReceiverAddr node addr | ||||
| * @return ESP32 error code | ||||
| * @author Hendrik Schutter | ||||
| * @date 21.01.2021 | ||||
| */ | ||||
| esp_err_t errMeshOtaUtilSendOTAVersionResponse(const mesh_addr_t* const cpcMeshReceiverAddr) | ||||
| { | ||||
|     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) | ||||
|     const esp_partition_t* pBootPartition = NULL; //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", cpcMeshReceiverAddr->addr[5]); | ||||
|     ESP_LOGD(LOG_TAG, "Send OTA_Version_Response to 0x%x", cpcMeshReceiverAddr->addr[5]); | ||||
|  | ||||
|     err = errMeshNetworkSendMeshPacket(cpcMeshReceiverAddr, &packet); | ||||
|     return err; | ||||
| } | ||||
|  | ||||
| /** | ||||
| * @fn void vMeshOtaUtilPrintOTAProgress(const uint32_t* const cpcu32TotalImageSize, const uint32_t* const cpcu32BytesWritten, const OTA_MESH_ROLE_t ceRole) | ||||
| * @brief print LOG for OTA process progress | ||||
| * @param cpcu32TotalImageSize size of OTA partition | ||||
| * @param cpcu32BytesWritten actual bytes written | ||||
| * @param ceRole role if this OTA process | ||||
| * @return void | ||||
| * @author Hendrik Schutter | ||||
| * @date 21.01.2021 | ||||
| */ | ||||
| void vMeshOtaUtilPrintOTAProgress(const uint32_t* const cpcu32TotalImageSize, const uint32_t* const cpcu32BytesWritten, const OTA_MESH_ROLE_t ceRole) | ||||
| { | ||||
|     uint32_t u32Percentage = 0U; | ||||
| @ -196,6 +260,14 @@ void vMeshOtaUtilPrintOTAProgress(const uint32_t* const cpcu32TotalImageSize, co | ||||
|         } | ||||
| } | ||||
|  | ||||
| /** | ||||
| * @fn void vMeshOtaUtilAddAllNeighboursToQueue(void) | ||||
| * @brief add all neigbhours (children and parent) to queue | ||||
| * @param void | ||||
| * @return void | ||||
| * @author Hendrik Schutter | ||||
| * @date 21.01.2021 | ||||
| */ | ||||
| void vMeshOtaUtilAddAllNeighboursToQueue(void) | ||||
| { | ||||
|     esp_err_t err = ESP_OK; | ||||
| @ -209,7 +281,6 @@ void vMeshOtaUtilAddAllNeighboursToQueue(void) | ||||
|     if(err == ESP_OK) | ||||
|         { | ||||
|             vMeshOtaUtilAddNodeToPossibleUpdatableQueue(addrParent.addr); | ||||
|             ESP_LOGI(LOG_TAG, "added parent"); | ||||
|         } | ||||
|  | ||||
|     err = ESP_OK; //reset error code | ||||
| @ -219,10 +290,17 @@ void vMeshOtaUtilAddAllNeighboursToQueue(void) | ||||
|     for (uint16_t u16Index = 0; ((u16Index < u16ChildrenSize) && (err == ESP_OK)); u16Index++) | ||||
|         { | ||||
|             vMeshOtaUtilAddNodeToPossibleUpdatableQueue(childrenAddr[u16Index].addr); | ||||
|             ESP_LOGI(LOG_TAG, "added child"); | ||||
|         } | ||||
| } | ||||
|  | ||||
| /** | ||||
| * @fn void vMeshOtaUtilClearOtaMessageQueue(const mesh_addr_t* const cpcMeshNodeAddr) | ||||
| * @brief remode all OTA messages from this node in queue | ||||
| * @param cpcMeshNodeAddr node addr | ||||
| * @return void | ||||
| * @author Hendrik Schutter | ||||
| * @date 21.01.2021 | ||||
| */ | ||||
| void vMeshOtaUtilClearOtaMessageQueue(const mesh_addr_t* const cpcMeshNodeAddr) | ||||
| { | ||||
|     MESH_PACKET_t sMeshPacket; //packet for sending and receiving | ||||
| @ -235,14 +313,18 @@ void vMeshOtaUtilClearOtaMessageQueue(const mesh_addr_t* const cpcMeshNodeAddr) | ||||
|                             //received OTA message is NOT from cpcMeshNodeAddr --> keep it in queue | ||||
|                             vMeshOtaUtilAddOtaMessageToQueue(&sMeshPacket); | ||||
|                         } | ||||
|                     else | ||||
|                         { | ||||
|                             ESP_LOGI(LOG_TAG, "Removed type %i from node 0x%x", sMeshPacket.type, cpcMeshNodeAddr->addr[5]); | ||||
|                         } | ||||
|                 } | ||||
|         }//end OTA message loop | ||||
| } | ||||
|  | ||||
| /** | ||||
| * @fn void vMeshOtaUtilClearNeighboursQueue(const mesh_addr_t* const cpcMeshNodeAddr) | ||||
| * @brief remode all instances of this node in queue | ||||
| * @param cpcMeshNodeAddr node addr | ||||
| * @return void | ||||
| * @author Hendrik Schutter | ||||
| * @date 21.01.2021 | ||||
| */ | ||||
| void vMeshOtaUtilClearNeighboursQueue(const mesh_addr_t* const cpcMeshNodeAddr) | ||||
| { | ||||
|     mesh_addr_t sNode; //packet for sending and receiving | ||||
| @ -255,15 +337,18 @@ void vMeshOtaUtilClearNeighboursQueue(const mesh_addr_t* const cpcMeshNodeAddr) | ||||
|                             //node is NOT cpcMeshNodeAddr --> keep it in queue | ||||
|                             vMeshOtaUtilAddNodeToPossibleUpdatableQueue(cpcMeshNodeAddr->addr); | ||||
|                         } | ||||
|                     else | ||||
|                         { | ||||
|                             ESP_LOGI(LOG_TAG, "Removed node 0x%x", cpcMeshNodeAddr->addr[5]); | ||||
|                         } | ||||
|                 } | ||||
|         }//end OTA message loop | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
| * @fn void vMeshOtaUtilAddNodeToPossibleUpdatableQueue(const uint8_t* const cpcu8MAC) | ||||
| * @brief add node instance to queue | ||||
| * @param cpcu8MAC MAC addr of node | ||||
| * @return void | ||||
| * @author Hendrik Schutter | ||||
| * @date 21.01.2021 | ||||
| */ | ||||
| void vMeshOtaUtilAddNodeToPossibleUpdatableQueue(const uint8_t* const cpcu8MAC) | ||||
| { | ||||
|     //send payload to node queues | ||||
| @ -276,10 +361,18 @@ void vMeshOtaUtilAddNodeToPossibleUpdatableQueue(const uint8_t* const cpcu8MAC) | ||||
|         } | ||||
|     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]); | ||||
|             ESP_LOGD(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]); | ||||
|         } | ||||
| } | ||||
|  | ||||
| /** | ||||
| * @fn void vMeshOtaUtilAddOtaMessageToQueue(const MESH_PACKET_t* const cpcuMeshPacket) | ||||
| * @brief add OTA message to queue | ||||
| * @param cpcuMeshPacket OTA message | ||||
| * @return void | ||||
| * @author Hendrik Schutter | ||||
| * @date 21.01.2021 | ||||
| */ | ||||
| void vMeshOtaUtilAddOtaMessageToQueue(const MESH_PACKET_t* const cpcuMeshPacket) | ||||
| { | ||||
|     //send ota packet to packet queue | ||||
| @ -292,14 +385,14 @@ void vMeshOtaUtilAddOtaMessageToQueue(const MESH_PACKET_t* const cpcuMeshPacket) | ||||
|             switch (cpcuMeshPacket->type) | ||||
|                 { | ||||
|                 case OTA_Abort: | ||||
|                     ESP_LOGI(LOG_TAG, "added ota message to queue: OTA_Abort from 0x%x", cpcuMeshPacket->meshSenderAddr.addr[5]); | ||||
|                     ESP_LOGD(LOG_TAG, "added ota message to queue: OTA_Abort from 0x%x", cpcuMeshPacket->meshSenderAddr.addr[5]); | ||||
|                     break; | ||||
|                 case OTA_Version_Request: | ||||
|                     ESP_LOGI(LOG_TAG, "added ota message to queue: OTA_Version_Request from 0x%x", cpcuMeshPacket->meshSenderAddr.addr[5]); | ||||
|                     ESP_LOGD(LOG_TAG, "added ota message to queue: OTA_Version_Request from 0x%x", cpcuMeshPacket->meshSenderAddr.addr[5]); | ||||
|                     break; | ||||
|  | ||||
|                 case OTA_Version_Response: | ||||
|                     ESP_LOGI(LOG_TAG, "added ota message to queue: OTA_Version Response from 0x%x", cpcuMeshPacket->meshSenderAddr.addr[5]); | ||||
|                     ESP_LOGD(LOG_TAG, "added ota message to queue: OTA_Version Response from 0x%x", cpcuMeshPacket->meshSenderAddr.addr[5]); | ||||
|                     break; | ||||
|                 default: | ||||
|                     break; | ||||
| @ -307,14 +400,20 @@ void vMeshOtaUtilAddOtaMessageToQueue(const MESH_PACKET_t* const cpcuMeshPacket) | ||||
|         } | ||||
| } | ||||
|  | ||||
| void vMeshOtaUtilChangeStateOfServerWorker(const bool cbState) //allow access via function ptn to network_handler | ||||
| /** | ||||
| * @fn void vMeshOtaUtilChangeStateOfServerWorker(const bool cbState) | ||||
| * @brief callback for mesh network if connectivity to server changed | ||||
| * @param cbState boolean state | ||||
| * @return void | ||||
| * @author Hendrik Schutter | ||||
| * @date 21.01.2021 | ||||
| */ | ||||
| void vMeshOtaUtilChangeStateOfServerWorker(const bool cbState) | ||||
| { | ||||
|     static bool bLastState = false; | ||||
|  | ||||
|     if(cbState != bLastState) //change only if necessary | ||||
|         { | ||||
|             ESP_LOGI(LOG_TAG, "server worker change handler"); | ||||
|  | ||||
|             if(cbState == true) | ||||
|                 { | ||||
|                     if (xSemaphoreGive(bsStartStopServerWorker)  != pdTRUE) | ||||
|  | ||||
| @ -1,3 +1,12 @@ | ||||
| /** | ||||
| * @file Mesh_Network.h | ||||
| * @brief Mesh network layer used by OTA and APP | ||||
| * @author Hendrik Schutter, init based in ESP32-IDE code | ||||
| * @date 20.01.2021 | ||||
| * | ||||
| * Additional Infos: Start network and send and receive data. | ||||
| */ | ||||
|  | ||||
| #ifndef H_MESH_NETWORK | ||||
| #define H_MESH_NETWORK | ||||
|  | ||||
|  | ||||
| @ -1,3 +1,10 @@ | ||||
| /** | ||||
| * @file Mesh_OTA.h | ||||
| * @brief Start and implement OTA updates via HTTPS from server and other mesh nodes (bidirectional) | ||||
| * @author Hendrik Schutter | ||||
| * @date 21.01.2021 | ||||
| */ | ||||
|  | ||||
| #ifndef H_MESH_OTA | ||||
| #define H_MESH_OTA | ||||
|  | ||||
|  | ||||
| @ -1,3 +1,11 @@ | ||||
| /** | ||||
| * @file Mesh_OTA_Globals.h | ||||
| * @brief global variables unsed in Mesh_OTA | ||||
| * @author Hendrik Schutter | ||||
| * @date 21.01.2021 | ||||
| * | ||||
| */ | ||||
|  | ||||
| #ifndef H_MESH_OTA_GLOBALS | ||||
| #define H_MESH_OTA_GLOBALS | ||||
|  | ||||
|  | ||||
| @ -1,3 +1,13 @@ | ||||
| /** | ||||
| * @file Mesh_OTA_Partition_Access.h | ||||
| * @brief Write and read partition if requested from Mesh_OTA | ||||
| * @author Hendrik Schutter | ||||
| * @date 21.01.2021 | ||||
| * | ||||
| * Additional Infos: Write image via HTTPS | ||||
| *                   Receive or transmit via Mesh | ||||
| */ | ||||
|  | ||||
| #ifndef H_MESH_OTA_PARTITION_ACCESS | ||||
| #define H_MESH_OTA_PARTITION_ACCESS | ||||
|  | ||||
|  | ||||
| @ -1,3 +1,10 @@ | ||||
| /** | ||||
| * @file Mesh_OTA_Util.h | ||||
| * @brief Utility and helper functions to perfrom mesh OTA updates | ||||
| * @author Hendrik Schutter | ||||
| * @date 21.01.2021 | ||||
| */ | ||||
|  | ||||
| #ifndef H_MESH_OTA_UTIL | ||||
| #define H_MESH_OTA_UTIL | ||||
|  | ||||
|  | ||||
		Reference in New Issue
	
	Block a user