Compare commits

9 Commits

12 changed files with 79 additions and 33 deletions

View File

@ -36,8 +36,8 @@ set(dependencies
espwifistack
date
espchrono
expected
fmt
nvs_flash
)
idf_component_register(

View File

@ -2,9 +2,9 @@
// system includes
#include <string>
#include <expected>
// 3rdparty lib includes
#include <tl/expected.hpp>
#include <fmt/core.h>
// local includes
@ -16,7 +16,7 @@ template<int MAX_LENGTH>
ConfigConstraintReturnType StringMaxSize(const std::string &str)
{
if (str.size() > MAX_LENGTH)
return tl::make_unexpected(fmt::format("String length {} exceeds maximum {}", str.size(), MAX_LENGTH));
return std::unexpected(fmt::format("String length {} exceeds maximum {}", str.size(), MAX_LENGTH));
return {};
}
@ -24,14 +24,14 @@ template<int MIN_LENGTH, int MAX_LENGTH>
ConfigConstraintReturnType StringMinMaxSize(const std::string &str)
{
if (str.size() < MIN_LENGTH || str.size() > MAX_LENGTH)
return tl::make_unexpected(fmt::format("String length {} exceeds range {} to {}", str.size(), MIN_LENGTH, MAX_LENGTH));
return std::unexpected(fmt::format("String length {} exceeds range {} to {}", str.size(), MIN_LENGTH, MAX_LENGTH));
return {};
}
inline ConfigConstraintReturnType StringEmpty(const std::string &str)
{
if (!str.empty())
return tl::make_unexpected("String has to be empty");
return std::unexpected("String has to be empty");
return {};
}
@ -49,16 +49,43 @@ ConfigConstraintReturnType StringOr(const std::string &str)
const auto result1 = callback1(str);
if (result1)
return {};
return tl::make_unexpected(fmt::format("None of the following 2 constraints succeded: {} | {}", result0.error(), result1.error()));
return std::unexpected(fmt::format("None of the following 2 constraints succeded: {} | {}", result0.error(), result1.error()));
}
template<ConfigWrapper<std::string>::ConstraintCallback callback0, ConfigWrapper<std::string>::ConstraintCallback callback1, ConfigWrapper<std::string>::ConstraintCallback callback2>
ConfigConstraintReturnType StringOr(const std::string &str)
{
const auto result0 = callback0(str);
if (result0)
return {};
const auto result1 = callback1(str);
if (result1)
return {};
const auto result2 = callback2(str);
if (result2)
return {};
return std::unexpected(fmt::format("None of the following 3 constraints succeded: {} | {} | {}", result0.error(), result1.error(), result2.error()));
}
template<ConfigWrapper<std::string>::ConstraintCallback callback0, ConfigWrapper<std::string>::ConstraintCallback callback1>
ConfigConstraintReturnType StringAnd(const std::string &str)
{
if (const auto result = callback0(str); !result)
return tl::make_unexpected(result.error());
return std::unexpected(result.error());
if (const auto result = callback1(str); !result)
return tl::make_unexpected(result.error());
return std::unexpected(result.error());
return {};
}
template<ConfigWrapper<std::string>::ConstraintCallback callback0, ConfigWrapper<std::string>::ConstraintCallback callback1, ConfigWrapper<std::string>::ConstraintCallback callback2>
ConfigConstraintReturnType StringAnd(const std::string &str)
{
if (const auto result = callback0(str); !result)
return std::unexpected(result.error());
if (const auto result = callback1(str); !result)
return std::unexpected(result.error());
if (const auto result = callback2(str); !result)
return std::unexpected(result.error());
return {};
}
@ -66,7 +93,7 @@ template<typename T, T ... ALLOWED_VALUES>
ConfigConstraintReturnType OneOf(typename ConfigWrapper<T>::value_t val)
{
if (!((ALLOWED_VALUES == val) || ...))
tl::make_unexpected("Value not one of the allowed ones");
return std::unexpected("Value not one of the allowed ones");
return {};
}
@ -74,7 +101,7 @@ template<typename T, T MIN_VALUE>
ConfigConstraintReturnType MinValue(typename ConfigWrapper<T>::value_t val)
{
if (val < MIN_VALUE)
return tl::make_unexpected(fmt::format("Value {} exceeds minimum {}", val, MIN_VALUE));
return std::unexpected(fmt::format("Value {} exceeds minimum {}", val, MIN_VALUE));
return {};
}
@ -82,7 +109,7 @@ template<typename T, T MAX_VALUE>
ConfigConstraintReturnType MaxValue(typename ConfigWrapper<T>::value_t val)
{
if (val > MAX_VALUE)
return tl::make_unexpected(fmt::format("Value {} exceeds maximum {}", val, MAX_VALUE));
return std::unexpected(fmt::format("Value {} exceeds maximum {}", val, MAX_VALUE));
return {};
}
@ -90,7 +117,7 @@ template<typename T, T MIN_VALUE, T MAX_VALUE>
ConfigConstraintReturnType MinMaxValue(typename ConfigWrapper<T>::value_t val)
{
if (val < MIN_VALUE || val > MAX_VALUE)
return tl::make_unexpected(fmt::format("Value {} exceeds range {} to {}", val, MIN_VALUE, MAX_VALUE));
return std::unexpected(fmt::format("Value {} exceeds range {} to {}", val, MIN_VALUE, MAX_VALUE));
return {};
}
@ -98,7 +125,7 @@ template<typename T>
ConfigConstraintReturnType MinMaxValue(typename ConfigWrapper<T>::value_t val, T MIN_VALUE, T MAX_VALUE)
{
if (val < MIN_VALUE || val > MAX_VALUE)
return tl::make_unexpected(fmt::format("Value {} exceeds range {} to {}", val, MIN_VALUE, MAX_VALUE));
return std::unexpected(fmt::format("Value {} exceeds range {} to {}", val, MIN_VALUE, MAX_VALUE));
return {};
}
@ -106,7 +133,7 @@ template<typename T, T MIN_VALUE, T MAX_VALUE>
ConfigConstraintReturnType MinMaxOrZeroValue(typename ConfigWrapper<T>::value_t val)
{
if (val != 0 && (val < MIN_VALUE || val > MAX_VALUE))
return tl::make_unexpected(fmt::format("Value {} exceeds constraint 0 or range {} to {}", val, MIN_VALUE, MAX_VALUE));
return std::unexpected(fmt::format("Value {} exceeds constraint 0 or range {} to {}", val, MIN_VALUE, MAX_VALUE));
return {};
}
} // namespace espconfig

