nvs_utilities.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. //#define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE
  2. #include "nvs_utilities.h"
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include "esp_system.h"
  6. #include "esp_log.h"
  7. #include "esp_console.h"
  8. #include "esp_vfs_dev.h"
  9. #include "driver/uart.h"
  10. #include "linenoise/linenoise.h"
  11. #include "argtable3/argtable3.h"
  12. #include "esp_vfs_fat.h"
  13. #include "nvs.h"
  14. #include "nvs_flash.h"
  15. #include "nvs_utilities.h"
  16. #include "config.h"
  17. const char current_namespace[] = "config";
  18. const char settings_partition[] = "settings";
  19. static const char * TAG = "nvs_utilities";
  20. typedef struct {
  21. nvs_type_t type;
  22. const char *str;
  23. } type_str_pair_t;
  24. static const type_str_pair_t type_str_pair[] = {
  25. { NVS_TYPE_I8, "i8" },
  26. { NVS_TYPE_U8, "u8" },
  27. { NVS_TYPE_U16, "u16" },
  28. { NVS_TYPE_I16, "i16" },
  29. { NVS_TYPE_U32, "u32" },
  30. { NVS_TYPE_I32, "i32" },
  31. { NVS_TYPE_U64, "u64" },
  32. { NVS_TYPE_I64, "i64" },
  33. { NVS_TYPE_STR, "str" },
  34. { NVS_TYPE_BLOB, "blob" },
  35. { NVS_TYPE_ANY, "any" },
  36. };
  37. static const size_t TYPE_STR_PAIR_SIZE = sizeof(type_str_pair) / sizeof(type_str_pair[0]);
  38. void print_blob(const char *blob, size_t len)
  39. {
  40. for (int i = 0; i < len; i++) {
  41. printf("%02x", blob[i]);
  42. }
  43. printf("\n");
  44. }
  45. nvs_type_t str_to_type(const char *type)
  46. {
  47. for (int i = 0; i < TYPE_STR_PAIR_SIZE; i++) {
  48. const type_str_pair_t *p = &type_str_pair[i];
  49. if (strcmp(type, p->str) == 0) {
  50. return p->type;
  51. }
  52. }
  53. return NVS_TYPE_ANY;
  54. }
  55. const char *type_to_str(nvs_type_t type)
  56. {
  57. for (int i = 0; i < TYPE_STR_PAIR_SIZE; i++) {
  58. const type_str_pair_t *p = &type_str_pair[i];
  59. if (p->type == type) {
  60. return p->str;
  61. }
  62. }
  63. return "Unknown";
  64. }
  65. void initialize_nvs() {
  66. ESP_LOGI(TAG, "Initializing flash nvs ");
  67. esp_err_t err = nvs_flash_init();
  68. if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
  69. ESP_LOGW(TAG, "%s. Erasing nvs flash", esp_err_to_name(err));
  70. ESP_ERROR_CHECK(nvs_flash_erase());
  71. err = nvs_flash_init();
  72. }
  73. if(err != ESP_OK){
  74. ESP_LOGE(TAG, "nvs_flash_init failed. %s.", esp_err_to_name(err));
  75. }
  76. ESP_ERROR_CHECK(err);
  77. ESP_LOGI(TAG, "Initializing nvs partition %s",settings_partition);
  78. err = nvs_flash_init_partition(settings_partition);
  79. if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
  80. ESP_LOGW(TAG, "%s. Erasing nvs on partition %s",esp_err_to_name(err),settings_partition);
  81. ESP_ERROR_CHECK(nvs_flash_erase_partition(settings_partition));
  82. err = nvs_flash_init_partition(settings_partition);
  83. }
  84. if(err!=ESP_OK){
  85. ESP_LOGE(TAG, "nvs_flash_init_partition failed. %s",esp_err_to_name(err));
  86. }
  87. ESP_ERROR_CHECK(err);
  88. ESP_LOGD(TAG, "nvs init completed");
  89. }
  90. esp_err_t nvs_load_config(){
  91. nvs_entry_info_t info;
  92. esp_err_t err = ESP_OK;
  93. size_t malloc_int = heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
  94. size_t malloc_spiram = heap_caps_get_free_size(MALLOC_CAP_SPIRAM);
  95. nvs_iterator_t it = nvs_entry_find(settings_partition, NULL, NVS_TYPE_ANY);
  96. if(it == NULL) {
  97. ESP_LOGW(TAG, "empty nvs partition %s, namespace %s",settings_partition,current_namespace );
  98. }
  99. while (it != NULL) {
  100. nvs_entry_info(it, &info);
  101. if(strstr(info.namespace_name, current_namespace)) {
  102. void * value = get_nvs_value_alloc(info.type,info.key);
  103. if(value==NULL)
  104. {
  105. ESP_LOGE(TAG, "nvs read failed.");
  106. return ESP_FAIL;
  107. }
  108. config_set_value(info.type, info.key, value);
  109. free(value );
  110. }
  111. it = nvs_entry_next(it);
  112. }
  113. char * json_string= config_alloc_get_json(false);
  114. if(json_string!=NULL) {
  115. ESP_LOGD(TAG, "config json : %s\n", json_string);
  116. free(json_string);
  117. }
  118. ESP_LOGD(TAG,"Config memory usage. Heap internal:%zu (min:%zu) (used:%zu) external:%zu (min:%zu) (used:%zd)",
  119. heap_caps_get_free_size(MALLOC_CAP_INTERNAL),
  120. heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL),
  121. malloc_int-heap_caps_get_free_size(MALLOC_CAP_INTERNAL),
  122. heap_caps_get_free_size(MALLOC_CAP_SPIRAM),
  123. heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM),
  124. malloc_spiram -heap_caps_get_free_size(MALLOC_CAP_SPIRAM));
  125. return err;
  126. }
  127. esp_err_t store_nvs_value(nvs_type_t type, const char *key, void * data) {
  128. if (type == NVS_TYPE_BLOB)
  129. return ESP_ERR_NVS_TYPE_MISMATCH;
  130. return store_nvs_value_len(type, key, data,0);
  131. }
  132. esp_err_t store_nvs_value_len(nvs_type_t type, const char *key, void * data,
  133. size_t data_len) {
  134. esp_err_t err;
  135. nvs_handle nvs;
  136. if (type == NVS_TYPE_ANY) {
  137. return ESP_ERR_NVS_TYPE_MISMATCH;
  138. }
  139. err = nvs_open_from_partition(settings_partition, current_namespace, NVS_READWRITE, &nvs);
  140. if (err != ESP_OK) {
  141. return err;
  142. }
  143. if (type == NVS_TYPE_I8) {
  144. err = nvs_set_i8(nvs, key, *(int8_t *) data);
  145. } else if (type == NVS_TYPE_U8) {
  146. err = nvs_set_u8(nvs, key, *(uint8_t *) data);
  147. } else if (type == NVS_TYPE_I16) {
  148. err = nvs_set_i16(nvs, key, *(int16_t *) data);
  149. } else if (type == NVS_TYPE_U16) {
  150. err = nvs_set_u16(nvs, key, *(uint16_t *) data);
  151. } else if (type == NVS_TYPE_I32) {
  152. err = nvs_set_i32(nvs, key, *(int32_t *) data);
  153. } else if (type == NVS_TYPE_U32) {
  154. err = nvs_set_u32(nvs, key, *(uint32_t *) data);
  155. } else if (type == NVS_TYPE_I64) {
  156. err = nvs_set_i64(nvs, key, *(int64_t *) data);
  157. } else if (type == NVS_TYPE_U64) {
  158. err = nvs_set_u64(nvs, key, *(uint64_t *) data);
  159. } else if (type == NVS_TYPE_STR) {
  160. err = nvs_set_str(nvs, key, data);
  161. } else if (type == NVS_TYPE_BLOB) {
  162. err = nvs_set_blob(nvs, key, (void *) data, data_len);
  163. }
  164. if (err == ESP_OK) {
  165. err = nvs_commit(nvs);
  166. if (err == ESP_OK) {
  167. ESP_LOGI(TAG, "Value stored under key '%s'", key);
  168. }
  169. }
  170. nvs_close(nvs);
  171. return err;
  172. }
  173. void * get_nvs_value_alloc(nvs_type_t type, const char *key) {
  174. nvs_handle nvs;
  175. esp_err_t err;
  176. void * value=NULL;
  177. err = nvs_open_from_partition(settings_partition, current_namespace, NVS_READONLY, &nvs);
  178. if (err != ESP_OK) {
  179. ESP_LOGE(TAG, "Could not open the nvs storage.");
  180. return NULL;
  181. }
  182. if (type == NVS_TYPE_I8) {
  183. value=malloc(sizeof(int8_t));
  184. err = nvs_get_i8(nvs, key, (int8_t *) value);
  185. } else if (type == NVS_TYPE_U8) {
  186. value=malloc(sizeof(uint8_t));
  187. err = nvs_get_u8(nvs, key, (uint8_t *) value);
  188. } else if (type == NVS_TYPE_I16) {
  189. value=malloc(sizeof(int16_t));
  190. err = nvs_get_i16(nvs, key, (int16_t *) value);
  191. } else if (type == NVS_TYPE_U16) {
  192. value=malloc(sizeof(uint16_t));
  193. err = nvs_get_u16(nvs, key, (uint16_t *) value);
  194. } else if (type == NVS_TYPE_I32) {
  195. value=malloc(sizeof(int32_t));
  196. err = nvs_get_i32(nvs, key, (int32_t *) value);
  197. } else if (type == NVS_TYPE_U32) {
  198. value=malloc(sizeof(uint32_t));
  199. err = nvs_get_u32(nvs, key, (uint32_t *) value);
  200. } else if (type == NVS_TYPE_I64) {
  201. value=malloc(sizeof(int64_t));
  202. err = nvs_get_i64(nvs, key, (int64_t *) value);
  203. } else if (type == NVS_TYPE_U64) {
  204. value=malloc(sizeof(uint64_t));
  205. err = nvs_get_u64(nvs, key, (uint64_t *) value);
  206. } else if (type == NVS_TYPE_STR) {
  207. size_t len=0;
  208. err = nvs_get_str(nvs, key, NULL, &len);
  209. if (err == ESP_OK) {
  210. value=malloc(len);
  211. err = nvs_get_str(nvs, key, value, &len);
  212. }
  213. } else if (type == NVS_TYPE_BLOB) {
  214. size_t len;
  215. err = nvs_get_blob(nvs, key, NULL, &len);
  216. if (err == ESP_OK) {
  217. value=malloc(len+1);
  218. err = nvs_get_blob(nvs, key, value, &len);
  219. }
  220. }
  221. if(err!=ESP_OK){
  222. ESP_LOGD(TAG, "Value not found for key %s",key);
  223. if(value!=NULL)
  224. free(value);
  225. value=NULL;
  226. }
  227. nvs_close(nvs);
  228. return value;
  229. }
  230. esp_err_t get_nvs_value(nvs_type_t type, const char *key, void*value, const uint8_t buf_size) {
  231. nvs_handle nvs;
  232. esp_err_t err;
  233. err = nvs_open_from_partition(settings_partition, current_namespace, NVS_READONLY, &nvs);
  234. if (err != ESP_OK) {
  235. return err;
  236. }
  237. if (type == NVS_TYPE_I8) {
  238. err = nvs_get_i8(nvs, key, (int8_t *) value);
  239. } else if (type == NVS_TYPE_U8) {
  240. err = nvs_get_u8(nvs, key, (uint8_t *) value);
  241. } else if (type == NVS_TYPE_I16) {
  242. err = nvs_get_i16(nvs, key, (int16_t *) value);
  243. } else if (type == NVS_TYPE_U16) {
  244. err = nvs_get_u16(nvs, key, (uint16_t *) value);
  245. } else if (type == NVS_TYPE_I32) {
  246. err = nvs_get_i32(nvs, key, (int32_t *) value);
  247. } else if (type == NVS_TYPE_U32) {
  248. err = nvs_get_u32(nvs, key, (uint32_t *) value);
  249. } else if (type == NVS_TYPE_I64) {
  250. err = nvs_get_i64(nvs, key, (int64_t *) value);
  251. } else if (type == NVS_TYPE_U64) {
  252. err = nvs_get_u64(nvs, key, (uint64_t *) value);
  253. } else if (type == NVS_TYPE_STR) {
  254. size_t len;
  255. if ((err = nvs_get_str(nvs, key, NULL, &len)) == ESP_OK) {
  256. if (len > buf_size) {
  257. //ESP_LOGE("Error reading value for %s. Buffer size: %d, Value Length: %d", key, buf_size, len);
  258. err = ESP_FAIL;
  259. } else {
  260. err = nvs_get_str(nvs, key, value, &len);
  261. }
  262. }
  263. } else if (type == NVS_TYPE_BLOB) {
  264. size_t len;
  265. if ((err = nvs_get_blob(nvs, key, NULL, &len)) == ESP_OK) {
  266. if (len > buf_size) {
  267. //ESP_LOGE("Error reading value for %s. Buffer size: %d, Value Length: %d",
  268. // key, buf_size, len);
  269. err = ESP_FAIL;
  270. } else {
  271. err = nvs_get_blob(nvs, key, value, &len);
  272. }
  273. }
  274. }
  275. nvs_close(nvs);
  276. return err;
  277. }
  278. esp_err_t erase_nvs(const char *key)
  279. {
  280. nvs_handle nvs;
  281. esp_err_t err = nvs_open(current_namespace, NVS_READWRITE, &nvs);
  282. if (err == ESP_OK) {
  283. err = nvs_erase_key(nvs, key);
  284. if (err == ESP_OK) {
  285. err = nvs_commit(nvs);
  286. if (err == ESP_OK) {
  287. ESP_LOGI(TAG, "Value with key '%s' erased", key);
  288. }
  289. }
  290. nvs_close(nvs);
  291. }
  292. return err;
  293. }