Advanced Distributed Systems module at HSLU
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

260 lines
7.2 KiB

/*
* challenge_nvs.c
*
* Created on: 08.12.2022
* Author: jonas
*/
#include "challenge_nvs.h"
#include "esp_log.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "nvs.h"
#include "McuUtility.h"
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
/* defines / constants */
#define TAG "CHALLENGE_NVS" /* tag for logging with ESP_LOG */
const char* NAMESPACE_NVS = "storage";
const char* ROBOT_MODE_KEY = "robot_mode";
const char* MQTT_IP_KEY = "mqtt_ip";
/* local vars */
bool initializedSuccessfully = false;
SemaphoreHandle_t semaphore = NULL;
/*! \brief Initialize the NVS storage. */
void Challenge_Nvs_Init(void){
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
esp_err_t err = nvs_flash_init();
if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
// NVS partition was truncated and needs to be erased
// Retry nvs_flash_init
ESP_ERROR_CHECK(nvs_flash_erase());
err = nvs_flash_init();
}
ESP_ERROR_CHECK( err );
initializedSuccessfully = (err == ESP_OK);
ESP_LOGI(TAG, "Initialized. Success=%s", initializedSuccessfully?"true":"false");
}
/*! \brief Deinitialize the NVS storage. */
void Challenge_Nvs_Deinit(void){
ESP_LOGI(TAG, "Deinitializing...");
esp_err_t err = nvs_flash_deinit();
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);
}
bool Challenge_Nvs_StoreRobotModeToNVS(bool mode){
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
uint8_t value = mode?1:0;
ESP_LOGI(TAG, "Updating robotMode in NVS ... ");
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){
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();
}
return success;
}
bool Challenge_Nvs_GetRobotModeFromNVS(bool *mode){
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;
}
// Read
ESP_LOGI(TAG, "Reading robot mode from NVS ... ");
uint8_t value = 0;
err = nvs_get_u8(my_handle, ROBOT_MODE_KEY, &value);
switch (err) {
case ESP_OK:
ESP_LOGI(TAG, "Reading robot mode done. Read robotMode = %i", value);
*mode = (bool)(value==1?true:false); // set value at pointer location
success = true;
break;
case ESP_ERR_NVS_NOT_FOUND:
ESP_LOGI(TAG, "Reading robot mode done. The value is not initialized yet!");
notInitialized = true;
break;
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
*mode = false; // set out variable to false too
}
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;
}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();
}
return success;
}
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;
}
// Read
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
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;
}