View File

@ -2,9 +2,9 @@
// system includes
#include <string>
#include <expected>
// 3rdparty lib includes
#include <tl/expected.hpp>
#include <fmt/core.h>
// local includes
@ -16,7 +16,7 @@ inline ConfigConstraintReturnType MinTimeSyncInterval(espchrono::milliseconds32
{
using namespace std::chrono_literals;
if (val < 15s)
return tl::make_unexpected("SNTPv4 RFC 4330 enforces a minimum update time of 15 seconds");
return std::unexpected("SNTPv4 RFC 4330 enforces a minimum update time of 15 seconds");
return {};
}
} // namespace espconfig

View File

@ -22,6 +22,9 @@ public:
#endif
esp_err_t init(const char *ns);
esp_err_t loadFromFlash();
//bool erase();
ConfigStatusReturnType reset();

View File

@ -12,6 +12,7 @@
#define INSTANTIATE_CONFIGMANAGER_TEMPLATES(Type) \
namespace espconfig { \
template esp_err_t ConfigManager<Type>::init(const char *ns); \
template esp_err_t ConfigManager<Type>::loadFromFlash(); \
/* template bool ConfigManager<Type>::erase(); */ \
template ConfigStatusReturnType ConfigManager<Type>::reset(); \
template ConfigWrapperInterface *ConfigManager<Type>::findConfigByKey(std::string_view key); \
@ -108,7 +109,13 @@ esp_err_t ConfigManager<ConfigContainer>::init(const char *ns)
ESP_LOGI(TAG, "initializing NVS took %lldms", std::chrono::floor<std::chrono::milliseconds>(after-before).count());
before = espchrono::millis_clock::now();
return loadFromFlash();
}
template<typename ConfigContainer>
esp_err_t ConfigManager<ConfigContainer>::loadFromFlash()
{
const auto before = espchrono::millis_clock::now();
bool success = true;
ConfigContainer::callForEveryConfig([&](ConfigWrapperInterface &config){
@ -120,7 +127,7 @@ esp_err_t ConfigManager<ConfigContainer>::init(const char *ns)
return false; // dont abort the loop
});
after = espchrono::millis_clock::now();
const auto after = espchrono::millis_clock::now();
ESP_LOGI(TAG, "loading all config params took %lldms", std::chrono::floor<std::chrono::milliseconds>(after-before).count());
@ -159,7 +166,7 @@ ConfigStatusReturnType ConfigManager<ConfigContainer>::reset()
});
if (!message.empty())
return tl::make_unexpected(std::move(message));
return std::unexpected(std::move(message));
return {};
}

