Files
espconfiglib/src/configmanager_priv.h
T
2021-11-01 22:21:08 +01:00

173 lines
6.0 KiB
C++

#pragma once
#include "configmanager.h"
// esp-idf includes
#include <esp_log.h>
#include <nvs_flash.h>
// local includes
#include "espchrono.h"
#define INSTANTIATE_CONFIGMANAGER_TEMPLATES(Type) \
namespace espconfig { \
template esp_err_t ConfigManager<Type>::init(const char *ns); \
/* template bool ConfigManager<Type>::erase(); */ \
template ConfigStatusReturnType ConfigManager<Type>::reset(); \
template ConfigWrapperInterface *ConfigManager<Type>::findConfigByKey(std::string_view key); \
} // namespace espconfig
namespace espconfig {
namespace {
constexpr const char * const TAG = "CONFIG";
} // namespace
template<typename ConfigContainer>
esp_err_t ConfigManager<ConfigContainer>::init(const char *ns)
{
ESP_LOGD(TAG, "called");
auto before = espchrono::millis_clock::now();
#ifndef CONFIG_NVS_ENCRYPTION
{
const auto result = nvs_flash_init_partition("nvs");
ESP_LOG_LEVEL_LOCAL((result == ESP_OK ? ESP_LOG_INFO : ESP_LOG_ERROR), TAG, "nvs_flash_init() for user returned: %s", esp_err_to_name(result));
if (result != ESP_OK)
return result;
}
#ifdef CONFIG_SEPARATE_FACTORY_NVS_PARTITION
{
const auto result = nvs_flash_init_partition("nvsFac");
ESP_LOG_LEVEL_LOCAL((result == ESP_OK ? ESP_LOG_INFO : ESP_LOG_ERROR), TAG, "nvs_flash_init() for factory returned: %s", esp_err_to_name(result));
if (result != ESP_OK)
return result;
}
#endif
#else
const esp_partition_t *key_part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS_KEYS, NULL);
if (!key_part)
{
ESP_LOGE(TAG, "nvs_keys partition not found!");
return ESP_ERR_NVS_PART_NOT_FOUND;
}
nvs_sec_cfg_t cfg;
{
const auto result = nvs_flash_read_security_cfg(key_part, &cfg);
ESP_LOG_LEVEL_LOCAL((result == ESP_OK ? ESP_LOG_INFO : ESP_LOG_ERROR), TAG, "nvs_flash_read_security_cfg() returned: %s", esp_err_to_name(result));
if (result != ESP_OK)
{
if (result == ESP_ERR_NVS_KEYS_NOT_INITIALIZED)
{
const auto result = nvs_flash_generate_keys(key_part, &cfg);
ESP_LOG_LEVEL_LOCAL((result == ESP_OK ? ESP_LOG_INFO : ESP_LOG_ERROR), TAG, "nvs_flash_generate_keys() returned: %s", esp_err_to_name(result));
if (result != ESP_OK)
return result;
}
else
return result;
}
}
{
const auto result = nvs_flash_secure_init_partition("nvs", &cfg);
ESP_LOG_LEVEL_LOCAL((result == ESP_OK ? ESP_LOG_INFO : ESP_LOG_ERROR), TAG, "nvs_flash_secure_init() for user returned: %s", esp_err_to_name(result));
if (result != ESP_OK)
return result;
}
#ifdef CONFIG_SEPARATE_FACTORY_NVS_PARTITION
{
const auto result = nvs_flash_secure_init_partition("nvsFac", &cfg);
ESP_LOG_LEVEL_LOCAL((result == ESP_OK ? ESP_LOG_INFO : ESP_LOG_ERROR), TAG, "nvs_flash_secure_init() for user returned: %s", esp_err_to_name(result));
if (result != ESP_OK)
return result;
}
#endif
#endif
{
const auto result = nvs_open_from_partition("nvs", ns, NVS_READWRITE, &nvs_handle_user);
ESP_LOG_LEVEL_LOCAL((result == ESP_OK ? ESP_LOG_INFO : ESP_LOG_ERROR), TAG, "nvs_open() for user partition returned: %s", esp_err_to_name(result));
if (result != ESP_OK)
return result;
}
#ifdef CONFIG_SEPARATE_FACTORY_NVS_PARTITION
{
const auto result = nvs_open_from_partition("nvsFac", ns, NVS_READWRITE, &nvs_handle_factory);
ESP_LOG_LEVEL_LOCAL((result == ESP_OK ? ESP_LOG_INFO : ESP_LOG_ERROR), TAG, "nvs_open() for factory partition returned: %s", esp_err_to_name(result));
if (result != ESP_OK)
return result;
}
#endif
auto after = espchrono::millis_clock::now();
ESP_LOGI(TAG, "initializing NVS took %lldms", std::chrono::milliseconds{after-before}.count());
before = espchrono::millis_clock::now();
bool success = true;
for (ConfigWrapperInterface &config : ConfigContainer::getAllConfigParams())
if (const auto result = config.loadFromFlash(nvs_handle_user); !result)
{
ESP_LOGE(TAG, "config parameter %s failed to load: %.*s", config.nvsName(), result.error().size(), result.error().data());
success = false;
}
after = espchrono::millis_clock::now();
ESP_LOGI(TAG, "loading all config params took %lldms", std::chrono::milliseconds{after-before}.count());
return success ? ESP_OK : ESP_FAIL;
}
//template<typename ConfigContainer>
//bool ConfigManager<ConfigContainer>::erase()
//{
// ESP_LOGW(TAG, "called");
// nvs_close(nvs_handle_user);
// const auto err = nvs_flash_erase();
// ESP_LOG_LEVEL_LOCAL((err == ESP_OK ? ESP_LOG_INFO : ESP_LOG_ERROR), TAG, "nvs_flash_erase() returned: %s", esp_err_to_name(err));
// if (err != ESP_OK)
// return false;
// return init();
//}
template<typename ConfigContainer>
ConfigStatusReturnType ConfigManager<ConfigContainer>::reset()
{
ESP_LOGW(TAG, "called");
std::string message;
for (ConfigWrapperInterface &config : ConfigContainer::getAllConfigParams())
if (const auto result = reset_config(config); !result)
{
if (!message.empty())
message.append(", ");
message.append(fmt::format("reset of {} failed: {}", config.nvsName(), result.error()));
}
if (!message.empty())
return tl::make_unexpected(std::move(message));
return {};
}
template<typename ConfigContainer>
ConfigWrapperInterface *ConfigManager<ConfigContainer>::findConfigByKey(std::string_view key)
{
const auto configParams = ConfigContainer::getAllConfigParams();
const auto iter = std::find_if(std::cbegin(configParams), std::cend(configParams),
[&key](const ConfigWrapperInterface &config){ return key == config.nvsName(); });
return iter != std::cend(configParams) ? &iter->get() : nullptr;
}
} // namespace espconfig