Browse Source

completet https ota

feature/blockingOTA
Hendrik Schutter 1 year ago
parent
commit
a0546aa3ef
  1. 58
      components/mesh_ota/HTTPS_client.c
  2. 132
      components/mesh_ota/Mesh_OTA.c
  3. 6
      components/mesh_ota/include/HTTPS_client.h
  4. 1
      components/mesh_ota/include/Mesh_OTA.h

58
components/mesh_ota/HTTPS_client.c

@ -22,47 +22,10 @@ https_client_ret_t https_clientInitialize()
i32RetHTTPClient = https_clientInitEmbedTLS();
if(i32RetHTTPClient == HTTPS_CLIENT_OK)
if (i32RetHTTPClient == HTTPS_CLIENT_ERROR_INIT_EMBEDTLS)
{
i32RetHTTPClient = https_clientConnectToServer();
}
if(i32RetHTTPClient == HTTPS_CLIENT_OK)
{
i32RetHTTPClient = https_clientValidateServer();
}
if(i32RetHTTPClient == HTTPS_CLIENT_OK)
{
i32RetHTTPClient = https_clientSendRequest();
}
switch (i32RetHTTPClient)
{
case HTTPS_CLIENT_ERROR_INIT_EMBEDTLS:
ESP_LOGE(TAG, "Unable to initialize EmbedTLS");
i32RetHTTPClient = HTTPS_CLIENT_ERROR;
break;
case HTTPS_CLIENT_ERROR_INIT_CONNECT_TWO_SERVER:
ESP_LOGE(TAG, "Unable to connect to server");
i32RetHTTPClient = HTTPS_CLIENT_ERROR;
break;
case HTTPS_CLIENT_ERROR_INIT_VALIDATE_SERVER:
ESP_LOGE(TAG, "Unable to validate the server");
i32RetHTTPClient = HTTPS_CLIENT_ERROR;
break;
case HTTPS_CLIENT_ERROR_INIT_SEND_REQUEST:
ESP_LOGE(TAG, "Unable to send request to server");
i32RetHTTPClient = HTTPS_CLIENT_ERROR;
break;
case HTTPS_CLIENT_OK:
ESP_LOGI(TAG, "HTTPS Client successfully initialized");
i32RetHTTPClient = HTTPS_CLIENT_OK;
break;
default:
i32RetHTTPClient = HTTPS_CLIENT_ERROR;
ESP_LOGE(TAG, "Unknown error while init https client");
break;
}
return i32RetHTTPClient;
}
@ -78,6 +41,7 @@ https_client_ret_t https_clientRetrieveData(char* pu8Data, uint32_t* pu32DataLen
while (bRetriveData)
{
mbedtls_ssl_conf_read_timeout(&sHTTPS_ClientConfig.conf, HTTPS_READ_TIMEOUT); //set timeout
//Reading HTTP response
i32RetRetrieveData = mbedtls_ssl_read(&sHTTPS_ClientConfig.ssl, (unsigned char *)(pu8Data+(*pu32BytesRead)), ((*pu32DataLenght)-(*pu32BytesRead)));
@ -105,13 +69,18 @@ https_client_ret_t https_clientRetrieveData(char* pu8Data, uint32_t* pu32DataLen
pu32BytesRead = 0;
}
if(i32RetRetrieveData == MBEDTLS_ERR_SSL_TIMEOUT )
{
//timeout --> stop reading
bRetriveData = false;
}
if(i32RetRetrieveData == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY)
{
//connection is going to be closed
i32RetHTTPClient = HTTPS_CLIENT_ERROR;
bRetriveData = false;
}
}
return i32RetHTTPClient;
}
@ -120,15 +89,6 @@ https_client_ret_t https_clientReset()
{
https_client_ret_t i32RetHTTPClient = HTTPS_CLIENT_OK;
i32RetHTTPClient = https_clientSendRequest();
return i32RetHTTPClient;
}
https_client_ret_t https_clientDeinitialize()
{
https_client_ret_t i32RetHTTPClient = HTTPS_CLIENT_OK;
i32RetHTTPClient = mbedtls_ssl_close_notify(&sHTTPS_ClientConfig.ssl); //close session
if(i32RetHTTPClient != ESP_OK)
@ -250,7 +210,7 @@ https_client_ret_t https_clientConnectToServer()
if(i32RetServerConnect == ESP_OK)
{
mbedtls_ssl_set_bio(&sHTTPS_ClientConfig.ssl, &sHTTPS_ClientConfig.server_fd, mbedtls_net_send, mbedtls_net_recv, NULL);
mbedtls_ssl_set_bio(&sHTTPS_ClientConfig.ssl, &sHTTPS_ClientConfig.server_fd, mbedtls_net_send, mbedtls_net_recv, mbedtls_net_recv_timeout);
//Performing the SSL/TLS handshake
while ((i32RetServerConnect = mbedtls_ssl_handshake(&sHTTPS_ClientConfig.ssl)) != 0)

132
components/mesh_ota/Mesh_OTA.c

@ -8,6 +8,8 @@ xQueueHandle queueMessageOTA; //mesh ota controll messages like "OTA_Version_Res
SemaphoreHandle_t bsStartStopServerWorker; //binary semaphore
const esp_partition_t* pOTAPartition; //pointer to ota partition
esp_err_t errMeshOTAInitialize()
{
esp_err_t err = ESP_OK;
@ -46,6 +48,17 @@ esp_err_t errMeshOTAInitialize()
ERROR_CHECK(errMeshNetworkSetOTAMessageHandleHandle(vAddOTAControllMessageToQueue));
ERROR_CHECK(errMeshNetworkSetChangeStateOfServerWorkerHandle(vChangeStateOfServerWorker));
if(err == ESP_OK)
{
pOTAPartition = esp_ota_get_next_update_partition(NULL); //get ota partition
if(pOTAPartition == NULL)
{
err = ESP_FAIL;
ESP_LOGE(LOG_TAG, "unable to get next ota partition");
}
}
if(err == ESP_OK)
{
xReturned = xTaskCreate(vTaskServerWorker, "vTaskServerWorker", 8192, NULL, 5, NULL);
@ -130,7 +143,7 @@ void vTaskServerWorker(void *arg)
{
esp_err_t err;
bool bNewOTAImage = false; // true if a new ota image was downloaded and validated
// bool bFirstRun = true;
bool bFirstRun = true;
while(true)
{
@ -140,16 +153,18 @@ void vTaskServerWorker(void *arg)
if (esp_mesh_is_root()) //check again that this node is the root node
{
// if(bFirstRun == true)
// {
if(bFirstRun == true)
{
ERROR_CHECK(https_clientInitialize());
// bFirstRun = false;
//}
bFirstRun = false;
}
ERROR_CHECK(errOTAHTTPS(&bNewOTAImage));
https_clientDeinitialize();
ERROR_CHECK(https_clientConnectToServer());
ERROR_CHECK(https_clientValidateServer());
ERROR_CHECK(https_clientSendRequest());
// https_clientReset();
ERROR_CHECK(errOTAHTTPS(&bNewOTAImage));
https_clientReset();
if(bNewOTAImage == true)
{
@ -167,85 +182,58 @@ void vTaskServerWorker(void *arg)
esp_err_t errOTAHTTPS(bool* pbNewOTAImage)
{
esp_err_t err = ESP_OK;
char buffer[1024U];
uint32_t u32BufferLenght = 1024U;
uint32_t u32BytesRead = 0;
char pcRemoteVersionNumber[12];
const esp_partition_t * currentPartition;
const esp_partition_t * otaPartition;
static esp_ota_handle_t otaHandle;
uint32_t u32StartOffset;
//esp_app_desc_t otaPartitionDesc;
esp_app_desc_t curPartitionDesc;
currentPartition = esp_ota_get_boot_partition();
ESP_LOGI(LOG_TAG, "Type: %d", (*currentPartition).subtype);
ESP_LOGI(LOG_TAG, "Start address: %d", (*currentPartition).address);
ESP_LOGI(LOG_TAG, "Size: %d", (*currentPartition).size);
ESP_LOGI(LOG_TAG, "Encrypted: %d", (*currentPartition).encrypted);
char u8OTABuffer[OTA_HTTPS_SEGMENT_SIZE]; //store image segment from server before ota write
uint32_t u32BufferLenght = OTA_HTTPS_SEGMENT_SIZE; //size of buffer
uint32_t u32BytesRead = 0; //number of bytes that are read from server, <= u32BufferLenght
char pcRemoteVersionNumber[12]; //string for version number in server image
const esp_partition_t* pBootPartition; //pointer to boot partition (that will booted after reset)
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
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(esp_ota_get_partition_description(currentPartition, &curPartitionDesc));
//ESP_LOGI(LOG_TAG, "currentPartition project_name: %s", (curPartitionDesc).project_name);
//ESP_LOGI(LOG_TAG, "currentPartition version: %s", (curPartitionDesc).version);
//ESP_LOGI(LOG_TAG, "currentPartition Timestamp: %s %s", (curPartitionDesc).date, (curPartitionDesc).time);
ERROR_CHECK(https_clientRetrieveData(u8OTABuffer, &u32BufferLenght, &u32BytesRead)); //read first bytes if image, including the version
ERROR_CHECK(errExtractVersionNumber(u8OTABuffer, &u32BytesRead, pcRemoteVersionNumber)); //extract version numbers
ERROR_CHECK(https_clientRetrieveData(buffer, &u32BufferLenght, &u32BytesRead)); //read first bytes if image, including the version
//ESP_LOGI(LOG_TAG, "Data received: %i", u32BytesRead);
ERROR_CHECK(errExtractVersionNumber(buffer, &u32BytesRead, pcRemoteVersionNumber));
if(err == ESP_OK)
if(err == ESP_OK) //check if version number is found
{
if(bNewerVersion((curPartitionDesc).version, pcRemoteVersionNumber)) //compare local and remote version
if(bNewerVersion((bootPartitionDesc).version, pcRemoteVersionNumber)) //compare local and remote version
{
// server image is newer --> OTA update required
ESP_LOGI(LOG_TAG, "server image is newer --> OTA update required");
otaPartition = esp_ota_get_next_update_partition(currentPartition);
if(otaPartition == NULL)
{
err = ESP_FAIL;
ESP_LOGE(LOG_TAG, "unable to get next ota partition");
}
ERROR_CHECK(errFindImageStart(buffer, &u32BufferLenght, &u32StartOffset)); //get image start offset
//ESP_LOGI(LOG_TAG, "first byte offset: %i", u32StartOffset);
//ESP_LOGI(LOG_TAG, "first byte: %x", buffer[u32StartOffset]);
ERROR_CHECK(errFindImageStart(u8OTABuffer, &u32BufferLenght, &u32StartOffset)); //get image start offset
//TODO lock ota mutex
ERROR_CHECK(esp_ota_begin(otaPartition, OTA_SIZE_UNKNOWN, &otaHandle));
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");
do
{
ESP_LOGI(LOG_TAG, "OTA-Data written: %i", u32BytesRead);
ERROR_CHECK(esp_ota_write(otaHandle, (const void*) buffer+u32StartOffset, (u32BytesRead-u32StartOffset)));
//TODO progress log
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
https_clientRetrieveData(buffer, &u32BufferLenght, &u32BytesRead); //download next data segment
ERROR_CHECK(https_clientRetrieveData(u8OTABuffer, &u32BufferLenght, &u32BytesRead)); //download next data segment
}
}
while ((u32BytesRead > 0) && (err == ESP_OK));
while ((u32BytesRead > 0) && (err == ESP_OK)); //loop until error or complete image downloaded
}
if(err == ESP_OK)
{
//no error occurred --> finish ota update process
ERROR_CHECK(esp_ota_end(otaHandle)); //finish process
ERROR_CHECK(esp_ota_set_boot_partition(otaPartition)); //set new image as boot
ERROR_CHECK(esp_ota_set_boot_partition(pOTAPartition)); //set new image as boot
if(err == ESP_OK)
{
*pbNewOTAImage = true; //image validated
@ -253,23 +241,17 @@ esp_err_t errOTAHTTPS(bool* pbNewOTAImage)
}
else
{
// error occurred --> abort ota update process
ESP_LOGE(LOG_TAG, "abort ota process");
//error occurred --> abort ota update process
ESP_LOGE(LOG_TAG, "abort ota process due to error 0x%x -> %s", err, esp_err_to_name(err));
ERROR_CHECK(esp_ota_abort(otaHandle));
*pbNewOTAImage = false; //ota update failed
}
//TODO unlock ota mutex
} //end newer version on server
} //end version number extracted
return err;
}
/*
* Return true if remote version is newer (higher) than local version
*/
@ -403,9 +385,9 @@ esp_err_t esp_mesh_ota_send(mesh_addr_t* dest)
static uint32_t u32index;
const esp_partition_t * currentPartition = esp_ota_get_boot_partition();
const esp_partition_t * pBootPartition = esp_ota_get_boot_partition();
if((*currentPartition).subtype == 0)
if((*pBootPartition).subtype == 0)
{
int data_read = 0;
@ -422,7 +404,7 @@ esp_err_t esp_mesh_ota_send(mesh_addr_t* dest)
else
{
ESP_LOGI(MESH_TAG, "OTA-Data read: %i", u32index);
err = esp_partition_read(currentPartition, (1024*u32index), packet.au8Payload, 1024 );
err = esp_partition_read(pBootPartition, (1024*u32index), packet.au8Payload, 1024 );
ESP_ERROR_CHECK(err);
data_read = 1024;
u32index++;
@ -438,7 +420,7 @@ esp_err_t esp_mesh_ota_send(mesh_addr_t* dest)
}
else
{
ESP_LOGI(MESH_TAG, "Subtype: %d", (*currentPartition).subtype);
ESP_LOGI(MESH_TAG, "Subtype: %d", (*pBootPartition).subtype);
}
return err;
}
@ -449,14 +431,14 @@ esp_err_t esp_mesh_ota_receive(mesh_addr_t* dest, struct ota_mesh_packet* packet
static esp_ota_handle_t otaHandle;
static uint32_t u32index;
const esp_partition_t * currentPartition = esp_ota_get_boot_partition();
const esp_partition_t * otaPartition = esp_ota_get_next_update_partition(currentPartition);
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(otaPartition, OTA_SIZE_UNKNOWN, &otaHandle);
err = esp_ota_begin(pOTAPartition, OTA_SIZE_UNKNOWN, &otaHandle);
ESP_ERROR_CHECK(err);
}
@ -480,11 +462,11 @@ esp_err_t esp_mesh_ota_receive(mesh_addr_t* dest, struct ota_mesh_packet* packet
err = esp_ota_end(otaHandle);
ESP_ERROR_CHECK(err);
esp_app_desc_t otaPartitionDesc;
err = esp_ota_get_partition_description(otaPartition, &otaPartitionDesc);
err = esp_ota_get_partition_description(pOTAPartition, &otaPartitionDesc);
ESP_ERROR_CHECK(err);
ESP_LOGI(MESH_TAG, "otaPartition project_name: %s", (otaPartitionDesc).project_name);
ESP_LOGI(MESH_TAG, "pOTAPartition project_name: %s", (otaPartitionDesc).project_name);
err = esp_ota_set_boot_partition(otaPartition);
err = esp_ota_set_boot_partition(pOTAPartition);
ESP_ERROR_CHECK(err);
struct ota_mesh_packet retPacket;

6
components/mesh_ota/include/HTTPS_client.h

@ -51,6 +51,8 @@
#define HTTPS_CLIENT_ERROR_INIT_VALIDATE_SERVER -4
#define HTTPS_CLIENT_ERROR_INIT_SEND_REQUEST -5
#define HTTPS_READ_TIMEOUT 1000 //ms
struct HTTPS_Client
{
mbedtls_entropy_context entropy;
@ -65,9 +67,11 @@ typedef int32_t https_client_ret_t;
typedef struct HTTPS_Client HTTPS_Client_t;
https_client_ret_t https_clientInitialize();
https_client_ret_t https_clientConnectToServer();
https_client_ret_t https_clientValidateServer();
https_client_ret_t https_clientSendRequest();
https_client_ret_t https_clientRetrieveData(char* pu8Data, uint32_t* pu32DataLenght, uint32_t* pu32BytesRead);
https_client_ret_t https_clientReset();
https_client_ret_t https_clientDeinitialize();
#endif /* H_HTTPS_CLIENT */

1
components/mesh_ota/include/Mesh_OTA.h

@ -20,6 +20,7 @@
#define QUEUE_NODES_SIZE 10
#define QUEUE_MESSAGE_OTA_SIZE 10
#define SERVER_CHECK_INTERVAL 30 //in seconds
#define OTA_HTTPS_SEGMENT_SIZE 2048U
#define ERROR_CHECK(x) if (err == ESP_OK) \
{ \

Loading…
Cancel
Save

Du besuchst diese Seite mit einem veralteten IPv4-Internetzugang. Möglicherweise treten in Zukunft Probleme mit der Erreichbarkeit und Performance auf. Bitte frage deinen Internetanbieter oder Netzwerkadministrator nach IPv6-Unterstützung.
You are visiting this site with an outdated IPv4 internet access. You may experience problems with accessibility and performance in the future. Please ask your ISP or network administrator for IPv6 support.
Weitere Infos | More Information
Klicke zum schließen | Click to close