@ -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_c lientInitialize( ) ) ;
ERROR_CHECK ( errHTTPSC lientInitialize( ) ) ;
bFirstRun = false ;
}
ERROR_CHECK ( https_c lientConnectToServer( ) ) ;
ERROR_CHECK ( https_c lientValidateServer( ) ) ;
ERROR_CHECK ( https_c lientSendRequest( ) ) ;
ERROR_CHECK ( errHTTPSC lientConnectToServer( ) ) ;
ERROR_CHECK ( errHTTPSC lientValidateServer( ) ) ;
ERROR_CHECK ( errHTTPSC lientSendRequest( ) ) ;
ERROR_CHECK ( errOTAHTTPS ( & bNewOTAImage ) ) ;
https_c lientReset( ) ;
errHTTPSC lientReset( ) ;
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_c lientRetrieveData( u8OTABuffer , & u32BufferLenght , & u32BytesRead ) ) ; //read first bytes if image, including the version
ERROR_CHECK ( errHTTPSC lientRetrieveData( 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 )
{