如何将 ESP32 NVS 值读入 std::string

在我们之前的文章中,我们讨论了如何获取 ESP32 上 NVS 值的长度/大小。基于此,我们可以将 NVS 值读入 std::string

策略

  1. 确定 NVS 中值的大小
  2. 分配确定大小的临时缓冲区
  3. 从 NVS 读取值到临时缓冲区
  4. 从值创建 std::string
  5. 清理临时缓冲区

将 NVS 值读取为 std::string 的实用函数

如果键在 NVS 中不存在,此函数将返回空字符串("")。

read_nvs_to_stdstring.cpp
#include <nvs.h>
#include <string>

std::string ReadNVSValueAsStdString(nvs_handle_t nvs, const char* key) {
    /**
     * Strategy:
     *  1. 确定 NVS 中值的大小
     *  2. Allocate temporary buffer of determined size
     *  3. 从 NVS 读取值到临时缓冲区
     *  4. Create std::string from value
     *  5. Cleanup
     */
    // 步骤 1:获取键的大小
    esp_err_t err;
    size_t value_size = 0;
    if((err = nvs_get_str(nvs, _key.c_str(), nullptr, &value_size)) != ESP_OK) {
        if(err == ESP_ERR_NVS_NOT_FOUND) {
            // 未找到,无错误
            return "";
        } else {
            printf("获取 NVS 键 %s 的大小失败:%s\r\n", key, esp_err_to_name(err));
            return;
        }
    }
    // 步骤 2:分配要读取的临时缓冲区
    char* buf = (char*)malloc(value_size);
    // 步骤 3:将值读入临时缓冲区。
    esp_err_t err;
    if((err = nvs_get_str(nvs, _key.c_str(), buf, &value_size)) != ESP_OK) {
        // "不存在"已在之前处理过,所以这是一个实际错误。
        // 我们假设值在读取大小(步骤 1)和现在之间没有改变。
        // 如果该假设有效,这将失败并返回 ESP_ERR_NVS_INVALID_LENGTH。
        // 然而,这在所有使用场景中极不可能。
        printf("读取 NVS 键 %s 失败:%s\r\n", key, esp_err_to_name(err));
        free(buf);
        return "";
    }
    // 步骤 4:创建字符串
    std::string value = std::string(buf, value_size);
    // 步骤 5:清理
    free(buf);

    return value;
}

使用示例

这假设你已按照我们之前的文章如何在 ESP32 上初始化 NVS中所示设置了 myNvs

example_usage.cpp
std::string value = ReadNVSValueAsStdString(myNvs, "MyKey");

C++17 优化

从 C++17 开始,你可以直接创建 std::string 而不是使用临时缓冲区,因为有一个 .data() 的重载返回非 const 指针 - 所以你可以直接写入 std::string 的缓冲区。

但是,由于我基于 PlatformIO 的工具链目前不支持这一点,我还没有编写该代码。


Check out similar posts by category: C/C++, ESP8266/ESP32