|
|
|
@ -10,19 +10,32 @@ |
|
|
|
#include "esp_system.h" |
|
|
|
#include "esp_system.h" |
|
|
|
#include "nvs_flash.h" |
|
|
|
#include "nvs_flash.h" |
|
|
|
#include "nvs.h" |
|
|
|
#include "nvs.h" |
|
|
|
|
|
|
|
#include "McuUtility.h" |
|
|
|
|
|
|
|
#include "freertos/FreeRTOS.h" |
|
|
|
|
|
|
|
#include "freertos/semphr.h" |
|
|
|
|
|
|
|
|
|
|
|
/* defines / constants */ |
|
|
|
/* defines / constants */ |
|
|
|
#define TAG "CHALLENGE_NVS" /* tag for logging with ESP_LOG */ |
|
|
|
#define TAG "CHALLENGE_NVS" /* tag for logging with ESP_LOG */ |
|
|
|
const char* NAMESPACE_NVS = "storage"; |
|
|
|
const char* NAMESPACE_NVS = "storage"; |
|
|
|
const char* ROBOT_MODE_KEY = "robot_mode"; |
|
|
|
const char* ROBOT_MODE_KEY = "robot_mode"; |
|
|
|
|
|
|
|
const char* MQTT_IP_KEY = "mqtt_ip"; |
|
|
|
|
|
|
|
|
|
|
|
/* local vars */ |
|
|
|
/* local vars */ |
|
|
|
bool initializedSuccessfully = false; |
|
|
|
bool initializedSuccessfully = false; |
|
|
|
|
|
|
|
SemaphoreHandle_t semaphore = NULL; |
|
|
|
|
|
|
|
|
|
|
|
/*! \brief Initialize the NVS storage. */ |
|
|
|
/*! \brief Initialize the NVS storage. */ |
|
|
|
void Challenge_Nvs_Init(void){ |
|
|
|
void Challenge_Nvs_Init(void){ |
|
|
|
ESP_LOGI(TAG, "Initializing..."); |
|
|
|
ESP_LOGI(TAG, "Initializing..."); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// initialize semaphore
|
|
|
|
|
|
|
|
semaphore = xSemaphoreCreateRecursiveMutex(); |
|
|
|
|
|
|
|
if(semaphore == NULL){ |
|
|
|
|
|
|
|
ESP_LOGE(TAG, "Failed to initialize semaphore for Challenge NVS!"); |
|
|
|
|
|
|
|
}else{ |
|
|
|
|
|
|
|
vQueueAddToRegistry(semaphore, "challenge_nvs_semphr"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Initialize NVS
|
|
|
|
// Initialize NVS
|
|
|
|
esp_err_t err = nvs_flash_init(); |
|
|
|
esp_err_t err = nvs_flash_init(); |
|
|
|
if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { |
|
|
|
if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { |
|
|
|
@ -42,97 +55,206 @@ void Challenge_Nvs_Deinit(void){ |
|
|
|
ESP_LOGI(TAG, "Deinitializing..."); |
|
|
|
ESP_LOGI(TAG, "Deinitializing..."); |
|
|
|
esp_err_t err = nvs_flash_deinit(); |
|
|
|
esp_err_t err = nvs_flash_deinit(); |
|
|
|
ESP_LOGI(TAG, "Deinitialized. Success=%s", err==ESP_OK?"true":"false"); |
|
|
|
ESP_LOGI(TAG, "Deinitialized. Success=%s", err==ESP_OK?"true":"false"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vSemaphoreDelete(semaphore); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* HELPERS FOR SEMAPHORE */ |
|
|
|
|
|
|
|
static bool Challenge_Nvs_AquireMutex(void){ |
|
|
|
|
|
|
|
if(xSemaphoreTakeRecursive(semaphore, pdMS_TO_TICKS(100)) != pdTRUE){ |
|
|
|
|
|
|
|
/* timeout */ |
|
|
|
|
|
|
|
ESP_LOGW(TAG, "Timemout while aquiring challenge NVS semaphore."); |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void Challenge_Nvs_ReleaseMutex(void){ |
|
|
|
|
|
|
|
xSemaphoreGive(semaphore); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
|
|
|
* \brief Stores the passed robot mode in NVS. |
|
|
|
|
|
|
|
* \param modeStationary Mode to store. True = stationary mode, False = mobile mode |
|
|
|
|
|
|
|
* \return true on success |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
bool Challenge_Nvs_StoreRobotModeToNVS(bool mode){ |
|
|
|
bool Challenge_Nvs_StoreRobotModeToNVS(bool mode){ |
|
|
|
bool success = false; |
|
|
|
bool success = false; |
|
|
|
|
|
|
|
|
|
|
|
// Open
|
|
|
|
if(Challenge_Nvs_AquireMutex()){ |
|
|
|
ESP_LOGI(TAG, "Opening Non-Volatile Storage (NVS) handle... "); |
|
|
|
// Open
|
|
|
|
nvs_handle_t my_handle; |
|
|
|
ESP_LOGI(TAG, "Opening Non-Volatile Storage (NVS) handle... "); |
|
|
|
esp_err_t err = nvs_open(NAMESPACE_NVS, NVS_READWRITE, &my_handle); |
|
|
|
nvs_handle_t my_handle; |
|
|
|
if (err != ESP_OK) { |
|
|
|
esp_err_t err = nvs_open(NAMESPACE_NVS, NVS_READWRITE, &my_handle); |
|
|
|
ESP_LOGE(TAG, "Error (%s) opening NVS handle!\n", esp_err_to_name(err)); |
|
|
|
if (err != ESP_OK) { |
|
|
|
return false; |
|
|
|
ESP_LOGE(TAG, "Error (%s) opening NVS handle!\n", esp_err_to_name(err)); |
|
|
|
} |
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Write
|
|
|
|
// Write
|
|
|
|
uint8_t value = mode?1:0; |
|
|
|
uint8_t value = mode?1:0; |
|
|
|
ESP_LOGI(TAG, "Updating robotMode in NVS ... "); |
|
|
|
ESP_LOGI(TAG, "Updating robotMode in NVS ... "); |
|
|
|
err = nvs_set_u8(my_handle, ROBOT_MODE_KEY, value); |
|
|
|
err = nvs_set_u8(my_handle, ROBOT_MODE_KEY, value); |
|
|
|
if(err != ESP_OK){ |
|
|
|
|
|
|
|
ESP_LOGE(TAG, "Failed to update robotMode in NVS. Error=(%s)", esp_err_to_name(err)); |
|
|
|
|
|
|
|
success = false; |
|
|
|
|
|
|
|
}else{ // successfully set
|
|
|
|
|
|
|
|
// Commit written value.
|
|
|
|
|
|
|
|
// After setting any values, nvs_commit() must be called to ensure changes are written
|
|
|
|
|
|
|
|
// to flash storage. Implementations may write to storage at other times,
|
|
|
|
|
|
|
|
// but this is not guaranteed.
|
|
|
|
|
|
|
|
ESP_LOGI(TAG, "Committing updates in NVS ... "); |
|
|
|
|
|
|
|
err = nvs_commit(my_handle); |
|
|
|
|
|
|
|
if(err != ESP_OK){ |
|
|
|
if(err != ESP_OK){ |
|
|
|
ESP_LOGE(TAG, "Failed to commit to NVS. Error=(%s)", esp_err_to_name(err)); |
|
|
|
ESP_LOGE(TAG, "Failed to update robotMode in NVS. Error=(%s)", esp_err_to_name(err)); |
|
|
|
success = false; |
|
|
|
success = false; |
|
|
|
}else{ |
|
|
|
}else{ // successfully set
|
|
|
|
ESP_LOGI(TAG, "Successfully committed changes to NVS."); |
|
|
|
// Commit written value.
|
|
|
|
success = true; |
|
|
|
// After setting any values, nvs_commit() must be called to ensure changes are written
|
|
|
|
|
|
|
|
// to flash storage. Implementations may write to storage at other times,
|
|
|
|
|
|
|
|
// but this is not guaranteed.
|
|
|
|
|
|
|
|
ESP_LOGI(TAG, "Committing updates in NVS ... "); |
|
|
|
|
|
|
|
err = nvs_commit(my_handle); |
|
|
|
|
|
|
|
if(err != ESP_OK){ |
|
|
|
|
|
|
|
ESP_LOGE(TAG, "Failed to commit to NVS. Error=(%s)", esp_err_to_name(err)); |
|
|
|
|
|
|
|
success = false; |
|
|
|
|
|
|
|
}else{ |
|
|
|
|
|
|
|
ESP_LOGI(TAG, "Successfully committed changes to NVS."); |
|
|
|
|
|
|
|
success = true; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Close
|
|
|
|
// Close
|
|
|
|
nvs_close(my_handle); |
|
|
|
nvs_close(my_handle); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Challenge_Nvs_ReleaseMutex(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return success; |
|
|
|
return success; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
|
|
|
* \brief Retrieve the robot mode stored in NVS. |
|
|
|
|
|
|
|
* \param mode Pointer to the location where to retrieve the mode to. True = stationary mode, False = mobile mode |
|
|
|
|
|
|
|
* \return true on success |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
bool Challenge_Nvs_GetRobotModeFromNVS(bool *mode){ |
|
|
|
bool Challenge_Nvs_GetRobotModeFromNVS(bool *mode){ |
|
|
|
bool success = false; |
|
|
|
bool success = false; |
|
|
|
bool notInitialized = false; |
|
|
|
bool notInitialized = false; |
|
|
|
|
|
|
|
|
|
|
|
// Open
|
|
|
|
if(Challenge_Nvs_AquireMutex()){ |
|
|
|
ESP_LOGI(TAG, "Opening Non-Volatile Storage (NVS) handle... "); |
|
|
|
// Open
|
|
|
|
nvs_handle_t my_handle; |
|
|
|
ESP_LOGI(TAG, "Opening Non-Volatile Storage (NVS) handle... "); |
|
|
|
esp_err_t err = nvs_open(NAMESPACE_NVS, NVS_READWRITE, &my_handle); |
|
|
|
nvs_handle_t my_handle; |
|
|
|
if (err != ESP_OK) { |
|
|
|
esp_err_t err = nvs_open(NAMESPACE_NVS, NVS_READWRITE, &my_handle); |
|
|
|
ESP_LOGE(TAG, "Error (%s) opening NVS handle!\n", esp_err_to_name(err)); |
|
|
|
if (err != ESP_OK) { |
|
|
|
return false; |
|
|
|
ESP_LOGE(TAG, "Error (%s) opening NVS handle!\n", esp_err_to_name(err)); |
|
|
|
} |
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
// Read
|
|
|
|
|
|
|
|
ESP_LOGI(TAG, "Reading robot mode from NVS ... "); |
|
|
|
// Read
|
|
|
|
uint8_t value = 0; |
|
|
|
ESP_LOGI(TAG, "Reading robot mode from NVS ... "); |
|
|
|
err = nvs_get_u8(my_handle, ROBOT_MODE_KEY, &value); |
|
|
|
uint8_t value = 0; |
|
|
|
switch (err) { |
|
|
|
err = nvs_get_u8(my_handle, ROBOT_MODE_KEY, &value); |
|
|
|
case ESP_OK: |
|
|
|
switch (err) { |
|
|
|
ESP_LOGI(TAG, "Reading robot mode done. Read robotMode = %i", value); |
|
|
|
case ESP_OK: |
|
|
|
*mode = (bool)(value==1?true:false); // set value at pointer location
|
|
|
|
ESP_LOGI(TAG, "Reading robot mode done. Read robotMode = %i", value); |
|
|
|
success = true; |
|
|
|
*mode = (bool)(value==1?true:false); // set value at pointer location
|
|
|
|
break; |
|
|
|
success = true; |
|
|
|
case ESP_ERR_NVS_NOT_FOUND: |
|
|
|
break; |
|
|
|
ESP_LOGI(TAG, "Reading robot mode done. The value is not initialized yet!"); |
|
|
|
case ESP_ERR_NVS_NOT_FOUND: |
|
|
|
notInitialized = true; |
|
|
|
ESP_LOGI(TAG, "Reading robot mode done. The value is not initialized yet!"); |
|
|
|
break; |
|
|
|
notInitialized = true; |
|
|
|
default : |
|
|
|
break; |
|
|
|
ESP_LOGI(TAG, "Error reading robot mode. Error=(%s)", esp_err_to_name(err)); |
|
|
|
default : |
|
|
|
|
|
|
|
ESP_LOGI(TAG, "Error reading robot mode. Error=(%s)", esp_err_to_name(err)); |
|
|
|
|
|
|
|
success = false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Close
|
|
|
|
|
|
|
|
nvs_close(my_handle); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(notInitialized){ |
|
|
|
|
|
|
|
success = Challenge_Nvs_StoreRobotModeToNVS(false); // initialize to false
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Challenge_Nvs_ReleaseMutex(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return success; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool Challenge_Nvs_StoreBrokerIpToNVS(char* ip){ |
|
|
|
|
|
|
|
bool success = false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(Challenge_Nvs_AquireMutex()){ |
|
|
|
|
|
|
|
// Open
|
|
|
|
|
|
|
|
ESP_LOGI(TAG, "Opening Non-Volatile Storage (NVS) handle... "); |
|
|
|
|
|
|
|
nvs_handle_t my_handle; |
|
|
|
|
|
|
|
esp_err_t err = nvs_open(NAMESPACE_NVS, NVS_READWRITE, &my_handle); |
|
|
|
|
|
|
|
if (err != ESP_OK) { |
|
|
|
|
|
|
|
ESP_LOGE(TAG, "Error (%s) opening NVS handle!\n", esp_err_to_name(err)); |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Write
|
|
|
|
|
|
|
|
ESP_LOGI(TAG, "Updating mqtt broker IP in NVS ... "); |
|
|
|
|
|
|
|
err = nvs_set_str(my_handle, MQTT_IP_KEY, ip); |
|
|
|
|
|
|
|
if(err != ESP_OK){ |
|
|
|
|
|
|
|
ESP_LOGE(TAG, "Failed to update mqtt broker IP in NVS. Error=(%s)", esp_err_to_name(err)); |
|
|
|
success = false; |
|
|
|
success = false; |
|
|
|
|
|
|
|
}else{ // successfully set
|
|
|
|
|
|
|
|
// Commit written value.
|
|
|
|
|
|
|
|
// After setting any values, nvs_commit() must be called to ensure changes are written
|
|
|
|
|
|
|
|
// to flash storage. Implementations may write to storage at other times,
|
|
|
|
|
|
|
|
// but this is not guaranteed.
|
|
|
|
|
|
|
|
ESP_LOGI(TAG, "Committing updates in NVS ... "); |
|
|
|
|
|
|
|
err = nvs_commit(my_handle); |
|
|
|
|
|
|
|
if(err != ESP_OK){ |
|
|
|
|
|
|
|
ESP_LOGE(TAG, "Failed to commit to NVS. Error=(%s)", esp_err_to_name(err)); |
|
|
|
|
|
|
|
success = false; |
|
|
|
|
|
|
|
}else{ |
|
|
|
|
|
|
|
ESP_LOGI(TAG, "Successfully committed changes to NVS."); |
|
|
|
|
|
|
|
success = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Close
|
|
|
|
|
|
|
|
nvs_close(my_handle); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Challenge_Nvs_ReleaseMutex(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Close
|
|
|
|
return success; |
|
|
|
nvs_close(my_handle); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool Challenge_Nvs_GetBrokerIpFromNVS(char *ip, size_t length){ |
|
|
|
|
|
|
|
bool success = false; |
|
|
|
|
|
|
|
bool notInitialized = false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(Challenge_Nvs_AquireMutex()){ |
|
|
|
|
|
|
|
// Open
|
|
|
|
|
|
|
|
ESP_LOGI(TAG, "Opening Non-Volatile Storage (NVS) handle... "); |
|
|
|
|
|
|
|
nvs_handle_t my_handle; |
|
|
|
|
|
|
|
esp_err_t err = nvs_open(NAMESPACE_NVS, NVS_READWRITE, &my_handle); |
|
|
|
|
|
|
|
if (err != ESP_OK) { |
|
|
|
|
|
|
|
ESP_LOGE(TAG, "Error (%s) opening NVS handle!\n", esp_err_to_name(err)); |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if(notInitialized){ |
|
|
|
// Read
|
|
|
|
success = Challenge_Nvs_StoreRobotModeToNVS(false); // initialize to false
|
|
|
|
ESP_LOGI(TAG, "Reading mqtt broker IP from NVS ... "); |
|
|
|
|
|
|
|
size_t required_size; |
|
|
|
|
|
|
|
nvs_get_str(my_handle, MQTT_IP_KEY, NULL, &required_size); // retrieve required size
|
|
|
|
|
|
|
|
char* value = pvPortMalloc(required_size); |
|
|
|
|
|
|
|
err = nvs_get_str(my_handle, MQTT_IP_KEY, value, &required_size); |
|
|
|
|
|
|
|
switch (err) { |
|
|
|
|
|
|
|
case ESP_OK: |
|
|
|
|
|
|
|
ESP_LOGI(TAG, "Reading mqtt broker ip done. Read IP = %s", value); |
|
|
|
|
|
|
|
McuUtility_strcpy((unsigned char*)ip, length, (unsigned char *)value); // copy ip to destination
|
|
|
|
|
|
|
|
ESP_LOGI(TAG, "Copied mqtt broker ip. ip=%s", ip); |
|
|
|
|
|
|
|
success = true; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case ESP_ERR_NVS_NOT_FOUND: |
|
|
|
|
|
|
|
ESP_LOGI(TAG, "Reading mqtt broker ip done. The value is not initialized yet!"); |
|
|
|
|
|
|
|
notInitialized = true; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
default : |
|
|
|
|
|
|
|
ESP_LOGI(TAG, "Error reading mqtt broker ip. Error=(%s)", esp_err_to_name(err)); |
|
|
|
|
|
|
|
success = false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Close
|
|
|
|
|
|
|
|
nvs_close(my_handle); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(notInitialized){ |
|
|
|
|
|
|
|
success = Challenge_Nvs_StoreBrokerIpToNVS("10.0.1.1"); // initialize to default IP
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Challenge_Nvs_ReleaseMutex(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return success; |
|
|
|
return success; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|