@ -160,41 +160,6 @@ void vChangeStateOfServerWorker(bool bState) //allow access via function ptn to
}
}
void vTaskOTAWorker ( void * arg )
{
while ( true )
{
if ( ( uxQueueSpacesAvailable ( queueNodes ) - QUEUE_NODES_SIZE ) = = 0 )
{
//nodes queue is empty
ESP_LOGI ( LOG_TAG , " nodes queue is empty " ) ;
if ( bWantReboot = = true )
{
ESP_LOGI ( LOG_TAG , " ESP32 Reboot ... " ) ;
//vTaskDelay( (1000) / portTICK_PERIOD_MS);
//esp_restart();
}
//read OTAMessages queue
//if OTA_Version_Response
// --> send OTA_Version_Request
// --> this version older --> start OTA_Rx --> vAddAllNeighboursToQueue(); //add all existing neighbours to queues
// --> this version newer --> start OTA_Tx
//if not OTA_Version_Response --> do nothing
}
vTaskDelay ( ( 1000 ) / portTICK_PERIOD_MS ) ;
}
}
void vTaskServerWorker ( void * arg )
{
esp_err_t err ;
@ -237,6 +202,61 @@ void vTaskServerWorker(void *arg)
}
}
void vTaskOTAWorker ( void * arg )
{
esp_err_t err = ESP_OK ;
bool bNewOTAImage ; //true if a new ota image was downloaded and validated
mesh_addr_t meshNodeAddr ; //node that should be checked for ota update
while ( true )
{
err = ESP_OK ;
bNewOTAImage = false ;
if ( ( uxQueueSpacesAvailable ( queueNodes ) - QUEUE_NODES_SIZE ) = = 0 )
{
//nodes queue is empty
ESP_LOGI ( LOG_TAG , " nodes queue is empty " ) ;
if ( bWantReboot = = true )
{
ESP_LOGI ( LOG_TAG , " ESP32 Reboot ... " ) ;
//vTaskDelay( (1000) / portTICK_PERIOD_MS);
//esp_restart();
}
ERROR_CHECK ( errOTAMeshSlave ( & bNewOTAImage ) ) ;
}
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 " ) ;
err = ESP_FAIL ;
}
ERROR_CHECK ( errOTAMeshMaster ( & bNewOTAImage , & meshNodeAddr ) ) ;
}
if ( bNewOTAImage = = true )
{
//set want reboot
ESP_LOGI ( LOG_TAG , " Updated successfully via Mesh, set pending reboot " ) ;
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 ;
@ -250,15 +270,17 @@ esp_err_t errOTAHTTPS(bool* pbNewOTAImage)
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 ( 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
@ -266,8 +288,6 @@ esp_err_t errOTAHTTPS(bool* pbNewOTAImage)
ERROR_CHECK ( errFindImageStart ( u8OTABuffer , & u32BufferLenght , & u32StartOffset ) ) ; //get image start offset
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 )
{
@ -306,16 +326,83 @@ esp_err_t errOTAHTTPS(bool* pbNewOTAImage)
ERROR_CHECK ( esp_ota_abort ( otaHandle ) ) ;
* pbNewOTAImage = false ; //ota update failed
}
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 " ) ;
}
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 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
* pbNewOTAImage = false ; //set default false
//read OTAMessages queue
if ( uxQueueSpacesAvailable ( queueMessageOTA ) < QUEUE_MESSAGE_OTA_SIZE )
{
//queue not empty
if ( xQueueReceive ( queueMessageOTA , & sOTAMessage , ( ( 100 ) / 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_Request ) ) //if OTA_Version_Request
{
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
//send OTA_Version_Response to sender of OTA_Version_Request packet
ERROR_CHECK ( errSendOTAVersionResponse ( & sOTAMessage . meshSenderAddr ) ) ;
if ( ( bNewerVersion ( ( bootPartitionDesc ) . version , ( char * ) sOTAMessage . au8Payload ) ) & & ( err = = ESP_OK ) ) //compare local and remote version
{
//remote newer as local
ESP_LOGI ( LOG_TAG , " 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 , " remote image on node is older --> OTA send required " ) ;
// --> this version newer --> start OTA_Tx
}
xSemaphoreGive ( bsOTAProcess ) ; //free binary semaphore, this allows other tasks to start the OTA process
}
}
return err ;
}
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
* 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
return err ;
}
/*
* Return true if remote version is newer ( higher ) than local version
*/
@ -328,8 +415,8 @@ bool bNewerVersion(const char* pu8Local, const char* pu8Remote)
bool bReturn = false ; //flag to stop loop
uint8_t u8Index = 0 ; //numbers counter in version string
strcpy ( u8LocalTmp , pu8Local ) ; //copy in tmp
strcpy ( u8RemoteTmp , pu8Remote ) ; //copy in tmp
strn cpy ( u8LocalTmp , pu8Local , 12 ) ; //copy in tmp
strn cpy ( u8RemoteTmp , pu8Remote , 12 ) ; //copy in tmp
char * pu8TokenLocal = strtok_r ( u8LocalTmp , " . " , & pu8saveptrLocal ) ; //split tokens
char * pu8TokenRemote = strtok_r ( u8RemoteTmp , " . " , & pu8saveptrRemote ) ; //split tokens
@ -469,23 +556,43 @@ void vAddAllNeighboursToQueue(void)
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 ; //number 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 ; u16Index + + )
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
err = errSendMeshPacket ( pMeshReceiverAddr , & packet ) ;
return err ;
}
/*
esp_err_t esp_mesh_ota_send ( mesh_addr_t * dest )
{
@ -591,4 +698,4 @@ esp_err_t esp_mesh_ota_receive(mesh_addr_t* dest, struct ota_mesh_packet* packet
return err ;
}
*/
*/