added rollback and fixed memory leaks
parent
6c74f93cf8
commit
5078f40e3c
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
void checkForUpdatesAndInstall(void *parameter);
|
||||
void checkIfOTAwasSuccessful(void *parameter);
|
||||
|
||||
extern bool updateAvailable;
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
#pragma once
|
||||
|
||||
void startOTAupdate();
|
||||
void startOTAupdate(bool forceUpdate);
|
||||
|
|
|
@ -11,22 +11,93 @@
|
|||
#include "esp_websocket_client.h"
|
||||
#include "esp_event.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <esp_log.h>
|
||||
#include <esp_system.h>
|
||||
|
||||
#include "mbedtls/base64.h"
|
||||
|
||||
#define CALC_BASE64_ENCODED_LENGTH(input_length) ((4 * ((input_length + 2) / 3)) + 1)
|
||||
|
||||
char cacheMessage[CONFIG_HTTP_SERVER_DEBUG_CACHE_LENGTH];
|
||||
char cacheMessageClone[CONFIG_HTTP_SERVER_DEBUG_CACHE_LENGTH];
|
||||
int cacheMessageIndex = 0;
|
||||
|
||||
SemaphoreHandle_t cacheMutex;
|
||||
|
||||
const char *TAG = "Console";
|
||||
const char *LOG_TAG = "[LOG]";
|
||||
|
||||
esp_websocket_client_handle_t client = NULL;
|
||||
|
||||
int skippedMessages = 0;
|
||||
|
||||
void sendOlderMessages()
|
||||
{
|
||||
if (esp_websocket_client_is_connected(client))
|
||||
{
|
||||
// printf("cacheMessageIndex:%i\n", cacheMessageIndex);
|
||||
|
||||
int newDataLength = 0;
|
||||
|
||||
// mutex lock
|
||||
if (xSemaphoreTake(cacheMutex, (TickType_t)10) == pdTRUE)
|
||||
{
|
||||
if (cacheMessageIndex > 0)
|
||||
{
|
||||
esp_websocket_client_send_text(client, cacheMessage, cacheMessageIndex, 1000 / portTICK_PERIOD_MS);
|
||||
// clone cacheMessage to cacheMessageClone
|
||||
memcpy(cacheMessageClone, cacheMessage, cacheMessageIndex);
|
||||
|
||||
newDataLength = cacheMessageIndex;
|
||||
|
||||
// clear cacheMessage
|
||||
cacheMessageIndex = 0;
|
||||
}
|
||||
|
||||
// mutex unlock
|
||||
xSemaphoreGive(cacheMutex);
|
||||
}
|
||||
|
||||
if (newDataLength > 0)
|
||||
{
|
||||
|
||||
cacheMessageClone[newDataLength - 1] = '\0';
|
||||
esp_websocket_client_send_text(client, cacheMessageClone, newDataLength, 1000 / portTICK_PERIOD_MS);
|
||||
newDataLength = 0;
|
||||
|
||||
/*// count \n in cacheMessage
|
||||
int count = 0;
|
||||
for (int i = 0; i < cacheMessageIndex; i++)
|
||||
{
|
||||
if (cacheMessage[i] == '\n')
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
printf("count:%i\n", count);
|
||||
|
||||
// split cacheMessage into multiple messages
|
||||
char *pch = strtok(cacheMessage, "\n");
|
||||
while (pch != NULL)
|
||||
{
|
||||
if (strlen(pch) > 0)
|
||||
{
|
||||
printf("pf-'%s'\n", pch);
|
||||
|
||||
esp_websocket_client_send_text(client, pch, strlen(pch), 1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
pch = strtok(NULL, "\n");
|
||||
}
|
||||
cacheMessageIndex = 0;*/
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,48 +106,104 @@ int jannex_LOG(const char *format, va_list args)
|
|||
int status = 0;
|
||||
|
||||
// sprintf to jannex_LOG func and dynamically allocate memory
|
||||
char *message;
|
||||
status = vasprintf(&message, format, args);
|
||||
char *esp_message;
|
||||
status = vasprintf(&esp_message, format, args);
|
||||
|
||||
// check if socket is online
|
||||
if (client != NULL && esp_websocket_client_is_connected(client))
|
||||
size_t encoded_length = 0;
|
||||
size_t input_length = strlen(esp_message);
|
||||
size_t message_length = CALC_BASE64_ENCODED_LENGTH(input_length) + 1;
|
||||
|
||||
char *message = (char *)malloc(message_length + 1 + 1); // + \n + \0
|
||||
|
||||
if (message != NULL)
|
||||
{
|
||||
sendOlderMessages();
|
||||
esp_websocket_client_send_text(client, message, strlen(message), 1000 / portTICK_PERIOD_MS);
|
||||
int ret = mbedtls_base64_encode((unsigned char *)message, message_length - 1, &encoded_length, (unsigned char *)esp_message, input_length);
|
||||
|
||||
if (ret != 0)
|
||||
{
|
||||
printf("Base64 encoding failed!");
|
||||
skippedMessages++;
|
||||
|
||||
goto END;
|
||||
}
|
||||
|
||||
// set last char to \n
|
||||
message[encoded_length] = '\n';
|
||||
message[encoded_length + 1] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cacheMessageIndex + strlen(message) + 1 > CONFIG_HTTP_SERVER_DEBUG_CACHE_LENGTH)
|
||||
printf("Memory allocation failed!");
|
||||
skippedMessages++;
|
||||
|
||||
goto END;
|
||||
}
|
||||
|
||||
message_length = encoded_length + 1;
|
||||
|
||||
// check if socket is online
|
||||
/*if (client != NULL && esp_websocket_client_is_connected(client))
|
||||
{
|
||||
// print last char of message in hex
|
||||
// printf("last char: %02x\n", message[encoded_length - 1]);
|
||||
|
||||
sendOlderMessages();
|
||||
|
||||
printf("message_length:%i\n", message_length);
|
||||
esp_websocket_client_send_text(client, message, message_length, 1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
else*/
|
||||
{
|
||||
// Take the mutex before writing to the variable
|
||||
if (xSemaphoreTake(cacheMutex, portMAX_DELAY) == pdTRUE)
|
||||
{
|
||||
|
||||
if (cacheMessageIndex + message_length + 1 > CONFIG_HTTP_SERVER_DEBUG_CACHE_LENGTH)
|
||||
{
|
||||
// Cache is full
|
||||
// replace at the end of the cache
|
||||
|
||||
strcpy(cacheMessage + CONFIG_HTTP_SERVER_DEBUG_CACHE_LENGTH - 30, " ! CONSOLE CACHE OVERFLOW ! \n");
|
||||
strcpy(cacheMessage + CONFIG_HTTP_SERVER_DEBUG_CACHE_LENGTH - 7, "!CCO!\n");
|
||||
cacheMessageIndex = CONFIG_HTTP_SERVER_DEBUG_CACHE_LENGTH;
|
||||
|
||||
xSemaphoreGive(cacheMutex);
|
||||
goto END;
|
||||
}
|
||||
|
||||
// cache message thread safe
|
||||
// xSemaphoreTake(cacheMessageSemaphore, portMAX_DELAY);
|
||||
|
||||
// cache message
|
||||
if (cacheMessageIndex == 0)
|
||||
{
|
||||
strcpy(cacheMessage + cacheMessageIndex, message);
|
||||
cacheMessageIndex += strlen(message);
|
||||
cacheMessageIndex += message_length;
|
||||
}
|
||||
else
|
||||
{
|
||||
// cacheMessage[cacheMessageIndex] = '\n';
|
||||
strcpy(cacheMessage + cacheMessageIndex, message);
|
||||
cacheMessageIndex += strlen(message);
|
||||
cacheMessageIndex += message_length;
|
||||
}
|
||||
|
||||
// Release the mutex
|
||||
xSemaphoreGive(cacheMutex);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unable to take the mutex
|
||||
// Handle the error
|
||||
}
|
||||
}
|
||||
|
||||
END:
|
||||
|
||||
free(esp_message);
|
||||
free(message);
|
||||
|
||||
if (status >= 0)
|
||||
{
|
||||
|
||||
return vprintf(format, args); // print to console
|
||||
}
|
||||
return status;
|
||||
|
@ -153,7 +280,10 @@ static void console_task(void *pvParameters)
|
|||
esp_websocket_client_config_t websocket_cfg = {
|
||||
.uri = CONFIG_HTTP_SERVER_DEBUG_URL,
|
||||
.port = CONFIG_HTTP_SERVER_DEBUG_PORT,
|
||||
|
||||
.task_stack = 1024 * 6,
|
||||
.reconnect_timeout_ms = 5000,
|
||||
.network_timeout_ms = 500,
|
||||
.ping_interval_sec = 10000,
|
||||
};
|
||||
|
||||
ESP_LOGI(TAG, "Connecting to %s... on port %d", websocket_cfg.uri, websocket_cfg.port);
|
||||
|
@ -176,12 +306,32 @@ static void console_task(void *pvParameters)
|
|||
|
||||
esp_websocket_client_destroy(client);*/
|
||||
|
||||
vTaskDelete(NULL);
|
||||
while (true)
|
||||
{
|
||||
sendOlderMessages();
|
||||
vTaskDelay(500 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
void initConsole()
|
||||
{
|
||||
cacheMutex = xSemaphoreCreateMutex();
|
||||
if (cacheMutex == NULL)
|
||||
{
|
||||
// Mutex creation failed
|
||||
// Handle the error
|
||||
printf("initConsole Mutex creation failed!!!!!!!!!!!");
|
||||
}
|
||||
|
||||
esp_log_set_vprintf(&jannex_LOG);
|
||||
|
||||
if (cacheMutex == NULL)
|
||||
{
|
||||
// Mutex creation failed
|
||||
// Handle the error
|
||||
printf("initConsole Mutex creation failed!!!!!!!!!!!");
|
||||
ESP_LOGE(TAG, "initConsole Mutex creation failed!!!!!!!!!!!");
|
||||
}
|
||||
}
|
||||
|
||||
void connectConsole()
|
||||
|
|
|
@ -22,6 +22,11 @@ esp_err_t https_get_request_SYNC(const char *url, char *out_buffer, int *out_buf
|
|||
};
|
||||
|
||||
esp_http_client_handle_t client = esp_http_client_init(&config);
|
||||
if (client == NULL)
|
||||
{
|
||||
ESP_LOGE(TAG, "Failed to initialize HTTP client");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
// GET Request
|
||||
esp_http_client_set_method(client, HTTP_METHOD_GET);
|
||||
|
|
43
src/jannex.c
43
src/jannex.c
|
@ -62,6 +62,28 @@ void initialize_sntp()
|
|||
}*/
|
||||
}
|
||||
|
||||
void startJannex(void *parameter)
|
||||
{
|
||||
defaultValuesToStorage();
|
||||
|
||||
#ifdef WIFI_ENABLED
|
||||
esp_log_level_set("esp-x509-crt-bundle", ESP_LOG_WARN);
|
||||
esp_log_level_set("wifi", ESP_LOG_WARN);
|
||||
init_wifi();
|
||||
#endif
|
||||
|
||||
#ifdef WEB_SERVER_ENABLED
|
||||
initServer();
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_HTTP_SERVER_ENABLE_DEBUG_MODE
|
||||
connectConsole();
|
||||
#endif // CONFIG_HTTP_SERVER_ENABLE_DEBUG_MODE
|
||||
|
||||
initialize_sntp();
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
void initJannex()
|
||||
{
|
||||
initStorage();
|
||||
|
@ -80,26 +102,11 @@ void initJannex()
|
|||
ESP_LOGI(jannexTAG, "Current Build date: %s", app_desc->date);
|
||||
ESP_LOGI(jannexTAG, "Current Build time: %s", app_desc->time);
|
||||
|
||||
defaultValuesToStorage();
|
||||
|
||||
#ifdef WIFI_ENABLED
|
||||
esp_log_level_set("esp-x509-crt-bundle", ESP_LOG_WARN);
|
||||
esp_log_level_set("wifi", ESP_LOG_WARN);
|
||||
init_wifi();
|
||||
#endif
|
||||
|
||||
#ifdef WEB_SERVER_ENABLED
|
||||
initServer();
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_HTTP_SERVER_ENABLE_DEBUG_MODE
|
||||
connectConsole();
|
||||
#endif // CONFIG_HTTP_SERVER_ENABLE_DEBUG_MODE
|
||||
|
||||
initialize_sntp();
|
||||
xTaskCreate(startJannex, "startJannex", 4096, NULL, 5, NULL);
|
||||
xTaskCreate(checkIfOTAwasSuccessful, "checkIfOTAwasSuccessful", 4096, NULL, 5, NULL);
|
||||
}
|
||||
|
||||
void updateJannex()
|
||||
{
|
||||
xTaskCreate(&checkForUpdatesAndInstall, "checkForUpdatesAndInstall", 8192, NULL, 5, NULL);
|
||||
xTaskCreate(checkForUpdatesAndInstall, "checkForUpdatesAndInstall", 8192, NULL, 5, NULL);
|
||||
}
|
152
src/ota.c
152
src/ota.c
|
@ -13,11 +13,38 @@
|
|||
#include "esp_app_desc.h"
|
||||
#include "esp_ota_ops.h"
|
||||
|
||||
#include "string.h"
|
||||
|
||||
// #include "esp_heap_trace.h"
|
||||
|
||||
// #define NUM_RECORDS 100
|
||||
// static heap_trace_record_t trace_record[NUM_RECORDS]; // This buffer must be in internal RAM
|
||||
|
||||
bool updateAvailable = false;
|
||||
bool isCheckingForUpdates = false;
|
||||
|
||||
void getNewestVersion()
|
||||
void printFreeHeap(int start)
|
||||
{
|
||||
|
||||
if (start == 0)
|
||||
{
|
||||
ESP_LOGI(jannexTAG, " \\/ \\/ \\/ \\/ \\/ Free heap: ");
|
||||
ESP_LOGI(jannexTAG, " %i", heap_caps_get_free_size(MALLOC_CAP_8BIT));
|
||||
}
|
||||
else if (start == -1)
|
||||
{
|
||||
ESP_LOGI(jannexTAG, " %i", heap_caps_get_free_size(MALLOC_CAP_8BIT));
|
||||
ESP_LOGI(jannexTAG, " /\\ /\\ /\\ /\\ /\\ Free heap: ");
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGI(jannexTAG, " %i", heap_caps_get_free_size(MALLOC_CAP_8BIT));
|
||||
}
|
||||
}
|
||||
|
||||
void getNewestVersion(bool forceUpdate)
|
||||
{
|
||||
|
||||
isCheckingForUpdates = true;
|
||||
|
||||
// buffer for the response
|
||||
|
@ -53,8 +80,10 @@ void getNewestVersion()
|
|||
ESP_LOGE(jannexTAG, "HTTP GET Response: %i %i %s", status_code, responseLength, response);
|
||||
ESP_LOGE(jannexTAG, "Parser failed");
|
||||
isCheckingForUpdates = false;
|
||||
return;
|
||||
|
||||
goto FREE_MEM;
|
||||
}
|
||||
|
||||
char newestVersion[32];
|
||||
|
||||
if (json_obj_get_string(&jctx, "error", newestVersion, sizeof(newestVersion)) == OS_SUCCESS)
|
||||
|
@ -62,7 +91,8 @@ void getNewestVersion()
|
|||
ESP_LOGW(jannexTAG, "Error: %s", newestVersion);
|
||||
// ERROR
|
||||
isCheckingForUpdates = false;
|
||||
return;
|
||||
|
||||
goto FREE_MEM;
|
||||
}
|
||||
|
||||
if (json_obj_get_string(&jctx, "version", newestVersion, sizeof(newestVersion)) == OS_SUCCESS)
|
||||
|
@ -73,7 +103,8 @@ void getNewestVersion()
|
|||
{
|
||||
ESP_LOGI(jannexTAG, "No version");
|
||||
isCheckingForUpdates = false;
|
||||
return;
|
||||
|
||||
goto FREE_MEM;
|
||||
}
|
||||
|
||||
// print current version
|
||||
|
@ -140,22 +171,95 @@ void getNewestVersion()
|
|||
updateAvailable = true;
|
||||
}
|
||||
|
||||
esp_partition_t *last_invalid_app = esp_ota_get_last_invalid_partition();
|
||||
if (last_invalid_app != NULL)
|
||||
{
|
||||
// get partition description
|
||||
|
||||
esp_app_desc_t last_app_desc;
|
||||
esp_err_t ret = esp_ota_get_partition_description(last_invalid_app, &last_app_desc);
|
||||
if (ret == ESP_OK)
|
||||
{
|
||||
ESP_LOGI(jannexTAG, "Last invalid app partition: %s", last_app_desc.version);
|
||||
// check if the last invalid partition is the same as the newest version
|
||||
if (strcmp(last_app_desc.version, newestVersion) == 0)
|
||||
{
|
||||
// the last invalid partition is the same as the newest version -> DONT update
|
||||
ESP_LOGE(jannexTAG, "BAD UPDATE DETECTED -> KEEP CURRENT VERSION AND DO NOT UPDATE");
|
||||
vTaskDelay(10000 / portTICK_PERIOD_MS);
|
||||
updateAvailable = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
ESP_LOGE(jannexTAG, "Could not get last invalid app partition description: %s", esp_err_to_name(ret));
|
||||
} /*
|
||||
else
|
||||
{
|
||||
ESP_LOGI(jannexTAG, "No invalid partition");
|
||||
}*/
|
||||
|
||||
isCheckingForUpdates = false;
|
||||
|
||||
// esp ota do update
|
||||
if (updateAvailable)
|
||||
{
|
||||
|
||||
startOTAupdate();
|
||||
startOTAupdate(forceUpdate);
|
||||
}
|
||||
|
||||
FREE_MEM:
|
||||
|
||||
json_parse_end(&jctx);
|
||||
// free(response); // crashes ESP
|
||||
}
|
||||
|
||||
void printFreeHeapTask(void *parameter)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
size_t heap = esp_get_free_heap_size();
|
||||
ESP_LOGI(jannexTAG, "Biggest free heap Block: %i", heap);
|
||||
ESP_LOGI(jannexTAG, "Total Free heap: %i", heap_caps_get_free_size(MALLOC_CAP_8BIT));
|
||||
|
||||
vTaskDelay(500 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
void checkForUpdatesAndInstall(void *parameter)
|
||||
{
|
||||
// ESP_ERROR_CHECK(heap_trace_init_standalone(trace_record, NUM_RECORDS));
|
||||
|
||||
xTaskCreate(printFreeHeapTask, "printFreeHeapTask", 4096, NULL, 5, NULL);
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(5000)); // Delay for 5000 milliseconds
|
||||
while (1)
|
||||
{
|
||||
|
||||
// get current ota state
|
||||
esp_partition_t *running = esp_ota_get_running_partition();
|
||||
esp_ota_img_states_t state;
|
||||
esp_err_t ret = esp_ota_get_state_partition(running, &state);
|
||||
|
||||
if (ret == ESP_OK)
|
||||
{
|
||||
if (state == ESP_OTA_IMG_PENDING_VERIFY)
|
||||
{
|
||||
ESP_LOGI(jannexTAG, "OTA update pending verify...");
|
||||
// The firmware is half-way through an OTA update, but it's waiting to verify.
|
||||
// We'll just reboot.
|
||||
vTaskDelay(pdMS_TO_TICKS(5000)); // Delay for 5000 milliseconds
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (isCheckingForUpdates == false)
|
||||
getNewestVersion();
|
||||
{
|
||||
// ESP_ERROR_CHECK(heap_trace_start(HEAP_TRACE_LEAKS));
|
||||
getNewestVersion(false);
|
||||
// ESP_ERROR_CHECK(heap_trace_stop());
|
||||
// heap_trace_dump();
|
||||
// vTaskDelay(pdMS_TO_TICKS(50000)); // Delay for 50000 milliseconds
|
||||
}
|
||||
|
||||
#ifdef CONFIG_FIRMWARE_UPDATE_SCAN_SECONDS
|
||||
if (CONFIG_FIRMWARE_UPDATE_SCAN_SECONDS >= 1)
|
||||
|
@ -169,3 +273,39 @@ void checkForUpdatesAndInstall(void *parameter)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void checkIfOTAwasSuccessful(void *parameter)
|
||||
{
|
||||
esp_partition_t *running = esp_ota_get_running_partition();
|
||||
esp_ota_img_states_t state;
|
||||
esp_err_t ret = esp_ota_get_state_partition(running, &state);
|
||||
|
||||
if (ret != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(jannexTAG, "esp_ota_get_state_partition failed! %i", ret);
|
||||
vTaskDelete(NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (state == ESP_OTA_IMG_PENDING_VERIFY)
|
||||
{
|
||||
ESP_LOGI(jannexTAG, "ESP_OTA_IMG_PENDING_VERIFY");
|
||||
vTaskDelay(1000 * 30 / portTICK_PERIOD_MS); // wait 30sec minute
|
||||
// run diagnostic function ...
|
||||
bool diagnostic_is_ok = true; // diagnostic();
|
||||
if (diagnostic_is_ok)
|
||||
{
|
||||
ESP_LOGI(jannexTAG, "Diagnostics completed successfully! Continuing execution ...");
|
||||
esp_ota_mark_app_valid_cancel_rollback();
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGE(jannexTAG, "Diagnostics failed! Start rollback to the previous version ...");
|
||||
esp_ota_mark_app_invalid_rollback_and_reboot();
|
||||
}
|
||||
}
|
||||
|
||||
ESP_LOGI(jannexTAG, "State: %i", state);
|
||||
|
||||
vTaskDelete(NULL);
|
||||
}
|
|
@ -47,7 +47,7 @@ esp_err_t _http_event_handler(esp_http_client_event_t *evt)
|
|||
return ESP_OK;
|
||||
}
|
||||
|
||||
void startOTAupdate()
|
||||
void startOTAupdate(bool forceUpdate)
|
||||
{
|
||||
// get mac address
|
||||
uint8_t mac[6];
|
||||
|
@ -65,7 +65,7 @@ void startOTAupdate()
|
|||
esp_http_client_config_t config = {
|
||||
.url = url,
|
||||
.crt_bundle_attach = esp_crt_bundle_attach,
|
||||
.buffer_size = 4096,
|
||||
.buffer_size = 4096 * 4,
|
||||
|
||||
.event_handler = _http_event_handler,
|
||||
.keep_alive_enable = true,
|
||||
|
|
|
@ -27,7 +27,7 @@ esp_err_t readStorage(const char *key, char *out_value, size_t *length, char *de
|
|||
case ESP_OK:
|
||||
// ESP_LOGI(TAG, "Current %s: %s", key, out_value);
|
||||
|
||||
return ret;
|
||||
break;
|
||||
case ESP_ERR_NVS_NOT_FOUND:
|
||||
ESP_LOGI(TAG, "The value is not initialized yet!\n");
|
||||
|
||||
|
@ -35,7 +35,12 @@ esp_err_t readStorage(const char *key, char *out_value, size_t *length, char *de
|
|||
default:
|
||||
ESP_LOGE(TAG, "Error (%s) reading!\n", esp_err_to_name(ret));
|
||||
}
|
||||
|
||||
nvs_close(my_handle);
|
||||
if (ret == ESP_OK)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
// if not found, set to default value
|
||||
|
|
Loading…
Reference in New Issue