diff --git a/.gitignore b/.gitignore index 19e3a2a..e73ccd5 100644 --- a/.gitignore +++ b/.gitignore @@ -60,3 +60,4 @@ test/build/ *.orig +Doxygen/html/ diff --git a/README.md b/README.md index 1b9f76c..8d93590 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,4 @@ # ESP32-Mesh-OTA -## Work in progress -code_example_output - -## Todo for first release - -### Refactoring -- architecture -- full error handling through all functions -- export as a component library - -### Features -- root node: Download new Firmware from HTTPS server instead using newest ota partition -- add example main app - - diff --git a/components/mesh_ota/Mesh_OTA.c b/components/mesh_ota/Mesh_OTA.c index bf1388b..699f5d9 100644 --- a/components/mesh_ota/Mesh_OTA.c +++ b/components/mesh_ota/Mesh_OTA.c @@ -114,7 +114,6 @@ esp_err_t errMeshOTAInitialize(void) err = ESP_FAIL; } } - return err; } @@ -162,7 +161,6 @@ void vMeshOtaTaskServerWorker(void *arg) //set want reboot ESP_LOGI(LOG_TAG, "Updated successfully via HTTPS, set pending reboot"); bWantReboot = true; - vMeshOtaUtilAddAllNeighboursToQueue(); //add all existing neighbours to queue (aparent will not be added because this node is the root) } vTaskDelay( (SERVER_CHECK_INTERVAL*1000) / portTICK_PERIOD_MS); //sleep till next server checks } @@ -182,6 +180,7 @@ void vMeshOtaTaskOTAWorker(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 + BaseType_t xReturned; while(true) { @@ -190,25 +189,30 @@ void vMeshOtaTaskOTAWorker(void *arg) if((uxQueueSpacesAvailable(queueNodes) - QUEUE_NODES_SIZE) == 0) { - //nodes queue is empty - if((bWantReboot == true) && (OTA_ALLOW_REBOOT == 1)) + ESP_LOGI(LOG_TAG, "//nodes queue is empty"); + + xReturned = xSemaphoreTake(bsOTAProcess, portMAX_DELAY); //wait for binary semaphore that allows to start the OTA process + if((xReturned == pdTRUE) && (bWantReboot == true) && (OTA_ALLOW_REBOOT == 1)) { ESP_LOGE(LOG_TAG, "ESP32 Reboot ..."); vTaskDelay( (1000) / portTICK_PERIOD_MS); esp_restart(); } + xSemaphoreGive(bsOTAProcess); //free binary semaphore, this allows other tasks to start the OTA process ERROR_CHECK(errMeshOtaSlaveEndpoint(&bNewOTAImage)); } else { - //queue not empty + ESP_LOGI(LOG_TAG, "//queue not empty %i", (uxQueueSpacesAvailable(queueNodes) - QUEUE_NODES_SIZE)); if (xQueueReceive(queueNodes, &meshNodeAddr, ((100) / portTICK_PERIOD_MS)) != pdTRUE) { ESP_LOGE(LOG_TAG, "Unable to receive OTA Messages from Queue"); err = ESP_FAIL; } + ESP_LOGI(LOG_TAG, "//handle node %x", meshNodeAddr.addr[5]); + ERROR_CHECK(errMeshOtaMasterEndpoint(&bNewOTAImage, &meshNodeAddr)); if (err != ESP_OK) @@ -275,7 +279,7 @@ esp_err_t errMeshOtaSlaveEndpoint(bool* const cpbNewOTAImage) if((bMeshOtaUtilNewerVersion((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"); + ESP_LOGI(LOG_TAG, "remote image on node is newer --> OTA update required from node \"%x:%x:%x:%x:%x:%x\"", sOTAMessage.meshSenderAddr.addr[0], sOTAMessage.meshSenderAddr.addr[1], sOTAMessage.meshSenderAddr.addr[2], sOTAMessage.meshSenderAddr.addr[3], sOTAMessage.meshSenderAddr.addr[4], sOTAMessage.meshSenderAddr.addr[5]); // --> this version older --> start OTA_Rx --> set cpbNewOTAImage true ERROR_CHECK(errMeshOtaPartitionAccessMeshReceive(cpbNewOTAImage, &sOTAMessage.meshSenderAddr)); } @@ -283,7 +287,7 @@ esp_err_t errMeshOtaSlaveEndpoint(bool* const cpbNewOTAImage) if((bMeshOtaUtilNewerVersion((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"); + ESP_LOGI(LOG_TAG, "remote image on node is older --> OTA send required to node \"%x:%x:%x:%x:%x:%x\"", sOTAMessage.meshSenderAddr.addr[0], sOTAMessage.meshSenderAddr.addr[1], sOTAMessage.meshSenderAddr.addr[2], sOTAMessage.meshSenderAddr.addr[3], sOTAMessage.meshSenderAddr.addr[4], sOTAMessage.meshSenderAddr.addr[5]); // --> this version newer --> start OTA_Tx ERROR_CHECK(errMeshOtaPartitionAccessMeshTransmit(&sOTAMessage.meshSenderAddr)); } @@ -343,7 +347,7 @@ esp_err_t errMeshOtaMasterEndpoint(bool* const cpbNewOTAImage, const mesh_addr_t if((bMeshOtaUtilNewerVersion((bootPartitionDesc).version, (char*) sOTAMessage.au8Payload)) && (err == ESP_OK)) //compare local and remote version { //remote newer as local - ESP_LOGI(LOG_TAG, "Mesh: remote image on node is newer --> OTA update required"); + ESP_LOGI(LOG_TAG, "remote image on node is newer --> OTA update required from node \"%x:%x:%x:%x:%x:%x\"", sOTAMessage.meshSenderAddr.addr[0], sOTAMessage.meshSenderAddr.addr[1], sOTAMessage.meshSenderAddr.addr[2], sOTAMessage.meshSenderAddr.addr[3], sOTAMessage.meshSenderAddr.addr[4], sOTAMessage.meshSenderAddr.addr[5]); // --> this version older --> start OTA_Rx --> set cpbNewOTAImage true ERROR_CHECK(errMeshOtaPartitionAccessMeshReceive(cpbNewOTAImage, &sOTAMessage.meshSenderAddr)); } @@ -351,7 +355,7 @@ esp_err_t errMeshOtaMasterEndpoint(bool* const cpbNewOTAImage, const mesh_addr_t if((bMeshOtaUtilNewerVersion((char*) sOTAMessage.au8Payload, (bootPartitionDesc).version)) && (err == ESP_OK)) //compare remote and local version { //local newer as remote - ESP_LOGI(LOG_TAG, "Mesh: remote image on node is older --> OTA send required"); + ESP_LOGI(LOG_TAG, "remote image on node is older --> OTA send required to node \"%x:%x:%x:%x:%x:%x\"", sOTAMessage.meshSenderAddr.addr[0], sOTAMessage.meshSenderAddr.addr[1], sOTAMessage.meshSenderAddr.addr[2], sOTAMessage.meshSenderAddr.addr[3], sOTAMessage.meshSenderAddr.addr[4], sOTAMessage.meshSenderAddr.addr[5]); // --> this version newer --> start OTA_Tx ERROR_CHECK(errMeshOtaPartitionAccessMeshTransmit(&sOTAMessage.meshSenderAddr)); } diff --git a/components/mesh_ota/Mesh_OTA_Partition_Access.c b/components/mesh_ota/Mesh_OTA_Partition_Access.c index a545b11..8a6e63f 100644 --- a/components/mesh_ota/Mesh_OTA_Partition_Access.c +++ b/components/mesh_ota/Mesh_OTA_Partition_Access.c @@ -89,6 +89,7 @@ esp_err_t errMeshOtaPartitionAccessHttps(bool* const cpbNewOTAImage) if(err == ESP_OK) { *cpbNewOTAImage = true; //image validated + vMeshOtaUtilAddAllNeighboursToQueue(); //add all existing neighbours to queue (aparent will not be added because this node is the root) } } else diff --git a/components/mesh_ota/Mesh_OTA_Util.c b/components/mesh_ota/Mesh_OTA_Util.c index c6ec2db..712329f 100644 --- a/components/mesh_ota/Mesh_OTA_Util.c +++ b/components/mesh_ota/Mesh_OTA_Util.c @@ -328,17 +328,24 @@ void vMeshOtaUtilClearOtaMessageQueue(const mesh_addr_t* const cpcMeshNodeAddr) void vMeshOtaUtilClearNeighboursQueue(const mesh_addr_t* const cpcMeshNodeAddr) { mesh_addr_t sNode; //packet for sending and receiving - for (uint32_t u32Index = 0; (u32Index < QUEUE_MESSAGE_OTA_SIZE); u32Index++) //loop through all OTA messages + for (uint32_t u32Index = 0; (u32Index < QUEUE_NODES_SIZE); u32Index++) //loop through all node queue { if (xQueueReceive(queueNodes, &sNode, 0) == pdTRUE) { - if(!(bMeshNetworkCheckMacEquality(sNode.addr, cpcMeshNodeAddr->addr))) + if((bMeshNetworkCheckMacEquality(sNode.addr, cpcMeshNodeAddr->addr))) { - //node is NOT cpcMeshNodeAddr --> keep it in queue - vMeshOtaUtilAddNodeToPossibleUpdatableQueue(cpcMeshNodeAddr->addr); + ESP_LOGI(LOG_TAG, "REMOVE_NODE: remove node %x", sNode.addr[5]); } + else + { + ESP_LOGI(LOG_TAG, "//node is NOT cpcMeshNodeAddr: %i --> keep it in queue", sNode.addr[5]); + vMeshOtaUtilAddNodeToPossibleUpdatableQueue(sNode.addr); + } + + }else{ + ESP_LOGI(LOG_TAG, "REMOVE_NODE: queue leer"); } - }//end OTA message loop + }//end nodes } /** @@ -361,7 +368,7 @@ void vMeshOtaUtilAddNodeToPossibleUpdatableQueue(const uint8_t* const cpcu8MAC) } else { - ESP_LOGD(LOG_TAG, "added node \"%x:%x:%x:%x:%x:%x\" to possible updatable queue", addrNode.addr[0], addrNode.addr[1], addrNode.addr[2], addrNode.addr[3], addrNode.addr[4], addrNode.addr[5]); + ESP_LOGI(LOG_TAG, "added node \"%x:%x:%x:%x:%x:%x\" to possible updatable queue", addrNode.addr[0], addrNode.addr[1], addrNode.addr[2], addrNode.addr[3], addrNode.addr[4], addrNode.addr[5]); } } diff --git a/components/mesh_ota/include/Mesh_OTA.h b/components/mesh_ota/include/Mesh_OTA.h index c6d7c4d..d28421f 100644 --- a/components/mesh_ota/include/Mesh_OTA.h +++ b/components/mesh_ota/include/Mesh_OTA.h @@ -18,14 +18,14 @@ #include "HTTPS_Client.h" #define ERASE_NVS //erase non volatile storage if full -#define QUEUE_NODES_SIZE 10 -#define QUEUE_MESSAGE_OTA_SIZE 10 +#define QUEUE_NODES_SIZE 20 +#define QUEUE_MESSAGE_OTA_SIZE 20 #define SERVER_CHECK_INTERVAL 30 //in seconds #define OTA_HTTPS_SEGMENT_SIZE 2048U #define OTA_PROGRESS_LOG_INTERVAL 7U #define OTA_MESH_SEGMENT_SIZE MESH_NETWORK_PAYLOAD_SIZE #define OTA_MESH_TIMEOUT 20000U //in ms -#define OTA_ALLOW_REBOOT 0 +#define OTA_ALLOW_REBOOT 1 #define ERROR_CHECK(x) if (err == ESP_OK) \ { \ diff --git a/components/mesh_ota/test/test_mesh_ota.c b/components/mesh_ota/test/test_mesh_ota.c index ff8a866..d14d66f 100644 --- a/components/mesh_ota/test/test_mesh_ota.c +++ b/components/mesh_ota/test/test_mesh_ota.c @@ -1,7 +1,7 @@ #include #include "unity.h" -#include "Mesh_OTA.h" +#include "Mesh_OTA_Util.h" #include "test_image_hex.h" // ### ### ### distinguish newer image version ### ### ### diff --git a/main/Blinky_LED.c b/main/Blinky_LED.c index 56160c3..d3e5102 100644 --- a/main/Blinky_LED.c +++ b/main/Blinky_LED.c @@ -61,6 +61,11 @@ esp_err_t errBlinkyLEDInitialize(void) err = ESP_FAIL; } } + +#ifdef NEW_VERSION + gpio_set_level(GPIO_LED_GREEN, 1); //switch on +#endif + return err; } @@ -79,8 +84,13 @@ void vGPIOInitialize(void) gpio_config_t gpioConf; //LED as Output - gpio_reset_pin(GPIO_LED); - gpio_set_direction(GPIO_LED, GPIO_MODE_OUTPUT); + gpio_reset_pin(GPIO_LED_BLUE); + gpio_set_direction(GPIO_LED_BLUE, GPIO_MODE_OUTPUT); + +#ifdef NEW_VERSION + gpio_reset_pin(GPIO_LED_GREEN); + gpio_set_direction(GPIO_LED_GREEN, GPIO_MODE_OUTPUT); +#endif //BTN as Input gpioConf.intr_type = GPIO_INTR_DISABLE; @@ -212,19 +222,19 @@ void vTaskReceiveData(void *arg) { case LED_ON: bLEDisOn = true; - gpio_set_level(GPIO_LED, 1); //switch on + gpio_set_level(GPIO_LED_BLUE, 1); //switch on ESP_LOGI(LOG_TAG,"switch LED ON"); break; case LED_OFF: bLEDisOn = false; - gpio_set_level(GPIO_LED, 0); //switch off + gpio_set_level(GPIO_LED_BLUE, 0); //switch off ESP_LOGI(LOG_TAG,"switch LED OFF"); break; default: bLEDisOn = false; - gpio_set_level(GPIO_LED, 0); //switch off + gpio_set_level(GPIO_LED_BLUE, 0); //switch off ESP_LOGI(LOG_TAG,"switch LED OFF"); break; } diff --git a/main/Blinky_LED.h b/main/Blinky_LED.h index c25cf04..909d5d4 100644 --- a/main/Blinky_LED.h +++ b/main/Blinky_LED.h @@ -20,9 +20,13 @@ #include "Mesh_OTA.h" +//#define NEW_VERSION #define GPIO_BOOT_BTN 0 //GPIO0 (Boot BTN) -#define GPIO_LED 2 //GPIO2 (internal blue LED in DevKit V1.0) +#define GPIO_LED_BLUE 2 //GPIO2 (internal blue LED in DevKit V1.0) +#ifdef NEW_VERSION +#define GPIO_LED_GREEN 13 //GPIO13 +#endif #define GPIO_INPUT_PIN_SEL (1ULL<