diff --git a/components/mesh_ota/Mesh_OTA.c b/components/mesh_ota/Mesh_OTA.c index 8610180..fe2f2d8 100644 --- a/components/mesh_ota/Mesh_OTA.c +++ b/components/mesh_ota/Mesh_OTA.c @@ -248,15 +248,10 @@ void vTaskOTAWorker(void *arg) bWantReboot = true; vAddAllNeighboursToQueue(); //add all existing neighbours to queue } - - - - vTaskDelay( (1000) / portTICK_PERIOD_MS); } } - esp_err_t errOTAHTTPS(bool* pbNewOTAImage) { esp_err_t err = ESP_OK; @@ -284,7 +279,7 @@ esp_err_t errOTAHTTPS(bool* pbNewOTAImage) 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"); + ESP_LOGI(LOG_TAG, "Server: image is newer --> OTA update required"); ERROR_CHECK(errFindImageStart(u8OTABuffer, &u32BufferLenght, &u32StartOffset)); //get image start offset @@ -306,7 +301,7 @@ esp_err_t errOTAHTTPS(bool* pbNewOTAImage) u32OTABytesWritten = u32OTABytesWritten + u32BytesRead; //update counter } } - while ((u32BytesRead > 0) && (err == ESP_OK)); //loop until error or complete image downloaded + while ((u32BytesRead > 0) && (err == ESP_OK) && (u32OTABytesWritten <= pOTAPartition->size)); //loop until error or complete image downloaded } if(err == ESP_OK) @@ -361,7 +356,7 @@ esp_err_t errOTAMeshSlave(bool* pbNewOTAImage) 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 - //send OTA_Version_Response to sender of OTA_Version_Request packet + //send OTA_Version_Response to sender of OTA_Version_Request packet wirh version in payload ERROR_CHECK(errSendOTAVersionResponse(&sOTAMessage.meshSenderAddr)); if((bNewerVersion((bootPartitionDesc).version, (char*) sOTAMessage.au8Payload)) && (err == ESP_OK)) //compare local and remote version @@ -388,26 +383,77 @@ esp_err_t errOTAMeshMaster(bool* pbNewOTAImage, mesh_addr_t* pMeshNodeAddr) esp_err_t err = ESP_OK; MESH_PACKET_t sOTAMessage; const esp_partition_t* pBootPartition; //pointer to boot partition (that will booted after reset) - esp_app_desc_t bootPartitionDesc; //Metadate from boot partition + esp_app_desc_t bootPartitionDesc; //Metadata from boot partition + bool bNodeIsConnected = false; + bool bNodeIsResponding = false; + *pbNewOTAImage = false; //set default false - //get node - //check if node is still connected - // --> send OTA_Version_Request - // --> read OTA_Version_Response (if from this node) (all other OTA message add again) - // --> this version older --> start OTA_Rx --> vAddAllNeighboursToQueue(); //add all existing neighbours to queues - // --> this version newer --> start OTA_Tx + if(bIsNodeNeighbour(pMeshNodeAddr) == true) //check if node is still connected + { + bNodeIsConnected = true; //node is one of the neighbours + xSemaphoreTake(bsOTAProcess, portMAX_DELAY); //wait for binary semaphore that allows to start the OTA process + ERROR_CHECK(errSendOTAVersionRequest(pMeshNodeAddr)); //send OTA_VERSION_REQUEST with local version in payload + //read OTA_Version_Response (if from this node) (all other OTA message add again) + // if(uxQueueSpacesAvailable(queueMessageOTA) < QUEUE_MESSAGE_OTA_SIZE) + //{ + + for (uint32_t u32Index = 0; u32Index < QUEUE_MESSAGE_OTA_SIZE; u32Index++) //loop through all OTA messages + { + if(uxQueueSpacesAvailable(queueMessageOTA) < QUEUE_MESSAGE_OTA_SIZE) + { + //queue not empty + if (xQueueReceive(queueMessageOTA, &sOTAMessage, ((3000) / portTICK_PERIOD_MS)) != pdTRUE) + { + ESP_LOGE(LOG_TAG, "Unable to receive OTA Messages from queue"); + err = ESP_FAIL; + } + + if((err == ESP_OK) && (sOTAMessage.type == OTA_Version_Response) && (bCheckMACEquality(sOTAMessage.meshSenderAddr.addr, pMeshNodeAddr->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 + + if((bNewerVersion((bootPartitionDesc).version, (char*) sOTAMessage.au8Payload)) && (err == ESP_OK)) //compare local and remote version + { + //remote newer as local + ESP_LOGI(LOG_TAG, "Mesh: remote image on node is newer --> OTA update required"); + // --> this version older --> start OTA_Rx --> set pbNewOTAImage true + } + + if((bNewerVersion((char*) sOTAMessage.au8Payload, (bootPartitionDesc).version)) && (err == ESP_OK)) //compare remote and local version + { + //local newer as remote + ESP_LOGI(LOG_TAG, "Mesh: remote image on node is older --> OTA send required"); + // --> this version newer --> start OTA_Tx + } + } + else + { + //send wrong OTA message back to queue + vAddOTAControllMessageToQueue(&sOTAMessage); + } + } + }//end loop + xSemaphoreGive(bsOTAProcess); //free binary semaphore, this allows other tasks to start the OTA process + } + + if((bNodeIsResponding == false) && (bNodeIsConnected == true)) + { + //add node back to queue if connected and NOT responding + vAddNodeToPossibleUpdatableQueue(pMeshNodeAddr->addr); + } return err; } - -/* - * Return true if remote version is newer (higher) than local version -*/ 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 @@ -593,6 +639,22 @@ esp_err_t errSendOTAVersionResponse(mesh_addr_t* pMeshReceiverAddr) return err; } +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 esp_mesh_ota_send(mesh_addr_t* dest) { diff --git a/components/mesh_ota/Mesh_network.c b/components/mesh_ota/Mesh_network.c index bb008c6..054b8b6 100644 --- a/components/mesh_ota/Mesh_network.c +++ b/components/mesh_ota/Mesh_network.c @@ -183,6 +183,41 @@ bool bIsRootNode() return esp_mesh_is_root(); } +bool bIsNodeNeighbour(mesh_addr_t* pNode) +{ + esp_err_t err = ESP_OK; + bool bReturn = false; + 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) + { + if(bCheckMACEquality(pNode->addr, addrParent.addr) == true) + { + bReturn = true; //node was found + } + } + + if(bReturn == false) + { + err = ESP_OK; //reset error code + + ERROR_CHECK(errGetChildren(childrenAddr, &u16ChildrenSize)); //get all children + + for (uint16_t u16Index = 0; ((u16Index < u16ChildrenSize) && (err == ESP_OK) && (bReturn == false)); u16Index++) + { + if(bCheckMACEquality(pNode->addr, childrenAddr[u16Index].addr) == true) + { + bReturn = true; //node was found + } + } + } + return bReturn; +} + esp_err_t errMeshNetworkSetAppReceiveHandle(void (*pAppRxHandleTmp)(uint8_t * pu8Data, uint8_t* pu8Sender)) { pAppRxHandle = pAppRxHandleTmp; //set handle from app as receive handle if an app packet is received diff --git a/components/mesh_ota/include/Mesh_OTA.h b/components/mesh_ota/include/Mesh_OTA.h index 0983e8f..7883271 100644 --- a/components/mesh_ota/include/Mesh_OTA.h +++ b/components/mesh_ota/include/Mesh_OTA.h @@ -45,6 +45,7 @@ esp_err_t errFindImageStart(const char* pu8Data, uint32_t* pu32DataLenght, uint void vPrintOTAProgress(const uint32_t* const pu32TotalImageSize, const uint32_t* const pu32BytesWritten); void vAddAllNeighboursToQueue(void); esp_err_t errSendOTAVersionResponse(mesh_addr_t* meshReceiverAddr); +esp_err_t errSendOTAVersionRequest(mesh_addr_t* meshReceiverAddr); //Handler void vAddNodeToPossibleUpdatableQueue(uint8_t* pu8MAC); diff --git a/components/mesh_ota/include/Mesh_network.h b/components/mesh_ota/include/Mesh_network.h index 93c2cf2..f69706f 100644 --- a/components/mesh_ota/include/Mesh_network.h +++ b/components/mesh_ota/include/Mesh_network.h @@ -87,6 +87,7 @@ void vGetOwnAddr(mesh_addr_t* pMeshOwnAddr); esp_err_t errGetParentNode(mesh_addr_t* pMeshParentAddr); esp_err_t errGetChildren(mesh_addr_t* pChildren, uint16_t* pu16ChildrenSize); bool bIsRootNode(); +bool bIsNodeNeighbour(mesh_addr_t* pNode); esp_err_t errStartReceiveTask(); void vTaskReceiveMeshData(void *arg);