mirror of
https://github.com/h2zero/esp-nimble-cpp.git
synced 2024-12-25 04:00:46 +01:00
Add persistent storage for Mesh config.
This commit is contained in:
parent
507f146477
commit
4786960902
9 changed files with 728 additions and 21 deletions
|
@ -12,6 +12,10 @@ elseif("nimble" IN_LIST BUILD_COMPONENTS OR "__nimble" IN_LIST __hack_component_
|
|||
list(APPEND ESP_NIMBLE_PRIV_REQUIRES
|
||||
nimble
|
||||
)
|
||||
elseif("bt" IN_LIST BUILD_COMPONENTS OR "__bt" IN_LIST __hack_component_targets)
|
||||
list(APPEND ESP_NIMBLE_PRIV_REQUIRES
|
||||
bt
|
||||
)
|
||||
endif()
|
||||
|
||||
if("arduino" IN_LIST BUILD_COMPONENTS OR __hack_component_targets MATCHES "__idf_arduino")
|
||||
|
@ -20,15 +24,7 @@ if("arduino" IN_LIST BUILD_COMPONENTS OR __hack_component_targets MATCHES "__idf
|
|||
)
|
||||
endif()
|
||||
|
||||
idf_component_register(
|
||||
REQUIRED_IDF_TARGETS
|
||||
"esp32"
|
||||
"esp32s3"
|
||||
"esp32c3"
|
||||
INCLUDE_DIRS
|
||||
"src"
|
||||
SRCS
|
||||
"src/NimBLE2904.cpp"
|
||||
set(srcs "src/NimBLE2904.cpp"
|
||||
"src/NimBLEAddress.cpp"
|
||||
"src/NimBLEAdvertisedDevice.cpp"
|
||||
"src/NimBLEAdvertising.cpp"
|
||||
|
@ -41,10 +37,6 @@ idf_component_register(
|
|||
"src/NimBLEEddystoneURL.cpp"
|
||||
"src/NimBLEExtAdvertising.cpp"
|
||||
"src/NimBLEHIDDevice.cpp"
|
||||
"src/NimBLEMeshCreateModel.c"
|
||||
"src/NimBLEMeshElement.cpp"
|
||||
"src/NimBLEMeshModel.cpp"
|
||||
"src/NimBLEMeshNode.cpp"
|
||||
"src/NimBLERemoteCharacteristic.cpp"
|
||||
"src/NimBLERemoteDescriptor.cpp"
|
||||
"src/NimBLERemoteService.cpp"
|
||||
|
@ -53,10 +45,36 @@ idf_component_register(
|
|||
"src/NimBLEServer.cpp"
|
||||
"src/NimBLEService.cpp"
|
||||
"src/NimBLEUtils.cpp"
|
||||
"src/NimBLEUUID.cpp"
|
||||
"src/NimBLEUUID.cpp")
|
||||
|
||||
if(CONFIG_BT_NIMBLE_MESH)
|
||||
list(APPEND srcs "src/NimBLEMeshCreateModel.c"
|
||||
"src/NimBLEMeshElement.cpp"
|
||||
"src/NimBLEMeshModel.cpp"
|
||||
"src/NimBLEMeshNode.cpp")
|
||||
endif()
|
||||
|
||||
if(CONFIG_NIMBLE_CPP_PERSIST_MESH_SETTINGS)
|
||||
list(APPEND srcs "src/mesh_config_store/config/config_store.c")
|
||||
endif()
|
||||
|
||||
idf_component_register(
|
||||
REQUIRED_IDF_TARGETS
|
||||
"esp32"
|
||||
"esp32s3"
|
||||
"esp32c3"
|
||||
INCLUDE_DIRS
|
||||
"src"
|
||||
SRCS "${srcs}"
|
||||
|
||||
REQUIRES
|
||||
bt
|
||||
nvs_flash
|
||||
PRIV_REQUIRES
|
||||
${ESP_NIMBLE_PRIV_REQUIRES}
|
||||
)
|
||||
|
||||
if(CONFIG_BT_NIMBLE_MESH AND CONFIG_NIMBLE_CPP_PERSIST_MESH_SETTINGS)
|
||||
idf_build_set_property(COMPILE_OPTIONS "-DMYNEWT_VAL_BLE_MESH_SETTINGS=1" APPEND)
|
||||
idf_build_set_property(COMPILE_OPTIONS "-I${COMPONENT_DIR}/src/mesh_config_store" APPEND)
|
||||
endif()
|
||||
|
|
8
Kconfig
8
Kconfig
|
@ -69,4 +69,12 @@ config NIMBLE_CPP_ATT_VALUE_INIT_LENGTH
|
|||
characteristic or descriptor is constructed before a value is read/notifed.
|
||||
Increasing this will reduce reallocations but increase memory footprint.
|
||||
|
||||
config NIMBLE_CPP_PERSIST_MESH_SETTINGS
|
||||
bool "Enable persistent storage of mesh config settings."
|
||||
default "n"
|
||||
depends on BT_NIMBLE_MESH
|
||||
help
|
||||
Enabling this option will store the provisioning and app key settings
|
||||
in non-volatile storage when using NimBLE Mesh.
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "nimconfig.h"
|
||||
#if CONFIG_BT_NIMBLE_MESH
|
||||
|
||||
#include "NimBLEMeshCreateModel.h"
|
||||
|
||||
static struct bt_mesh_model_cb mod_cb = {
|
||||
|
@ -28,3 +31,5 @@ struct bt_mesh_model createGenModel(int16_t _id, struct bt_mesh_model_op* op,
|
|||
struct bt_mesh_model mod = BT_MESH_MODEL_CB(_id, op, pub, udata, &mod_cb);
|
||||
return mod;
|
||||
}
|
||||
|
||||
#endif // CONFIG_BT_NIMBLE_MESH
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "nimconfig.h"
|
||||
#if CONFIG_BT_NIMBLE_MESH
|
||||
|
||||
#include "NimBLEMeshElement.h"
|
||||
#include "NimBLELog.h"
|
||||
#include "NimBLEMeshCreateModel.h"
|
||||
|
@ -139,4 +142,4 @@ bt_mesh_elem* NimBLEMeshElement::start() {
|
|||
return m_pElem;
|
||||
}
|
||||
|
||||
|
||||
#endif // CONFIG_BT_NIMBLE_MESH
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "nimconfig.h"
|
||||
#if CONFIG_BT_NIMBLE_MESH
|
||||
|
||||
#include "NimBLEMeshModel.h"
|
||||
#include "NimBLEUtils.h"
|
||||
#include "NimBLELog.h"
|
||||
|
@ -693,3 +696,5 @@ void NimBLEHealthSrvCallbacks::attentionOff(bt_mesh_model *model)
|
|||
NimBLEMeshModel* pModel = NimBLEDevice::getMeshNode()->getHealthModel(model);
|
||||
pModel->m_callbacks->attentionOff(pModel);
|
||||
}
|
||||
|
||||
#endif // CONFIG_BT_NIMBLE_MESH
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
#include "nimconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
#if CONFIG_BT_NIMBLE_MESH
|
||||
|
||||
#include "NimBLEMeshNode.h"
|
||||
#include "NimBLELog.h"
|
||||
|
@ -206,5 +206,4 @@ bool NimBLEMeshNode::start() {
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
#endif // CONFIG_BT_ENABLED
|
||||
#endif // CONFIG_BT_NIMBLE_MESH
|
||||
|
|
295
src/mesh_config_store/base64/base64.h
Normal file
295
src/mesh_config_store/base64/base64.h
Normal file
|
@ -0,0 +1,295 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
#ifndef __UTIL_BASE64_H
|
||||
#define __UTIL_BASE64_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct base64_decoder {
|
||||
/*** public */
|
||||
const char *src;
|
||||
void *dst;
|
||||
int src_len; /* <=0 if src ends with '\0' */
|
||||
int dst_len; /* <=0 if dst unbounded */
|
||||
|
||||
/*** private */
|
||||
char buf[4];
|
||||
int buf_len;
|
||||
};
|
||||
|
||||
static const char base64_chars[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
static int
|
||||
pos(char c)
|
||||
{
|
||||
const char *p;
|
||||
for (p = base64_chars; *p; p++)
|
||||
if (*p == c)
|
||||
return p - base64_chars;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
base64_encode(const void *data, int size, char *s, uint8_t should_pad)
|
||||
{
|
||||
char *p;
|
||||
int i;
|
||||
int c;
|
||||
const unsigned char *q;
|
||||
char *last;
|
||||
int diff;
|
||||
|
||||
p = s;
|
||||
|
||||
q = (const unsigned char *) data;
|
||||
last = NULL;
|
||||
i = 0;
|
||||
while (i < size) {
|
||||
c = q[i++];
|
||||
c *= 256;
|
||||
if (i < size)
|
||||
c += q[i];
|
||||
i++;
|
||||
c *= 256;
|
||||
if (i < size)
|
||||
c += q[i];
|
||||
i++;
|
||||
p[0] = base64_chars[(c & 0x00fc0000) >> 18];
|
||||
p[1] = base64_chars[(c & 0x0003f000) >> 12];
|
||||
p[2] = base64_chars[(c & 0x00000fc0) >> 6];
|
||||
p[3] = base64_chars[(c & 0x0000003f) >> 0];
|
||||
last = p;
|
||||
p += 4;
|
||||
}
|
||||
|
||||
if (last) {
|
||||
diff = i - size;
|
||||
if (diff > 0) {
|
||||
if (should_pad) {
|
||||
memset(last + (4 - diff), '=', diff);
|
||||
} else {
|
||||
p = last + (4 - diff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*p = 0;
|
||||
|
||||
return (p - s);
|
||||
}
|
||||
|
||||
int
|
||||
base64_pad(char *buf, int len)
|
||||
{
|
||||
int remainder;
|
||||
|
||||
remainder = len % 4;
|
||||
if (remainder == 0) {
|
||||
return (0);
|
||||
}
|
||||
|
||||
memset(buf, '=', 4 - remainder);
|
||||
|
||||
return (4 - remainder);
|
||||
}
|
||||
|
||||
#define DECODE_ERROR -1
|
||||
|
||||
static unsigned int
|
||||
token_decode(const char *token, int len)
|
||||
{
|
||||
int i;
|
||||
unsigned int val = 0;
|
||||
int marker = 0;
|
||||
|
||||
if (len < 4) {
|
||||
return DECODE_ERROR;
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
val *= 64;
|
||||
if (token[i] == '=') {
|
||||
marker++;
|
||||
} else if (marker > 0) {
|
||||
return DECODE_ERROR;
|
||||
} else {
|
||||
val += pos(token[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (marker > 2) {
|
||||
return DECODE_ERROR;
|
||||
}
|
||||
|
||||
return (marker << 24) | val;
|
||||
}
|
||||
|
||||
int
|
||||
base64_decoder_go(struct base64_decoder *dec)
|
||||
{
|
||||
unsigned int marker;
|
||||
unsigned int val;
|
||||
uint8_t *dst;
|
||||
char sval;
|
||||
int read_len;
|
||||
int src_len;
|
||||
int src_rem;
|
||||
int src_off;
|
||||
int dst_len;
|
||||
int dst_off;
|
||||
int i;
|
||||
|
||||
dst = dec->dst;
|
||||
dst_off = 0;
|
||||
src_off = 0;
|
||||
|
||||
/* A length <= 0 means "unbounded". */
|
||||
if (dec->src_len <= 0) {
|
||||
src_len = INT_MAX;
|
||||
} else {
|
||||
src_len = dec->src_len;
|
||||
}
|
||||
if (dec->dst_len <= 0) {
|
||||
dst_len = INT_MAX;
|
||||
} else {
|
||||
dst_len = dec->dst_len;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
src_rem = src_len - src_off;
|
||||
if (src_rem == 0) {
|
||||
/* End of source input. */
|
||||
break;
|
||||
}
|
||||
|
||||
if (dec->src[src_off] == '\0') {
|
||||
/* End of source string. */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Account for possibility of partial token from previous call. */
|
||||
read_len = 4 - dec->buf_len;
|
||||
|
||||
/* Detect invalid input. */
|
||||
for (i = 0; i < read_len; i++) {
|
||||
sval = dec->src[src_off + i];
|
||||
if (sval == '\0') {
|
||||
/* Incomplete input. */
|
||||
return -1;
|
||||
}
|
||||
if (sval != '=' && strchr(base64_chars, sval) == NULL) {
|
||||
/* Invalid base64 character. */
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (src_rem < read_len) {
|
||||
/* Input contains a partial token. Stash it for use during the
|
||||
* next call.
|
||||
*/
|
||||
memcpy(&dec->buf[dec->buf_len], &dec->src[src_off], src_rem);
|
||||
dec->buf_len += src_rem;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Copy full token into buf and decode it. */
|
||||
memcpy(&dec->buf[dec->buf_len], &dec->src[src_off], read_len);
|
||||
val = token_decode(dec->buf, read_len);
|
||||
if (val == DECODE_ERROR) {
|
||||
return -1;
|
||||
}
|
||||
src_off += read_len;
|
||||
dec->buf_len = 0;
|
||||
|
||||
marker = (val >> 24) & 0xff;
|
||||
|
||||
if (dst_off >= dst_len) {
|
||||
break;
|
||||
}
|
||||
dst[dst_off] = (val >> 16) & 0xff;
|
||||
dst_off++;
|
||||
|
||||
if (marker < 2) {
|
||||
if (dst_off >= dst_len) {
|
||||
break;
|
||||
}
|
||||
dst[dst_off] = (val >> 8) & 0xff;
|
||||
dst_off++;
|
||||
}
|
||||
|
||||
if (marker < 1) {
|
||||
if (dst_off >= dst_len) {
|
||||
break;
|
||||
}
|
||||
dst[dst_off] = val & 0xff;
|
||||
dst_off++;
|
||||
}
|
||||
}
|
||||
|
||||
return dst_off;
|
||||
}
|
||||
|
||||
int
|
||||
base64_decode(const char *str, void *data)
|
||||
{
|
||||
struct base64_decoder dec = {
|
||||
.src = str,
|
||||
.dst = data,
|
||||
};
|
||||
|
||||
return base64_decoder_go(&dec);
|
||||
}
|
||||
|
||||
int
|
||||
base64_decode_maxlen(const char *str, void *data, int len)
|
||||
{
|
||||
struct base64_decoder dec = {
|
||||
.src = str,
|
||||
.dst = data,
|
||||
.dst_len = len,
|
||||
};
|
||||
|
||||
return base64_decoder_go(&dec);
|
||||
}
|
||||
|
||||
int
|
||||
base64_decode_len(const char *str)
|
||||
{
|
||||
int len;
|
||||
|
||||
len = strlen(str);
|
||||
while (len && str[len - 1] == '=') {
|
||||
len--;
|
||||
}
|
||||
return len * 3 / 4;
|
||||
}
|
||||
|
||||
#define BASE64_ENCODE_SIZE(__size) (((((__size) - 1) / 3) * 4) + 4)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __UTIL_BASE64_H__ */
|
238
src/mesh_config_store/config/config.h
Normal file
238
src/mesh_config_store/config/config.h
Normal file
|
@ -0,0 +1,238 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
#ifndef __SYS_CONFIG_H_
|
||||
#define __SYS_CONFIG_H_
|
||||
|
||||
#include "../../nimconfig.h"
|
||||
#if defined(CONFIG_NIMBLE_CPP_IDF)
|
||||
# include <os/queue.h>
|
||||
#else
|
||||
# include "nimble/porting/nimble/include/os/queue.h"
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define CONF_MAX_DIR_DEPTH 8 /* max depth of config tree */
|
||||
#define CONF_MAX_NAME_LEN (8 * CONF_MAX_DIR_DEPTH)
|
||||
|
||||
/**
|
||||
* Type of configuration value.
|
||||
*/
|
||||
typedef enum conf_type {
|
||||
CONF_NONE = 0,
|
||||
CONF_DIR,
|
||||
/** 8-bit signed integer */
|
||||
CONF_INT8,
|
||||
/** 16-bit signed integer */
|
||||
CONF_INT16,
|
||||
/** 32-bit signed integer */
|
||||
CONF_INT32,
|
||||
/** 64-bit signed integer */
|
||||
CONF_INT64,
|
||||
/** String */
|
||||
CONF_STRING,
|
||||
/** Bytes */
|
||||
CONF_BYTES,
|
||||
/** Floating point */
|
||||
CONF_FLOAT,
|
||||
/** Double precision */
|
||||
CONF_DOUBLE,
|
||||
/** Boolean */
|
||||
CONF_BOOL,
|
||||
/** 8-bit unsigned integer */
|
||||
CONF_UINT8,
|
||||
/** 16-bit unsigned integer */
|
||||
CONF_UINT16,
|
||||
/** 32-bit unsigned integer */
|
||||
CONF_UINT32,
|
||||
/** 64-bit unsigned integer */
|
||||
CONF_UINT64,
|
||||
} __attribute__((__packed__)) conf_type_t;
|
||||
|
||||
/**
|
||||
* Parameter to commit handler describing where data is going to.
|
||||
*/
|
||||
enum conf_export_tgt {
|
||||
/** Value is to be persisted */
|
||||
CONF_EXPORT_PERSIST,
|
||||
/** Value is to be display */
|
||||
CONF_EXPORT_SHOW
|
||||
};
|
||||
|
||||
typedef enum conf_export_tgt conf_export_tgt_t;
|
||||
|
||||
/**
|
||||
* Handler for getting configuration items, this handler is called
|
||||
* per-configuration section. Configuration sections are delimited
|
||||
* by '/', for example:
|
||||
*
|
||||
* - section/name/value
|
||||
*
|
||||
* Would be passed as:
|
||||
*
|
||||
* - argc = 3
|
||||
* - argv[0] = section
|
||||
* - argv[1] = name
|
||||
* - argv[2] = value
|
||||
*
|
||||
* The handler returns the value into val, null terminated, up to
|
||||
* val_len_max.
|
||||
*
|
||||
* @param argc The number of sections in the configuration variable
|
||||
* @param argv The array of configuration sections
|
||||
* @param val A pointer to the buffer to return the configuration
|
||||
* value into.
|
||||
* @param val_len_max The maximum length of the val buffer to copy into.
|
||||
*
|
||||
* @return A pointer to val or NULL if error.
|
||||
*/
|
||||
typedef char *(*conf_get_handler_t)(int argc, char **argv, char *val, int val_len_max);
|
||||
typedef char *(*conf_get_handler_ext_t)(int argc, char **argv, char *val, int val_len_max, void *arg);
|
||||
|
||||
/**
|
||||
* Set the configuration variable pointed to by argc and argv. See
|
||||
* description of ch_get_handler_t for format of these variables. This sets the
|
||||
* configuration variable to the shadow value, but does not apply the configuration
|
||||
* change. In order to apply the change, call the ch_commit() handler.
|
||||
*
|
||||
* @param argc The number of sections in the configuration variable.
|
||||
* @param argv The array of configuration sections
|
||||
* @param val The value to configure that variable to
|
||||
*
|
||||
* @return 0 on success, non-zero error code on failure.
|
||||
*/
|
||||
typedef int (*conf_set_handler_t)(int argc, char **argv, char *val);
|
||||
typedef int (*conf_set_handler_ext_t)(int argc, char **argv, char *val, void *arg);
|
||||
|
||||
/**
|
||||
* Commit shadow configuration state to the active configuration.
|
||||
*
|
||||
* @return 0 on success, non-zero error code on failure.
|
||||
*/
|
||||
typedef int (*conf_commit_handler_t)(void);
|
||||
typedef int (*conf_commit_handler_ext_t)(void *arg);
|
||||
|
||||
/**
|
||||
* Called per-configuration variable being exported.
|
||||
*
|
||||
* @param name The name of the variable to export
|
||||
* @param val The value of the variable to export
|
||||
*/
|
||||
typedef void (*conf_export_func_t)(char *name, char *val);
|
||||
|
||||
/**
|
||||
* Export all of the configuration variables, calling the export_func
|
||||
* per variable being exported.
|
||||
*
|
||||
* @param export_func The export function to call.
|
||||
* @param tgt The target of the export, either for persistence or display.
|
||||
*
|
||||
* @return 0 on success, non-zero error code on failure.
|
||||
*/
|
||||
typedef int (*conf_export_handler_t)(conf_export_func_t export_func,
|
||||
conf_export_tgt_t tgt);
|
||||
typedef int (*conf_export_handler_ext_t)(conf_export_func_t export_func,
|
||||
conf_export_tgt_t tgt, void *arg);
|
||||
|
||||
/**
|
||||
* Configuration handler, used to register a config item/subtree.
|
||||
*/
|
||||
struct conf_handler {
|
||||
SLIST_ENTRY(conf_handler) ch_list;
|
||||
/**
|
||||
* The name of the conifguration item/subtree
|
||||
*/
|
||||
char *ch_name;
|
||||
|
||||
/**
|
||||
* Whether to use the extended callbacks.
|
||||
* false: standard
|
||||
* true: extended
|
||||
*/
|
||||
bool ch_ext;
|
||||
|
||||
/** Get configuration value */
|
||||
union {
|
||||
conf_get_handler_t ch_get;
|
||||
conf_get_handler_ext_t ch_get_ext;
|
||||
};
|
||||
|
||||
/** Set configuration value */
|
||||
union {
|
||||
conf_set_handler_t ch_set;
|
||||
conf_set_handler_ext_t ch_set_ext;
|
||||
};
|
||||
|
||||
/** Commit configuration value */
|
||||
union {
|
||||
conf_commit_handler_t ch_commit;
|
||||
conf_commit_handler_ext_t ch_commit_ext;
|
||||
};
|
||||
|
||||
/** Export configuration value */
|
||||
union {
|
||||
conf_export_handler_t ch_export;
|
||||
conf_export_handler_ext_t ch_export_ext;
|
||||
};
|
||||
|
||||
/** Custom argument that gets passed to the extended callbacks */
|
||||
void *ch_arg;
|
||||
};
|
||||
|
||||
/**
|
||||
* Register a handler for configurations items.
|
||||
*
|
||||
* @param cf Structure containing registration info.
|
||||
*
|
||||
* @return 0 on success, non-zero on failure.
|
||||
*/
|
||||
int conf_register(struct conf_handler *cf);
|
||||
|
||||
/**
|
||||
* Load configuration from registered persistence sources. Handlers for
|
||||
* configuration subtrees registered earlier will be called for encountered
|
||||
* values.
|
||||
*
|
||||
* @return 0 on success, non-zero on failure.
|
||||
*/
|
||||
int conf_load(void);
|
||||
|
||||
/**
|
||||
* Write a single configuration value to persisted storage (if it has
|
||||
* changed value).
|
||||
*
|
||||
* @param name Name/key of the configuration item.
|
||||
* @param var Value of the configuration item.
|
||||
*
|
||||
* @return 0 on success, non-zero on failure.
|
||||
*/
|
||||
int conf_save_one(const char *name, char *var);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#define SYSINIT_PANIC_ASSERT_MSG(rc, msg) assert(rc)
|
||||
|
||||
#endif /* __SYS_CONFIG_H_ */
|
136
src/mesh_config_store/config/config_store.c
Normal file
136
src/mesh_config_store/config/config_store.c
Normal file
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include "nimconfig.h"
|
||||
#ifdef ESP_PLATFORM
|
||||
#if CONFIG_BT_NIMBLE_MESH && CONFIG_NIMBLE_CPP_PERSIST_MESH_SETTINGS
|
||||
|
||||
#include "config.h"
|
||||
#include "nvs.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
static struct conf_handler* config_handler;
|
||||
|
||||
int conf_parse_name(char *name, int *name_argc, char *name_argv[])
|
||||
{
|
||||
char *tok;
|
||||
char *tok_ptr;
|
||||
const char *sep = "/";
|
||||
int i;
|
||||
|
||||
tok = strtok_r(name, sep, &tok_ptr);
|
||||
|
||||
i = 0;
|
||||
while (tok) {
|
||||
name_argv[i++] = tok;
|
||||
tok = strtok_r(NULL, sep, &tok_ptr);
|
||||
}
|
||||
*name_argc = i;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int conf_load(void)
|
||||
{
|
||||
esp_err_t err;
|
||||
nvs_handle handle;
|
||||
|
||||
err = nvs_open(config_handler->ch_name, NVS_READONLY, &handle);
|
||||
if (err != ESP_OK) return err;
|
||||
|
||||
nvs_iterator_t it = nvs_entry_find("nvs", config_handler->ch_name, NVS_TYPE_ANY);
|
||||
|
||||
while (it != NULL) {
|
||||
nvs_entry_info_t info;
|
||||
nvs_entry_info(it, &info);
|
||||
it = nvs_entry_next(it);
|
||||
|
||||
size_t required_size = 0;
|
||||
err = nvs_get_str(handle, info.key, NULL, &required_size);
|
||||
if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) return err;
|
||||
|
||||
char* val = malloc(required_size);
|
||||
if (required_size > 0) {
|
||||
err = nvs_get_str(handle, info.key, val, &required_size);
|
||||
if (err != ESP_OK) {
|
||||
free(val);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
int name_argc;
|
||||
char *name_argv[8];
|
||||
conf_parse_name(info.key, &name_argc, name_argv);
|
||||
|
||||
config_handler->ch_set(name_argc, &name_argv[0], val);
|
||||
free(val);
|
||||
}
|
||||
|
||||
nvs_close(handle);
|
||||
config_handler->ch_commit();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
int conf_save_one(const char *name, char *var)
|
||||
{
|
||||
esp_err_t err;
|
||||
nvs_handle_t handle;
|
||||
int name_argc;
|
||||
char *name_argv[CONF_MAX_DIR_DEPTH];
|
||||
char n[CONF_MAX_NAME_LEN];
|
||||
|
||||
strcpy(n, name);
|
||||
conf_parse_name(n, &name_argc, name_argv);
|
||||
|
||||
err = nvs_open(name_argv[0], NVS_READWRITE, &handle);
|
||||
if (err != ESP_OK) return err;
|
||||
|
||||
const char* key = name_argv[1];
|
||||
if (name_argc > 2) {
|
||||
key = name;
|
||||
while (*key != '/') {
|
||||
key++;
|
||||
}
|
||||
key++;
|
||||
}
|
||||
|
||||
if (var) {
|
||||
err = nvs_set_str(handle, key, var);
|
||||
if (err != ESP_OK) return err;
|
||||
} else {
|
||||
err = nvs_erase_key(handle, key);
|
||||
if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) return err;
|
||||
}
|
||||
|
||||
err = nvs_commit(handle);
|
||||
if (err != ESP_OK) return err;
|
||||
|
||||
nvs_close(handle);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
int conf_register(struct conf_handler *cf)
|
||||
{
|
||||
config_handler = cf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // CONFIG_BT_NIMBLE_MESH && MYNEWT_VAL_BLE_MESH_SETTINGS
|
||||
#endif // ESP_PLATFORM
|
Loading…
Reference in a new issue