added OTA process mutex; progress log; reboot flag

This commit is contained in:
2021-01-18 19:03:32 +01:00
parent a0546aa3ef
commit 88fd2c69a9
5 changed files with 86 additions and 40 deletions

View File

@ -1,19 +1,21 @@
#include "Mesh_OTA.h"
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 err = ESP_OK;
BaseType_t xReturned;
bWantReboot = false;
//create queue to store nodes for ota worker task
queueNodes = xQueueCreate(QUEUE_NODES_SIZE, sizeof(mesh_addr_t));
@ -44,6 +46,26 @@ esp_err_t errMeshOTAInitialize()
}
}
if(err == ESP_OK)
{
bsOTAProcess = xSemaphoreCreateBinary();
if( bsOTAProcess == NULL )
{
ESP_LOGE(LOG_TAG, "Unable to create Mutex to grant access to OTA Process");
err = ESP_FAIL;
}
}
if(err == ESP_OK)
{
xSemaphoreGive(bsOTAProcess); //unlock binary semaphore
if( bsOTAProcess == NULL )
{
ESP_LOGE(LOG_TAG, "Unable to unlock Mutex to grant access to OTA Process");
err = ESP_FAIL;
}
}
ERROR_CHECK(errMeshNetworkSetChildConnectedHandle(vAddNodeToPossibleUpdatableQueue));
ERROR_CHECK(errMeshNetworkSetOTAMessageHandleHandle(vAddOTAControllMessageToQueue));
ERROR_CHECK(errMeshNetworkSetChangeStateOfServerWorkerHandle(vChangeStateOfServerWorker));
@ -72,7 +94,6 @@ esp_err_t errMeshOTAInitialize()
return err;
}
void vAddNodeToPossibleUpdatableQueue(uint8_t* pu8Data)
{
//send payload to node queue
@ -89,7 +110,6 @@ void vAddNodeToPossibleUpdatableQueue(uint8_t* pu8Data)
}
}
void vAddOTAControllMessageToQueue(MESH_PACKET_t* puMeshPacket)
{
//send ota packet to packet queue
@ -103,7 +123,6 @@ void vAddOTAControllMessageToQueue(MESH_PACKET_t* puMeshPacket)
}
}
void vChangeStateOfServerWorker(bool bState) //allow access via function ptn to networl_handler
{
static bool bLastState = false;
@ -142,38 +161,39 @@ void vTaskOTAWorker(void *arg)
void vTaskServerWorker(void *arg)
{
esp_err_t err;
bool bNewOTAImage = false; // true if a new ota image was downloaded and validated
bool bNewOTAImage; //true if a new ota image was downloaded and validated
bool bFirstRun = true;
while(true)
{
err = ESP_OK;
bNewOTAImage = false;
xSemaphoreTake(bsStartStopServerWorker, portMAX_DELAY); //wait for binary semaphore that allows to start the worker
xSemaphoreGive(bsStartStopServerWorker); //free binary semaphore, this allows the handler to change is to taken
if (esp_mesh_is_root()) //check again that this node is the root node
{
ESP_LOGI(LOG_TAG, "Checking firmware image on server");
if(bFirstRun == true)
{
ERROR_CHECK(https_clientInitialize());
ERROR_CHECK(errHTTPSClientInitialize());
bFirstRun = false;
}
ERROR_CHECK(https_clientConnectToServer());
ERROR_CHECK(https_clientValidateServer());
ERROR_CHECK(https_clientSendRequest());
ERROR_CHECK(errHTTPSClientConnectToServer());
ERROR_CHECK(errHTTPSClientValidateServer());
ERROR_CHECK(errHTTPSClientSendRequest());
ERROR_CHECK(errOTAHTTPS(&bNewOTAImage));
https_clientReset();
errHTTPSClientReset();
if(bNewOTAImage == true)
{
//set want reboot
ESP_LOGI(LOG_TAG, "Updated successfully via HTTPS, will reboot if possible");
ESP_LOGI(LOG_TAG, "Updated successfully via HTTPS, set pending reboot");
bWantReboot = true;
}
vTaskDelay( (SERVER_CHECK_INTERVAL*1000) / portTICK_PERIOD_MS); //sleep till next server check
}
}
@ -190,11 +210,12 @@ esp_err_t errOTAHTTPS(bool* pbNewOTAImage)
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
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
ERROR_CHECK(https_clientRetrieveData(u8OTABuffer, &u32BufferLenght, &u32BytesRead)); //read first bytes if image, including the version
ERROR_CHECK(errHTTPSClientRetrieveData(u8OTABuffer, &u32BufferLenght, &u32BytesRead)); //read first bytes if image, including the version
ERROR_CHECK(errExtractVersionNumber(u8OTABuffer, &u32BytesRead, pcRemoteVersionNumber)); //extract version numbers
@ -207,23 +228,24 @@ esp_err_t errOTAHTTPS(bool* pbNewOTAImage)
ERROR_CHECK(errFindImageStart(u8OTABuffer, &u32BufferLenght, &u32StartOffset)); //get image start offset
//TODO lock ota mutex
xSemaphoreTake(bsOTAProcess, portMAX_DELAY); //wait for binary semaphore that allows to start the OTA process
ERROR_CHECK(esp_ota_begin(pOTAPartition, OTA_SIZE_UNKNOWN, &otaHandle)); //start ota update process
if(err == ESP_OK)
{
//image download and ota partition write
ESP_LOGI(LOG_TAG, "start ota https download");
ESP_LOGI(LOG_TAG, "start OTA download via HTTPS");
do
{
//TODO progress log
vPrintOTAProgress(&(pOTAPartition->size), &u32OTABytesWritten);
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(https_clientRetrieveData(u8OTABuffer, &u32BufferLenght, &u32BytesRead)); //download next data segment
ERROR_CHECK(errHTTPSClientRetrieveData(u8OTABuffer, &u32BufferLenght, &u32BytesRead)); //download next data segment
u32OTABytesWritten = u32OTABytesWritten + u32BytesRead; //update counter
}
}
while ((u32BytesRead > 0) && (err == ESP_OK)); //loop until error or complete image downloaded
@ -246,8 +268,12 @@ esp_err_t errOTAHTTPS(bool* pbNewOTAImage)
ERROR_CHECK(esp_ota_abort(otaHandle));
*pbNewOTAImage = false; //ota update failed
}
//TODO unlock ota mutex
} //end newer version on server
xSemaphoreGive(bsOTAProcess); //free binary semaphore, this allows other tasks to start the OTA process
}
else
{
ESP_LOGI(LOG_TAG, "server image is NOT newer --> OTA update NOT required");
}
} //end version number extracted
return err;
}
@ -378,6 +404,27 @@ esp_err_t errExtractVersionNumber(const char* pu8Data, uint32_t* pu32DataLenght,
return err;
}
inline void vPrintOTAProgress(const uint32_t* const pu32TotalImageSize, const uint32_t* const pu32BytesWritten)
{
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)
{
ESP_LOGI(LOG_TAG, "OTA update progress: %i %%", u32Percentage);
u32LastPercentage = u32Percentage;
}
}
/*
esp_err_t esp_mesh_ota_send(mesh_addr_t* dest)
{