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
|
list(APPEND ESP_NIMBLE_PRIV_REQUIRES
|
||||||
nimble
|
nimble
|
||||||
)
|
)
|
||||||
|
elseif("bt" IN_LIST BUILD_COMPONENTS OR "__bt" IN_LIST __hack_component_targets)
|
||||||
|
list(APPEND ESP_NIMBLE_PRIV_REQUIRES
|
||||||
|
bt
|
||||||
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if("arduino" IN_LIST BUILD_COMPONENTS OR __hack_component_targets MATCHES "__idf_arduino")
|
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()
|
endif()
|
||||||
|
|
||||||
idf_component_register(
|
set(srcs "src/NimBLE2904.cpp"
|
||||||
REQUIRED_IDF_TARGETS
|
|
||||||
"esp32"
|
|
||||||
"esp32s3"
|
|
||||||
"esp32c3"
|
|
||||||
INCLUDE_DIRS
|
|
||||||
"src"
|
|
||||||
SRCS
|
|
||||||
"src/NimBLE2904.cpp"
|
|
||||||
"src/NimBLEAddress.cpp"
|
"src/NimBLEAddress.cpp"
|
||||||
"src/NimBLEAdvertisedDevice.cpp"
|
"src/NimBLEAdvertisedDevice.cpp"
|
||||||
"src/NimBLEAdvertising.cpp"
|
"src/NimBLEAdvertising.cpp"
|
||||||
|
@ -41,10 +37,6 @@ idf_component_register(
|
||||||
"src/NimBLEEddystoneURL.cpp"
|
"src/NimBLEEddystoneURL.cpp"
|
||||||
"src/NimBLEExtAdvertising.cpp"
|
"src/NimBLEExtAdvertising.cpp"
|
||||||
"src/NimBLEHIDDevice.cpp"
|
"src/NimBLEHIDDevice.cpp"
|
||||||
"src/NimBLEMeshCreateModel.c"
|
|
||||||
"src/NimBLEMeshElement.cpp"
|
|
||||||
"src/NimBLEMeshModel.cpp"
|
|
||||||
"src/NimBLEMeshNode.cpp"
|
|
||||||
"src/NimBLERemoteCharacteristic.cpp"
|
"src/NimBLERemoteCharacteristic.cpp"
|
||||||
"src/NimBLERemoteDescriptor.cpp"
|
"src/NimBLERemoteDescriptor.cpp"
|
||||||
"src/NimBLERemoteService.cpp"
|
"src/NimBLERemoteService.cpp"
|
||||||
|
@ -53,10 +45,36 @@ idf_component_register(
|
||||||
"src/NimBLEServer.cpp"
|
"src/NimBLEServer.cpp"
|
||||||
"src/NimBLEService.cpp"
|
"src/NimBLEService.cpp"
|
||||||
"src/NimBLEUtils.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
|
REQUIRES
|
||||||
bt
|
bt
|
||||||
nvs_flash
|
nvs_flash
|
||||||
PRIV_REQUIRES
|
PRIV_REQUIRES
|
||||||
${ESP_NIMBLE_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()
|
||||||
|
|
14
Kconfig
14
Kconfig
|
@ -33,7 +33,7 @@ config NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT
|
||||||
Enabling this option will display return code values as text
|
Enabling this option will display return code values as text
|
||||||
messages in the debug log. This will use approximately 8kB
|
messages in the debug log. This will use approximately 8kB
|
||||||
of flash memory.
|
of flash memory.
|
||||||
|
|
||||||
config NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT
|
config NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT
|
||||||
bool "Show NimBLE gap events as text in debug log."
|
bool "Show NimBLE gap events as text in debug log."
|
||||||
default "n"
|
default "n"
|
||||||
|
@ -47,7 +47,7 @@ config NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT
|
||||||
default "n"
|
default "n"
|
||||||
help
|
help
|
||||||
Enabling this option will display advertisment types recieved
|
Enabling this option will display advertisment types recieved
|
||||||
while scanning as text messages in the debug log.
|
while scanning as text messages in the debug log.
|
||||||
This will use approximately 250 bytes of flash memory.
|
This will use approximately 250 bytes of flash memory.
|
||||||
|
|
||||||
config NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
|
config NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
|
||||||
|
@ -68,5 +68,13 @@ config NIMBLE_CPP_ATT_VALUE_INIT_LENGTH
|
||||||
when the constructor is called. This is also the size used when a remote
|
when the constructor is called. This is also the size used when a remote
|
||||||
characteristic or descriptor is constructed before a value is read/notifed.
|
characteristic or descriptor is constructed before a value is read/notifed.
|
||||||
Increasing this will reduce reallocations but increase memory footprint.
|
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
|
endmenu
|
||||||
|
|
|
@ -6,6 +6,9 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "nimconfig.h"
|
||||||
|
#if CONFIG_BT_NIMBLE_MESH
|
||||||
|
|
||||||
#include "NimBLEMeshCreateModel.h"
|
#include "NimBLEMeshCreateModel.h"
|
||||||
|
|
||||||
static struct bt_mesh_model_cb mod_cb = {
|
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);
|
struct bt_mesh_model mod = BT_MESH_MODEL_CB(_id, op, pub, udata, &mod_cb);
|
||||||
return mod;
|
return mod;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // CONFIG_BT_NIMBLE_MESH
|
||||||
|
|
|
@ -6,6 +6,9 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "nimconfig.h"
|
||||||
|
#if CONFIG_BT_NIMBLE_MESH
|
||||||
|
|
||||||
#include "NimBLEMeshElement.h"
|
#include "NimBLEMeshElement.h"
|
||||||
#include "NimBLELog.h"
|
#include "NimBLELog.h"
|
||||||
#include "NimBLEMeshCreateModel.h"
|
#include "NimBLEMeshCreateModel.h"
|
||||||
|
@ -139,4 +142,4 @@ bt_mesh_elem* NimBLEMeshElement::start() {
|
||||||
return m_pElem;
|
return m_pElem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // CONFIG_BT_NIMBLE_MESH
|
||||||
|
|
|
@ -6,6 +6,9 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "nimconfig.h"
|
||||||
|
#if CONFIG_BT_NIMBLE_MESH
|
||||||
|
|
||||||
#include "NimBLEMeshModel.h"
|
#include "NimBLEMeshModel.h"
|
||||||
#include "NimBLEUtils.h"
|
#include "NimBLEUtils.h"
|
||||||
#include "NimBLELog.h"
|
#include "NimBLELog.h"
|
||||||
|
@ -693,3 +696,5 @@ void NimBLEHealthSrvCallbacks::attentionOff(bt_mesh_model *model)
|
||||||
NimBLEMeshModel* pModel = NimBLEDevice::getMeshNode()->getHealthModel(model);
|
NimBLEMeshModel* pModel = NimBLEDevice::getMeshNode()->getHealthModel(model);
|
||||||
pModel->m_callbacks->attentionOff(pModel);
|
pModel->m_callbacks->attentionOff(pModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // CONFIG_BT_NIMBLE_MESH
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "nimconfig.h"
|
#include "nimconfig.h"
|
||||||
#if defined(CONFIG_BT_ENABLED)
|
#if CONFIG_BT_NIMBLE_MESH
|
||||||
|
|
||||||
#include "NimBLEMeshNode.h"
|
#include "NimBLEMeshNode.h"
|
||||||
#include "NimBLELog.h"
|
#include "NimBLELog.h"
|
||||||
|
@ -206,5 +206,4 @@ bool NimBLEMeshNode::start() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // CONFIG_BT_NIMBLE_MESH
|
||||||
#endif // CONFIG_BT_ENABLED
|
|
||||||
|
|
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