View File

@ -3,21 +3,23 @@
// system includes
#include <cstdint>
#include <string>
#include <bit>
// esp-idf includes
#include <nvs.h>
// local includes
#include "futurecpp.h"
namespace espconfig {
inline esp_err_t nvs_get(nvs_handle handle, const char* key, int8_t* out_value) { return nvs_get_i8 (handle, key, out_value); }
inline esp_err_t nvs_get(nvs_handle handle, const char* key, uint8_t* out_value) { return nvs_get_u8 (handle, key, out_value); }
//inline esp_err_t nvs_get(nvs_handle handle, const char* key, char* out_value) { return nvs_get_i8 (handle, key, (int8_t*)out_value); }
//inline esp_err_t nvs_get(nvs_handle handle, const char* key, unsigned char* out_value) { return nvs_get_u8 (handle, key, (uint8_t*)out_value); }
inline esp_err_t nvs_get(nvs_handle handle, const char* key, int16_t* out_value) { return nvs_get_i16(handle, key, out_value); }
inline esp_err_t nvs_get(nvs_handle handle, const char* key, uint16_t* out_value){ return nvs_get_u16(handle, key, out_value); }
inline esp_err_t nvs_get(nvs_handle handle, const char* key, int32_t* out_value) { return nvs_get_i32(handle, key, out_value); }
inline esp_err_t nvs_get(nvs_handle handle, const char* key, uint32_t* out_value){ return nvs_get_u32(handle, key, out_value); }
inline esp_err_t nvs_get(nvs_handle handle, const char* key, int* out_value) { return nvs_get_i32(handle, key, (int32_t*)out_value); }
inline esp_err_t nvs_get(nvs_handle handle, const char* key, unsigned int* out_value){ return nvs_get_u32(handle, key, (uint32_t*)out_value); }
inline esp_err_t nvs_get(nvs_handle handle, const char* key, int64_t* out_value) { return nvs_get_i64(handle, key, out_value); }
inline esp_err_t nvs_get(nvs_handle handle, const char* key, uint64_t* out_value){ return nvs_get_u64(handle, key, out_value); }
inline esp_err_t nvs_get(nvs_handle handle, const char* key, bool* out_value)
@ -67,6 +69,8 @@ inline esp_err_t nvs_set(nvs_handle handle, const char* key, int16_t value)
inline esp_err_t nvs_set(nvs_handle handle, const char* key, uint16_t value) { return nvs_set_u16(handle, key, value); }
inline esp_err_t nvs_set(nvs_handle handle, const char* key, int32_t value) { return nvs_set_i32(handle, key, value); }
inline esp_err_t nvs_set(nvs_handle handle, const char* key, uint32_t value) { return nvs_set_u32(handle, key, value); }
inline esp_err_t nvs_set(nvs_handle handle, const char* key, int value) { return nvs_set_i32(handle, key, value); }
inline esp_err_t nvs_set(nvs_handle handle, const char* key, unsigned int value) { return nvs_set_u32(handle, key, value); }
inline esp_err_t nvs_set(nvs_handle handle, const char* key, const int64_t &value) { return nvs_set_i64(handle, key, value); }
inline esp_err_t nvs_set(nvs_handle handle, const char* key, const uint64_t &value) { return nvs_set_u64(handle, key, value); }
inline esp_err_t nvs_set(nvs_handle handle, const char* key, bool value) { return nvs_set_u8 (handle, key, value); }

View File

@ -2,6 +2,7 @@
// system includes
#include <type_traits>
#include <utility>
// esp-idf includes
#include <nvs.h>
@ -22,6 +23,6 @@
\
inline esp_err_t nvs_set(nvs_handle handle, const char* key, Name value) \
{ \
return nvs_set(handle, key, std::underlying_type_t<Name>(value)); \
return nvs_set(handle, key, std::to_underlying(value)); \
} \
} // namespace espconfig

