@ -130,7 +130,7 @@ void vAddOTAControllMessageToQueue(MESH_PACKET_t* puMeshPacket)
}
else
{
ESP_LOGI ( LOG_TAG , " added ota controll message to queue " ) ;
ESP_LOGI ( LOG_TAG , " added ota message to queue: %i (type) " , puMeshPacket - > type ) ;
}
}
@ -239,6 +239,12 @@ void vTaskOTAWorker(void *arg)
}
ERROR_CHECK ( errOTAMeshMaster ( & bNewOTAImage , & meshNodeAddr ) ) ;
if ( err ! = ESP_OK )
{
//OTA process faild --> add back to queue
vAddNodeToPossibleUpdatableQueue ( meshNodeAddr . addr ) ;
}
}
if ( bNewOTAImage = = true )
@ -290,7 +296,7 @@ esp_err_t errOTAHTTPS(bool* pbNewOTAImage)
ESP_LOGI ( LOG_TAG , " start OTA download via HTTPS " ) ;
do
{
vPrintOTAProgress ( & ( pOTAPartition - > size ) , & u32OTABytesWritten ) ;
vPrintOTAProgress ( & ( pOTAPartition - > size ) , & u32OTABytesWritten , Receiver ) ;
ERROR_CHECK ( esp_ota_write ( otaHandle , ( const void * ) u8OTABuffer + u32StartOffset , ( u32BytesRead - u32StartOffset ) ) ) ;
if ( err = = ESP_OK )
@ -364,6 +370,7 @@ esp_err_t errOTAMeshSlave(bool* pbNewOTAImage)
//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
ERROR_CHECK ( errOTAMeshReceive ( pbNewOTAImage , & sOTAMessage . meshSenderAddr ) ) ;
}
if ( ( bNewerVersion ( ( char * ) sOTAMessage . au8Payload , ( bootPartitionDesc ) . version ) ) & & ( err = = ESP_OK ) ) //compare remote and local version
@ -371,6 +378,7 @@ esp_err_t errOTAMeshSlave(bool* pbNewOTAImage)
//local newer as remote
ESP_LOGI ( LOG_TAG , " remote image on node is older --> OTA send required " ) ;
// --> this version newer --> start OTA_Tx
ERROR_CHECK ( errOTAMeshTransmit ( & sOTAMessage . meshSenderAddr ) ) ;
}
xSemaphoreGive ( bsOTAProcess ) ; //free binary semaphore, this allows other tasks to start the OTA process
}
@ -396,10 +404,6 @@ esp_err_t errOTAMeshMaster(bool* pbNewOTAImage, mesh_addr_t* pMeshNodeAddr)
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 )
@ -422,6 +426,7 @@ esp_err_t errOTAMeshMaster(bool* pbNewOTAImage, mesh_addr_t* pMeshNodeAddr)
//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
ERROR_CHECK ( errOTAMeshReceive ( pbNewOTAImage , & sOTAMessage . meshSenderAddr ) ) ;
}
if ( ( bNewerVersion ( ( char * ) sOTAMessage . au8Payload , ( bootPartitionDesc ) . version ) ) & & ( err = = ESP_OK ) ) //compare remote and local version
@ -429,14 +434,20 @@ esp_err_t errOTAMeshMaster(bool* pbNewOTAImage, mesh_addr_t* pMeshNodeAddr)
//local newer as remote
ESP_LOGI ( LOG_TAG , " Mesh: remote image on node is older --> OTA send required " ) ;
// --> this version newer --> start OTA_Tx
ERROR_CHECK ( errOTAMeshTransmit ( & sOTAMessage . meshSenderAddr ) ) ;
}
}
else
else if ( err = = ESP_OK )
{
//send wrong OTA message back to queue
//received from wrong node or type --> back to queue
vAddOTAControllMessageToQueue ( & sOTAMessage ) ;
}
}
else
{
// OTA Message queue is empty --> wait some time
vTaskDelay ( ( 1000 / QUEUE_MESSAGE_OTA_SIZE ) / portTICK_PERIOD_MS ) ;
}
} //end loop
xSemaphoreGive ( bsOTAProcess ) ; //free binary semaphore, this allows other tasks to start the OTA process
}
@ -575,7 +586,7 @@ esp_err_t errExtractVersionNumber(const char* pu8Data, uint32_t* pu32DataLenght,
return err ;
}
void vPrintOTAProgress ( const uint32_t * const pu32TotalImageSize , const uint32_t * const pu32BytesWritten )
void vPrintOTAProgress ( const uint32_t * const pu32TotalImageSize , const uint32_t * const pu32BytesWritten , OTA_MESH_ROLE_t eRole )
{
uint32_t u32Percentage = 0U ;
static uint32_t u32LastPercentage = 0U ;
@ -591,7 +602,18 @@ void vPrintOTAProgress(const uint32_t* const pu32TotalImageSize, const uint32_t*
if ( ( u32Percentage - u32LastPercentage ) > = OTA_PROGRESS_LOG_INTERVAL )
{
ESP_LOGI ( LOG_TAG , " OTA update progress: %i %% " , u32Percentage ) ;
if ( eRole = = Transmitter )
{
ESP_LOGI ( LOG_TAG , " Transmitting OTA update: %i %% " , u32Percentage ) ;
}
if ( eRole = = Receiver )
{
ESP_LOGI ( LOG_TAG , " Receiving OTA update: %i %% " , u32Percentage ) ;
}
u32LastPercentage = u32Percentage ;
}
}
@ -655,109 +677,216 @@ esp_err_t errSendOTAVersionRequest(mesh_addr_t* pMeshReceiverAddr)
return err ;
}
/*
esp_err_t esp_mesh_ota_send ( mesh_addr_t * dest )
esp_err_t errOTAMeshTransmit ( mesh_addr_t * pMeshNodeAddr )
{
esp_err_t err = ESP_OK ;
const esp_partition_t * pBootPartition ; //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 ;
static uint32_t u32index ;
pBootPartition = esp_ota_get_boot_partition ( ) ; //get boot partition (that will booted after reset), not the running partition
const esp_partition_t * pBootPartition = esp_ota_get_boot_partition ( ) ;
//loop through partition to read in segmensts until end or error or abort called
while ( ( ( OTA_MESH_SEGMENT_SIZE * u32Index ) < pBootPartition - > size ) & & ( err = = ESP_OK ) & & ( bAbort = = false ) )
{
bNodeIsResponding = false ; //reset to default
if ( ( * pBootPartition ) . subtype = = 0 )
{
// read partition with offset based in index
ERROR_CHECK ( esp_partition_read ( pBootPartition , ( OTA_MESH_SEGMENT_SIZE * u32Index ) , sMeshPacket . au8Payload , OTA_MESH_SEGMENT_SIZE ) ) ;
u32OTABytesWritten = ( ( u32Index + 1 ) * OTA_MESH_SEGMENT_SIZE ) ;
vPrintOTAProgress ( & ( pBootPartition - > size ) , & u32OTABytesWritten , Transmitter ) ;
int data_read = 0 ;
if ( err = = ESP_OK )
{
//no error while read --> send OTA_DATA packet
sMeshPacket . type = OTA_Data ;
struct ota_mesh_packet packet ;
packet . type = OTA_Data ;
if ( ( OTA_MESH_SEGMENT_SIZE * ( u32Index + 1 ) ) > = pBootPartition - > size ) //check if last segment
{
//last partition image segment --> send OTA_Complete
sMeshPacket . type = OTA_Complete ;
}
if ( u32index = = 1024 )
{
//all data read
data_read = 0 ;
u32index = 0 ;
}
else
{
ESP_LOGI ( MESH_TAG , " OTA-Data read: %i " , u32index ) ;
err = esp_partition_read ( pBootPartition , ( 1024 * u32index ) , packet . au8Payload , 1024 ) ;
ESP_ERROR_CHECK ( err ) ;
data_read = 1024 ;
u32index + + ;
}
err = errSendMeshPacket ( pMeshNodeAddr , & sMeshPacket ) ;
}
else
{
// error while read --> send OTA_ABORT and abort this OTA process
sMeshPacket . type = OTA_Abort ;
bAbort = true ;
errSendMeshPacket ( pMeshNodeAddr , & sMeshPacket ) ;
}
if ( data_read > 0 )
{
//send ota fragemnt to node
esp_mesh_send_packet ( dest , & packet ) ;
}
// 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
if ( xQueueReceive ( queueMessageOTA , & sMeshPacket , ( ( 3000 ) / portTICK_PERIOD_MS ) ) ! = pdTRUE )
{
ESP_LOGE ( LOG_TAG , " Unable to receive OTA Messages from queue " ) ;
err = ESP_FAIL ;
}
ESP_ERROR_CHECK ( err ) ;
}
else
{
ESP_LOGI ( MESH_TAG , " Subtype: %d " , ( * pBootPartition ) . subtype ) ;
}
if ( ( err = = ESP_OK ) & & ( bCheckMACEquality ( sMeshPacket . meshSenderAddr . addr , pMeshNodeAddr - > addr ) ) ) //if OTA_Version_Request
{
//packet from node received
switch ( sMeshPacket . type )
{
case OTA_ACK : //increase index for next round
u32Index + + ;
bNodeIsResponding = true ;
break ;
case OTA_Abort : //abort this OTA process
bAbort = true ;
bNodeIsResponding = true ;
break ;
default :
//receives wrong OTA message type from node --> back to queue
vAddOTAControllMessageToQueue ( & sMeshPacket ) ;
break ;
}
}
else if ( err = = ESP_OK )
{
//received from wrong node --> back to queue
vAddOTAControllMessageToQueue ( & sMeshPacket ) ;
}
}
else
{
// OTA Message queue is empty --> wait some time
vTaskDelay ( ( 1000 / QUEUE_MESSAGE_OTA_SIZE ) / portTICK_PERIOD_MS ) ;
}
} //end OTA message loop
if ( bNodeIsResponding = = false )
{
//no abort was called but node didn’t responded
bAbort = true ;
err = ESP_FAIL ; //this OTA process failed with error
}
} //end of partition segment loop
return err ;
}
esp_err_t esp_mesh_ota_receive ( mesh_addr_t * dest , struct ota_mesh_packet * packet )
esp_err_t errOTAMeshReceive ( bool * pbNewOTAImage , mesh_addr_t * pMeshNodeAddr )
{
esp_err_t err = ESP_OK ;
static esp_ota_handle_t otaHandle ;
static uint32_t u32index ;
const esp_partition_t * pBootPartition = esp_ota_get_boot_partition ( ) ;
const esp_partition_t * pOTAPartition = esp_ota_get_next_update_partition ( pBootPartition ) ;
if ( u32index = = 0 )
{
//first run
err = esp_ota_begin ( pOTAPartition , OTA_SIZE_UNKNOWN , & otaHandle ) ;
ESP_ERROR_CHECK ( err ) ;
}
ESP_LOGI ( MESH_TAG , " OTA-Data write: %i " , u32index ) ;
err = esp_ota_write ( otaHandle , packet - > au8Payload , 1024 ) ;
if ( err ! = ESP_OK )
{
ESP_LOGE ( MESH_TAG , " OTA-Data write error: %i at %i " , err , u32index ) ;
}
ESP_ERROR_CHECK ( err ) ;
if ( u32index > = 1023 )
{
//ota update complete
MESH_PACKET_t sMeshPacket ; //packet for sending and receiving
bool bComplete = false ; //complete the OTA process
bool bAbort = false ; //abort the OTA process
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
* pbNewOTAImage = false ;
ESP_LOGI ( MESH_TAG , " OTA-Data complete arrived: %i " , u32index ) ;
err = esp_ota_end ( otaHandle ) ;
ESP_ERROR_CHECK ( err ) ;
esp_app_desc_t otaPartitionDesc ;
err = esp_ota_get_partition_description ( pOTAPartition , & otaPartitionDesc ) ;
ESP_ERROR_CHECK ( err ) ;
ESP_LOGI ( MESH_TAG , " pOTAPartition project_name: %s " , ( otaPartitionDesc ) . project_name ) ;
ERROR_CHECK ( esp_ota_begin ( pOTAPartition , OTA_SIZE_UNKNOWN , & otaHandle ) ) ; //start ota update process
err = esp_ota_set_boot_partition ( pOTAPartition ) ;
ESP_ERROR_CHECK ( err ) ;
//partition segement loop through partition to read in segmensts until end or error or abort called
while ( ( bComplete = = false ) & & ( err = = ESP_OK ) & & ( bAbort = = false ) & & ( u32OTABytesWritten < = pOTAPartition - > size ) )
{
bNodeIsResponding = false ; //reset to default
struct ota_mesh_packet retPacket ;
retPacket . type = OTA_Complete ;
ESP_ERROR_CHECK ( esp_mesh_send_packet ( dest , & retPacket ) ) ; //send back to parent
// loop through all OTA messages or until abort is called
for ( uint32_t u32Index = 0 ; ( ( u32Index < QUEUE_MESSAGE_OTA_SIZE ) & & ( bAbort = = false ) ) ; u32Index + + ) //loop through all OTA messages
{
if ( uxQueueSpacesAvailable ( queueMessageOTA ) < QUEUE_MESSAGE_OTA_SIZE )
{
//queue not empty
if ( xQueueReceive ( queueMessageOTA , & sMeshPacket , ( ( 3000 ) / portTICK_PERIOD_MS ) ) ! = pdTRUE )
{
ESP_LOGE ( LOG_TAG , " Unable to receive OTA Messages from queue " ) ;
err = ESP_FAIL ;
}
//check if this node has children --> Update them
if ( ( err = = ESP_OK ) & & ( bCheckMACEquality ( sMeshPacket . meshSenderAddr . addr , pMeshNodeAddr - > addr ) ) ) //if OTA_Version_Request
{
//packet from node received
switch ( sMeshPacket . type )
{
case OTA_Complete : //signal end of this OTA process, fall through because same behavior as OTA_Data
bComplete = true ;
//fall through
case OTA_Data : //data segement received
bNodeIsResponding = true ;
ERROR_CHECK ( esp_ota_write ( otaHandle , sMeshPacket . au8Payload , OTA_MESH_SEGMENT_SIZE ) ) ;
u32OTABytesWritten = ( ( u32Index + 1 ) * OTA_MESH_SEGMENT_SIZE ) ;
vPrintOTAProgress ( & ( pOTAPartition - > size ) , & u32OTABytesWritten , Receiver ) ;
break ;
case OTA_Abort : //abort this OTA process
bAbort = true ;
bNodeIsResponding = true ;
break ;
default :
//receives wrong OTA message type from node --> back to queue
vAddOTAControllMessageToQueue ( & sMeshPacket ) ;
break ;
}
}
else if ( err = = ESP_OK )
{
//received from wrong node --> back to queue
vAddOTAControllMessageToQueue ( & sMeshPacket ) ;
}
}
else
{
// OTA Message queue is empty --> wait some time
vTaskDelay ( ( 1000 / QUEUE_MESSAGE_OTA_SIZE ) / portTICK_PERIOD_MS ) ;
}
esp_restart ( ) ;
}
} //end of OTA message loop
u32index + + ;
if ( bNodeIsResponding = = false )
{
//no abort was called but node didn’t responded --> error
bAbort = true ; //this will stop the partition segement loop
err = ESP_FAIL ; //this OTA process failed with error
}
else
{
//node has responded with OTA_DATA or OTA_Complete or OTA_ABORT
if ( err = = ESP_OK )
{
if ( bAbort = = false )
{
//no error while ota write --> send OTA_ACK packet
sMeshPacket . type = OTA_ACK ;
err = errSendMeshPacket ( pMeshNodeAddr , & sMeshPacket ) ;
}
}
else
{
// error while read --> send OTA_ABORT and abort this OTA process
sMeshPacket . type = OTA_Abort ;
bAbort = true ;
errSendMeshPacket ( pMeshNodeAddr , & sMeshPacket ) ;
}
}
} //end of partition segement loop
if ( bComplete = = true )
{
//all OTA segments received --> validate
ERROR_CHECK ( esp_ota_end ( otaHandle ) ) ;
ERROR_CHECK ( esp_ota_set_boot_partition ( pOTAPartition ) ) ;
if ( err = = ESP_OK )
{
//successfully updated OTA partition
* pbNewOTAImage = true ;
}
}
else
{
//not all OTA segments received --> abort this OTA process
ERROR_CHECK ( esp_ota_abort ( otaHandle ) ) ;
}
return err ;
}
*/