@ -67,7 +67,7 @@ esp_err_t errMeshOTAInitialize()
}
ERROR_CHECK ( errMeshNetworkSetChildConnectedHandle ( vAddNodeToPossibleUpdatableQueue ) ) ;
ERROR_CHECK ( errMeshNetworkSetOTAMessageHandleHandle ( vAddOTAControll MessageToQueue ) ) ;
ERROR_CHECK ( errMeshNetworkSetOTAMessageHandleHandle ( vAddOta MessageToQueue ) ) ;
ERROR_CHECK ( errMeshNetworkSetChangeStateOfServerWorkerHandle ( vChangeStateOfServerWorker ) ) ;
if ( err = = ESP_OK )
@ -121,7 +121,7 @@ void vAddNodeToPossibleUpdatableQueue(uint8_t* pu8MAC)
}
}
void vAddOTAControll MessageToQueue ( MESH_PACKET_t * puMeshPacket )
void vAddOta MessageToQueue ( MESH_PACKET_t * puMeshPacket )
{
//send ota packet to packet queue
if ( xQueueSend ( queueMessageOTA , puMeshPacket , portMAX_DELAY ) ! = pdPASS )
@ -130,7 +130,21 @@ void vAddOTAControllMessageToQueue(MESH_PACKET_t* puMeshPacket)
}
else
{
ESP_LOGI ( LOG_TAG , " added ota message to queue: %i (type) " , puMeshPacket - > type ) ;
switch ( puMeshPacket - > type )
{
case OTA_Abort :
ESP_LOGI ( LOG_TAG , " added ota message to queue: OTA_Abort from 0x%x " , puMeshPacket - > meshSenderAddr . addr [ 5 ] ) ;
break ;
case OTA_Version_Request :
ESP_LOGI ( LOG_TAG , " added ota message to queue: OTA_Version_Request from 0x%x " , puMeshPacket - > meshSenderAddr . addr [ 5 ] ) ;
break ;
case OTA_Version_Response :
ESP_LOGI ( LOG_TAG , " added ota message to queue: OTA_Version Response from 0x%x " , puMeshPacket - > meshSenderAddr . addr [ 5 ] ) ;
break ;
default :
break ;
}
}
}
@ -220,7 +234,7 @@ void vTaskOTAWorker(void *arg)
if ( bWantReboot = = true )
{
ESP_LOGI( LOG_TAG, " ESP32 Reboot ..." ) ;
// ESP_LOGI( LOG_TAG, " ESP32 Reboot ...");
//vTaskDelay( (1000) / portTICK_PERIOD_MS);
//esp_restart();
}
@ -402,6 +416,7 @@ esp_err_t errOTAMeshMaster(bool* pbNewOTAImage, mesh_addr_t* pMeshNodeAddr)
bNodeIsConnected = true ; //node is one of the neighbours
xSemaphoreTake ( bsOTAProcess , portMAX_DELAY ) ; //wait for binary semaphore that allows to start the OTA process
ESP_LOGI ( LOG_TAG , " Mesh-Master: send Version_Request to 0x%x " , pMeshNodeAddr - > addr [ 5 ] ) ;
ERROR_CHECK ( errSendOTAVersionRequest ( pMeshNodeAddr ) ) ; //send OTA_VERSION_REQUEST with local version in payload
for ( uint32_t u32Index = 0 ; u32Index < QUEUE_MESSAGE_OTA_SIZE ; u32Index + + ) //loop through all OTA messages
@ -440,12 +455,13 @@ esp_err_t errOTAMeshMaster(bool* pbNewOTAImage, mesh_addr_t* pMeshNodeAddr)
else if ( err = = ESP_OK )
{
//received from wrong node or type --> back to queue
vAddOTAControll MessageToQueue ( & sOTAMessage ) ;
vAddOta MessageToQueue ( & sOTAMessage ) ;
}
}
else
{
// OTA Message queue is empty --> wait some time
ESP_LOGI ( LOG_TAG , " OTA-Master: OTA Message queue is empty --> wait some time " ) ;
vTaskDelay ( ( 1000 / QUEUE_MESSAGE_OTA_SIZE ) / portTICK_PERIOD_MS ) ;
}
} //end loop
@ -455,6 +471,7 @@ esp_err_t errOTAMeshMaster(bool* pbNewOTAImage, mesh_addr_t* pMeshNodeAddr)
if ( ( bNodeIsResponding = = false ) & & ( bNodeIsConnected = = true ) )
{
//add node back to queue if connected and NOT responding
ESP_LOGI ( LOG_TAG , " OTA-Master: connected and NOT responding --> add node back to queue " ) ;
vAddNodeToPossibleUpdatableQueue ( pMeshNodeAddr - > addr ) ;
}
return err ;
@ -657,10 +674,33 @@ esp_err_t errSendOTAVersionResponse(mesh_addr_t* pMeshReceiverAddr)
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
ESP_LOGI ( LOG_TAG , " Send OTA_Version_Response to 0x%x " , pMeshReceiverAddr - > addr [ 5 ] ) ;
err = errSendMeshPacket ( pMeshReceiverAddr , & packet ) ;
return err ;
}
void vClearOtaMessageQueue ( mesh_addr_t * pMeshNodeAddr )
{
MESH_PACKET_t sMeshPacket ; //packet for sending and receiving
for ( uint32_t u32Index = 0 ; ( u32Index < QUEUE_MESSAGE_OTA_SIZE ) ; u32Index + + ) //loop through all OTA messages
{
if ( xQueueReceive ( queueMessageOTA , & sMeshPacket , 0 ) = = pdTRUE )
{
if ( ! ( bCheckMACEquality ( sMeshPacket . meshSenderAddr . addr , pMeshNodeAddr - > addr ) ) )
{
//received OTA message is NOT from pMeshNodeAddr --> keep it in queue
vAddOtaMessageToQueue ( & sMeshPacket ) ;
}
else
{
ESP_LOGI ( LOG_TAG , " Removed type %i from node 0x%x " , sMeshPacket . type , pMeshNodeAddr - > addr [ 5 ] ) ;
}
}
} //end OTA message loop
}
esp_err_t errSendOTAVersionRequest ( mesh_addr_t * pMeshReceiverAddr )
{
esp_err_t err = ESP_OK ;
@ -682,21 +722,22 @@ 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
// 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 ;
uint32_t u32SegmentCounter = 0U ;
pBootPartition = esp_ota_get_boot_partition ( ) ; //get boot partition (that will booted after reset), not the running 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 ) )
while ( ( ( OTA_MESH_SEGMENT_SIZE * u32SegmentCounter ) < pBootPartition - > size ) & & ( err = = ESP_OK ) & & ( bAbort = = false ) )
{
bNodeIsResponding = false ; //reset to default
// 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 ) ;
ERROR_CHECK ( esp_partition_read ( pBootPartition , ( OTA_MESH_SEGMENT_SIZE * u32SegmentCounter ) , sMeshPacket . au8Payload , OTA_MESH_SEGMENT_SIZE ) ) ;
u32OTABytesWritten = ( ( u32SegmentCounter + 1 ) * OTA_MESH_SEGMENT_SIZE ) ;
vPrintOTAProgress ( & ( pBootPartition - > size ) , & u32OTABytesWritten , Transmitter ) ;
if ( err = = ESP_OK )
@ -704,12 +745,13 @@ esp_err_t errOTAMeshTransmit(mesh_addr_t* pMeshNodeAddr)
//no error while read --> send OTA_DATA packet
sMeshPacket . type = OTA_Data ;
if ( ( OTA_MESH_SEGMENT_SIZE * ( u32Index + 1 ) ) > = pBootPartition - > size ) //check if last segment
if ( ( OTA_MESH_SEGMENT_SIZE * ( u32SegmentCounter + 1 ) ) > = pBootPartition - > size ) //check if last segment
{
//last partition image segment --> send OTA_Complete
ESP_LOGI ( LOG_TAG , " OTA-TX: last segment--> send Complete " ) ;
sMeshPacket . type = OTA_Complete ;
}
//ESP_LOGI(LOG_TAG, "OTA-TX: send packet");
err = errSendMeshPacket ( pMeshNodeAddr , & sMeshPacket ) ;
}
else
@ -717,61 +759,69 @@ esp_err_t errOTAMeshTransmit(mesh_addr_t* pMeshNodeAddr)
// error while read --> send OTA_ABORT and abort this OTA process
sMeshPacket . type = OTA_Abort ;
bAbort = true ;
ESP_LOGI ( LOG_TAG , " OTA-TX: error while read --> send ABORT " ) ;
errSendMeshPacket ( pMeshNodeAddr , & sMeshPacket ) ;
}
// 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)
// if( uxQueueSpacesAvailable( queueMessageOTA) < QUEUE_MESSAGE_OTA_SIZE)
// {
//queue not empty
if ( xQueueReceive ( queueMessageOTA , & sMeshPacket , ( ( OTA_MESH_TIMEOUT ) / portTICK_PERIOD_MS ) ) ! = pdTRUE )
{
//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_LOGE ( LOG_TAG , " Unable to receive OTA Messages from queue " ) ;
err = ESP_FAIL ;
}
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
if ( ( err = = ESP_OK ) & & ( bCheckMACEquality ( sMeshPacket . meshSenderAddr . addr , pMeshNodeAddr - > addr ) ) ) //if OTA_Version_Request
{
// OTA Message queue is empty --> wait some time
vTaskDelay ( ( 1000 / QUEUE_MESSAGE_OTA_SIZE ) / portTICK_PERIOD_MS ) ;
//packet from node received
switch ( sMeshPacket . type )
{
case OTA_ACK : //increase index for next round
u32Index + + ;
bNodeIsResponding = true ;
u32Index = QUEUE_MESSAGE_OTA_SIZE ; //this will end the loop through all OTA messages
break ;
case OTA_Abort : //abort this OTA process
bAbort = true ;
bNodeIsResponding = true ;
break ;
default :
//receives wrong OTA message type from node --> back to queue
//vAddOtaMessageToQueue(&sMeshPacket);
break ;
}
}
else if ( err = = ESP_OK )
{
//received from wrong node --> back to queue
vAddOtaMessageToQueue ( & sMeshPacket ) ;
}
/*
}
else
{
// OTA Message queue is empty --> wait some time
ESP_LOGI(LOG_TAG, "OTA-TX: ota message queue empty --> wait");
vTaskDelay( (OTA_MESH_TIMEOUT) / portTICK_PERIOD_MS);
}
*/
} //end OTA message loop
if ( bNodeIsResponding = = false )
{
//no abort was called but node didn’ t responded
ESP_LOGE ( LOG_TAG , " OTA-TX: no abort was called but node didn’ t responded --> error " ) ;
bAbort = true ;
err = ESP_FAIL ; //this OTA process failed with error
}
u32SegmentCounter + + ;
} //end of partition segment loop
vClearOtaMessageQueue ( pMeshNodeAddr ) ;
return err ;
}
@ -785,6 +835,7 @@ esp_err_t errOTAMeshReceive(bool* pbNewOTAImage, mesh_addr_t* pMeshNodeAddr)
uint32_t u32OTABytesWritten = 0U ; //counter unsed for progress log
static esp_ota_handle_t otaHandle ; //OTA process handle
* pbNewOTAImage = false ;
uint32_t u32SegmentCounter = 0U ;
ERROR_CHECK ( esp_ota_begin ( pOTAPartition , OTA_SIZE_UNKNOWN , & otaHandle ) ) ; //start ota update process
@ -796,56 +847,64 @@ esp_err_t errOTAMeshReceive(bool* pbNewOTAImage, mesh_addr_t* pMeshNodeAddr)
// 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)
//if( uxQueueSpacesAvailable( queueMessageOTA) < QUEUE_MESSAGE_OTA_SIZE)
// {
//queue not empty
if ( xQueueReceive ( queueMessageOTA , & sMeshPacket , ( ( OTA_MESH_TIMEOUT ) / portTICK_PERIOD_MS ) ) ! = pdTRUE )
{
//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_LOGE ( LOG_TAG , " Unable to receive OTA Messages from queue " ) ;
err = ESP_FAIL ;
}
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
if ( ( err = = ESP_OK ) & & ( bCheckMACEquality ( sMeshPacket . meshSenderAddr . addr , pMeshNodeAddr - > addr ) ) ) //if OTA_Version_Request
{
// OTA Message queue is empty --> wait some time
vTaskDelay ( ( 1000 / QUEUE_MESSAGE_OTA_SIZE ) / portTICK_PERIOD_MS ) ;
//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 ;
ESP_LOGI ( LOG_TAG , " OTA-RX: rec Complete --> last segment " ) ;
//fall through
case OTA_Data : //data segement received
bNodeIsResponding = true ;
ERROR_CHECK ( esp_ota_write ( otaHandle , sMeshPacket . au8Payload , OTA_MESH_SEGMENT_SIZE ) ) ;
u32OTABytesWritten = ( ( u32SegmentCounter + 1 ) * OTA_MESH_SEGMENT_SIZE ) ;
vPrintOTAProgress ( & ( pOTAPartition - > size ) , & u32OTABytesWritten , Receiver ) ;
u32Index = QUEUE_MESSAGE_OTA_SIZE ; //this will end the loop through all OTA messages
break ;
case OTA_Abort : //abort this OTA process
bAbort = true ;
bNodeIsResponding = true ;
ESP_LOGI ( LOG_TAG , " OTA-RX: rec Abort " ) ;
//this will end the loop through all OTA messages
break ;
default :
//receives wrong OTA message type from node --> back to queue
//vAddOtaMessageToQueue(&sMeshPacket);
break ;
}
}
else if ( err = = ESP_OK )
{
//received from wrong node --> back to queue
vAddOtaMessageToQueue ( & sMeshPacket ) ;
}
/* }
else
{
ESP_LOGI(LOG_TAG, "OTA-RX: ota message queue empty --> wait");
// OTA Message queue is empty --> wait some time
vTaskDelay( (OTA_MESH_TIMEOUT) / portTICK_PERIOD_MS);
}
*/
} //end of OTA message loop
if ( bNodeIsResponding = = false )
{
//no abort was called but node didn’ t responded --> error
ESP_LOGI ( LOG_TAG , " OTA-RX: 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
}
@ -858,6 +917,7 @@ esp_err_t errOTAMeshReceive(bool* pbNewOTAImage, mesh_addr_t* pMeshNodeAddr)
if ( bAbort = = false )
{
//no error while ota write --> send OTA_ACK packet
//ESP_LOGI(LOG_TAG, "OTA-RX: no error while ota write --> send OTA_ACK packet");
sMeshPacket . type = OTA_ACK ;
err = errSendMeshPacket ( pMeshNodeAddr , & sMeshPacket ) ;
}
@ -867,14 +927,17 @@ esp_err_t errOTAMeshReceive(bool* pbNewOTAImage, mesh_addr_t* pMeshNodeAddr)
// error while read --> send OTA_ABORT and abort this OTA process
sMeshPacket . type = OTA_Abort ;
bAbort = true ;
ESP_LOGI ( LOG_TAG , " OTA-RX: abort --> send ABORT " ) ;
errSendMeshPacket ( pMeshNodeAddr , & sMeshPacket ) ;
}
}
u32SegmentCounter + + ;
} //end of partition segement loop
if ( bComplete = = true )
{
//all OTA segments received --> validate
ESP_LOGI ( LOG_TAG , " OTA-RX: validate image " ) ;
ERROR_CHECK ( esp_ota_end ( otaHandle ) ) ;
ERROR_CHECK ( esp_ota_set_boot_partition ( pOTAPartition ) ) ;
if ( err = = ESP_OK )
@ -888,5 +951,6 @@ esp_err_t errOTAMeshReceive(bool* pbNewOTAImage, mesh_addr_t* pMeshNodeAddr)
//not all OTA segments received --> abort this OTA process
ERROR_CHECK ( esp_ota_abort ( otaHandle ) ) ;
}
vClearOtaMessageQueue ( pMeshNodeAddr ) ;
return err ;
}