/** * @file nvsIo.cpp * @author Gustice * @brief Read-Write access to specific NVS partition * * @copyright Copyright (c) 2024 */ #include "nvsIo.hpp" #include "esp_err.h" #include "esp_log.h" #include #include static const char *TAG = "NVS"; static esp_err_t storeBlob(nvs_handle_t nvs, const char *key, const char *str_values) { uint8_t value; size_t str_len = strlen(str_values); size_t blob_len = str_len / 2; if (str_len % 2) { ESP_LOGE(TAG, "Blob data must contain even number of characters"); return ESP_ERR_NVS_TYPE_MISMATCH; } char *blob = (char *)malloc(blob_len); if (blob == NULL) { return ESP_ERR_NO_MEM; } for (int i = 0, j = 0; i < str_len; i++) { char ch = str_values[i]; if (ch >= '0' && ch <= '9') { value = ch - '0'; } else if (ch >= 'A' && ch <= 'F') { value = ch - 'A' + 10; } else if (ch >= 'a' && ch <= 'f') { value = ch - 'a' + 10; } else { ESP_LOGE(TAG, "Blob data contain invalid character"); free(blob); return ESP_ERR_NVS_TYPE_MISMATCH; } if (i & 1) { blob[j++] += value; } else { blob[j] = value << 4; } } esp_err_t err = nvs_set_blob(nvs, key, blob, blob_len); free(blob); if (err == ESP_OK) { err = nvs_commit(nvs); } return err; } template <> esp_err_t NvsIo::setValueByStr(const char *key, const char *strValue) { int32_t value = strtol(strValue, NULL, 0); if (value < INT8_MIN || value > INT8_MAX || errno == ERANGE) { throw CoreException(ErrMsg_TooLong); } return setInt8(key, (int8_t)value); } template <> esp_err_t NvsIo::setValueByStr(const char *key, const char *strValue) { uint32_t value = strtoul(strValue, NULL, 0); if (value > UINT8_MAX || errno == ERANGE) { throw CoreException(ErrMsg_TooLong); } return setUint8(key, (uint8_t)value); } template <> esp_err_t NvsIo::setValueByStr(const char *key, const char *strValue) { int32_t value = strtol(strValue, NULL, 0); if (value < INT16_MIN || value > INT16_MAX || errno == ERANGE) { throw CoreException(ErrMsg_TooLong); } return setInt16(key, (int16_t)value); } template <> esp_err_t NvsIo::setValueByStr(const char *key, const char *strValue) { uint32_t value = strtoul(strValue, NULL, 0); if (value > UINT16_MAX || errno == ERANGE) { throw CoreException(ErrMsg_TooLong); } return setUint16(key, (uint16_t)value); } template <> esp_err_t NvsIo::setValueByStr(const char *key, const char *strValue) { int32_t value = strtol(strValue, NULL, 0); if (errno == ERANGE) { throw CoreException(ErrMsg_TooLong); } return setInt32(key, value); } template <> esp_err_t NvsIo::setValueByStr(const char *key, const char *strValue) { uint32_t value = strtoul(strValue, NULL, 0); if (errno == ERANGE) { throw CoreException(ErrMsg_TooLong); } return setUint32(key, value); } template <> esp_err_t NvsIo::setValueByStr(const char *key, const char *strValue) { int64_t value = strtoll(strValue, NULL, 0); if (errno == ERANGE) { throw CoreException(ErrMsg_TooLong); } return setInt64(key, value); } template <> esp_err_t NvsIo::setValueByStr(const char *key, const char *strValue) { uint64_t value = strtoull(strValue, NULL, 0); if (errno == ERANGE) { throw CoreException(ErrMsg_TooLong); } return setUint64(key, value); } esp_err_t NvsIo::setString(const char *key, const char *strValue) { return nvs_set_str(_nvs, key, strValue); } esp_err_t NvsIo::setBlob(const char *key, const char *strValue) { return storeBlob(_nvs, key, strValue); } std::optional NvsIo::getString(const char *key) { size_t len; if (nvs_get_str(_nvs, key, NULL, &len) != ESP_OK) { return {std::nullopt}; } auto str = std::make_unique(len); if ((nvs_get_str(_nvs, key, str.get(), &len)) != ESP_OK) { return {std::nullopt}; } return {str.get()}; } std::optional> NvsIo::getBlob(const char *key) { size_t len; if (nvs_get_blob(_nvs, key, NULL, &len) != ESP_OK) { return {std::nullopt}; } auto blob = std::make_unique(len); if (nvs_get_blob(_nvs, key, blob.get(), &len) != ESP_OK) { return {std::nullopt}; } std::vector vec; vec.reserve(len); vec.insert(vec.end(), blob.get(), blob.get() + len); return {vec}; }