nvs_handle.hpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. #ifndef NVS_HANDLE_HPP_
  2. #define NVS_HANDLE_HPP_
  3. #include <string>
  4. #include <memory>
  5. #include <type_traits>
  6. #include "nvs.h"
  7. namespace nvs {
  8. /**
  9. * The possible blob types. This is a helper definition for template functions.
  10. */
  11. enum class ItemType : uint8_t {
  12. U8 = NVS_TYPE_U8,
  13. I8 = NVS_TYPE_I8,
  14. U16 = NVS_TYPE_U16,
  15. I16 = NVS_TYPE_I16,
  16. U32 = NVS_TYPE_U32,
  17. I32 = NVS_TYPE_I32,
  18. U64 = NVS_TYPE_U64,
  19. I64 = NVS_TYPE_I64,
  20. SZ = NVS_TYPE_STR,
  21. BLOB = 0x41,
  22. BLOB_DATA = NVS_TYPE_BLOB,
  23. BLOB_IDX = 0x48,
  24. ANY = NVS_TYPE_ANY
  25. };
  26. /**
  27. * @brief A handle allowing nvs-entry related operations on the NVS.
  28. *
  29. * @note The scope of this handle may vary depending on the implementation, but normally would be the namespace of
  30. * a particular partition. Outside that scope, nvs entries can't be accessed/altered.
  31. */
  32. class NVSHandle {
  33. public:
  34. virtual ~NVSHandle() { }
  35. /**
  36. * @brief set value for given key
  37. *
  38. * Sets value for key. Note that physical storage will not be updated until nvs_commit function is called.
  39. *
  40. * @param[in] key Key name. Maximal length is determined by the underlying
  41. * implementation, but is guaranteed to be at least
  42. * 15 characters. Shouldn't be empty.
  43. * @param[in] value The value to set. Allowed types are the ones declared in ItemType as well as enums.
  44. * For strings, the maximum length (including null character) is
  45. * 4000 bytes.
  46. * Note that enums loose their type information when stored in NVS. Ensure that the correct
  47. * enum type is used during retrieval with \ref get_item!
  48. *
  49. * @return
  50. * - ESP_OK if value was set successfully
  51. * - ESP_ERR_NVS_READ_ONLY if storage handle was opened as read only
  52. * - ESP_ERR_NVS_INVALID_NAME if key name doesn't satisfy constraints
  53. * - ESP_ERR_NVS_NOT_ENOUGH_SPACE if there is not enough space in the
  54. * underlying storage to save the value
  55. * - ESP_ERR_NVS_REMOVE_FAILED if the value wasn't updated because flash
  56. * write operation has failed. The value was written however, and
  57. * update will be finished after re-initialization of nvs, provided that
  58. * flash operation doesn't fail again.
  59. * - ESP_ERR_NVS_VALUE_TOO_LONG if the string value is too long
  60. */
  61. template<typename T>
  62. esp_err_t set_item(const char *key, T value);
  63. virtual
  64. esp_err_t set_string(const char *key, const char* value) = 0;
  65. /**
  66. * @brief get value for given key
  67. *
  68. * These functions retrieve value for the key, given its name. If key does not
  69. * exist, or the requested variable type doesn't match the type which was used
  70. * when setting a value, an error is returned.
  71. *
  72. * In case of any error, out_value is not modified.
  73. *
  74. * @param[in] key Key name. Maximal length is determined by the underlying
  75. * implementation, but is guaranteed to be at least
  76. * 15 characters. Shouldn't be empty.
  77. * @param value The output value. All integral types which are declared in ItemType as well as enums
  78. * are allowed. Note however that enums lost their type information when stored in NVS.
  79. * Ensure that the correct enum type is used during retrieval with \ref get_item!
  80. *
  81. * @return
  82. * - ESP_OK if the value was retrieved successfully
  83. * - ESP_ERR_NVS_NOT_FOUND if the requested key doesn't exist
  84. * - ESP_ERR_NVS_INVALID_NAME if key name doesn't satisfy constraints
  85. * - ESP_ERR_NVS_INVALID_LENGTH if length is not sufficient to store data
  86. */
  87. template<typename T>
  88. esp_err_t get_item(const char *key, T &value);
  89. /**
  90. * @brief set variable length binary value for given key
  91. *
  92. * This family of functions set value for the key, given its name. Note that
  93. * actual storage will not be updated until nvs_commit function is called.
  94. *
  95. * @param[in] key Key name. Maximal length is 15 characters. Shouldn't be empty.
  96. * @param[in] blob The blob value to set.
  97. * @param[in] len length of binary value to set, in bytes; Maximum length is
  98. * 508000 bytes or (97.6% of the partition size - 4000) bytes
  99. * whichever is lower.
  100. *
  101. * @return
  102. * - ESP_OK if value was set successfully
  103. * - ESP_ERR_NVS_READ_ONLY if storage handle was opened as read only
  104. * - ESP_ERR_NVS_INVALID_NAME if key name doesn't satisfy constraints
  105. * - ESP_ERR_NVS_NOT_ENOUGH_SPACE if there is not enough space in the
  106. * underlying storage to save the value
  107. * - ESP_ERR_NVS_REMOVE_FAILED if the value wasn't updated because flash
  108. * write operation has failed. The value was written however, and
  109. * update will be finished after re-initialization of nvs, provided that
  110. * flash operation doesn't fail again.
  111. * - ESP_ERR_NVS_VALUE_TOO_LONG if the value is too long
  112. *
  113. * @note compare to \ref nvs_set_blob in nvs.h
  114. */
  115. virtual esp_err_t set_blob(const char *key, const void* blob, size_t len) = 0;
  116. /**
  117. * @brief get value for given key
  118. *
  119. * These functions retrieve the data of an entry, given its key. If key does not
  120. * exist, or the requested variable type doesn't match the type which was used
  121. * when setting a value, an error is returned.
  122. *
  123. * In case of any error, out_value is not modified.
  124. *
  125. * Both functions expect out_value to be a pointer to an already allocated variable
  126. * of the given type.
  127. *
  128. * It is suggested that nvs_get/set_str is used for zero-terminated C strings, and
  129. * nvs_get/set_blob used for arbitrary data structures.
  130. *
  131. * @param[in] key Key name. Maximal length is determined by the underlying
  132. * implementation, but is guaranteed to be at least
  133. * 15 characters. Shouldn't be empty.
  134. * @param out_str/ Pointer to the output value.
  135. * out_blob
  136. * @param[inout] length A non-zero pointer to the variable holding the length of out_value.
  137. * It will be set to the actual length of the value
  138. * written. For nvs_get_str this includes the zero terminator.
  139. *
  140. * @return
  141. * - ESP_OK if the value was retrieved successfully
  142. * - ESP_ERR_NVS_NOT_FOUND if the requested key doesn't exist
  143. * - ESP_ERR_NVS_INVALID_NAME if key name doesn't satisfy constraints
  144. * - ESP_ERR_NVS_INVALID_LENGTH if length is not sufficient to store data
  145. */
  146. virtual esp_err_t get_string(const char *key, char* out_str, size_t len) = 0;
  147. virtual esp_err_t get_blob(const char *key, void* out_blob, size_t len) = 0;
  148. /**
  149. * @brief Looks up the size of an entry's data.
  150. *
  151. * For strings, this size includes the zero terminator.
  152. */
  153. virtual esp_err_t get_item_size(ItemType datatype, const char *key, size_t &size) = 0;
  154. /**
  155. * @brief Erases an entry.
  156. */
  157. virtual esp_err_t erase_item(const char* key) = 0;
  158. /**
  159. * Erases all entries in the scope of this handle. The scope may vary, depending on the implementation.
  160. *
  161. * @not If you want to erase the whole nvs flash (partition), refer to \ref
  162. */
  163. virtual esp_err_t erase_all() = 0;
  164. /**
  165. * Commits all changes done through this handle so far.
  166. */
  167. virtual esp_err_t commit() = 0;
  168. /**
  169. * @brief Calculate all entries in the scope of the handle.
  170. *
  171. * @param[out] used_entries Returns amount of used entries from a namespace on success.
  172. *
  173. *
  174. * @return
  175. * - ESP_OK if the changes have been written successfully.
  176. * Return param used_entries will be filled valid value.
  177. * - ESP_ERR_NVS_NOT_INITIALIZED if the storage driver is not initialized.
  178. * Return param used_entries will be filled 0.
  179. * - ESP_ERR_INVALID_ARG if nvs_stats equal to NULL.
  180. * - Other error codes from the underlying storage driver.
  181. * Return param used_entries will be filled 0.
  182. */
  183. virtual esp_err_t get_used_entry_count(size_t& usedEntries) = 0;
  184. protected:
  185. virtual esp_err_t set_typed_item(ItemType datatype, const char *key, const void* data, size_t dataSize) = 0;
  186. virtual esp_err_t get_typed_item(ItemType datatype, const char *key, void* data, size_t dataSize) = 0;
  187. };
  188. /**
  189. * @brief Opens non-volatile storage and returns a handle object.
  190. *
  191. * The handle is automatically closed on desctruction. The scope of the handle is the namespace ns_name
  192. * in a particular partition partition_name.
  193. * The parameters partition_name, ns_name and open_mode have the same meaning and restrictions as the parameters
  194. * part_name, name and open_mode in \ref nvs_open_from_partition, respectively.
  195. *
  196. * @param err an optional pointer to an esp_err_t result of the open operation, having the same meaning as the return
  197. * value in \ref nvs_open_from_partition:
  198. * - ESP_OK if storage handle was opened successfully
  199. * - ESP_ERR_NVS_NOT_INITIALIZED if the storage driver is not initialized
  200. * - ESP_ERR_NVS_PART_NOT_FOUND if the partition with label "nvs" is not found
  201. * - ESP_ERR_NVS_NOT_FOUND id namespace doesn't exist yet and
  202. * mode is NVS_READONLY
  203. * - ESP_ERR_NVS_INVALID_NAME if namespace name doesn't satisfy constraints
  204. * - other error codes from the underlying storage driver
  205. *
  206. * @return shared pointer of an nvs handle on success, an empty shared pointer otherwise
  207. */
  208. std::unique_ptr<NVSHandle> open_nvs_handle_from_partition(const char *partition_name,
  209. const char *ns_name,
  210. nvs_open_mode_t open_mode,
  211. esp_err_t *err = nullptr);
  212. /**
  213. * @brief This function does the same as \ref open_nvs_handle_from_partition but uses the default nvs partition
  214. * instead of a partition_name parameter.
  215. */
  216. std::unique_ptr<NVSHandle> open_nvs_handle(const char *ns_name,
  217. nvs_open_mode_t open_mode,
  218. esp_err_t *err = nullptr);
  219. // Helper functions for template usage
  220. /**
  221. * Help to translate all integral types into ItemType.
  222. */
  223. template<typename T, typename std::enable_if<std::is_integral<T>::value, void*>::type = nullptr>
  224. constexpr ItemType itemTypeOf()
  225. {
  226. return static_cast<ItemType>(((std::is_signed<T>::value)?0x10:0x00) | sizeof(T));
  227. }
  228. /**
  229. * Help to translate all enum types into integral ItemType.
  230. */
  231. template<typename T, typename std::enable_if<std::is_enum<T>::value, int>::type = 0>
  232. constexpr ItemType itemTypeOf()
  233. {
  234. return static_cast<ItemType>(((std::is_signed<T>::value)?0x10:0x00) | sizeof(T));
  235. }
  236. template<typename T>
  237. constexpr ItemType itemTypeOf(const T&)
  238. {
  239. return itemTypeOf<T>();
  240. }
  241. // Template Implementations
  242. template<typename T>
  243. esp_err_t NVSHandle::set_item(const char *key, T value) {
  244. return set_typed_item(itemTypeOf(value), key, &value, sizeof(value));
  245. }
  246. template<typename T>
  247. esp_err_t NVSHandle::get_item(const char *key, T &value) {
  248. return get_typed_item(itemTypeOf(value), key, &value, sizeof(value));
  249. }
  250. } // nvs
  251. #endif // NVS_HANDLE_HPP_