Files
deckenlampe/main/configwrapper.h
T
2021-07-15 16:38:04 +02:00

151 lines
6.8 KiB
C++

#pragma once
// system includes
#include <string>
#include <cstdint>
#include <utility>
// esp-idf includes
#include <nvs.h>
#include <hal/gpio_types.h>
// 3rdparty lib includes
#include <tl/expected.hpp>
#include <fmt/core.h>
// local includes
#include "espchrono.h"
#include "futurecpp.h"
namespace deckenlampe {
extern nvs_handle_t nvsHandle;
template<typename T> esp_err_t nvs_get(nvs_handle handle, const char* key, T* out_value) = delete;
template<typename T> esp_err_t nvs_set(nvs_handle handle, const char* key, T value) = delete;
template<typename T>
class ConfigWrapper
{
public:
ConfigWrapper(const char *key, const T &value) : m_key{key}, m_value{value} {}
const char *key() const { return m_key; }
const T &value() const { return m_value; }
void setValue(const T &value) { m_value = value; }
tl::expected<T, std::string> readFromFlash() const;
tl::expected<void, std::string> writeToFlash(const T &value);
private:
const char * const m_key;
T m_value;
};
template<typename T>
tl::expected<T, std::string> ConfigWrapper<T>::readFromFlash() const
{
T val;
const auto result = nvs_get(nvsHandle, m_key, &val);
//ESP_LOG_LEVEL_LOCAL((result == ESP_OK ? ESP_LOG_INFO : ESP_LOG_ERROR), TAG, "nvs_flash_init(): %s", esp_err_to_name(result));
if (result == ESP_OK)
return val;
else
return tl::make_unexpected(fmt::format("nvs_get() {} failed with {}", m_key, esp_err_to_name(result)));
}
template<typename T>
tl::expected<void, std::string> ConfigWrapper<T>::writeToFlash(const T &value)
{
return {};
}
template<> inline esp_err_t nvs_get(nvs_handle handle, const char* key, int8_t* out_value) { return nvs_get_i8 (handle, key, out_value); }
template<> inline esp_err_t nvs_get(nvs_handle handle, const char* key, uint8_t* out_value) { return nvs_get_u8 (handle, key, out_value); }
template<> inline esp_err_t nvs_get(nvs_handle handle, const char* key, int16_t* out_value) { return nvs_get_i16(handle, key, out_value); }
template<> inline esp_err_t nvs_get(nvs_handle handle, const char* key, uint16_t* out_value){ return nvs_get_u16(handle, key, out_value); }
template<> inline esp_err_t nvs_get(nvs_handle handle, const char* key, int32_t* out_value) { return nvs_get_i32(handle, key, out_value); }
template<> inline esp_err_t nvs_get(nvs_handle handle, const char* key, uint32_t* out_value){ return nvs_get_u32(handle, key, out_value); }
template<> inline esp_err_t nvs_get(nvs_handle handle, const char* key, int64_t* out_value) { return nvs_get_i64(handle, key, out_value); }
template<> inline esp_err_t nvs_get(nvs_handle handle, const char* key, uint64_t* out_value){ return nvs_get_u64(handle, key, out_value); }
template<> inline esp_err_t nvs_get(nvs_handle handle, const char* key, bool* out_value)
{
uint8_t temp;
const auto result = nvs_get(handle, key, &temp);
if (result == ESP_OK && out_value)
*out_value = temp;
return result;
}
template<> inline esp_err_t nvs_get(nvs_handle handle, const char* key, gpio_num_t* out_value)
{
std::underlying_type_t<gpio_num_t> temp;
const auto result = nvs_get(handle, key, &temp);
if (result == ESP_OK && out_value)
*out_value = gpio_num_t(temp);
return result;
}
template<> inline esp_err_t nvs_get(nvs_handle handle, const char* key, float* out_value)
{
uint32_t temp;
const auto result = nvs_get(handle, key, &temp);
if (result == ESP_OK)
*out_value = std::bit_cast<float>(temp);
return result;
}
template<> inline esp_err_t nvs_get(nvs_handle handle, const char* key, double* out_value)
{
uint64_t temp;
const auto result = nvs_get(handle, key, &temp);
if (result == ESP_OK)
*out_value = std::bit_cast<double>(temp);
return result;
}
template<> inline esp_err_t nvs_get(nvs_handle handle, const char* key, std::string* out_value)
{
size_t length;
if (const esp_err_t result = nvs_get_str(handle, key, nullptr, &length); result != ESP_OK)
return result;
char buf[length];
if (const esp_err_t result = nvs_get_str(handle, key, buf, &length); result != ESP_OK)
return result;
*out_value = buf;
return ESP_OK;
}
template<> inline esp_err_t nvs_set(nvs_handle handle, const char* key, int8_t value) { return nvs_set_i8 (handle, key, value); }
template<> inline esp_err_t nvs_set(nvs_handle handle, const char* key, uint8_t value) { return nvs_set_u8 (handle, key, value); }
template<> inline esp_err_t nvs_set(nvs_handle handle, const char* key, int16_t value) { return nvs_set_i16(handle, key, value); }
template<> inline esp_err_t nvs_set(nvs_handle handle, const char* key, uint16_t value) { return nvs_set_u16(handle, key, value); }
template<> inline esp_err_t nvs_set(nvs_handle handle, const char* key, int32_t value) { return nvs_set_i32(handle, key, value); }
template<> inline esp_err_t nvs_set(nvs_handle handle, const char* key, uint32_t value) { return nvs_set_u32(handle, key, value); }
template<> inline esp_err_t nvs_set(nvs_handle handle, const char* key, int64_t value) { return nvs_set_i64(handle, key, value); }
template<> inline esp_err_t nvs_set(nvs_handle handle, const char* key, uint64_t value) { return nvs_set_u64(handle, key, value); }
template<> inline esp_err_t nvs_set(nvs_handle handle, const char* key, bool value) { return nvs_set_u8 (handle, key, value); }
template<> inline esp_err_t nvs_set(nvs_handle handle, const char* key, gpio_num_t value) { return nvs_set (handle, key, std::to_underlying(value)); }
template<> inline esp_err_t nvs_set(nvs_handle handle, const char* key, float value) { return nvs_set(handle, key, std::bit_cast<uint32_t>(value)); }
template<> inline esp_err_t nvs_set(nvs_handle handle, const char* key, double value) { return nvs_set(handle, key, std::bit_cast<uint64_t>(value)); }
template<> inline esp_err_t nvs_set(nvs_handle handle, const char* key, const std::string &value) { return nvs_set_str(handle, key, value.c_str()); }
#define IMPLEMENT_NVS_GET_SET_CHRONO(Name) \
template<> inline esp_err_t nvs_get(nvs_handle handle, const char* key, Name* out_value) \
{ \
Name::rep temp; \
const auto result = nvs_get(handle, key, &temp); \
if (result == ESP_OK && out_value) \
*out_value = Name{temp}; \
return result; \
} \
\
template<> inline esp_err_t nvs_set(nvs_handle handle, const char* key, Name value) { return nvs_set(handle, key, Name::rep(value.count())); }
IMPLEMENT_NVS_GET_SET_CHRONO(espchrono::milliseconds32)
IMPLEMENT_NVS_GET_SET_CHRONO(espchrono::seconds32)
IMPLEMENT_NVS_GET_SET_CHRONO(espchrono::minutes32)
IMPLEMENT_NVS_GET_SET_CHRONO(espchrono::hours32)
#undef IMPLEMENT_NVS_GET_SET_CHRONO
} // namespace deckenlampe