MeshX 0.3
This repository provides an implementation for Bluetooth Low Energy (BLE) Mesh network nodes. The project allows you to create BLE mesh nodes that can communicate with each other, enabling the development of smart home solutions or other IoT-based applications.
Loading...
Searching...
No Matches
meshx_nvs.c
Go to the documentation of this file.
1
13#include "meshx_nvs.h"
15
16#define MESHX_NVS_INIT_MAGIC 0x5489
17
18#ifdef CONFIG_BLE_MESH_SPECIFIC_PARTITION
19#define MESHX_NVS_PARTITION CONFIG_BLE_MESH_PARTITION_NAME
20#endif
21
22#define MESHX_NVS_NAMESPACE_PID "MESHX_PID"
23#define MESHX_NVS_NAMESPACE_CID "MESHX_CID"
24#define MESHX_NVS_TIMER_NAME "MESHX_COMMIT_TIMER"
25#define MESHX_NVS_ELEMENT_CTX "MESHX_API_%04x"
26#define MESHX_NVS_RELOAD_ONE_SHOT 0
27#define MESHX_KEY_NAME_MAX_SIZE 16
28#define MESHX_KEY_VALUE_MAX_SIZE 256
29
41
47
48#if CONFIG_ENABLE_UNIT_TEST
49#define MESHX_NVS_UNIT_TEST_KEY "MESHX_UT"
50
51static meshx_err_t meshx_nvs_unit_test_cb_handler(int cmd_id, int argc, char **argv);
52#endif
53
58
59#if MESHX_NVS_TIMER_PERIOD
66static void meshx_nvs_os_timer_cb(const meshx_os_timer_t *p_timer)
67{
68 MESHX_UNUSED(p_timer);
71
72 err = meshx_nvs_commit();
73 if (err)
74 MESHX_LOGE(MODULE_ID_COMPONENT_MESHX_NVS, "meshx_nvs_commit %p", (void *)err);
75}
76#endif /* MESHX_NVS_TIMER_PERIOD */
77
89static meshx_err_t meshx_nvs_erase_prod_init(uint16_t cid, uint16_t pid)
90{
92 err = meshx_nvs_erase();
93 if (err)
94 {
95 MESHX_LOGE(MODULE_ID_COMPONENT_MESHX_NVS, "meshx_nvs_erase %p", (void *)err);
96 return err;
97 }
98
99 meshx_nvs_inst.pid = pid;
100 meshx_nvs_inst.cid = cid;
101
102 err = meshx_nvs_set(
104 &(meshx_nvs_inst.pid),
105 sizeof(meshx_nvs_inst.pid),
107
108 if (err)
109 {
110 MESHX_LOGE(MODULE_ID_COMPONENT_MESHX_NVS, "meshx_nvs_set %p", (void *)err);
111 return err;
112 }
113
114 err = meshx_nvs_set(
116 &(meshx_nvs_inst.cid),
117 sizeof(meshx_nvs_inst.cid),
119
120 if (err)
121 {
122 MESHX_LOGE(MODULE_ID_COMPONENT_MESHX_NVS, "meshx_nvs_set %p", (void *)err);
123 return err;
124 }
125
126 return err;
127}
128
136{
138#if CONFIG_ENABLE_UNIT_TEST
140 if (err)
141 {
142 MESHX_LOGE(MODULE_ID_COMPONENT_MESHX_NVS, "unit_test reg failed: (%d)", err);
143 return err;
144 }
145#endif /* CONFIG_ENABLE_UNIT_TEST */
146 return err;
147}
148
165meshx_err_t meshx_nvs_open(uint16_t cid, uint16_t pid, uint32_t commit_timeout_ms)
166{
168 {
169 return MESHX_INVALID_STATE;
170 }
171
172 meshx_err_t err;
173
174 err = meshx_nvs_plat_open(&(meshx_nvs_inst.meshx_nvs_handle));
175 if (err)
176 {
177 MESHX_LOGE(MODULE_ID_COMPONENT_MESHX_NVS, "nvs_open %p", (void *)err);
178 return err;
179 }
180
181#if MESHX_NVS_TIMER_PERIOD
182 if(commit_timeout_ms == 0)
183 {
184 commit_timeout_ms = MESHX_NVS_TIMER_PERIOD;
185 }
188 commit_timeout_ms,
190 &meshx_nvs_os_timer_cb,
191 &(meshx_nvs_inst.meshx_nvs_commit_tmr));
192 if (err)
193 {
194 MESHX_LOGE(MODULE_ID_COMPONENT_MESHX_NVS, "os_timer_create %p", (void *)err);
195 return err;
196 }
197#else
198 MESHX_UNUSED(commit_timeout_ms);
199#endif /* MESHX_NVS_TIMER_PERIOD */
200
202
203 err = meshx_nvs_get(
205 &(meshx_nvs_inst.cid),
206 sizeof(meshx_nvs_inst.cid));
207
208 err += meshx_nvs_get(
210 &(meshx_nvs_inst.pid),
211 sizeof(meshx_nvs_inst.pid));
212
213 if(err != MESHX_SUCCESS)
214 {
215 MESHX_LOGW(MODULE_ID_COMPONENT_MESHX_NVS, "Product ID not found in NVS reinitializing MeshX NVS");
216 err = meshx_nvs_erase_prod_init(cid, pid);
217 }
218
219 else
220 {
221 if (meshx_nvs_inst.cid == cid && meshx_nvs_inst.pid == pid)
222 {
223 MESHX_LOGI(MODULE_ID_COMPONENT_MESHX_NVS, "Product ID match: %x|%x", meshx_nvs_inst.pid, meshx_nvs_inst.cid);
224 }
225 else
226 {
227 MESHX_LOGW(MODULE_ID_COMPONENT_MESHX_NVS, "Product ID mismatch: %x|%x", meshx_nvs_inst.pid, meshx_nvs_inst.cid);
228 err = meshx_nvs_erase_prod_init(cid, pid);
229 }
230 }
231
232 return err;
233}
234
244{
246 return MESHX_INVALID_STATE;
247
248 return meshx_nvs_plat_erase(meshx_nvs_inst.meshx_nvs_handle);
249}
250
260{
262 return MESHX_INVALID_STATE;
263
267
268 while (cur) {
269 err = meshx_nvs_plat_write(meshx_nvs_inst.meshx_nvs_handle, cur->key, cur->data, cur->len);
270 if (err) {
271 MESHX_LOGE(MODULE_ID_COMPONENT_MESHX_NVS, "commit failed for key: %s", cur->key);
272 }
273 prev = cur;
274 cur = cur->next;
275 free(prev);
276 }
277
279
280 if (err == MESHX_SUCCESS) {
281 // Only commit to platform once, after all writes
282 err = meshx_nvs_plat_commit(meshx_nvs_inst.meshx_nvs_handle);
283 }
284
285 return err;
286}
287
288
298{
301 return MESHX_INVALID_STATE;
302
303 err = meshx_nvs_plat_close(meshx_nvs_inst.meshx_nvs_handle);
304 if (err)
305 {
306 MESHX_LOGE(MODULE_ID_COMPONENT_MESHX_NVS, "nvs_close %p", (void *)err);
307 }
308
309#if MESHX_NVS_TIMER_PERIOD
310 err = meshx_os_timer_delete(&(meshx_nvs_inst.meshx_nvs_commit_tmr));
311#endif /* MESHX_NVS_TIMER_PERIOD */
312 meshx_nvs_inst.init = 0;
313 return err;
314}
315
327{
329 return MESHX_INVALID_STATE;
330
331 return meshx_nvs_plat_remove(meshx_nvs_inst.meshx_nvs_handle, key);
332}
333
346meshx_err_t meshx_nvs_get(char const *key, void *blob, uint16_t blob_size)
347{
349 return MESHX_INVALID_STATE;
350 return meshx_nvs_plat_read(meshx_nvs_inst.meshx_nvs_handle, key, blob, blob_size);
351}
352
366meshx_err_t meshx_nvs_set(char const* key, void const* blob, uint16_t blob_size, bool arm_timer)
367{
369 return MESHX_INVALID_STATE;
370
371 if (blob_size > MESHX_KEY_VALUE_MAX_SIZE)
372 return MESHX_INVALID_ARG;
373
374 // Check if key already exists in list → overwrite instead of duplicate
376 while (cur) {
377 if (strncmp(cur->key, key, MESHX_KEY_NAME_MAX_SIZE-1) == 0)
378 {
379 cur->key[MESHX_KEY_NAME_MAX_SIZE - 1] = '\0';
380 memcpy(cur->data, blob, blob_size);
381 cur->len = blob_size;
382 goto restart_timer; // skip new node alloc
383 }
384 cur = cur->next;
385 }
386
387 // Allocate new node
388 meshx_nvs_write_list_t *node = malloc(sizeof(meshx_nvs_write_list_t));
389 if (!node) return MESHX_NO_MEM;
390
391 strncpy(node->key, key, MESHX_KEY_NAME_MAX_SIZE);
392 memcpy(node->data, blob, blob_size);
393 node->len = blob_size;
396
397restart_timer:
398 if (arm_timer)
399 {
400#if MESHX_NVS_TIMER_PERIOD
401 meshx_err_t err = meshx_os_timer_restart(meshx_nvs_inst.meshx_nvs_commit_tmr);
402 if (err)
403 MESHX_LOGE(MODULE_ID_COMPONENT_MESHX_NVS, "os_timer_restart err: %p", (void*)err);
404#endif
405 }
406
407 return MESHX_SUCCESS;
408}
409
410
424meshx_err_t meshx_nvs_element_ctx_get(uint16_t element_id, void *blob, size_t blob_size)
425{
427 snprintf(key, MESHX_KEY_NAME_MAX_SIZE, MESHX_NVS_ELEMENT_CTX, element_id);
428 return meshx_nvs_get(key, blob, blob_size);
429}
430
444meshx_err_t meshx_nvs_element_ctx_set(uint16_t element_id, const void *blob, size_t blob_size)
445{
447 snprintf(key, MESHX_KEY_NAME_MAX_SIZE, MESHX_NVS_ELEMENT_CTX, element_id);
448 return meshx_nvs_set(key, blob, (uint16_t) blob_size, MESHX_NVS_AUTO_COMMIT);
449}
450
463{
465 snprintf(key, MESHX_KEY_NAME_MAX_SIZE, MESHX_NVS_ELEMENT_CTX, element_id);
466 return meshx_nvs_remove(key);
467}
468
469#if CONFIG_ENABLE_UNIT_TEST
470
484
500static meshx_err_t meshx_nvs_unit_test_cb_handler(int cmd_id, int argc, char **argv)
501{
503 uint32_t ut_blob = 0xDEAD;
504 uint32_t ut_blob_get = 0x00;
505 bool arm_timer;
506
507 MESHX_UNUSED(argc);
508 MESHX_LOGD(MODULE_ID_COMPONENT_MESHX_NVS, "argc|cmd_id: %d|%d", argc, cmd_id);
509 if (cmd_id >= MESHX_NVS_CLI_MAX)
510 {
511 MESHX_LOGE(MODULE_ID_COMPONENT_MESHX_NVS, "Invalid number of arguments");
512 return MESHX_INVALID_ARG;
513 }
514
515 switch(cmd_id)
516 {
518 /* MeshX NVS Open uses defaut values */
520 break;
522 arm_timer = UT_GET_ARG(0, bool, argv) == 0 ? MESHX_NVS_NO_AUTO_COMMIT : MESHX_NVS_AUTO_COMMIT;
523 err = meshx_nvs_set(MESHX_NVS_UNIT_TEST_KEY, &ut_blob, sizeof(ut_blob), arm_timer);
524 break;
526 err = meshx_nvs_get(MESHX_NVS_UNIT_TEST_KEY, &ut_blob_get, sizeof(ut_blob_get));
527 if(err == MESHX_SUCCESS && ut_blob != ut_blob_get)
528 MESHX_LOGE(MODULE_ID_COMPONENT_MESHX_NVS, "MESHX NVS Integrety Test Failed");
529 break;
531 err = meshx_nvs_commit();
532 break;
535 break;
537 err = meshx_nvs_erase();
538 break;
540 err = meshx_nvs_close();
541 break;
542 default:
543 err = MESHX_INVALID_ARG;
544 break;
545 }
546
547 return err;
548}
549#endif /* CONFIG_ENABLE_UNIT_TEST */
#define CONFIG_PID_ID
#define CONFIG_CID_ID
Application Main.
#define MESHX_UNUSED(x)
Definition meshx_err.h:15
meshx_err_t
MeshX Error Codes.
Definition meshx_err.h:39
@ MESHX_SUCCESS
Definition meshx_err.h:40
@ MESHX_INVALID_ARG
Definition meshx_err.h:42
@ MESHX_INVALID_STATE
Definition meshx_err.h:45
@ MESHX_NO_MEM
Definition meshx_err.h:44
#define MESHX_LOGW(module_id, format,...)
Definition meshx_log.h:87
#define MESHX_LOGI(module_id, format,...)
Definition meshx_log.h:100
#define MESHX_LOGE(module_id, format,...)
Definition meshx_log.h:73
#define MESHX_LOGD(module_id, format,...)
Definition meshx_log.h:113
meshx_err_t meshx_nvs_element_ctx_set(uint16_t element_id, const void *blob, size_t blob_size)
Store the context of a specific element to NVS.
Definition meshx_nvs.c:444
meshx_err_t meshx_nvs_init(void)
MeshX NVS Initialisation.
Definition meshx_nvs.c:135
meshx_err_t meshx_nvs_close(void)
Close the NVS handle.
Definition meshx_nvs.c:297
enum meshx_nvs_cli_cmd meshx_nvs_cli_cmd_t
MeshX NVS unit test command IDs.
meshx_err_t meshx_nvs_element_ctx_get(uint16_t element_id, void *blob, size_t blob_size)
Retrieve the context of a specific element from NVS.
Definition meshx_nvs.c:424
#define MESHX_KEY_NAME_MAX_SIZE
Definition meshx_nvs.c:27
#define MESHX_NVS_INIT_MAGIC
Definition meshx_nvs.c:16
#define MESHX_NVS_UNIT_TEST_KEY
Definition meshx_nvs.c:49
#define MESHX_NVS_RELOAD_ONE_SHOT
Definition meshx_nvs.c:26
meshx_err_t meshx_nvs_element_ctx_remove(uint16_t element_id)
Remove the context of a specific element from NVS.
Definition meshx_nvs.c:462
#define MESHX_NVS_NAMESPACE_PID
Definition meshx_nvs.c:22
#define MESHX_NVS_TIMER_NAME
Definition meshx_nvs.c:24
#define MESHX_NVS_NAMESPACE_CID
Definition meshx_nvs.c:23
#define MESHX_NVS_ELEMENT_CTX
Definition meshx_nvs.c:25
meshx_err_t meshx_nvs_remove(char const *key)
Remove a key-value pair from the NVS.
Definition meshx_nvs.c:326
#define MESHX_KEY_VALUE_MAX_SIZE
Definition meshx_nvs.c:28
static meshx_nvs_t meshx_nvs_inst
: MeshX NVS Instance
Definition meshx_nvs.c:57
struct meshx_nvs_write_list meshx_nvs_write_list_t
meshx_err_t meshx_nvs_open(uint16_t cid, uint16_t pid, uint32_t commit_timeout_ms)
Open the NVS with a timeout.
Definition meshx_nvs.c:165
meshx_err_t meshx_nvs_set(char const *key, void const *blob, uint16_t blob_size, bool arm_timer)
Set a value in the NVS.
Definition meshx_nvs.c:366
meshx_nvs_write_list_t * meshx_nvs_write_list_head
Head of the linked list used to store key-value pairs that need to be written to NVS.
Definition meshx_nvs.c:46
meshx_err_t meshx_nvs_commit(void)
Commit changes to the NVS.
Definition meshx_nvs.c:259
meshx_err_t meshx_nvs_erase(void)
Erase all key-value pairs stored in the NVS.
Definition meshx_nvs.c:243
static meshx_err_t meshx_nvs_erase_prod_init(uint16_t cid, uint16_t pid)
Erase the NVS and set the product ID.
Definition meshx_nvs.c:89
meshx_err_t meshx_nvs_get(char const *key, void *blob, uint16_t blob_size)
Get a value from the NVS.
Definition meshx_nvs.c:346
meshx_nvs_cli_cmd
MeshX NVS unit test command IDs.
Definition meshx_nvs.c:474
@ MESHX_NVS_CLI_CMD_SET
Definition meshx_nvs.c:476
@ MESHX_NVS_CLI_CMD_REMOVE
Definition meshx_nvs.c:479
@ MESHX_NVS_CLI_CMD_COMMIT
Definition meshx_nvs.c:478
@ MESHX_NVS_CLI_CMD_CLOSE
Definition meshx_nvs.c:481
@ MESHX_NVS_CLI_MAX
Definition meshx_nvs.c:482
@ MESHX_NVS_CLI_CMD_ERASE
Definition meshx_nvs.c:480
@ MESHX_NVS_CLI_CMD_OPEN
Definition meshx_nvs.c:475
@ MESHX_NVS_CLI_CMD_GET
Definition meshx_nvs.c:477
static meshx_err_t meshx_nvs_unit_test_cb_handler(int cmd_id, int argc, char **argv)
Callback handler for MeshX NVS unit test command.
Definition meshx_nvs.c:500
Header file for MeshX Non-Volatile Storage (NVS) operations.
struct meshx_nvs meshx_nvs_t
#define MESHX_NVS_NO_AUTO_COMMIT
Definition meshx_nvs.h:26
#define MESHX_NVS_TIMER_PERIOD
Definition meshx_nvs.h:22
#define MESHX_NVS_AUTO_COMMIT
Definition meshx_nvs.h:25
meshx_err_t meshx_nvs_plat_read(uintptr_t p_nvs_handle, char const *key, uint8_t *p_data, uint16_t len)
Read blob value for given key from non-volatile storage.
Definition esp_nvs.c:92
meshx_err_t meshx_nvs_plat_open(uintptr_t *p_nvs_handle)
Open non-volatile storage with a given namespace from the default partition.
Definition esp_nvs.c:34
meshx_err_t meshx_nvs_plat_write(uintptr_t p_nvs_handle, char const *key, uint8_t const *p_data, uint16_t len)
Write a blob value to the non-volatile storage with a given key and namespace.
Definition esp_nvs.c:126
meshx_err_t meshx_nvs_plat_commit(uintptr_t p_nvs_handle)
Commit changes to the non-volatile storage.
Definition esp_nvs.c:208
meshx_err_t meshx_nvs_plat_erase(uintptr_t p_nvs_handle)
Erase all key-value pairs in the given namespace.
Definition esp_nvs.c:156
meshx_err_t meshx_nvs_plat_remove(uintptr_t p_nvs_handle, char const *key)
Remove a key-value pair from the non-volatile storage with a given key and namespace.
Definition esp_nvs.c:181
meshx_err_t meshx_nvs_plat_close(uintptr_t p_nvs_handle)
Close the non-volatile storage handle.
Definition esp_nvs.c:72
struct meshx_os_timer meshx_os_timer_t
Alias for the meshx_os_timer structure.
meshx_err_t meshx_os_timer_create(const char *name, uint32_t period, bool reload, meshx_os_timer_cb_t cb, meshx_os_timer_t **timer_handle)
Create a timer.
meshx_err_t meshx_os_timer_restart(const meshx_os_timer_t *timer_handle)
Restart a timer.
meshx_err_t meshx_os_timer_delete(meshx_os_timer_t **timer_handle)
Delete a timer.
#define OS_TMER_GET_TIMER_NAME(timer)
return timer registered name pointer
@ MODULE_ID_COMPONENT_MESHX_NVS
Definition module_id.h:27
Linked list structure used to store key-value pairs that need to be written to NVS.
Definition meshx_nvs.c:35
struct meshx_nvs_write_list * next
Definition meshx_nvs.c:39
uint8_t data[MESHX_KEY_VALUE_MAX_SIZE]
Definition meshx_nvs.c:38
char key[MESHX_KEY_NAME_MAX_SIZE]
Definition meshx_nvs.c:37
meshx_err_t register_unit_test(module_id_t module_id, module_callback_t callback)
Register a unit test for a specific module.
Definition unit_test.c:149
#define UT_GET_ARG(_x, _type, _argv)
Macro to extract an argument from the argument list.
Definition unit_test.h:27