View File

@ -3,9 +3,7 @@
// system includes
#include <string>
#include <type_traits>
// 3rdparty lib includes
#include <tl/expected.hpp>
#include <expected>
// local includes
#include "configwrapperinterface.h"
@ -21,7 +19,7 @@ class ConfigWrapper : public ConfigWrapperInterface
CPP_DISABLE_COPY_MOVE(ConfigWrapper)
public:
using value_t = typename std::conditional<std::is_same<T, std::string>::value, const T &, T>::type;
using value_t = std::conditional_t<std::is_same<T, std::string>::value, const T &, T>;
using ConstraintCallback = ConfigConstraintReturnType(*)(value_t);
ConfigWrapper() = default;

View File

@ -10,6 +10,7 @@ INSTANTIATE_CONFIGWRAPPER_TEMPLATES(uint16_t)
INSTANTIATE_CONFIGWRAPPER_TEMPLATES(int16_t)
INSTANTIATE_CONFIGWRAPPER_TEMPLATES(uint32_t)
INSTANTIATE_CONFIGWRAPPER_TEMPLATES(int32_t)
INSTANTIATE_CONFIGWRAPPER_TEMPLATES(int)
INSTANTIATE_CONFIGWRAPPER_TEMPLATES(uint64_t)
INSTANTIATE_CONFIGWRAPPER_TEMPLATES(int64_t)
INSTANTIATE_CONFIGWRAPPER_TEMPLATES(float)

View File

@ -9,6 +9,8 @@ INSTANTIATE_CONFIGWRAPPER_TEMPLATES(std::optional<int16_t>)
INSTANTIATE_CONFIGWRAPPER_TEMPLATES(std::optional<uint16_t>)
INSTANTIATE_CONFIGWRAPPER_TEMPLATES(std::optional<int32_t>)
INSTANTIATE_CONFIGWRAPPER_TEMPLATES(std::optional<uint32_t>)
INSTANTIATE_CONFIGWRAPPER_TEMPLATES(std::optional<int>)
INSTANTIATE_CONFIGWRAPPER_TEMPLATES(std::optional<unsigned int>)
INSTANTIATE_CONFIGWRAPPER_TEMPLATES(std::optional<int64_t>)
INSTANTIATE_CONFIGWRAPPER_TEMPLATES(std::optional<uint64_t>)
INSTANTIATE_CONFIGWRAPPER_TEMPLATES(std::optional<float>)

View File

@ -1,6 +1,9 @@
#pragma once
#include "sdkconfig.h"
#pragma push_macro("LOG_LOCAL_LEVEL")
#undef LOG_LOCAL_LEVEL
#define LOG_LOCAL_LEVEL CONFIG_LOG_LOCAL_LEVEL_CONFIG
// system includes
@ -150,7 +153,7 @@ ConfigStatusReturnType ConfigWrapper<T>::forceReset(nvs_handle_t nvsHandle)
}
if (result != ESP_OK)
return tl::make_unexpected(std::string{"nvs_erase_key() failed with "} + esp_err_to_name(result));
return std::unexpected(std::string{"nvs_erase_key() failed with "} + esp_err_to_name(result));
return {};
}
@ -170,8 +173,10 @@ ConfigStatusReturnType ConfigWrapper<T>::writeToFlash(nvs_handle_t nvsHandle, va
m_touched = true;
if (result != ESP_OK)
return tl::make_unexpected(std::string{"nvs_set() failed with "} + esp_err_to_name(result));
return std::unexpected(std::string{"nvs_set() failed with "} + esp_err_to_name(result));
return {};
}
} // namespace espconfig
#pragma pop_macro("LOG_LOCAL_LEVEL")

View File

@ -2,19 +2,17 @@
// system includes
#include <string>
#include <expected>
// esp-idf includes
#include <nvs.h>
// 3rdparty lib includes
#include <tl/expected.hpp>
// local includes
#include "cppmacros.h"
namespace espconfig {
using ConfigStatusReturnType = tl::expected<void, std::string>;
using ConfigStatusReturnType = std::expected<void, std::string>;
class ConfigWrapperInterface
{