ble_mesh: Miscellaneous updates

1. Store node name in nvs when Provisioner sets node name
2. Add an API to store node composition data
3. Update lightness last when lightness actual is changed
4. Add ble mesh english/chinese documents
5. Update ble mesh tx/rx test example
6. Add params to provisioner bind appkey comp event
7. Fix node ignoring relay messages issue
8. Fix PreviousAddress endianess in Friend Request
9. Support using a specific partition for ble mesh
10. Fix compile warning when proxy related macros are disabled
11. Not using internal macros in esp_ble_mesh_defs.h
12. No device address needed when PB-ADV is used
This commit is contained in:
lly
2020-01-03 20:11:08 +08:00
committed by baohongde
parent 3222dfef0e
commit db3fa3a100
41 changed files with 3880 additions and 638 deletions

View File

@@ -1794,15 +1794,6 @@ if BLE_MESH
ability to act as a proxy between a Mesh GATT Client and a Mesh network.
This option should be enabled if a node is going to be a Proxy Server.
config BLE_MESH_GATT_PROXY_CLIENT
bool "BLE Mesh GATT Proxy Client"
select BLE_MESH_PROXY
default n
help
This option enables support for Mesh GATT Proxy Client. The Proxy Client
can use the GATT bearer to send mesh messages to a node that supports the
advertising bearer.
config BLE_MESH_NODE_ID_TIMEOUT
int "Node Identity advertising timeout"
depends on BLE_MESH_GATT_PROXY_SERVER
@@ -1817,12 +1808,10 @@ if BLE_MESH
node, it will start to advertise using Node Identity during the time
set by this option. And after that, Network ID will be advertised.
if BLE_MESH_PROXY
config BLE_MESH_PROXY_FILTER_SIZE
int "Maximum number of filter entries per Proxy Client"
default 1
default 3 if BLE_MESH_GATT_PROXY_SERVER
depends on BLE_MESH_GATT_PROXY_SERVER
default 4
range 1 32767
help
This option specifies how many Proxy Filter entries the local node supports.
@@ -1830,7 +1819,14 @@ if BLE_MESH
list of addresses which can be used to decide which messages will be forwarded
to the Proxy Client by the Proxy Server.
endif # BLE_MESH_PROXY
config BLE_MESH_GATT_PROXY_CLIENT
bool "BLE Mesh GATT Proxy Client"
select BLE_MESH_PROXY
default n
help
This option enables support for Mesh GATT Proxy Client. The Proxy Client
can use the GATT bearer to send mesh messages to a node that supports the
advertising bearer.
config BLE_MESH_NET_BUF_POOL_USAGE
bool "BLE Mesh net buffer pool usage tracking"
@@ -1854,6 +1850,29 @@ if BLE_MESH
AppKey, etc.
if BLE_MESH_SETTINGS
config BLE_MESH_SPECIFIC_PARTITION
bool "Use a specific NVS partition for BLE Mesh"
default n
help
When selected, the mesh stack will use a specified NVS partition instead of
default NVS partition. Note that the specified partition must be registered
with NVS using nvs_flash_init_partition() API, and the partition must exists
in the csv file.
When Provisioner needs to store a large amount of nodes' information in the
flash (e.g. more than 20), this option is recommended to be enabled.
if BLE_MESH_SPECIFIC_PARTITION
config BLE_MESH_PARTITION_NAME
string "Name of the NVS partition for BLE Mesh"
default "BLE-MESH"
help
This value defines the name of the specified NVS partition used by the
mesh stack.
endif # BLE_MESH_SPECIFIC_PARTITION
config BLE_MESH_STORE_TIMEOUT
int "Delay (in seconds) before storing anything persistently"
range 0 1000000

View File

@@ -279,10 +279,10 @@ const char *esp_ble_mesh_provisioner_get_node_name(uint16_t index)
return bt_mesh_provisioner_get_node_name(index);
}
int esp_ble_mesh_provisioner_get_node_index(const char *name)
uint16_t esp_ble_mesh_provisioner_get_node_index(const char *name)
{
if (!name || (strlen(name) > ESP_BLE_MESH_NODE_NAME_MAX_LEN)) {
return -EINVAL;
return ESP_BLE_MESH_INVALID_NODE_INDEX;
}
return bt_mesh_provisioner_get_node_index(name);
@@ -379,6 +379,28 @@ const uint8_t *esp_ble_mesh_provisioner_get_local_net_key(uint16_t net_idx)
return bt_mesh_provisioner_local_net_key_get(net_idx);
}
esp_err_t esp_ble_mesh_provisioner_store_node_comp_data(uint16_t addr, uint8_t *data, uint16_t length)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
if (!ESP_BLE_MESH_ADDR_IS_UNICAST(addr) || !data || length <= 14) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_PROVISIONER_STORE_NODE_COMP_DATA;
arg.store_node_comp_data.addr = addr;
arg.store_node_comp_data.length = length;
arg.store_node_comp_data.data = data;
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), btc_ble_mesh_prov_arg_deep_copy)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
#endif /* CONFIG_BLE_MESH_PROVISIONER */
#if (CONFIG_BLE_MESH_FAST_PROV)

View File

@@ -292,7 +292,8 @@ esp_err_t esp_ble_mesh_provisioner_prov_device_with_addr(const uint8_t uuid[16],
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
if (uuid == NULL || addr == NULL || addr_type > ESP_BLE_MESH_ADDR_TYPE_RANDOM ||
if (uuid == NULL || (bearer == ESP_BLE_MESH_PROV_GATT && (addr == NULL ||
addr_type > ESP_BLE_MESH_ADDR_TYPE_RANDOM)) ||
(bearer != ESP_BLE_MESH_PROV_ADV && bearer != ESP_BLE_MESH_PROV_GATT) ||
!ESP_BLE_MESH_ADDR_IS_UNICAST(unicast_addr)) {
return ESP_ERR_INVALID_ARG;
@@ -305,8 +306,10 @@ esp_err_t esp_ble_mesh_provisioner_prov_device_with_addr(const uint8_t uuid[16],
msg.act = BTC_BLE_MESH_ACT_PROVISIONER_PROV_DEV_WITH_ADDR;
memcpy(arg.provisioner_prov_dev_with_addr.uuid, uuid, 16);
if (addr) {
memcpy(arg.provisioner_prov_dev_with_addr.addr, addr, BD_ADDR_LEN);
arg.provisioner_prov_dev_with_addr.addr_type = addr_type;
}
arg.provisioner_prov_dev_with_addr.bearer = bearer;
arg.provisioner_prov_dev_with_addr.oob_info = oob_info;
arg.provisioner_prov_dev_with_addr.unicast_addr = unicast_addr;

View File

@@ -207,10 +207,10 @@ const char *esp_ble_mesh_provisioner_get_node_name(uint16_t index);
*
* @param[in] name: Name of the node (end by '\0').
*
* @return Node index on success, or (negative) error code from errno.h on failure.
* @return Node index on success, or an invalid value (0xFFFF) on failure.
*
*/
int esp_ble_mesh_provisioner_get_node_index(const char *name);
uint16_t esp_ble_mesh_provisioner_get_node_index(const char *name);
/**
* @brief This function is called to get the provisioned node information.
@@ -222,6 +222,18 @@ int esp_ble_mesh_provisioner_get_node_index(const char *name);
*/
esp_ble_mesh_node_t *esp_ble_mesh_provisioner_get_node_info(const uint8_t uuid[16]);
/**
* @brief This function is called to store the Composition Data of the node.
*
* @param[in] addr: Element address of the node
* @param[in] data: Pointer of Composition Data
* @param[in] length: Length of Composition Data
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_provisioner_store_node_comp_data(uint16_t addr, uint8_t *data, uint16_t length);
/**
* @brief This function is called to set the app key for the local BLE Mesh stack.
*

File diff suppressed because it is too large Load Diff

View File

@@ -114,6 +114,15 @@ void btc_ble_mesh_prov_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
LOG_ERROR("%s, Failed to allocate memory, act %d", __func__, msg->act);
}
break;
case BTC_BLE_MESH_ACT_PROVISIONER_STORE_NODE_COMP_DATA:
LOG_DEBUG("%s, BTC_BLE_MESH_ACT_PROVISIONER_STORE_NODE_COMP_DATA", __func__);
dst->store_node_comp_data.data = osi_calloc(src->store_node_comp_data.length);
if (dst->store_node_comp_data.data) {
memcpy(dst->store_node_comp_data.data, src->store_node_comp_data.data, src->store_node_comp_data.length);
} else {
LOG_ERROR("%s, Failed to allocate memory, act %d", __func__, msg->act);
}
break;
default:
LOG_DEBUG("%s, Unknown deep copy act %d", __func__, msg->act);
break;
@@ -142,6 +151,11 @@ static void btc_ble_mesh_prov_arg_deep_free(btc_msg_t *msg)
osi_free(arg->proxy_client_remove_filter_addr.addr);
}
break;
case BTC_BLE_MESH_ACT_PROVISIONER_STORE_NODE_COMP_DATA:
if (arg->store_node_comp_data.data) {
osi_free(arg->store_node_comp_data.data);
}
break;
default:
break;
}
@@ -1576,6 +1590,9 @@ void btc_ble_mesh_prov_call_handler(btc_msg_t *msg)
act = ESP_BLE_MESH_NODE_PROV_INPUT_STRING_COMP_EVT;
param.node_prov_input_str_comp.err_code = bt_mesh_input_string(arg->input_string.string);
break;
#endif /* CONFIG_BLE_MESH_NODE */
#if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \
CONFIG_BLE_MESH_GATT_PROXY_SERVER
case BTC_BLE_MESH_ACT_SET_DEVICE_NAME:
act = ESP_BLE_MESH_NODE_SET_UNPROV_DEV_NAME_COMP_EVT;
param.node_set_unprov_dev_name_comp.err_code = bt_mesh_set_device_name(arg->set_device_name.name);
@@ -1594,7 +1611,7 @@ void btc_ble_mesh_prov_call_handler(btc_msg_t *msg)
param.node_proxy_gatt_disable_comp.err_code = bt_mesh_proxy_gatt_disable();
break;
#endif /* CONFIG_BLE_MESH_GATT_PROXY_SERVER */
#endif /* CONFIG_BLE_MESH_NODE */
#endif /* (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || CONFIG_BLE_MESH_GATT_PROXY_SERVER */
#if CONFIG_BLE_MESH_PROVISIONER
case BTC_BLE_MESH_ACT_PROVISIONER_READ_OOB_PUB_KEY:
act = ESP_BLE_MESH_PROVISIONER_PROV_READ_OOB_PUB_KEY_COMP_EVT;
@@ -1693,13 +1710,9 @@ void btc_ble_mesh_prov_call_handler(btc_msg_t *msg)
break;
case BTC_BLE_MESH_ACT_PROVISIONER_SET_NODE_NAME:
act = ESP_BLE_MESH_PROVISIONER_SET_NODE_NAME_COMP_EVT;
param.provisioner_set_node_name_comp.node_index = arg->set_node_name.index;
param.provisioner_set_node_name_comp.err_code =
bt_mesh_provisioner_set_node_name(arg->set_node_name.index, arg->set_node_name.name);
if (param.provisioner_set_node_name_comp.err_code) {
param.provisioner_set_node_name_comp.node_index = ESP_BLE_MESH_INVALID_NODE_INDEX;
} else {
param.provisioner_set_node_name_comp.node_index = arg->set_node_name.index;
}
break;
case BTC_BLE_MESH_ACT_PROVISIONER_SET_LOCAL_APP_KEY: {
const u8_t *app_key = NULL;
@@ -1708,18 +1721,18 @@ void btc_ble_mesh_prov_call_handler(btc_msg_t *msg)
app_key = arg->add_local_app_key.app_key;
}
act = ESP_BLE_MESH_PROVISIONER_ADD_LOCAL_APP_KEY_COMP_EVT;
param.provisioner_add_app_key_comp.app_idx = arg->add_local_app_key.app_idx;
param.provisioner_add_app_key_comp.err_code =
bt_mesh_provisioner_local_app_key_add(app_key, arg->add_local_app_key.net_idx,
&arg->add_local_app_key.app_idx);
if (param.provisioner_add_app_key_comp.err_code) {
param.provisioner_add_app_key_comp.app_idx = ESP_BLE_MESH_KEY_UNUSED;
} else {
param.provisioner_add_app_key_comp.app_idx = arg->add_local_app_key.app_idx;
}
break;
}
case BTC_BLE_MESH_ACT_PROVISIONER_BIND_LOCAL_MOD_APP:
act = ESP_BLE_MESH_PROVISIONER_BIND_APP_KEY_TO_MODEL_COMP_EVT;
param.provisioner_bind_app_key_to_model_comp.element_addr = arg->local_mod_app_bind.elem_addr;
param.provisioner_bind_app_key_to_model_comp.app_idx = arg->local_mod_app_bind.app_idx;
param.provisioner_bind_app_key_to_model_comp.company_id = arg->local_mod_app_bind.cid;
param.provisioner_bind_app_key_to_model_comp.model_id = arg->local_mod_app_bind.model_id;
param.provisioner_bind_app_key_to_model_comp.err_code =
bt_mesh_provisioner_bind_local_model_app_idx(arg->local_mod_app_bind.elem_addr,
arg->local_mod_app_bind.model_id,
@@ -1733,15 +1746,18 @@ void btc_ble_mesh_prov_call_handler(btc_msg_t *msg)
net_key = arg->add_local_net_key.net_key;
}
act = ESP_BLE_MESH_PROVISIONER_ADD_LOCAL_NET_KEY_COMP_EVT;
param.provisioner_add_net_key_comp.net_idx = arg->add_local_net_key.net_idx;
param.provisioner_add_net_key_comp.err_code =
bt_mesh_provisioner_local_net_key_add(net_key, &arg->add_local_net_key.net_idx);
if (param.provisioner_add_net_key_comp.err_code) {
param.provisioner_add_net_key_comp.net_idx = ESP_BLE_MESH_KEY_UNUSED;
} else {
param.provisioner_add_net_key_comp.net_idx = arg->add_local_net_key.net_idx;
}
break;
}
case BTC_BLE_MESH_ACT_PROVISIONER_STORE_NODE_COMP_DATA:
act = ESP_BLE_MESH_PROVISIONER_STORE_NODE_COMP_DATA_COMP_EVT;
param.provisioner_store_node_comp_data_comp.addr = arg->store_node_comp_data.addr;
param.provisioner_store_node_comp_data_comp.err_code =
bt_mesh_provisioner_store_node_comp_data(arg->store_node_comp_data.addr,
arg->store_node_comp_data.data, arg->store_node_comp_data.length);
break;
#endif /* CONFIG_BLE_MESH_PROVISIONER */
#if CONFIG_BLE_MESH_FAST_PROV
case BTC_BLE_MESH_ACT_SET_FAST_PROV_INFO:

View File

@@ -56,6 +56,7 @@ typedef enum {
BTC_BLE_MESH_ACT_PROVISIONER_SET_LOCAL_APP_KEY,
BTC_BLE_MESH_ACT_PROVISIONER_BIND_LOCAL_MOD_APP,
BTC_BLE_MESH_ACT_PROVISIONER_ADD_LOCAL_NET_KEY,
BTC_BLE_MESH_ACT_PROVISIONER_STORE_NODE_COMP_DATA,
BTC_BLE_MESH_ACT_SET_FAST_PROV_INFO,
BTC_BLE_MESH_ACT_SET_FAST_PROV_ACTION,
BTC_BLE_MESH_ACT_LPN_ENABLE,
@@ -170,6 +171,11 @@ typedef union {
uint8_t net_key[16];
uint16_t net_idx;
} add_local_net_key;
struct ble_mesh_provisioner_store_node_comp_data_args {
uint16_t addr;
uint16_t length;
uint8_t *data;
} store_node_comp_data;
struct ble_mesh_set_fast_prov_info_args {
uint16_t unicast_min;
uint16_t unicast_max;

View File

@@ -192,8 +192,8 @@ static void adv_thread(void *p)
while (1) {
*buf = NULL;
#if !defined(CONFIG_BLE_MESH_RELAY_ADV_BUF)
#if CONFIG_BLE_MESH_NODE
if (IS_ENABLED(CONFIG_BLE_MESH_PROXY)) {
#if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \
CONFIG_BLE_MESH_GATT_PROXY_SERVER
xQueueReceive(xBleMeshQueue, &msg, K_NO_WAIT);
while (!(*buf)) {
s32_t timeout;
@@ -204,15 +204,12 @@ static void adv_thread(void *p)
BT_DBG("Mesh Proxy Advertising stop");
bt_mesh_proxy_adv_stop();
}
} else {
xQueueReceive(xBleMeshQueue, &msg, portMAX_DELAY);
}
#else
xQueueReceive(xBleMeshQueue, &msg, portMAX_DELAY);
#endif
#endif /* (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || CONFIG_BLE_MESH_GATT_PROXY_SERVER */
#else /* !defined(CONFIG_BLE_MESH_RELAY_ADV_BUF) */
#if CONFIG_BLE_MESH_NODE
if (IS_ENABLED(CONFIG_BLE_MESH_PROXY)) {
#if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \
CONFIG_BLE_MESH_GATT_PROXY_SERVER
handle = xQueueSelectFromSet(xBleMeshQueueSet, K_NO_WAIT);
if (handle) {
if (uxQueueMessagesWaiting(xBleMeshQueue)) {
@@ -238,16 +235,6 @@ static void adv_thread(void *p)
}
}
}
} else {
handle = xQueueSelectFromSet(xBleMeshQueueSet, portMAX_DELAY);
if (handle) {
if (uxQueueMessagesWaiting(xBleMeshQueue)) {
xQueueReceive(xBleMeshQueue, &msg, K_NO_WAIT);
} else if (uxQueueMessagesWaiting(xBleMeshRelayQueue)) {
xQueueReceive(xBleMeshRelayQueue, &msg, K_NO_WAIT);
}
}
}
#else
handle = xQueueSelectFromSet(xBleMeshQueueSet, portMAX_DELAY);
if (handle) {
@@ -257,7 +244,7 @@ static void adv_thread(void *p)
xQueueReceive(xBleMeshRelayQueue, &msg, K_NO_WAIT);
}
}
#endif
#endif /* (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || CONFIG_BLE_MESH_GATT_PROXY_SERVER */
#endif /* !defined(CONFIG_BLE_MESH_RELAY_ADV_BUF) */
if (*buf == NULL) {
@@ -435,10 +422,8 @@ static bool ignore_relay_packet(u32_t timestamp)
u32_t now = k_uptime_get_32();
u32_t interval;
if (now > timestamp) {
if (now >= timestamp) {
interval = now - timestamp;
} else if (now == timestamp) {
interval = BLE_MESH_MAX_TIME_INTERVAL;
} else {
interval = BLE_MESH_MAX_TIME_INTERVAL - (timestamp - now) + 1;
}

View File

@@ -64,7 +64,10 @@ static BT_OCTET32 bt_mesh_private_key = {
static bt_mesh_scan_cb_t *bt_mesh_scan_dev_found_cb;
static void bt_mesh_scan_result_callback(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data);
#if defined(CONFIG_BLE_MESH_NODE) && CONFIG_BLE_MESH_NODE
#if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \
CONFIG_BLE_MESH_GATT_PROXY_SERVER
/* Using UUID with a fixed pattern 0x96 for BLE Mesh GATT Proxy Server */
#define BLE_MESH_GATTS_APP_UUID_BYTE 0x96
/* the gatt database list to save the attribute table */
static sys_slist_t bt_mesh_gatts_db;
@@ -78,10 +81,11 @@ static future_t *future_mesh;
/* Static Functions */
static struct bt_mesh_gatt_attr *bt_mesh_gatts_find_attr_by_handle(u16_t handle);
#endif /* defined(CONFIG_BLE_MESH_NODE) && CONFIG_BLE_MESH_NODE */
#endif
#if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \
CONFIG_BLE_MESH_GATT_PROXY_CLIENT
/* Using UUID with a fixed pattern 0x97 for BLE Mesh GATT Proxy Client */
#define BLE_MESH_GATTC_APP_UUID_BYTE 0x97
static struct gattc_prov_info {
/* Service to be found depends on the type of adv pkt received */
@@ -472,7 +476,8 @@ int bt_le_scan_stop(void)
return 0;
}
#if defined(CONFIG_BLE_MESH_NODE) && CONFIG_BLE_MESH_NODE
#if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \
CONFIG_BLE_MESH_GATT_PROXY_SERVER
static void bt_mesh_bta_gatts_cb(tBTA_GATTS_EVT event, tBTA_GATTS *p_data)
{
switch (event) {
@@ -1049,7 +1054,7 @@ int bt_mesh_gatts_set_local_device_name(const char *name)
return 0;
}
#endif /* defined(CONFIG_BLE_MESH_NODE) && CONFIG_BLE_MESH_NODE */
#endif /* (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || CONFIG_BLE_MESH_GATT_PROXY_SERVER */
#if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \
CONFIG_BLE_MESH_GATT_PROXY_CLIENT
@@ -1682,31 +1687,32 @@ void bt_mesh_conn_unref(struct bt_mesh_conn *conn)
void bt_mesh_gatt_init(void)
{
tBT_UUID app_uuid = {LEN_UUID_128, {0}};
BTA_GATT_SetLocalMTU(GATT_DEF_BLE_MTU_SIZE);
#if CONFIG_BLE_MESH_NODE
/* Fill our internal UUID with a fixed pattern 0x96 for the ble mesh */
memset(&app_uuid.uu.uuid128, 0x96, LEN_UUID_128);
BTA_GATTS_AppRegister(&app_uuid, bt_mesh_bta_gatts_cb);
#if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \
CONFIG_BLE_MESH_GATT_PROXY_SERVER
tBT_UUID gatts_app_uuid = {LEN_UUID_128, {0}};
memset(&gatts_app_uuid.uu.uuid128, BLE_MESH_GATTS_APP_UUID_BYTE, LEN_UUID_128);
BTA_GATTS_AppRegister(&gatts_app_uuid, bt_mesh_bta_gatts_cb);
#endif
#if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \
CONFIG_BLE_MESH_GATT_PROXY_CLIENT
tBT_UUID gattc_app_uuid = {LEN_UUID_128, {0}};
for (int i = 0; i < ARRAY_SIZE(bt_mesh_gattc_info); i++) {
bt_mesh_gattc_info[i].conn.handle = 0xFFFF;
bt_mesh_gattc_info[i].mtu = GATT_DEF_BLE_MTU_SIZE; /* Default MTU_SIZE 23 */
bt_mesh_gattc_info[i].wr_desc_done = false;
}
memset(&app_uuid.uu.uuid128, BLE_MESH_GATTC_APP_UUID_BYTE, LEN_UUID_128);
BTA_GATTC_AppRegister(&app_uuid, bt_mesh_bta_gattc_cb);
memset(&gattc_app_uuid.uu.uuid128, BLE_MESH_GATTC_APP_UUID_BYTE, LEN_UUID_128);
BTA_GATTC_AppRegister(&gattc_app_uuid, bt_mesh_bta_gattc_cb);
#endif
}
void bt_mesh_gatt_deinit(void)
{
#if CONFIG_BLE_MESH_NODE
#if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \
CONFIG_BLE_MESH_GATT_PROXY_SERVER
BTA_GATTS_AppDeregister(bt_mesh_gatts_if);
#endif

View File

@@ -324,7 +324,7 @@ static int send_friend_req(struct bt_mesh_lpn *lpn)
.criteria = LPN_CRITERIA,
.recv_delay = LPN_RECV_DELAY,
.poll_to = LPN_POLL_TO,
.prev_addr = lpn->old_friend,
.prev_addr = sys_cpu_to_be16(lpn->old_friend),
.num_elem = comp->elem_count,
.lpn_counter = sys_cpu_to_be16(lpn->counter),
};

View File

@@ -326,7 +326,9 @@ int bt_mesh_init(const struct bt_mesh_prov *prov,
return err;
}
if (IS_ENABLED(CONFIG_BLE_MESH_PROXY)) {
bt_mesh_gatt_init();
}
if (IS_ENABLED(CONFIG_BLE_MESH_PROV)) {
if (IS_ENABLED(CONFIG_BLE_MESH_NODE)) {
@@ -358,7 +360,9 @@ int bt_mesh_init(const struct bt_mesh_prov *prov,
bt_mesh_adv_init();
if (IS_ENABLED(CONFIG_BLE_MESH_PROXY)) {
if (IS_ENABLED(CONFIG_BLE_MESH_NODE)) {
if ((IS_ENABLED(CONFIG_BLE_MESH_NODE) &&
IS_ENABLED(CONFIG_BLE_MESH_PB_GATT)) ||
IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER)) {
bt_mesh_proxy_init();
}
if ((IS_ENABLED(CONFIG_BLE_MESH_PROVISIONER) &&
@@ -501,12 +505,16 @@ int bt_mesh_provisioner_net_start(bt_mesh_prov_bearer_t bearers)
bt_mesh_provisioner_pb_gatt_enable();
}
bt_mesh_atomic_set_bit(bt_mesh.flags, BLE_MESH_VALID_PROV);
if (bt_mesh_beacon_get() == BLE_MESH_BEACON_ENABLED) {
bt_mesh_beacon_enable();
}
if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND)) {
bt_mesh_friend_init();
}
bt_mesh_atomic_set_bit(bt_mesh.flags, BLE_MESH_VALID_PROV);
return 0;
}
@@ -583,13 +591,18 @@ int bt_mesh_provisioner_disable(bt_mesh_prov_bearer_t bearers)
bt_mesh_atomic_and(bt_mesh.flags, ~(BIT(BLE_MESH_PROVISIONER) | BIT(BLE_MESH_VALID_PROV)));
/* When Provisioner is disabled, the device role indicated by bt_mesh.flags
* will not be cleared.
* will not be cleared, because when Provisioner is restarted after disabled,
* its previous information can be recovered from flash properly.
*/
if (bt_mesh_beacon_get() == BLE_MESH_BEACON_ENABLED) {
bt_mesh_beacon_disable();
}
if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND)) {
bt_mesh_friend_clear_net_idx(BLE_MESH_KEY_ANY);
}
}
return 0;
}

View File

@@ -253,6 +253,9 @@ static int provisioner_remove_node(u16_t index)
bt_mesh_clear_node_info(node->unicast_addr, is_prov);
}
if (mesh_nodes[index]->comp_data) {
osi_free(mesh_nodes[index]->comp_data);
}
osi_free(mesh_nodes[index]);
mesh_nodes[index] = NULL;
@@ -660,6 +663,69 @@ int bt_mesh_provisioner_restore_node_info(struct bt_mesh_node *node, bool prov)
return provisioner_store_node(node, prov, false, NULL);
}
static struct bt_mesh_node *provisioner_find_node_with_elem_addr(u16_t addr)
{
struct bt_mesh_node *node = NULL;
size_t i;
BT_DBG("%s", __func__);
if (!BLE_MESH_ADDR_IS_UNICAST(addr)) {
BT_ERR("%s, Not a unicast address 0x%04x", __func__, addr);
return NULL;
}
bt_mesh_provisioner_lock();
for (i = 0U; i < ARRAY_SIZE(mesh_nodes); i++) {
node = mesh_nodes[i];
if (node && addr >= node->unicast_addr &&
addr < (node->unicast_addr + node->element_num)) {
bt_mesh_provisioner_unlock();
return node;
}
}
bt_mesh_provisioner_unlock();
return NULL;
}
int bt_mesh_provisioner_restore_node_name(u16_t addr, const char *name)
{
struct bt_mesh_node *node = NULL;
node = provisioner_find_node_with_elem_addr(addr);
if (node == NULL) {
BT_ERR("%s, Node 0x%04x not exist", __func__, addr);
return -ENODEV;
}
strncpy(node->name, name, BLE_MESH_NODE_NAME_SIZE);
return 0;
}
int bt_mesh_provisioner_restore_node_comp_data(u16_t addr, const u8_t *data, u16_t length, bool prov)
{
struct bt_mesh_node *node = NULL;
node = provisioner_find_node_with_elem_addr(addr);
if (node == NULL) {
BT_ERR("%s, Node 0x%04x not exist", __func__, addr);
return -ENODEV;
}
node->comp_data = osi_calloc(length);
if (!node->comp_data) {
BT_ERR("%s, Failed to allocate memory", __func__);
return -ENOMEM;
}
node->comp_length = length;
memcpy(node->comp_data, data, length);
return 0;
}
/* Provisioner related internal test functions */
int bt_mesh_provisioner_store_node_info(struct bt_mesh_node *node)
@@ -674,29 +740,7 @@ int bt_mesh_provisioner_store_node_info(struct bt_mesh_node *node)
struct bt_mesh_node *bt_mesh_provisioner_get_node_info(u16_t unicast_addr)
{
struct bt_mesh_node *node = NULL;
size_t i;
BT_DBG("%s", __func__);
if (!BLE_MESH_ADDR_IS_UNICAST(unicast_addr)) {
BT_ERR("%s, Not a unicast address 0x%04x", __func__, unicast_addr);
return NULL;
}
bt_mesh_provisioner_lock();
for (i = 0U; i < ARRAY_SIZE(mesh_nodes); i++) {
node = mesh_nodes[i];
if (node && unicast_addr >= node->unicast_addr &&
unicast_addr < (node->unicast_addr + node->element_num)) {
bt_mesh_provisioner_unlock();
return node;
}
}
bt_mesh_provisioner_unlock();
return NULL;
return provisioner_find_node_with_elem_addr(unicast_addr);
}
/* Provisioner related node name management functions */
@@ -720,11 +764,9 @@ int bt_mesh_provisioner_set_node_name(u16_t index, const char *name)
BT_DBG("name len is %d, name is %s", strlen(name), name);
length = (strlen(name) <= NODE_NAME_SIZE) ? strlen(name) : NODE_NAME_SIZE;
length = (strlen(name) <= BLE_MESH_NODE_NAME_SIZE) ? strlen(name) : BLE_MESH_NODE_NAME_SIZE;
for (i = 0U; i < ARRAY_SIZE(mesh_nodes); i++) {
if (!mesh_nodes[i] || !mesh_nodes[i]->name) {
continue;
}
if (mesh_nodes[i]) {
name_len = strlen(mesh_nodes[i]->name);
if (length != name_len) {
continue;
@@ -734,8 +776,15 @@ int bt_mesh_provisioner_set_node_name(u16_t index, const char *name)
return -EEXIST;
}
}
}
memset(mesh_nodes[index]->name, 0, BLE_MESH_NODE_NAME_SIZE);
strncpy(mesh_nodes[index]->name, name, length);
if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) {
bt_mesh_store_node_name(mesh_nodes[index],
index < CONFIG_BLE_MESH_MAX_PROV_NODES ? true : false);
}
return 0;
}
@@ -752,7 +801,7 @@ const char *bt_mesh_provisioner_get_node_name(u16_t index)
return mesh_nodes[index]->name;
}
int bt_mesh_provisioner_get_node_index(const char *name)
u16_t bt_mesh_provisioner_get_node_index(const char *name)
{
size_t length, name_len;
size_t i;
@@ -760,24 +809,58 @@ int bt_mesh_provisioner_get_node_index(const char *name)
BT_DBG("%s", __func__);
if (!name) {
return -EINVAL;
BT_ERR("%s, Invalid parameter", __func__);
return BLE_MESH_INVALID_NODE_INDEX;
}
length = (strlen(name) <= NODE_NAME_SIZE) ? strlen(name) : NODE_NAME_SIZE;
length = (strlen(name) <= BLE_MESH_NODE_NAME_SIZE) ? strlen(name) : BLE_MESH_NODE_NAME_SIZE;
for (i = 0U; i < ARRAY_SIZE(mesh_nodes); i++) {
if (!mesh_nodes[i] || !mesh_nodes[i]->name) {
continue;
}
if (mesh_nodes[i]) {
name_len = strlen(mesh_nodes[i]->name);
if (length != name_len) {
continue;
}
if (!strncmp(mesh_nodes[i]->name, name, length)) {
return i;
return (u16_t)i;
}
}
}
BT_ERR("%s, Node name %s not exist", __func__, name);
return BLE_MESH_INVALID_NODE_INDEX;
}
int bt_mesh_provisioner_store_node_comp_data(u16_t addr, const u8_t *data, u16_t length)
{
struct bt_mesh_node *node = NULL;
if (!BLE_MESH_ADDR_IS_UNICAST(addr) || !data ||
(length % 2) || length <= 14) {
BT_ERR("%s, Invalid parameter", __func__);
return -EINVAL;
}
node = provisioner_find_node_with_elem_addr(addr);
if (node == NULL) {
BT_ERR("%s, Node 0x%04x not exist", __func__, addr);
return -ENODEV;
}
node->comp_data = osi_calloc(length);
if (node->comp_data == NULL) {
BT_ERR("%s, Failed to allocate memory", __func__);
return -ENOMEM;
}
memcpy(node->comp_data, data, length);
node->comp_length = length;
if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) {
bt_mesh_store_node_comp_data(node,
(node - mesh_nodes[0]) < CONFIG_BLE_MESH_MAX_PROV_NODES ? true : false);
}
return 0;
}
/* Provisioner related NetKey and AppKey functions */

View File

@@ -20,21 +20,29 @@
#include "mesh_access.h"
#include "net.h"
#define NODE_NAME_SIZE 31
#define BLE_MESH_INVALID_NODE_INDEX 0xFFFF
#define BLE_MESH_NODE_NAME_SIZE 31
/* Each node information stored by provisioner */
struct bt_mesh_node {
char name[NODE_NAME_SIZE]; /* Node name */
/* Device information */
u8_t addr[6]; /* Node device address */
u8_t addr_type; /* Node device address type */
u8_t dev_uuid[16]; /* Device UUID */
u8_t dev_uuid[16]; /* Node Device UUID */
u16_t oob_info; /* Node OOB information */
/* Provisioning information */
u16_t unicast_addr; /* Node unicast address */
u8_t element_num; /* Node element number */
u16_t net_idx; /* Node NetKey Index */
u8_t flags; /* Node key refresh flag and iv update flag */
u32_t iv_index; /* Node IV Index */
u8_t dev_key[16]; /* Node device key */
/* Additional information */
char name[BLE_MESH_NODE_NAME_SIZE]; /* Node name */
u16_t comp_length; /* Length of Composition Data */
u8_t *comp_data; /* Value of Composition Data */
} __packed;
/* The following APIs are for key init, node provision & node reset. */
@@ -76,6 +84,10 @@ struct bt_mesh_app_key *bt_mesh_provisioner_app_key_find(u16_t app_idx);
int bt_mesh_provisioner_restore_node_info(struct bt_mesh_node *node, bool prov);
int bt_mesh_provisioner_restore_node_name(u16_t addr, const char *name);
int bt_mesh_provisioner_restore_node_comp_data(u16_t addr, const u8_t *data, u16_t length, bool prov);
/* The following APIs are for provisioner application use. */
int bt_mesh_provisioner_store_node_info(struct bt_mesh_node *node);
@@ -86,7 +98,9 @@ int bt_mesh_provisioner_set_node_name(u16_t index, const char *name);
const char *bt_mesh_provisioner_get_node_name(u16_t index);
int bt_mesh_provisioner_get_node_index(const char *name);
u16_t bt_mesh_provisioner_get_node_index(const char *name);
int bt_mesh_provisioner_store_node_comp_data(u16_t addr, const u8_t *data, u16_t length);
int bt_mesh_provisioner_local_app_key_add(const u8_t app_key[16], u16_t net_idx, u16_t *app_idx);

View File

@@ -593,7 +593,7 @@ static bool is_unprov_dev_being_provision(const u8_t uuid[16])
*/
if (bt_mesh_provisioner_find_node_with_uuid(uuid, false)) {
BT_WARN("Device has already been provisioned");
return -EALREADY;
return true;
}
#endif
@@ -972,7 +972,7 @@ int bt_mesh_provisioner_prov_device_with_addr(const u8_t uuid[16], const u8_t ad
return -ENOTSUP;
}
if (addr == NULL || addr_type > BLE_MESH_ADDR_RANDOM) {
if (bearer == BLE_MESH_PROV_GATT && (addr == NULL || addr_type > BLE_MESH_ADDR_RANDOM)) {
BT_ERR("%s, Invalid device address info", __func__);
return -EINVAL;
}
@@ -1002,8 +1002,10 @@ int bt_mesh_provisioner_prov_device_with_addr(const u8_t uuid[16], const u8_t ad
return err;
}
if (addr) {
dev_addr.type = addr_type;
memcpy(dev_addr.val, addr, BLE_MESH_ADDR_LEN);
}
if (bearer == BLE_MESH_PROV_ADV) {
#if defined(CONFIG_BLE_MESH_PB_ADV)
@@ -1813,7 +1815,7 @@ static void prov_capabilities(const u8_t idx, const u8_t *data)
u8_t auth_method, auth_action, auth_size;
element_num = data[0];
BT_INFO("Elements: %u", element_num);
BT_INFO("Elements: 0x%02x", element_num);
if (!element_num) {
BT_ERR("%s, Invalid element number", __func__);
goto fail;
@@ -1821,7 +1823,7 @@ static void prov_capabilities(const u8_t idx, const u8_t *data)
link[idx].element_num = element_num;
algorithms = sys_get_be16(&data[1]);
BT_INFO("Algorithms: %u", algorithms);
BT_INFO("Algorithms: 0x%04x", algorithms);
if (algorithms != BIT(PROV_ALG_P256)) {
BT_ERR("%s, Invalid algorithms", __func__);
goto fail;
@@ -1845,7 +1847,7 @@ static void prov_capabilities(const u8_t idx, const u8_t *data)
static_oob = (prov_ctx.static_oob_len ? static_oob : 0x00);
output_size = data[5];
BT_INFO("Output OOB Size: %u", output_size);
BT_INFO("Output OOB Size: 0x%02x", output_size);
if (output_size > 0x08) {
BT_ERR("%s, Invalid Output OOB size", __func__);
goto fail;
@@ -1867,7 +1869,7 @@ static void prov_capabilities(const u8_t idx, const u8_t *data)
}
input_size = data[8];
BT_INFO("Input OOB Size: %u", input_size);
BT_INFO("Input OOB Size: 0x%02x", input_size);
if (input_size > 0x08) {
BT_ERR("%s, Invalid Input OOB size", __func__);
goto fail;

View File

@@ -786,20 +786,26 @@ bool bt_mesh_proxy_client_beacon_send(struct bt_mesh_subnet *sub)
/* NULL means we send Secure Network Beacon on all subnets */
if (!sub) {
if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) {
#if CONFIG_BLE_MESH_NODE
if (bt_mesh_is_provisioned()) {
for (i = 0U; i < ARRAY_SIZE(bt_mesh.sub); i++) {
if (bt_mesh.sub[i].net_idx != BLE_MESH_KEY_UNUSED) {
send = bt_mesh_proxy_client_beacon_send(&bt_mesh.sub[i]);
}
}
} else if (IS_ENABLED(CONFIG_BLE_MESH_PROVISIONER) && bt_mesh_is_provisioner_en()) {
return send;
}
#endif /* CONFIG_BLE_MESH_NODE */
#if CONFIG_BLE_MESH_PROVISIONER
if (bt_mesh_is_provisioner_en()) {
for (i = 0U; i < ARRAY_SIZE(bt_mesh.p_sub); i++) {
if (bt_mesh.p_sub[i] && bt_mesh.p_sub[i]->net_idx != BLE_MESH_KEY_UNUSED) {
send = bt_mesh_proxy_client_beacon_send(bt_mesh.p_sub[i]);
}
}
return send;
}
#endif /* CONFIG_BLE_MESH_PROVISIONER */
return send;
}

View File

@@ -26,7 +26,8 @@
#include "access.h"
#include "proxy_server.h"
#if CONFIG_BLE_MESH_NODE
#if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \
CONFIG_BLE_MESH_GATT_PROXY_SERVER
/* Not support enabling Proxy Client and Proxy Server simultaneously */
_Static_assert(!(IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER) &&IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_CLIENT)),
@@ -83,7 +84,7 @@ static bool prov_fast_adv;
static struct bt_mesh_proxy_client {
struct bt_mesh_conn *conn;
#if CONFIG_BLE_MESH_PROXY
#if defined(CONFIG_BLE_MESH_GATT_PROXY_SERVER)
u16_t filter[CONFIG_BLE_MESH_PROXY_FILTER_SIZE];
#endif
enum __packed {
@@ -592,7 +593,7 @@ static void proxy_connected(struct bt_mesh_conn *conn, u8_t err)
client->conn = bt_mesh_conn_ref(conn);
client->filter_type = NONE;
#if CONFIG_BLE_MESH_PROXY
#if defined(CONFIG_BLE_MESH_GATT_PROXY_SERVER)
(void)memset(client->filter, 0, sizeof(client->filter));
#endif
net_buf_simple_reset(&client->buf);
@@ -1463,4 +1464,4 @@ int bt_mesh_proxy_deinit(void)
return 0;
}
#endif /* CONFIG_BLE_MESH_NODE */
#endif /* (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || CONFIG_BLE_MESH_GATT_PROXY_SERVER */

View File

@@ -166,6 +166,19 @@ struct prov_info {
u16_t alloc_addr;
};
struct node_info {
u8_t addr[6];
u8_t addr_type;
u8_t dev_uuid[16];
u16_t oob_info;
u16_t unicast_addr;
u8_t element_num;
u16_t net_idx;
u8_t flags;
u32_t iv_index;
u8_t dev_key[16];
} __packed;
#define DEVICE_ROLE_BITS (BIT(BLE_MESH_NODE) | BIT(BLE_MESH_PROVISIONER))
static int role_set(const char *name)
@@ -1032,11 +1045,101 @@ free:
return err;
}
static int node_info_set(u16_t addr, bool prov, bool *exist)
{
struct bt_mesh_node node = {0};
struct node_info info = {0};
char get[16] = {'\0'};
int err;
sprintf(get, prov ? "mesh/pn/%04x/i" : "mesh/sn/%04x/i", addr);
err = bt_mesh_load_core_settings(get, (u8_t *)&info, sizeof(info), exist);
if (err) {
BT_ERR("%s, Failed to load node %s", __func__, get);
return -EIO;
}
if (*exist == false) {
return 0;
}
memcpy(node.addr, info.addr, BLE_MESH_ADDR_LEN);
node.addr_type = info.addr_type;
memcpy(node.dev_uuid, info.dev_uuid, 16);
node.oob_info = info.oob_info;
node.unicast_addr = info.unicast_addr;
node.element_num = info.element_num;
node.net_idx = info.net_idx;
node.flags = info.flags;
node.iv_index = info.iv_index;
memcpy(node.dev_key, info.dev_key, 16);
err = bt_mesh_provisioner_restore_node_info(&node, prov);
if (err) {
BT_ERR("%s, Failed to restore node 0x%04x", __func__, addr);
return -EIO;
}
BT_INFO("Restored node 0x%04x, uuid %s", addr, bt_hex(node.dev_uuid, 16));
return 0;
}
static int node_name_set(u16_t addr, bool prov)
{
char name[BLE_MESH_NODE_NAME_SIZE] = {0};
char get[16] = {'\0'};
bool exist;
int err;
sprintf(get, prov ? "mesh/pn/%04x/n" : "mesh/sn/%04x/n", addr);
err = bt_mesh_load_core_settings(get, (u8_t *)name, BLE_MESH_NODE_NAME_SIZE, &exist);
if (err) {
BT_ERR("%s, Failed to load node name %s", __func__, get);
return -EIO;
}
if (exist == false) {
return 0;
}
err = bt_mesh_provisioner_restore_node_name(addr, name);
if (err) {
BT_ERR("%s, Failed to restore node name 0x%04x", __func__, addr);
return -EIO;
}
BT_INFO("Restored node 0x%04x, name %s", addr, name);
return 0;
}
static int node_comp_data_set(u16_t addr, bool prov)
{
struct net_buf_simple *buf = NULL;
char get[16] = {'\0'};
int err;
sprintf(get, prov ? "mesh/pn/%04x/c" : "mesh/sn/%04x/c", addr);
buf = bt_mesh_get_core_settings_item(get);
if (!buf) {
return 0;
}
err = bt_mesh_provisioner_restore_node_comp_data(addr, buf->data, buf->len, prov);
if (err) {
BT_ERR("%s, Failed to restore node comp data 0x%04x", __func__, addr);
}
BT_INFO("Restored node 0x%04x, comp data %s", addr, bt_hex(buf->data, buf->len));
bt_mesh_free_buf(buf);
return err;
}
static int p_node_set(const char *name)
{
struct net_buf_simple *buf = NULL;
struct bt_mesh_node node = {0};
char get[16] = {'\0'};
bool exist, prov;
size_t length;
int err = 0;
@@ -1052,11 +1155,14 @@ static int p_node_set(const char *name)
for (i = 0U; i < length / SETTINGS_ITEM_SIZE; i++) {
u16_t addr = net_buf_simple_pull_le16(buf);
sprintf(get, prov ? "mesh/pnd/%04x" : "mesh/snd/%04x", addr);
if (!BLE_MESH_ADDR_IS_UNICAST(addr)) {
BT_ERR("%s, 0x%04x is not a unicast address", __func__, addr);
goto free;
}
err = bt_mesh_load_core_settings(get, (u8_t *)&node, sizeof(node), &exist);
err = node_info_set(addr, prov, &exist);
if (err) {
BT_ERR("%s, Failed to load node %s", __func__, get);
BT_ERR("%s, Failed to load node 0x%04x info", __func__, addr);
goto free;
}
@@ -1064,13 +1170,17 @@ static int p_node_set(const char *name)
continue;
}
err = bt_mesh_provisioner_restore_node_info(&node, prov);
err = node_name_set(addr, prov);
if (err) {
BT_ERR("%s, Failed to store node 0x%04x", __func__, node.unicast_addr);
BT_ERR("%s, Failed to load node 0x%04x name", __func__, addr);
goto free;
}
BT_INFO("Restored node 0x%04x, uuid %s", node.unicast_addr, bt_hex(node.dev_uuid, 16));
err = node_comp_data_set(addr, prov);
if (err) {
BT_ERR("%s, Failed to load node 0x%04x comp data", __func__, addr);
goto free;
}
}
free:
@@ -1153,11 +1263,17 @@ int settings_core_load(void)
settings[i].func(settings[i].name);
if (!strcmp(settings[i].name, "mesh/role") &&
!bt_mesh_is_node() && !bt_mesh_is_provisioner()) {
BT_INFO("Device just starts up");
if (!strcmp(settings[i].name, "mesh/role")) {
u8_t role = bt_mesh_atomic_get(bt_mesh.flags) & DEVICE_ROLE_BITS;
if (role == 0U) {
BT_INFO("Device just starts up, nothing restored");
return 0;
}
if (role != BIT(BLE_MESH_NODE) && role != BIT(BLE_MESH_PROVISIONER)) {
BT_ERR("Invalid restored device role %d", role);
return 0;
}
}
}
return 0;
@@ -2133,9 +2249,13 @@ void bt_mesh_store_label(void)
* key: "mesh/p_appkey" -> write/read to set/get all Provisioner AppKey Index
* key: "mesh/pak/xxxx" -> write/read to set/get the "xxxx" AppKey
* key: "mesh/p_pnode" -> write/read to set/get all self-provisioned nodes info
* key: "mesh/pnd/xxxx" -> write/read to set/get the "xxxx" provisioned node info
* key: "mesh/pn/xxxx/i" -> write/read to set/get the "xxxx" provisioned node info
* key: "mesh/pn/xxxx/n" -> write/read to set/get the "xxxx" provisioned node name
* key: "mesh/pn/xxxx/c" -> write/read to set/get the "xxxx" provisioned node composition data
* key: "mesh/p_snode" -> write/read to set/get all locally stored nodes info
* key: "mesh/snd/xxxx" -> write/read to set/get the "xxxx" stored node info
* key: "mesh/sn/xxxx/i" -> write/read to set/get the "xxxx" stored node info
* key: "mesh/sn/xxxx/n" -> write/read to set/get the "xxxx" stored node name
* key: "mesh/sn/xxxx/c" -> write/read to set/get the "xxxx" stored node composition data
*/
void bt_mesh_store_prov_info(u16_t primary_addr, u16_t alloc_addr)
{
@@ -2146,8 +2266,7 @@ void bt_mesh_store_prov_info(u16_t primary_addr, u16_t alloc_addr)
val.primary_addr = primary_addr;
val.alloc_addr = alloc_addr;
bt_mesh_save_core_settings("mesh/p_prov",
(const u8_t *)&val, sizeof(val));
bt_mesh_save_core_settings("mesh/p_prov", (const u8_t *)&val, sizeof(val));
}
static void clear_p_net_key(u16_t net_idx)
@@ -2323,6 +2442,7 @@ void bt_mesh_clear_rpl_single(u16_t src)
void bt_mesh_store_node_info(struct bt_mesh_node *node, bool prov)
{
struct node_info val = {0};
char name[16] = {'\0'};
int err;
@@ -2331,8 +2451,19 @@ void bt_mesh_store_node_info(struct bt_mesh_node *node, bool prov)
return;
}
sprintf(name, prov ? "mesh/pnd/%04x" : "mesh/snd/%04x", node->unicast_addr);
err = bt_mesh_save_core_settings(name, (const u8_t *)node, sizeof(struct bt_mesh_node));
memcpy(val.addr, node->addr, BLE_MESH_ADDR_LEN);
val.addr_type = node->addr_type;
memcpy(val.dev_uuid, node->dev_uuid, 16);
val.oob_info = node->oob_info;
val.unicast_addr = node->unicast_addr;
val.element_num = node->element_num;
val.net_idx = node->net_idx;
val.flags = node->flags;
val.iv_index = node->iv_index;
memcpy(val.dev_key, node->dev_key, 16);
sprintf(name, prov ? "mesh/pn/%04x/i" : "mesh/sn/%04x/i", node->unicast_addr);
err = bt_mesh_save_core_settings(name, (const u8_t *)&val, sizeof(val));
if (err) {
BT_ERR("%s, Failed to save node %s", __func__, name);
return;
@@ -2349,7 +2480,16 @@ static void clear_node(u16_t addr, bool prov)
char name[16] = {'\0'};
int err;
sprintf(name, prov ? "mesh/pnd/%04x" : "mesh/snd/%04x", addr);
/* Clear node information */
sprintf(name, prov ? "mesh/pn/%04x/i" : "mesh/sn/%04x/i", addr);
bt_mesh_save_core_settings(name, NULL, 0);
/* Clear node name */
sprintf(name, prov ? "mesh/pn/%04x/n" : "mesh/sn/%04x/n", addr);
bt_mesh_save_core_settings(name, NULL, 0);
/* Clear node composition data */
sprintf(name, prov ? "mesh/pn/%04x/c" : "mesh/sn/%04x/c", addr);
bt_mesh_save_core_settings(name, NULL, 0);
err = bt_mesh_remove_core_settings_item(prov ? "mesh/p_pnode" : "mesh/p_snode", addr);
@@ -2369,6 +2509,54 @@ void bt_mesh_clear_node_info(u16_t unicast_addr, bool prov)
clear_node(unicast_addr, prov);
}
void bt_mesh_store_node_name(struct bt_mesh_node *node, bool prov)
{
char node_name[BLE_MESH_NODE_NAME_SIZE] = {0};
char name[16] = {'\0'};
int err;
if (node == NULL) {
BT_ERR("%s, Invalid node", __func__);
return;
}
strncpy(node_name, node->name, BLE_MESH_NODE_NAME_SIZE);
sprintf(name, prov ? "mesh/pn/%04x/n" : "mesh/sn/%04x/n", node->unicast_addr);
err = bt_mesh_save_core_settings(name, (const u8_t *)node_name, BLE_MESH_NODE_NAME_SIZE);
if (err) {
BT_ERR("%s, Failed to save node name %s", __func__, name);
}
}
void bt_mesh_store_node_comp_data(struct bt_mesh_node *node, bool prov)
{
char name[16] = {'\0'};
u8_t *data = NULL;
int err;
if (node == NULL) {
BT_ERR("%s, Invalid node", __func__);
return;
}
data = osi_calloc(node->comp_length);
if (!data) {
BT_ERR("%s, Failed to allocate memory", __func__);
return;
}
memcpy(data, node->comp_data, node->comp_length);
sprintf(name, prov ? "mesh/pn/%04x/c" : "mesh/sn/%04x/c", node->unicast_addr);
err = bt_mesh_save_core_settings(name, (const u8_t *)data, node->comp_length);
if (err) {
BT_ERR("%s, Failed to save node comp data %s", __func__, name);
}
osi_free(data);
}
#endif /* CONFIG_BLE_MESH_PROVISIONER */
int settings_core_init(void)

View File

@@ -52,6 +52,8 @@ void bt_mesh_clear_p_app_key(struct bt_mesh_app_key *key);
void bt_mesh_clear_rpl_single(u16_t src);
void bt_mesh_store_node_info(struct bt_mesh_node *node, bool prov);
void bt_mesh_clear_node_info(u16_t unicast_addr, bool prov);
void bt_mesh_store_node_name(struct bt_mesh_node *node, bool prov);
void bt_mesh_store_node_comp_data(struct bt_mesh_node *node, bool prov);
#endif
int bt_mesh_settings_init(void);

View File

@@ -18,6 +18,7 @@
#include <errno.h>
#include "nvs.h"
#include "nvs_flash.h"
#include "sdkconfig.h"
#include "mesh_util.h"
@@ -65,12 +66,25 @@ static struct settings_context settings_ctx[] = {
void bt_mesh_settings_foreach(void)
{
int i, err;
size_t i;
int err;
for (i = 0; i < ARRAY_SIZE(settings_ctx); i++) {
#if CONFIG_BLE_MESH_SPECIFIC_PARTITION
err = nvs_flash_init_partition(CONFIG_BLE_MESH_PARTITION_NAME);
if (err != ESP_OK) {
BT_ERR("Failed to init mesh partition, name %s, err %d", CONFIG_BLE_MESH_PARTITION_NAME, err);
return;
}
#endif
for (i = 0U; i < ARRAY_SIZE(settings_ctx); i++) {
struct settings_context *ctx = &settings_ctx[i];
#if CONFIG_BLE_MESH_SPECIFIC_PARTITION
err = nvs_open_from_partition(CONFIG_BLE_MESH_PARTITION_NAME, ctx->nvs_name, NVS_READWRITE, &ctx->handle);
#else
err = nvs_open(ctx->nvs_name, NVS_READWRITE, &ctx->handle);
#endif
if (err != ESP_OK) {
BT_ERR("%s, Open nvs failed, name %s, err %d", __func__, ctx->nvs_name, err);
continue;
@@ -95,9 +109,9 @@ void bt_mesh_settings_foreach(void)
void bt_mesh_settings_deforeach(void)
{
int i;
size_t i;
for (i = 0; i < ARRAY_SIZE(settings_ctx); i++) {
for (i = 0U; i < ARRAY_SIZE(settings_ctx); i++) {
struct settings_context *ctx = &settings_ctx[i];
if (ctx->settings_deinit && ctx->settings_deinit()) {
@@ -107,6 +121,10 @@ void bt_mesh_settings_deforeach(void)
nvs_close(ctx->handle);
}
#if CONFIG_BLE_MESH_SPECIFIC_PARTITION
nvs_flash_deinit_partition(CONFIG_BLE_MESH_PARTITION_NAME);
#endif
}
/* API used to get BLE Mesh related nvs handle */

View File

@@ -235,7 +235,7 @@
#define BLE_MESH_MODEL_OP_LIGHT_HSL_DEFAULT_SET BLE_MESH_MODEL_OP_2(0x82, 0x7F)
#define BLE_MESH_MODEL_OP_LIGHT_HSL_DEFAULT_SET_UNACK BLE_MESH_MODEL_OP_2(0x82, 0x80)
#define BLE_MESH_MODEL_OP_LIGHT_HSL_RANGE_SET BLE_MESH_MODEL_OP_2(0x82, 0x81)
#define BLE_MESH_MODEL_OP_LIGHT_HSL_RANGE_SET_UNACK BLE_MESH_MODEL_OP_2(0x82, 0x82) /* Model spec is wrong */
#define BLE_MESH_MODEL_OP_LIGHT_HSL_RANGE_SET_UNACK BLE_MESH_MODEL_OP_2(0x82, 0x82)
/* Light xyL Message Opcode */
#define BLE_MESH_MODEL_OP_LIGHT_XYL_GET BLE_MESH_MODEL_OP_2(0x82, 0x83)

View File

@@ -192,6 +192,15 @@ int bt_mesh_update_binding_state(struct bt_mesh_model *model,
bt_mesh_server_stop_transition(&srv->actual_transition);
srv->state->lightness_actual = value->light_lightness_actual.lightness;
/**
* Whenever the Light Lightness Actual state is changed with a non-transactional
* message or a completed sequence of transactional messages to a non-zero value,
* the value of the Light Lightness Last shall be set to the value of the Light
* Lightness Actual.
*/
if (srv->state->lightness_actual) {
srv->state->lightness_last = srv->state->lightness_actual;
}
light_lightness_publish(model, BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_STATUS);
break;
}

View File

@@ -55,6 +55,20 @@ INPUT = \
../../components/bt/bluedroid/api/include/api/esp_hf_client_api.h \
## NimBLE related Bluetooth APIs
../../components/nimble/esp-hci/include/esp_nimble_hci.h \
## ESP BLE Mesh APIs
../../components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_common_api.h \
../../components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_local_data_operation_api.h \
../../components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_low_power_api.h \
../../components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_networking_api.h \
../../components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_provisioning_api.h \
../../components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_proxy_api.h \
../../components/bt/esp_ble_mesh/api/models/include/esp_ble_mesh_config_model_api.h \
../../components/bt/esp_ble_mesh/api/models/include/esp_ble_mesh_generic_model_api.h \
../../components/bt/esp_ble_mesh/api/models/include/esp_ble_mesh_health_model_api.h \
../../components/bt/esp_ble_mesh/api/models/include/esp_ble_mesh_lighting_model_api.h \
../../components/bt/esp_ble_mesh/api/models/include/esp_ble_mesh_sensor_model_api.h \
../../components/bt/esp_ble_mesh/api/models/include/esp_ble_mesh_time_scene_model_api.h \
../../components/bt/esp_ble_mesh/api/esp_ble_mesh_defs.h \
##
## Ethernet - API Reference
##

View File

@@ -59,6 +59,8 @@ These third party libraries can be included into the application (firmware) prod
* `mynewt-nimble`_ Apache Mynewt NimBLE, Copyright 2015-2018, The Apache Software Foundation, is licensed under Apache License 2.0.
* :component:`BLE Mesh <bt/esp_ble_mesh>` is adapted from Zephyr Project, Copyright (c) 2017-2018 Intel Corporation and licensed under Apache License 2.0
Build Tools
-----------

View File

@@ -0,0 +1,395 @@
ESP-BLE-MESH Architecture
=========================
:link_to_translation:`zh_CN:[中文]`
This document introduces ESP-BLE-MESH architecture overview, ESP-BLE-MESH architecture implementation as well as ESP-BLE-MESH auxiliary routines.
- ESP-BLE-MESH Architecture Overview
- Describes the five major parts of ESP-BLE-MESH architecture and the functionality of each part.
- ESP-BLE-MESH Architecture Implementation
- Describes the basic functions of ESP-BLE-MESH files, the correspondence between files and ESP-BLE-MESH architecture, and the interface for calling among files.
- ESP-BLE-MESH Auxiliary Routines
- Describe the auxiliary routines of ESP-BLE-MESH, such as Mesh network management, Mesh features, etc.
1. ESP-BLE-MESH Architecture Overview
-------------------------------------
Currently ESP-BLE-MESH has implemented most functions of Mesh Profile and all the Client Models defined in Mesh Model specification. Those missing functions/models are under development and will be provided soon. ESP-BLE-MESH architecture has been granted the official Bluetooth `certification <https://launchstudio.bluetooth.com/ListingDetails/76255>`__.
.. figure:: ../../../_static/esp-ble-mesh-architecture.png
:align: center
Figure 1.1 ESP-BLE-MESH Architecture Diagram
ESP-BLE-MESH architecture includes five key parts:
- ``Mesh Protocol Stack``
- ``Mesh Networking`` is responsible for processing of messages of ESP-BLE-MESH nodes.
- ``Mesh Provisioning`` is responsible for provisioning flow of ESP-BLE-MESH devices.
- ``Mesh Models`` is responsible for the implementation of SIG-defined models.
- ``Network Management``
- Implements several network management procedures, including node removal procedure, IV Index recovery procedure, etc.
- ``Features``
- Include several ESP-BLE-MESH features, e.g. Low Power feature, Friend feature, Relay feature, etc.
- ``Mesh Bearer Layer``
- Includes ``Advertising Bearer`` and ``GATT Bearer``. The bearer layer is crucial to ESP-BLE-MESH protocol stack which is built on Bluetooth Low-Energy technology, because the protocol stack must make use of the bearer layer to transmit data via the BLE advertising channel and connection channel.
- ``Applications``
- Based on ESP-BLE-MESH protocol stack and ``Mesh Models``.
- By calling API and handling Event, ``Applications`` interact with ``Mesh Networking`` and ``Mesh Provisioning`` in ESP-BLE-MESH protocol stack, as well as a series of Models provided by ``Mesh Models``.
1.1 Mesh Protocol Stack
-----------------------
1.1.1 Mesh Networking
^^^^^^^^^^^^^^^^^^^^^
``Mesh Networking`` in the protocol stack architecture implements the following functions:
- The communication between nodes in the Mesh network.
- Encryption and decryption of messages in the Mesh network.
- Management of Mesh network resources (Network Key, IV Index, etc.).
- Segmentation and reassembly of Mesh network messages.
- Model mapping of messages between different models.
- For more features, please see :doc:`ble-mesh-feature-list`.
The implementation of ``Mesh Networking`` functions is based on hierarchy structure. Functions of each layer are shown in Table 1.1:
.. list-table:: Table 1.1 Mesh Networking Architecture Description
:widths: 40 150
:header-rows: 1
* - Layer
- Function
* - Access Layer
- Access Layer not only defines the format of application data, but also defines and controls the encryption and decryption of the data packets conducted by Upper Transport Layer.
* - Upper Transport Layer
- Upper Transport Layer encrypts, decrypts, and authenticates application data to and from the access layer; it also handles special messages called "transport control messages", including messages related to "friendship" and heartbeat messages.
* - Lower Transport Layer
- Lower Transport Layer handles segmentation and reassembly of PDU.
* - Network Layer
- Network Layer defines the address type and format of the network messages, and implements the relay function of the device.
1.1.2 Mesh Provisioning
^^^^^^^^^^^^^^^^^^^^^^^
``Mesh Provisioning`` in the protocol stack architecture implements the following functions:
- Provisioning of unprovisioned devices.
- Allocation of Mesh network resources (unicast address, IV Index, NetKey, etc.).
- Four authentication methods support during provisioning.
- For more features, please see :doc:`ble-mesh-feature-list`.
The implementation of ``Mesh Provisioning`` functions is based on hierarchy structure. Functions of each layer are shown in Table 1.2:
.. list-table:: Table 1.2 Mesh Provisioning Architecture Description
:widths: 40 150
:header-rows: 1
* - Layer
- Function
* - Provisioning PDUs
- Provisioning PDUs from different layers are handled using provisioning protocol.
* - Generic Provisioning PDU/Proxy PDU
- The Provisioning PDUs are transmitted to an unprovisioned device using a Generic Provisioning layer or Proxy protocol layer.
* - PB-ADV/PB-GATT
- These layers define how the Provisioning PDUs are transmitted as transactions that can be segmented and reassembled.
* - Advertising/Provisioning Service
- The provisioning bearers define how sessions are established such that the transactions from the generic provisioning layer can be delivered to a single device.
1.1.3 Mesh Models
^^^^^^^^^^^^^^^^^
``Mesh Models`` in the protocol stack architecture implements the following functions:
- Configuration Client/Server Models
- Health Client/Server Models
- Generic Client/Server Models
- Sensor Client/Server Models
- Time and Scenes Client/Server Models
- Lighting Client/Server Models
Functions of each layer are shown in Table 1.3:
.. list-table:: Table 1.3 Mesh Models Architecture Description
:widths: 40 150
:header-rows: 1
* - Layer
- Function
* - Model Layer
- Model Layer implements models used to standardize the operation of typical user scenarios, including Generic Client/Server Models, Sensor Client/Server Models, Time and Scenes Client/Server Models, Lighting Client/Server Models and several vendor models.
* - Foundation Model Layer
- Foundation Model Layer implements models related to ESP-BLE-MESH configuration, management, self diagnosis, etc.
1.2 Mesh Network Management
---------------------------
``Network Management`` implements the following functions:
- Node removal procedure is used to remove a node from the network.
- IV Index recovery procedure is used to recover a node's IV Index.
- IV update procedure is used to update the nodes' IV Index.
- Key refresh procedure is used to update the nodes' NetKey, AppKey, etc.
- Network creation procedure is used to create a mesh network.
- NVS storage is used to store node's networking information.
1.3 Mesh Features
-----------------
``Features`` includes the following options:
- Low Power feature is used to reduce node's power consumption.
- Friend feature is used to store messages for Low Power nodes.
- Relay feature is used to relay/forward Network PDUs received by a node over the advertising bearer.
- Proxy Server/Client are two node roles in proxy protocol, which enable nodes to send and receive Network PDUs, mesh beacons, proxy configuration messages and Provisioning PDUs over a connection-oriented bearer.
1.4 Mesh Bearer Layer
---------------------
``Bearers`` in the protocol stack architecture are responsible for passing of data between ESP-BLE-MESH protocol stack and Bluetooth Low Energy Core.
``Bearers`` can be taken as a carrier layer based on Bluetooth Low Energy Core, which implements the function of receiving and transmitting data for the ESP-BLE-MESH protocol stack.
.. list-table:: Table 1.3 Mesh Bearers Description
:widths: 40 150
:header-rows: 1
* - Layer
- Function
* - GATT Bearer
- The GATT Bearer uses the Proxy protocol to transmit and receive ``Proxy PDUs`` between two devices over a GATT connection.
* - Advertising Bearer
- When using the Advertising Bearer, a mesh packet shall be sent in the Advertising Data of a ``Bluetooth Low Energy advertising PDU`` using the Mesh Message AD Type.
1.5 Mesh Applications
---------------------
The ``Applications`` in the protocol stack architecture implement the corresponding functions by calling the API provided by the ESP-BLE-MESH protocol stack and processing the Event reported by the protocol stack. There are some common applications, such as gateway, lighting and etc.
Interaction between application layer``Applications``and ``API / Event``
- Application layer calls API
- Call the provisioning-related API for provisioning.
- Call the model-related API to send messages.
- Call the device-attributes-related API to get local information about the device.
- Application layer processes Event
The application layer is designed based on events, which take parameters to the application layer. Events are mainly divided into two categories.
- The events completed by calling API.
- Such as nodes sending messages.
- The events that the protocol stack actively reports to the application layer.
- The Event that the protocol stack actively reports.
- The Event that Model actively reports.
- The event is reported by the callback function registered by the application layer, and the callback function also contains the corresponding processing of the event.
Interaction between ``API / Event`` and ESP-BLE-MESH protocol stack
- API used by user mainly calls functions provided by ``Mesh Networking``, ``Mesh Provisioning`` and ``Mesh Models``.
- The interaction between ``API / Event`` and the protocol stack does not operate across the hierarchy of the protocol stack. For example, API does not call functions related to ``Network Layer``.
2. ESP-BLE-MESH Architecture Implementation
-------------------------------------------
The design and implementation of ESP-BLE-MESH architecture is based on layers and modules. In details, Section 2.1 (Mesh Networking Implementation), Section 2.2 (Mesh Provisioning Implementation) and Section 2.3 (Mesh Bearers Implementation) are based on layers, and Section 2.4 (Mesh Models Implementation) is on modules.
- **Layer-based Approach**: With Layer-based approach, the architecture is designed according to the layers specified in the Mesh Profile Specification. Each layer has its unique files which include APIs of this layer and etc. The specific design is shown in Figure 2.1.
- **Module-based Approach**: Every file implements an independent function that can be called by other programs.
.. figure:: ../../../_static/esp-ble-mesh-interface.png
:align: center
Figure 2.1 ESP-BLE-MESH Architecture Implementation Diagram
The design of ESP-BLE-MESH architecture uses layer-based approach. The sequence of layers which data packets are processed through is fixed, i.e., the processing of packets will form a ``message flow``. Thus, we could see flows of messages from the Protocol Stack Interface Diagram in Figure 2.1.
2.1 Mesh Protocol Stack Implementation
--------------------------------------
2.1.1 Mesh Networking Implementation
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The list of files and the functions implemented in each file in ``Mesh Networking`` are shown in Table 2.1:
.. list-table:: Table 2.1 Mesh Networking File Description
:widths: 40 150
:header-rows: 1
* - File
- Functionality
* - :component_file:`access.c <bt/esp_ble_mesh/mesh_core/access.c>`
- ESP-BLE-MESH Access Layer
* - :component_file:`transport.c <bt/esp_ble_mesh/mesh_core/transport.c>`
- ESP-BLE-MESH Lower/Upper Transport Layer
* - :component_file:`net.c <bt/esp_ble_mesh/mesh_core/net.c>`
- ESP-BLE-MESH Network Layer
* - :component_file:`adv.c <bt/esp_ble_mesh/mesh_core/adv.c>`
- A task used to send ESP-BLE-MESH advertising packets, a callback used to handle received advertising packets and APIs used to allocate adv buffers
2.1.2 Mesh Provisioning Implementation
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The implementation of Mesh Provisioning is divided into two chunks due to the Node/Provisioner coexistence.
Specific files that provide implementation of provisioning of Node are shown in Table 2.2:
.. list-table:: Table 2.2 Mesh Provisioning (Node) File Description
:widths: 40 150
:header-rows: 1
* - File
- Functionality
* - :component_file:`prov.c <bt/esp_ble_mesh/mesh_core/prov.c>`
- ESP-BLE-MESH Node provisioning (PB-ADV & PB-GATT)
* - :component_file:`proxy.c <bt/esp_ble_mesh/mesh_core/proxy.c>`
- ESP-BLE-MESH Proxy Server related functionalities
* - :component_file:`beacon.c <bt/esp_ble_mesh/mesh_core/beacon.c>`
- APIs used to handle ESP-BLE-MESH Beacons
Specific files that implement functions of Provisioner are shown in Table 2.3:
.. list-table:: Table 2.3 Mesh Provisioning (Provisioner) File Description
:widths: 40 150
:header-rows: 1
* - File
- Functionality
* - :component_file:`provisioner_prov.c <bt/esp_ble_mesh/mesh_core/provisioner_prov.c>`
- ESP-BLE-MESH Provisioner provisioning (PB-ADV & PB-GATT)
* - :component_file:`provisioner_proxy.c <bt/esp_ble_mesh/mesh_core/provisioner_proxy.c>`
- ESP-BLE-MESH Proxy Client related functionalities
* - :component_file:`provisioner_beacon.c <bt/esp_ble_mesh/mesh_core/provisioner_beacon.c>`
- ESP-BLE-MESH Provisioner receives Unprovisioned Device Beacon
2.1.3 Mesh Models Implementation
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Mesh Models are used to implement the specific functions of model in nodes. Server model is used to maintain node status. Client model is used to obtain and modify node state.
.. list-table:: Table 2.4 Mesh Models File Description
:widths: 40 150
:header-rows: 1
* - File
- Functionality
* - :component_file:`cfg_cli.c <bt/esp_ble_mesh/mesh_core/cfg_cli.c>`
- Send Configuration Client messages and receive corresponding response messages
* - :component_file:`cfg_srv.c <bt/esp_ble_mesh/mesh_core/cfg_srv.c>`
- Receive Configuration Client messages and send proper response messages
* - :component_file:`health_cli.c <bt/esp_ble_mesh/mesh_core/health_cli.c>`
- Send Health Client messages and receive corresponding response messages
* - :component_file:`health_srv.c <bt/esp_ble_mesh/mesh_core/health_srv.c>`
- Receive Health Client messages and send proper response messages
* - :component_file:`client_common.c <bt/esp_ble_mesh/mesh_models/client/client_common.c>`
- ESP-BLE-MESH model related operations
* - :component_file:`generic_client.c <bt/esp_ble_mesh/mesh_models/client/generic_client.c>`
- Send ESP-BLE-MESH Generic Client messages and receive corresponding response messages
* - :component_file:`lighting_client.c <bt/esp_ble_mesh/mesh_models/client/lighting_client.c>`
- Send ESP-BLE-MESH Lighting Client messages and receive corresponding response messages
* - :component_file:`sensor_client.c <bt/esp_ble_mesh/mesh_models/client/sensor_client.c>`
- Send ESP-BLE-MESH Sensor Client messages and receive corresponding response messages
* - :component_file:`time_scene_client.c <bt/esp_ble_mesh/mesh_models/client/time_scene_client.c>`
- Send ESP-BLE-MESH Time Scene Client messages and receive corresponding response messages
* - :component_file:`generic_server.c <bt/esp_ble_mesh/mesh_models/server/generic_server.c>`
- Receive ESP-BLE-MESH Generic Client messages and send corresponding response messages
* - :component_file:`lighting_server.c <bt/esp_ble_mesh/mesh_models/server/lighting_server.c>`
- Receive ESP-BLE-MESH Lighting Client messages and send corresponding response messages
* - :component_file:`sensor_server.c <bt/esp_ble_mesh/mesh_models/server/sensor_server.c>`
- Receive ESP-BLE-MESH Sensor Client messages and send corresponding response messages
* - :component_file:`time_scene_server.c <bt/esp_ble_mesh/mesh_models/server/time_scene_server.c>`
- Receive ESP-BLE-MESH Time Scene Client messages and send corresponding response messages
2.2 Mesh Bearers Implementation
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Portability is fully considered in the implementation of Mesh Bearers. When the ESP-BLE-MESH protocol stack is being ported to other platforms, users only need to modify :component_file:`mesh_bearer_adapt.c <bt/esp_ble_mesh/mesh_core/mesh_bearer_adapt.c>`.
.. list-table:: Table 2.5 Mesh Bearers File Description
:widths: 40 150
:header-rows: 1
* - File
- Functionality
* - :component_file:`mesh_bearer_adapt.c <bt/esp_ble_mesh/mesh_core/mesh_bearer_adapt.c>`
- ESP-BLE-MESH Bearer Layer adapterThis file provides the interfaces used to receive and send ESP-BLE-MESH ADV & GATT related packets.
.. note::
:component_file:`mesh_bearer_adapt.c <bt/esp_ble_mesh/mesh_core/mesh_bearer_adapt.c>` is the implementation of ``Advertising Bearer`` and ``GATT Bearer`` in Mesh Networking framework.
2.3 Mesh Applications Implementation
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
We have provided a series of application examples for customer development, and users can develop products based on :ref:`esp-ble-mesh-examples`.
3. Auxiliary Routine
---------------------
Auxiliary routine refers to optional functions in the ESP-BLE-MESH protocol stack. The design of the auxiliary routine generally implement the truncation of code through :ref:`CONFIG_BLE_MESH`.
3.1 Features
^^^^^^^^^^^^
- Low Power
- Friend
- Relay
- Proxy Client/Server
3.2 Network Management
^^^^^^^^^^^^^^^^^^^^^^
- Node Removal procedure
- IV Index Recovery procedure
- IV Update procedure
- Key Refresh procedure
- Network Creation procedure
- NVS Storage
3.3 Auxiliary Routine Implementation
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
When adopting the design of independent module, the two main factors should be considered:
- The module can not be implemented hierarchically, and it can be completely independent, which means it does not rely on the implementation of other modules.
- The functions in the module will be used repeatedly, so it is reasonable to design it into a module. Independent module is shown in Table 3.1:
.. list-table:: Table 3.1 Module File Description
:widths: 40 150
:header-rows: 1
* - File
- Functionality
* - :component_file:`lpn.c <bt/esp_ble_mesh/mesh_core/lpn.c>`
- ESP-BLE-MESH Low Power functionality
* - :component_file:`friend.c <bt/esp_ble_mesh/mesh_core/friend.c>`
- ESP-BLE-MESH Friend functionality
* - :component_file:`net.c <bt/esp_ble_mesh/mesh_core/net.c>`
- ESP-BLE-MESH Relay feature, network creation, IV Update procedure, IV Index recovery procedure, Key Refresh procedure related functionalities
* - :component_file:`proxy.c <bt/esp_ble_mesh/mesh_core/proxy.c>`
- ESP-BLE-MESH Proxy Server related functionalities
* - :component_file:`provisioner_proxy.c <bt/esp_ble_mesh/mesh_core/provisioner_proxy.c>`
- ESP-BLE-MESH Proxy Client related functionalities
* - :component_file:`settings.c <bt/esp_ble_mesh/mesh_core/settings.c>`
- ESP-BLE-MESH Node NVS storage functionality
* - :component_file:`mesh_main.c <bt/esp_ble_mesh/mesh_core/mesh_main.c>`
- ESP-BLE-MESH node removal related functionality

View File

@@ -0,0 +1,663 @@
ESP-BLE-MESH FAQ
================
This document provides a summary of frequently asked questions about developing with ESP-BLE-MESH, and is divided into seven sections:
* :ref:`ble-mesh-faq-provisioner-development`
* :ref:`ble-mesh-faq-node-development`
* :ref:`ble-mesh-faq-ble-mesh-and-wi-fi-coexistence`
* :ref:`ble-mesh-faq-fast-provisioning`
* :ref:`ble-mesh-faq-log-help`
* :ref:`ble-mesh-faq-example-help`
* :ref:`ble-mesh-faq-others`
Users could refer to the sections for quick answer to their questions. This document will be updated based on the feedback collected via various channels.
.. _ble-mesh-faq-provisioner-development:
1. Provisioner Development
--------------------------
Generally, a Provisioner is used to provision unprovisioned devices and form a mesh network. And after provisioning, roles of the unprovisioned devices will be changed to those of a node.
1.1 What is the flow for an unprovisioned device to join ESP-BLE-MESH network?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
There are two phases for a device to join ESP-BLE-MESH network via a Provisioner, namely, provisioning and configuration.
- The phase of provisioning is to assign unicast address, add NetKey and etc. to a device. By provisioning, the device joins the ESP-BLE-MESH network and its role is changed from an unprovisioned device to a node.
- The phase of configuration is to add AppKeys to the node and bind AppKeys to corresponding models. And some items are optional during configuration, including adding subscription addresses to the node, set publication information, etc. By configuration, the node can actually transmit messages to a Provisioner and receive messages from it.
1.2 If a Provisioner wants to change states of a node, what requirements should be met for a Provisioner?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Client model that corresponds to server model of the node is required.
- NetKey and AppKey used to encrypt messages shall be owned by both the node and the Provisioner.
- The address owned by the node shall be known, which could be its unicast address or subscription address.
1.3 How can NetKey and AppKey be used?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- NetKey is used for encryption of messages in Network Layer. Nodes with the same NetKey are assumed to be in the same subnet while those with different NetKeys cannot communicate with each other.
- AppKey is used for encryption of messages in Upper Transport Layer. If client model and server model are bound to different AppKeys, the communication cannot be achieved.
1.4 How to generate a NetKey or AppKey for Provisioner? Can we use a fixed NetKey or AppKey?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- The API :cpp:func:`esp_ble_mesh_provisioner_add_local_net_key` can be used to add a NetKey with a fixed or random value.
- The API :cpp:func:`esp_ble_mesh_provisioner_add_local_app_key` can be used to add an AppKey with a fixed or random value.
1.5 Is the unicast address of Provisioner fixed?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The value of :code:`prov_unicast_addr` in :cpp:type:`esp_ble_mesh_prov_t` is used to set the unicast address of Provisioner, it can be set only once during initialization and can't be changed afterwards.
1.6 Can the address of Provisioner serve as destination address of the node-reporting-status message
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The unicast address of Provisioner can be set only once during initialization and can't be changed afterwards. In theory, it can serve as the destination address of the node-reporting-status message, provided that the unicast address of the Provisioner is known by nodes. Nodes can know the unicast address of Provisioner during configuration since Provisioner sends messages to them with its unicast address used as the source address.
Subscription address can also be used. Provisioner subscribes to a group address or virtual address, and nodes send messages to the subscription address.
1.7 Is the unicast address of the node that is firstly provisioned by Provisioner to ESP-BLE-MESH network fixed
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The value of :code:`prov_start_address` in :cpp:type:`esp_ble_mesh_prov_t` is used to set the starting address when the Provisioner provisions unprovisioned devices, i.e. the unicast address of the node it firstly provisioned. It can be set only once during initialization and can't be changed afterwards.
1.8 Is the unicast address of the node that mobile App firstly provisioned fixed?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The App will decide the unicast address, and currently most of them are fixed.
1.9 How to know which unprovisioned device is the Provisioner that is provisioning currently?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The value of :code:`prov_attention` in :cpp:type:`esp_ble_mesh_prov_t` is used by Provisioner set to unprovisioned device during provisioning. It can be set only once during initialization and can't be changed afterwards. When the unprovisioned device is joining the mesh network, it can display in a specific way like flashing light to notify Provisioner that it is being provisioned.
1.10 How many ways to authenticate the devices during provisioning? Which way was used in the :example:`provided examples <bluetooth/esp_ble_mesh>`?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
There are four authentication methods, i.e. No OOB, Static OOB, Output OOB and Input OOB. In the provided examples, No OOB is used.
1.11 What information can be carried by the advertising packets of the unprovisioned device before provisioning into the network?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Device UUID
- OOB Info
- URL Hash (optional)
1.12 Can such information be used for device identification?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
For example, each unprovisioned device contains a unique Device UUID, which can be used for device identification.
1.13 How is the unicast address assigned when the node provisioned by Provisioner contains multiple elements?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Provisioner will assign an unicast address for the primary element of the node, and unicast address of the remaining elements are incremented one by one.
- For example: If an unprovisioned device has three elements, i.e. the primary element, the second element and the third element. After provisioning, the primary element address of the node is 0x0002 while the second element address is 0x0003, and the third element address is 0x0004.
1.14 How can Provisioner get and parse the :ref:`Composition Data <ble-mesh-terminology-composition>` of nodes through Configuration Client Model?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Provisioner can get the Composition Data of nodes using the :ref:`Configuration Client Model <ble-mesh-terminology-foundation-models>` API :cpp:func:`esp_ble_mesh_config_client_set_state` with :code:`comp_data_get` in the parameter :cpp:type:`esp_ble_mesh_cfg_client_get_state_t` set properly.
- Users can refer to the following code to parse the Composition Data:
.. code:: c
#include <stdio.h>
#include <string.h>
#include <stdint.h>
//test date: 0C001A0001000800030000010501000000800100001003103F002A00
//0C00 1A00 0100 0800 0300 0001 05 01 0000 0080 0100 0010 0310 3F002A00
// CID is 0x000C
// PID is 0x001A
// VID is 0x0001
// CRPL is 0x0008
// Features is 0x0003 Relay and Friend features.
// Loc is “front” 0x0100
// NumS is 5
// NumV is 1
// The Bluetooth SIG Models supported are: 0x0000, 0x8000, 0x0001, 0x1000, 0x1003
// The Vendor Models supported are: Company Identifier 0x003F and Model Identifier 0x002A
typedef struct {
int16_t cid;
int16_t pid;
int16_t vid;
int16_t crpl;
int16_t features;
int16_t all_models;
uint8_t sig_models;
uint8_t vnd_models;
} esp_ble_mesh_composition_head;
typedef struct {
uint16_t model_id;
uint16_t vendor_id;
} tsModel;
typedef struct {
// reserve space for up to 20 SIG models
uint16_t SIG_models[20];
uint8_t numSIGModels;
// reserve space for up to 4 vendor models
tsModel Vendor_models[4];
uint8_t numVendorModels;
} esp_ble_mesh_composition_decode;
int decode_comp_data(esp_ble_mesh_composition_head *head, esp_ble_mesh_composition_decode *data, uint8_t *mystr, int size)
{
int pos_sig_base;
int pos_vnd_base;
int i;
memcpy(head, mystr, sizeof(*head));
if(size < sizeof(*head) + head->sig_models * 2 + head->vnd_models * 4) {
return -1;
}
pos_sig_base = sizeof(*head) - 1;
for(i = 1; i < head->sig_models * 2; i = i + 2) {
data->SIG_models[i/2] = mystr[i + pos_sig_base] | (mystr[i + pos_sig_base + 1] << 8);
printf("%d: %4.4x\n", i/2, data->SIG_models[i/2]);
}
pos_vnd_base = head->sig_models * 2 + pos_sig_base;
for(i = 1; i < head->vnd_models * 2; i = i + 2) {
data->Vendor_models[i/2].model_id = mystr[i + pos_vnd_base] | (mystr[i + pos_vnd_base + 1] << 8);
printf("%d: %4.4x\n", i/2, data->Vendor_models[i/2].model_id);
data->Vendor_models[i/2].vendor_id = mystr[i + pos_vnd_base + 2] | (mystr[i + pos_vnd_base + 3] << 8);
printf("%d: %4.4x\n", i/2, data->Vendor_models[i/2].vendor_id);
}
return 0;
}
void app_main(void)
{
esp_ble_mesh_composition_head head = {0};
esp_ble_mesh_composition_decode data = {0};
uint8_t mystr[] = { 0x0C, 0x00, 0x1A, 0x00,
0x01, 0x00, 0x08, 0x00,
0x03, 0x00, 0x00, 0x01,
0x05, 0x01, 0x00, 0x00,
0x00, 0x80, 0x01, 0x00,
0x00, 0x10, 0x03, 0x10,
0x3F, 0x00, 0x2A, 0x00};
int ret;
ret = decode_comp_data(&head, &data, mystr, sizeof(mystr));
if (ret == -1) {
printf("decode_comp_data error");
}
}
1.15 How can Provisioner further configure nodes through obtained Composition Data?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Provisioner do the following configuration by calling the :ref:`Configuration Client Model <ble-mesh-terminology-foundation-models>` API :cpp:func:`esp_ble_mesh_config_client_set_state`.
- Add AppKey to nodes with :code:`app_key_add` in the parameter :cpp:type:`esp_ble_mesh_cfg_client_set_state_t` set properly.
- Add subscription address to the models of nodes with :code:`model_sub_add` in the parameter :cpp:type:`esp_ble_mesh_cfg_client_set_state_t` set properly.
- Set publication information to the models of nodes with :code:`model_pub_set` in the parameter :cpp:type:`esp_ble_mesh_cfg_client_set_state_t` set properly.
1.16 Can nodes add corresponding configurations for themselves?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This method can be used in special cases like testing period.
- Here is an example to show nodes add new group addresses for their models.
.. code:: c
esp_err_t example_add_fast_prov_group_address(uint16_t model_id, uint16_t group_addr)
{
const esp_ble_mesh_comp_t *comp = NULL;
esp_ble_mesh_elem_t *element = NULL;
esp_ble_mesh_model_t *model = NULL;
int i, j;
if (!ESP_BLE_MESH_ADDR_IS_GROUP(group_addr)) {
return ESP_ERR_INVALID_ARG;
}
comp = esp_ble_mesh_get_composition_data();
if (!comp) {
return ESP_FAIL;
}
for (i = 0; i < comp->element_count; i++) {
element = &comp->elements[i];
model = esp_ble_mesh_find_sig_model(element, model_id);
if (!model) {
continue;
}
for (j = 0; j < ARRAY_SIZE(model->groups); j++) {
if (model->groups[j] == group_addr) {
break;
}
}
if (j != ARRAY_SIZE(model->groups)) {
ESP_LOGW(TAG, "%s: Group address already exists, element index: %d", __func__, i);
continue;
}
for (j = 0; j < ARRAY_SIZE(model->groups); j++) {
if (model->groups[j] == ESP_BLE_MESH_ADDR_UNASSIGNED) {
model->groups[j] = group_addr;
break;
}
}
if (j == ARRAY_SIZE(model->groups)) {
ESP_LOGE(TAG, "%s: Model is full of group addresses, element index: %d", __func__, i);
}
}
return ESP_OK;
}
.. note::
When the NVS storage of the node is enabled, group address added and AppKey bound by this method will not be saved in the NVS when the device is powered off currently. These configuration information can only be saved if they are configured by Configuration Client Model.
1.17 How does Provisioner control nodes by grouping?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Generally there are two approaches to implement group control in ESP-BLE-MESH network, group address approach and virtual address approach. And supposing there are 10 devices, i.e., five devices with blue lights and five devices with red lights.
- Method 1: 5 blue lights can subscribe to a group address, 5 red lights subscribe to another one. By sending messages to different group addresses, Provisioner can realize group control.
- Method 2: 5 blue lights can subscribe to a virtual address, 5 red lights subscribe to another one. By sending messages to different virtual addresses, Provisioner can realize group control.
1.18 How does Provisioner add nodes to multiple subnets?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Provisioner can add multiple NetKeys to nodes during configuration, and nodes sharing the same NetKey belong to the same subnet. Provisioner can communicate with nodes on different subnets by using different NetKeys.
1.19 How does Provisioner know if a node in the mesh network is offline?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Node offline is usually defined as: the condition that the node cannot be properly communicated with other nodes in the mesh network due to power failure or some other reasons.
There is no connection between nodes and nodes in the ESP-BLE-MESH network. They communicate with each other through advertising channels.
An example is given here to show how to detect a node is offline by Provisioner.
- The node can periodically send heartbeat messages to Provisioner. And if Provisioner failed to receive heartbeat messages in a certain period, the node is considered to be offline.
.. note::
The heartbeat message should be designed into a single package (less than 11 bytes), so the transmission and reception of it can be more efficient.
1.20 What operations should be performed when Provisioner removes nodes from the network?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Usually when Provisioner tries to remove node from the mesh network, the procedure includes three main steps:
- Firstly, Provisioner adds the node that need to be removed to the "blacklist".
- Secondly, Provisioner performs the :ref:`Key Refresh procedure <ble-mesh-terminology-network-management>`.
- Lastly, the node performs node reset procedure, and switches itself to an unprovisioned device.
1.21 In the Key Refresh procedure, how does Provisioner update the Netkey owned by nodes?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Provisioner updates the NetKey of nodes using the :ref:`Configuration Client Model <ble-mesh-terminology-foundation-models>` API :cpp:func:`esp_ble_mesh_config_client_set_state` with :code:`net_key_update` in the parameter :cpp:type:`esp_ble_mesh_cfg_client_set_state_t` set properly.
- Provisioner updates the AppKey of nodes using the :ref:`Configuration Client Model <ble-mesh-terminology-foundation-models>` API :cpp:func:`esp_ble_mesh_config_client_set_state` with :code:`app_key_update` in the parameter :cpp:type:`esp_ble_mesh_cfg_client_set_state_t` set properly.
1.22 How does Provisioner manage nodes in the mesh network?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ESP-BLE-MESH implements several functions related to basic node management in the example, such as :cpp:func:`esp_ble_mesh_store_node_info`. And ESP-BLE-MESH also provides the API :cpp:func:`esp_ble_mesh_provisioner_set_node_name` which can be used to set the node's local name and the API :cpp:func:`esp_ble_mesh_provisioner_get_node_name` which can be used to get the node's local name.
1.23 What does Provisioner need when trying to control the server model of nodes?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Provisioner must include corresponding client model before controlling the server model of nodes.
Provisioner shall add its local NetKey and AppKey.
- Provisioner add NetKey by calling the API :cpp:func:`esp_ble_mesh_provisioner_add_local_net_key`.
- Provisioner add AppKey by calling the API :cpp:func:`esp_ble_mesh_provisioner_add_local_app_key`.
Provisioner shall configure its own client model.
- Provisioner bind AppKey to its own client model by calling the API :cpp:func:`esp_ble_mesh_provisioner_bind_app_key_to_local_model`.
1.24 How does Provisoner control the server model of nodes?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ESP-BLE-MESH supports all SIG-defined client models. Provisioner can use these client models to control the server models of nodes. And the client models are divided into 6 categories with each category has the corresponding functions.
- Configuration Client Model
- The API :cpp:func:`esp_ble_mesh_config_client_get_state` can be used to get the :cpp:type:`esp_ble_mesh_cfg_client_get_state_t` values of Configuration Server Model.
- The API :cpp:func:`esp_ble_mesh_config_client_set_state` can be used to set the :cpp:type:`esp_ble_mesh_cfg_client_set_state_t` values of Configuration Server Model.
- Health Client Model
- The API :cpp:func:`esp_ble_mesh_health_client_get_state` can be used to get the :cpp:type:`esp_ble_mesh_health_client_get_state_t` values of Health Server Model.
- The API :cpp:func:`esp_ble_mesh_health_client_set_state` can be used to set the :cpp:type:`esp_ble_mesh_health_client_set_state_t` values of Health Server Model.
- Generic Client Models
- The API :cpp:func:`esp_ble_mesh_generic_client_get_state` can be used to get the :cpp:type:`esp_ble_mesh_generic_client_get_state_t` values of Generic Server Models.
- The API :cpp:func:`esp_ble_mesh_generic_client_set_state` can be used to set the :cpp:type:`esp_ble_mesh_generic_client_set_state_t` values of Generic Server Models.
- Lighting Client Models
- The API :cpp:func:`esp_ble_mesh_light_client_get_state` can be used to get the :cpp:type:`esp_ble_mesh_light_client_get_state_t` values of Lighting Server Models.
- The API :cpp:func:`esp_ble_mesh_light_client_set_state` can be used to set the :cpp:type:`esp_ble_mesh_light_client_set_state_t` values of Lighting Server Models.
- Sensor Client Models
- The API :cpp:func:`esp_ble_mesh_sensor_client_get_state` can be used to get the :cpp:type:`esp_ble_mesh_sensor_client_get_state_t` values of Sensor Server Model.
- The API :cpp:func:`esp_ble_mesh_sensor_client_set_state` can be used to set the :cpp:type:`esp_ble_mesh_sensor_client_set_state_t` values of Sensor Server Model.
- Time and Scenes Client Models
- The API :cpp:func:`esp_ble_mesh_time_scene_client_get_state` can be used to get the :cpp:type:`esp_ble_mesh_time_scene_client_get_state_t` values of Time and Scenes Server Models.
- The API :cpp:func:`esp_ble_mesh_time_scene_client_set_state` can be used to set the :cpp:type:`esp_ble_mesh_time_scene_client_set_state_t` values of Time and Scenes Server Models.
.. _ble-mesh-faq-node-development:
2. Node Development
-------------------
2.1 What kind of models are included by nodes?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- In ESP-BLE-MESH, nodes are all composed of a series of models with each model implements some functions of the node.
- Model has two types, client model and server model. Client model can get and set the states of server model.
- Model can also be divided into SIG model and vendor model. All behaviors of SIG models are officially defined while behaviors of vendor models are defined by users.
2.2 Is the format of messages corresponding to each model fixed?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Messages, which consist of opcode and payload, are divided by opcode.
- The type and the format of the messages corresponding to models are both fixed, which means the messages transmitted between models are fixed.
2.3 Which functions can be used to send messages with the models of nodes?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- For client models, users can use the API :cpp:func:`esp_ble_mesh_client_model_send_msg` to send messages.
- For server models, users can use the API :cpp:func:`esp_ble_mesh_server_model_send_msg` to send messages.
- For publication, users call the API :cpp:func:`esp_ble_mesh_model_publish` to publish messages.
2.4 How to achieve the transmission of messages without packet loss?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Acknowledegd message is needed if users want to transmit messages without packet loss. The default time to wait for corresponding response is set in :ref:`CONFIG_BLE_MESH_CLIENT_MSG_TIMEOUT`. If the sender waits for the response until the timer expires, the corresponding timeout event would be triggered.
.. note::
Response timeout can be set in the API :cpp:func:`esp_ble_mesh_client_model_send_msg`. The default value (4 seconds) would be applied if the parameter :code:`msg_timeout` is set to **0**.
2.5 How to send unacknowledged messages?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
For client models, users can use the API :cpp:func:`esp_ble_mesh_client_model_send_msg` with the parameter :code:`need_rsp` set to :code:`false` to send unacknowledged messages.
For server models, the messages sent by using the API :cpp:func:`esp_ble_mesh_server_model_send_msg` are always unacknowledged messages.
2.6 How to add subscription address to models?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Subscription address can be added through Configuration Client Model.
2.7 What is the difference between messages sent and published by models?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Messages sent by calling the API :cpp:func:`esp_ble_mesh_client_model_send_msg` or :cpp:func:`esp_ble_mesh_server_model_send_msg` will be sent in the duration determined by the Network Transmit state.
Messages published by calling the API :cpp:func:`esp_ble_mesh_model_publish` will be published determined by the Model Publication state. And the publication of messages is generally periodic or with a fixed number of counts. The publication period and publication count are controlled by the Model Publication state, and can be configured through Configuration Client Model.
2.8 How many bytes can be carried when sending unsegmented messages?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The total payload length (which can be set by users) of unsegmented message is 11 octets, so if the opcode of the message is 2 octets, then the message can carry 9-octets of valid information. For vendor messages, due to the 3-octets opcode, the remaining payload length is 8 octets.
2.9 When should the :ref:`Relay <ble-mesh-terminology-features>` feature of nodes be enabled?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Users can enable the Relay feature of all nodes when nodes detected in the mesh network are sparse.
For dense mesh network, users can choose to just enable the Relay feature of several nodes.
And users can enable the Relay feature by default if the mesh network size is unknown.
2.10 When should the :ref:`Proxy <ble-mesh-terminology-features>` feature of node be enabled?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If the unprovisioned device is expected to be provisioned by a phone, then it should enable the Proxy feature since almost all the phones do not support sending ESP-BLE-MESH packets through advertising bearer currently. And after the unprovisioned device is provisioned successfully and becoming a Proxy node, it will communicate with the phone using GATT bearer and using advertising bearer to communicate with other nodes in the mesh network.
2.11 How to use the Proxy filter?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The Proxy filter is used to reduce the number of Network PDUs exchanged between a Proxy Client (e.g. the phone) and a Proxy Server (e.g. the node). And with the Proxy filter, Proxy Client can explicitly request to receive only mesh messages with certain destination addresses from Proxy Server.
2.12 When a message can be relayed by a Relay node?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If a message need to be relayed, the following conditions should be met.
- The message is in the mesh network.
- The message is not sent to the unicast address of the node.
- The value of TTL in the message is greater than 1.
2.13 If a message is segmented into several segments, should the other Relay nodes just relay when one of these segments is received or wait until the message is received completely?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Relay nodes will forward segments when one of them are received rather than keeping waiting until all the segments are received.
2.14 What is the principle of reducing power consumption using :ref:`Low Power <ble-mesh-terminology-features>` feature?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- When the radio is turned on for listening, the device is consuming energy. When low power feature of the node is enabled, it will turn off its radio in the most of the time.
- And cooperation is needed between low power node and friend node, thus low power node can receive messages at an appropriate or lower frequency without the need to keep listening.
- When there are some new messages for low power node, its friend node will store the messages for it. And low power node can poll friend nodes to see if there are new messages at a fixed interval.
2.15 How to continue the communication on the network after powering-down and powering-up again?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Enable the configuration :code:`Store ESP-BLE-MESH Node configuration persistently` in `menuconfig`.
2.16 How to send out the self-test results of nodes?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
It is recommended that nodes can publish its self-test results periodically through Health Server Model.
2.17 How to transmit information between nodes?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
One possible application scenario for transmitting information between nodes is that spray nodes would be triggered once smoke alarm detected high smoke concentration. There are two approaches in implementation.
- Approach 1 is that spray node subscribes to a group address. When smoke alarm detects high smoke concentration, it will publish a message whose destination address is the group address which has been subscribed by spray node.
- Approach 2 is that Provisioner can configure the unicast address of spray node to the smoke alarm. When high smoke concentration is detected, smoke alarm can use send messages to the spray node with the spray node's unicast address as the destination address.
2.18 Is gateway a must for nodes communication?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Situation 1: nodes only communicate within the mesh network. In this situation, no gateway is need. ESP-BLE-MESH network is a flooded network, messages in the network have no fixed paths, and nodes can communicate with each other freely.
- Situation 2: if users want to control the nodes remotely, for example turn on some nodes before getting home, then a gateway is needed.
2.19 When will the IV Update procedure be performed?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
IV Update procedure would be performed once sequence number of messages sent detected by the bottom layer of node reached a critical value.
2.20 How to perform IV Update procedure?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Nodes can perform IV Update procedure with Secure Network Beacon.
.. _ble-mesh-faq-ble-mesh-and-wi-fi-coexistence:
3. ESP-BLE-MESH and Wi-Fi Coexistence
-------------------------------------
3.1 Which modes does Wi-Fi support when it coexists with ESP-BLE-MESH?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Currently only Wi-Fi station mode supports the coexistence.
3.2 Why is the Wi-Fi throughput so low when Wi-Fi and ESP-BLE-MESH coexist?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The `ESP32-DevKitC <../../hw-reference/get-started-devkitc>`_ board without PSRAM can run properly but the throughput of it is low since it has no PSRAM. When Bluetooth and Wi-Fi coexist, the throughput of ESP32-DevKitC with PSRAM can be stabilized to more than 1Mbps.
And some configurations in menuconfig shall be enabled to support PSRAM.
- :code:`ESP32-specific --> Support for external,SPI-connected RAM --> Try to allocate memories of Wi-Fi and LWIP...`
- :code:`Bluetooth --> Bluedroid Enable --> BT/BLE will first malloc the memory from the PSRAM`
- :code:`Bluetooth --> Bluedroid Enable --> Use dynamic memory allocation in BT/BLE stack.`
- :code:`Bluetooth --> Bluetooth controller --> BLE full scan feature supported.`
- :code:`Wi-Fi --> Software controls Wi-Fi/Bluetooth coexistence --> Wi-Fi`
.. _ble-mesh-faq-fast-provisioning:
4. Fast Provisioning
--------------------
4.1 Why is fast provisioning needed?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Normally when they are several unprovisioned devices, users can provision them one by one. But when it comes to a large number of unprovisioned devices (e.g. 100), provisioning them one by one will take huge amount of time. With fast provisioning, users can provision 100 unprovisioned devices in about 50 seconds.
4.2 Why EspBleMesh App would wait for a long time or keep waiting during fast provisioning?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
After the App provisioned one Proxy node, it will disconnect from the App during fast provisioning, and reconnect with the App when all the nodes are provisioned.
4.3 Why is the number of node addresses displayed in the App is more than that of existing node addresses?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Each time after a fast provisioning process, and before starting a new one, the node addresses in the App should be cleared, otherwise the number of the node address will be incorrect.
4.4 What is the usage of the **count** value which was input in EspBleMesh App?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The **count** value is provided to the Proxy node which is provisioned by the App so as to determine when to start Proxy advertising in advance.
4.5 When will Configuration Client Model of the node running :example:`ble_mesh_fast_prov_server <bluetooth/esp_ble_mesh/ble_mesh_fast_provision/ble_mesh_fast_prov_server>` example start to work?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Configuration Client Model will start to work after the Temporary Provisioner functionality is enabled.
4.6 Will the Temporary Provisioner functionality be enabled all the time?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
After the nodes receive messages used to turn on/off lights, all the nodes will disable its Temporary Provisioner functionality and become nodes.
.. _ble-mesh-faq-log-help:
5. Log Help
-----------
You can find meaning of errors or warnings when they appear at the bottom of ESP-BLE-MESH stack.
5.1 What is the meaning of warning :code:`ran out of retransmit attempts`?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
When the node transmits a segmented message, and due to some reasons, the receiver doesn't receive the complete message. Then the node will retransmit the message. When the retransmission count reaches the maximum number, which is 4 currently, then this warning will appear.
5.2 What is the meaning of warning :code:`Duplicate found in Network Message Cache`?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
When the node receives a message, it will compare the message with the ones stored in the network cache. If the same has been found in the cache, which means it has been received before, then the message will be dropped.
5.3 What is the meaning of warning :code:`Incomplete timer expired`?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
When the node doesn't receive all the segments of a segmented message during a certain period (e.g. 10 seconds), then the Incomplete timer will expire and this warning will appear.
5.4 What is the meaning of warning :code:`No matching TX context for ack`?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
When the node receives a segment ack and it doesn't find any self-send segmented message related with this ack, then this warning will appear.
5.5 What is the meaning of warning :code:`No free slots for new incoming segmented messages`?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
When the node has no space for receiving new segmented message, this warning will appear. Users can make the space larger through the configuration :ref:`CONFIG_BLE_MESH_RX_SEG_MSG_COUNT`.
5.6 What is the meaning of error :code:`Model not bound to Appkey 0x0000`
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
When the node sends messages with a model and the model has not been bound to the AppKey with AppKey Index 0x000, then this error will appear.
5.7 What is the meaning of error :code:`Busy sending message to DST xxxx`?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This error means client model of the node has transmitted a message to the target node and now is waiting for a response, users can not send messages to the same node with the same unicast address. After the corresponding response is received or timer is expired, then another message can be sent.
.. _ble-mesh-faq-example-help:
6. Example Help
---------------
6.1 How are the ESP-BLE-MESH callback functions classified?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- The API :cpp:func:`esp_ble_mesh_register_prov_callback` is used to register callback function used to handle provisioning and networking related events.
- The API :cpp:func:`esp_ble_mesh_register_config_client_callback` is used to register callback function used to handle Configuration Client Model related events.
- The API :cpp:func:`esp_ble_mesh_register_config_server_callback` is used to register callback function used to handle Configuration Server Model related events.
- The API :cpp:func:`esp_ble_mesh_register_health_client_callback` is used to register callback function used to handle Health Client Model related events.
- The API :cpp:func:`esp_ble_mesh_register_health_server_callback` is used to register callback function used to handle Health Server Model related events.
- The API :cpp:func:`esp_ble_mesh_register_generic_client_callback` is used to register callback function used to handle Generic Client Models related events.
- The API :cpp:func:`esp_ble_mesh_register_light_client_callback` is used to register callback function used to handle Lighting Client Models related events.
- The API :cpp:func:`esp_ble_mesh_register_sensor_client_callback` is used to register callback function used to handle Sensor Client Model related events.
- The API :cpp:func:`esp_ble_mesh_register_time_scene_client_callback` is used to register callback function used to handle Time and Scenes Client Models related events.
- The API :cpp:func:`esp_ble_mesh_register_custom_model_callback` is used to register callback function used to handle vendor model and unrealized server models related events.
.. _ble-mesh-faq-others:
7. Others
---------
7.1 How to print the message context?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The examples use :cpp:func:`ESP_LOG_BUFFER_HEX` to print the message context while the ESP-BLE-MESH protocol stack uses :cpp:func:`bt_hex`.
7.2 Which API can be used to restart ESP32?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The API :cpp:func:`esp_restart`.
7.3 How to monitor the remaining space of the stack of a task?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The API :cpp:func:`vTaskList` can be used to print the remaining space of the task stack periodically.
7.4 How to change the level of log without changing the menuconfig output level?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The API :cpp:func:`esp_log_level_set` can be used to change the log output level rather than using menuconfig to change it.

View File

@@ -0,0 +1,147 @@
ESP-BLE-MESH Feature List
=========================
Supported Features
------------------
Mesh Core
"""""""""
* Provisioning: Node Role
* PB-ADV and PB-GATT
* OOB Authentication
* Provisioning: Provisioner Role
* PB-ADV and PB-GATT
* OOB Authentication
* Networking
* Relay
* Segmentation and Reassembly
* Key Refresh Procedure
* IV Update Procedure
* Friend
* Low Power
* Proxy Server
* Proxy Client
* Multiple Client Models Run Simultaneously
* Support multiple client models send packets to different nodes simultaneously
* No blocking between client model and server model
* NVS Storing
* Store provisioning and configuration information of ESP-BLE-MESH Node
Mesh Models
"""""""""""
* Foundation models
* Configuration Server model
* Configuration Client model
* Health Server model
* Health Client model
* Generic client models
* Generic OnOff Client
* Generic Level Client
* Generic Default Transition Time Client
* Generic Power OnOff Client
* Generic Power Level Client
* Generic Battery Client
* Generic Location Client
* Generic Property Client
* Sensor client models
* Sensor Client
* Time and Scenes client models
* Time Client
* Scene Client
* Scheduler Client
* Lighting client models
* Light Lightness Client
* Light CTL Client
* Light HSL Client
* Light xyL Client
* Light LC Client
* Generic server models
* Generic OnOff Server
* Generic Level Server
* Generic Default Transition Time Server
* Generic Power OnOff Server
* Generic Power OnOff Setup Server
* Generic Power Level Server
* Generic Power Level Setup Server
* Generic Battery Server
* Generic Location Server
* Generic Location Setup Server
* Generic User Property Server
* Generic Admin Property Server
* Generic Manufacturer Property Server
* Generic Client Property Server
* Sensor server models
* Sensor Server
* Sensor Setup Server
* Time and Scenes server models
* Time Server
* Time Setup Server
* Scene Server
* Scene Setup Server
* Scheduler Server
* Scheduler Setup Server
* Lighting server models
* Light Lightness Server
* Light Lightness Setup Server
* Light CTL Server
* Light CTL Temperature Server
* Light CTL Setup Server
* Light HSL Server
* Light HSL Hue Server
* Light HSL Saturation Server
* Light HSL Setup Server
* Light xyL Server
* Light xyL Setup Server
* Light LC Server
* Light LC Setup Server
Mesh Applications
"""""""""""""""""
* ESP-BLE-MESH Node
* :example:`Tutorial <bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/tutorial/BLE_Mesh_Node_OnOff_Client_Example_Walkthrough.md>`
* :example:`Tutorial <bluetooth/esp_ble_mesh/ble_mesh_node/onoff_server/tutorial/BLE_Mesh_Node_OnOff_Server_Example_Walkthrough.md>`
* :example:`Example <bluetooth/esp_ble_mesh/ble_mesh_node>`
* ESP-BLE-MESH Provisioner
* :example:`Tutorial <bluetooth/esp_ble_mesh/ble_mesh_provisioner/tutorial/BLE_Mesh_Provisioner_Example_Walkthrough.md>`
* :example:`Example <bluetooth/esp_ble_mesh/ble_mesh_provisioner>`
* ESP-BLE-MESH Fast Provisioning
* :example:`Fast Provisioning Client Model Tutorial <bluetooth/esp_ble_mesh/ble_mesh_fast_provision/ble_mesh_fast_prov_client/tutorial/BLE_Mesh_Fast_Prov_Client_Example_Walkthrough.md>`
* :example:`Fast Provisioning Server Model Tutorial <bluetooth/esp_ble_mesh/ble_mesh_fast_provision/ble_mesh_fast_prov_server/tutorial/BLE_Mesh_Fast_Prov_Server_Example_Walkthrough.md>`
* :example:`Example <bluetooth/esp_ble_mesh/ble_mesh_fast_provision>`
* `Demo Video <http://download.espressif.com/BLE_MESH/BLE_Mesh_Demo/V0.4_Demo_Fast_Provision/ESP32_BLE_Mesh_Fast_Provision.mp4>`__
* ESP-BLE-MESH and Wi-Fi Coexistence
* :example:`Tutorial <bluetooth/esp_ble_mesh/ble_mesh_wifi_coexist/tutorial/BLE_Mesh_WiFi_Coexist_Example_Walkthrough.md>`
* :example:`Example <bluetooth/esp_ble_mesh/ble_mesh_wifi_coexist>`
* `Demo Video <http://download.espressif.com/BLE_MESH/BLE_Mesh_Demo/V0.5_Demo_Coexistence/ESP_BLE_MESH_%26_WIFI_Coexistence.mp4>`__
* ESP-BLE-MESH Console Commands
* :example:`Example <bluetooth/esp_ble_mesh/ble_mesh_console>`
Future Release Features
-----------------------
Mesh Core
"""""""""
* Provisioner NVS Storage
Mesh Applications
"""""""""""""""""
* Fast OTA
* Friendship

View File

@@ -0,0 +1,274 @@
************
ESP-BLE-MESH
************
Bluetooth® mesh networking enables many-to-many (m:m) device communications and is optimized for creating large-scale device networks.
Devices may relay data to other devices not in direct radio range of the originating device. In this way, mesh networks can span very large physical areas and contain large numbers of devices. It is ideally suited for building automation, sensor networks, and other IoT solutions where tens, hundreds, or thousands of devices need to reliably and securely communicate with one another.
Bluetooth mesh is not a wireless communications technology, but a networking technology. This technology is dependent upon Bluetooth Low Energy (BLE) - a wireless communications protocol stack.
Built on top of Zephyr Bluetooth Mesh stack, the ESP-BLE-MESH implementation supports device provisioning and node control. It also supports such node features as Proxy, Relay, Low power and Friend.
Please see the :doc:`ble-mesh-architecture` for information about the implementation of ESP-BLE-MESH architecture and :doc:`ESP-BLE-MESH API Reference <../../api-reference/bluetooth/esp-ble-mesh>` for information about respective API.
ESP-BLE-MESH is implemented and certified based on the latest Mesh Profile v1.0.1, users can refer `here <https://launchstudio.bluetooth.com/ListingDetails/94304>`_ for the certification details of ESP-BLE-MESH.
.. note::
If you are looking for Wi-Fi based implementation of mesh for ESP32, please check another product by Espressif called ESP-MESH. For more information and documentation see :doc:`ESP-MESH <../../api-reference/network/esp_mesh>`.
.. _getting-started-with-ble-mesh:
Getting Started with ESP-BLE-MESH
=================================
This section is intended to help you get started with ESP-BLE-MESH for the hardware based on the ESP32 chip by Espressif.
We are going to demonstrate process of setting and operation of a small ESP-BLE-MESH network of three nodes. This process will cover device provisioning and node configuration, and then sending on/off commands to Generic OnOff Server Models on specific nodes.
If you are new to ESP-IDF, please first set up development environment, compile , flash and run example application following top level ESP-IDF :doc:`../../get-started/index` documentation.
What You Need
-------------
Hardware:
* Three ESP32 boards, see :ref:`options <get-started-ble-mesh-check-hardware>`.
* USB cables to connect the boards.
* Computer configured with ESP-IDF.
* Mobile phone or tablet running Android or iOS.
Software:
* Example application :example:`bluetooth/esp_ble_mesh/ble_mesh_node/onoff_server` code to load to the ESP32 boards.
* Mobile App: **nRF Mesh** for Android or iOS. Optionally you can use some other Apps:
- `EspBleMesh <https://github.com/EspressifApp/EspBLEMeshForAndroid/releases/tag/v1.0.0>`_ Android App
- Silicon Labs Android or iOS App
Installation Step by Step
-------------------------
This is a detailed roadmap to walk you through the installation process.
.. _get-started-ble-mesh-check-hardware:
Step 1. Check Hardware
""""""""""""""""""""""
Both `ESP32-DevKitC`_ and `ESP-WROVER-KIT`_ development boards are supported for ESP-BLE-MESH implementation. You can choose particular board through menuconfig: :code:`idf.py menuconfig` > ``Example Configuration`` > ``Board selection for ESP-BLE-MESH``
.. note::
If you plan to use `ESP32-DevKitC`_, connect a RGB LED to GPIO pins 25, 26 and 27.
Step 2. Configure Software
""""""""""""""""""""""""""
Enter the :example:`bluetooth/esp_ble_mesh/ble_mesh_node/onoff_server` example directory, run :code:`idf.py menuconfig` to select your board and then run :code:`idf.py build` to compile the example.
Step 3. Upload Application to Nodes
"""""""""""""""""""""""""""""""""""
After the :example:`bluetooth/esp_ble_mesh/ble_mesh_node/onoff_server` example is compiled successfully, users can run :code:`idf.py flash` to upload the same generated binary files into each of the three development boards.
Once boards are powered on, the RGB LED on each board should turn **GREEN**.
.. figure:: ../../../_static/ble-mesh-device-power-on.png
:align: center
ESP-BLE-MESH Devices Power On
Step 4. Provision Nodes
"""""""""""""""""""""""
In this section, we will use the **nRF Mesh Android** App to demonstrate how to provision an unprovisioned device. Users can also get its iOS version from the App Store.
4.1 Scanner
^^^^^^^^^^^
The Scanner is App's functionality to search for unprovisioned devices in range. Open the App, press **Scanner** at the bottom and the search will start. After a short while we should see three unprovisioned devices displayed.
.. figure:: ../../../_static/ble-mesh-scanner.png
:align: center
:height: 370
nRF Mesh - Scanner
4.2 Identify
^^^^^^^^^^^^
Users can select any unprovisioned device, then the App will try to set up a connection with the selected device. After the BLE connection is established successfully (sometimes users need to try multiple times to get connected), and proper ESP-BLE-MESH GATT Service is discovered, users can see the **IDENTIFY** interface button on the screen. The IDENTIFY operation can be used to tell users which device is going to be provisioned.
.. note::
The IDENTIFY operation also needs some cooperation on the device side, then users can see which device is in the provisioning process. Currently when pressing the **IDENTIFY** interface button, no signs can been seen from the device except from the log on the serial monitor.
After the **IDENTIFY** interface button is pressed, users can see the **PROVISION** interface button.
.. figure:: ../../../_static/ble-mesh-identify-provision.png
:align: center
:height: 370
nRF Mesh - IDENTIFY - PROVISION
4.3 Provision
^^^^^^^^^^^^^
Then, the App will try to provision the unprovisioned device. When the device is provisioned successfully, the RGB LED on the board will turn off, and the App will implement the following procedures:
#. Disconnect with the node
#. Try to reconnect with the node
#. Connect successfully and discover ESP-BLE-MESH GATT Service
#. Get Composition Data of the node and add AppKey to it
When all the procedures are finished, the node is configured properly. And after pressing **OK**, users can see that unicast address is assigned, and Composition Data of the node is decoded successfully.
.. figure:: ../../../_static/ble-mesh-config-complete.png
:align: center
:height: 370
nRF Mesh - Configuration Complete
Sometimes in procedure 2, the App may fail to reconnect with the node. In this case, after pressing **OK**, users can see that only unicast address of the node has been assigned, but no Composition Data has been got. Then users need to press **CONNECT** on the top right, and the previously provisioned node will be displayed on the screen, and users need to choose it and try to connect with the node.
.. figure:: ../../../_static/ble-mesh-initial-config-fail.png
:align: center
:height: 370
nRF Mesh - Initial Configuration Failed
After connecting successfully, the App will show the interface buttons which can be used to get Composition Data and add AppKey.
.. figure:: ../../../_static/ble-mesh-reconnect-initial-config.png
:align: center
:height: 370
nRF Mesh - Reconnect - Initial Configuration
If the device is the second or the third one which has been provisioned by the App, and after pressing **CONNECT**, users can see two or three nodes on the screen. In this situation, users can choose any device to connect with, once succeed then go back to the main screen to choose the node which needs to be configured.
Here an example of three devices listed.
* The left picture shows that the third device is provisioned successfully, but the App failed to connect with it. When it tries to reconnect with the third node, three nodes are displayed on the App.
* The right picture shows that after connecting with any node successfully, the App displays the information of the three nodes. Users can see that the App has got the Composition Data of the first and the second nodes, but for the third one, only the unicast address has been assigned to it while the Composition Data is unknown.
.. figure:: ../../../_static/ble-mesh-reconnect-three.png
:align: center
:height: 370
nRF Mesh - Reconnect - Three Nodes
4.4 Configuration
^^^^^^^^^^^^^^^^^
When provisioning and initial configuration are finished, users can start to configure the node, such as binding AppKey with each model with the elements, setting publication information to it, etc.
Example below shows how to bind AppKey with Generic OnOff Server Model within the Primary Element.
.. figure:: ../../../_static/ble-mesh-model-bind-appkey.png
:align: center
:height: 370
nRF Mesh - Model Bind AppKey
.. note::
No need to bind AppKey with the Configuration Server Model, since it only uses the DevKey to encrypt messages in the Upper Transport Layer.
Step 5. Operate Network
"""""""""""""""""""""""
After all the Generic OnOff Server Models within the three elements are bound with proper AppKey, users can use the App to turn on/off the RGB LED.
In the :example:`bluetooth/esp_ble_mesh/ble_mesh_node/onoff_server` example, the first Generic OnOff Server Model is used to control the **RED** color, the second one is used to control the **GREEN** color and the third one is used to control the **BLUE** color.
.. figure:: ../../../_static/ble-mesh-generic-onoff.png
:align: center
:height: 370
nRF Mesh - Generic OnOff Control
The following screenshot shows different board with different color on.
.. figure:: ../../../_static/ble-mesh-three-nodes-on.png
:align: center
Three ESP-BLE-MESH Nodes On
.. note::
For **nRF Mesh** iOS App [version 1.0.4], when the node contains more than one element, the App is not behaving correctly. If users try to turn on/off the second or the third Generic OnOff Server Model, the message sent by the App is destinated to the first Generic OnOff Server Model within the Primary Element.
.. _esp-ble-mesh-examples:
ESP-BLE-MESH Examples
=====================
* :example:`ESP-BLE-MESH Node OnOff Server <bluetooth/esp_ble_mesh/ble_mesh_node/onoff_server/tutorial/BLE_Mesh_Node_OnOff_Server_Example_Walkthrough.md>` - shows the use of ESP-BLE-MESH as a node having a Configuration Server model and a Generic OnOff Server model. A ESP-BLE-MESH Provisioner can then provision the unprovisioned device and control a RGB LED representing on/off state, see :example:`example code <bluetooth/esp_ble_mesh/ble_mesh_node/onoff_server>`.
* :example:`ESP-BLE-MESH Node OnOff Client <bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/tutorial/BLE_Mesh_Node_OnOff_Client_Example_Waclthrough.md>` - shows how a Generic OnOff Client model works within a node. The node has a Configuration Server model and a Generic OnOff Client model, see :example:`example code <bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client>`.
* :example:`ESP-BLE-MESH Provisioner <bluetooth/esp_ble_mesh/ble_mesh_provisioner/tutorial/Ble_Mesh_Provisioner_Example_Walkthrough.md>` - shows how a device can act as an ESP-BLE-MESH Provisioner to provision devices. The Provisioner has a Configuration Server model, a Configuration Client model and a Generic OnOff Client model, see :example:`example code <bluetooth/esp_ble_mesh/ble_mesh_provisioner>`.
* ESP-BLE-MESH Fast Provisioning - :example:`Client <bluetooth/esp_ble_mesh/ble_mesh_fast_provision/ble_mesh_fast_prov_client/tutorial/BLE_Mesh_Fast_Prov_Client_Example_Walkthrough.md>` and :example:`Server <bluetooth/esp_ble_mesh/ble_mesh_fast_provision/ble_mesh_fast_prov_server/tutorial/BLE_Mesh_Fast_Prov_Server_Example_Walkthrough.md>` - this example is used for showing how fast provisioning can be used in order to create a mesh network. It takes no more than 60 seconds to provision 100 devices, see :example:`example client code <bluetooth/esp_ble_mesh/ble_mesh_fast_provision/ble_mesh_fast_prov_client>` and :example:`example server code <bluetooth/esp_ble_mesh/ble_mesh_fast_provision/ble_mesh_fast_prov_server>`.
* :example:`ESP-BLE-MESH and Wi-Fi Coexistence <bluetooth/esp_ble_mesh/ble_mesh_wifi_coexist/tutorial/BLE_Mesh_WiFi_Coexist_Example_Walkthrough.md>` - an example that demonstrates the Wi-Fi and Bluetooth (BLE/BR/EDR) coexistence feature of ESP32. Simply put, users can use the Wi-Fi while operating Bluetooth, see :example:`example code <bluetooth/esp_ble_mesh/ble_mesh_wifi_coexist>`.
* ESP-BLE-MESH Node Console - an example that implements BLE Mesh node basic features. Within this example a node can be scanned and provisioned by Provisioner and reply to get/set message from Provisioner, see :example:`example node code <bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node>` and :example:`example Provisioner code <bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner>`.
.. _esp-ble-mesh-demo-videos:
ESP-BLE-MESH Demo Videos
========================
* `Provisioning of ESP-BLE-MESH nodes using Smartphone App <http://download.espressif.com/BLE_MESH/Docs4Customers/esp-ble-mesh-demo.mp4>`_
* `Espressif Fast Provisioning using ESP-BLE-MESH App <http://download.espressif.com/BLE_MESH/BLE_Mesh_Demo/V0.4_Demo_Fast_Provision/ESP32_BLE_Mesh_Fast_Provision.mp4>`_
* `Espressif ESP-BLE-MESH and Wi-Fi Coexistence <http://download.espressif.com/BLE_MESH/BLE_Mesh_Demo/V0.5_Demo_Coexistence/ESP_BLE_MESH_%26_WIFI_Coexistence.mp4>`_
ESP-BLE-MESH FAQ
================
* :ref:`ble-mesh-faq-provisioner-development`
* :ref:`ble-mesh-faq-node-development`
* :ref:`ble-mesh-faq-ble-mesh-and-wi-fi-coexistence`
* :ref:`ble-mesh-faq-fast-provisioning`
* :ref:`ble-mesh-faq-log-help`
* :ref:`ble-mesh-faq-example-help`
* :ref:`ble-mesh-faq-others`
Related Documents
=================
.. toctree::
:maxdepth: 1
ble-mesh-feature-list
ble-mesh-architecture
ble-mesh-faq
ble-mesh-terminology
Bluetooth SIG Documentation
---------------------------
- `BLE Mesh Core Specification <https://www.bluetooth.org/docman/handlers/downloaddoc.ashx?doc_id=429633>`_
- `BLE Mesh Model Specification <https://www.bluetooth.org/docman/handlers/downloaddoc.ashx?doc_id=429634>`_
- `An Intro to Bluetooth Mesh Part 1 <http://blog.bluetooth.com/an-intro-to-bluetooth-mesh-part1>`_ / `Part 2 <http://blog.bluetooth.com/an-intro-to-bluetooth-mesh-part2>`__
- `The Fundamental Concepts of Bluetooth Mesh Networking, Part 1 <http://blog.bluetooth.com/the-fundamental-concepts-of-bluetooth-mesh-networking-part-1>`_ / `Part 2 <http://blog.bluetooth.com/the-fundamental-concepts-of-bluetooth-mesh-networking-part-2>`__
- `Bluetooth Mesh Networking: Friendship <http://blog.bluetooth.com/bluetooth-mesh-networking-series-friendship>`_
- `Management of Devices in a Bluetooth Mesh Network <http://blog.bluetooth.com/management-of-devices-bluetooth-mesh-network>`_
- `Bluetooth Mesh Security Overview <http://blog.bluetooth.com/bluetooth-mesh-security-overview>`_
- `Provisioning a Bluetooth Mesh Network Part 1 <http://blog.bluetooth.com/provisioning-a-bluetooth-mesh-network-part-1>`_ / `Part 2 <http://blog.bluetooth.com/provisioning-a-bluetooth-mesh-network-part-2>`__
.. _ESP32-DevKitC: https://www.espressif.com/en/products/hardware/esp32-devkitc/overview
.. _ESP-WROVER-KIT: https://www.espressif.com/en/products/hardware/esp-wrover-kit/overview

View File

@@ -0,0 +1,221 @@
ESP-BLE-MESH Terminology
========================
:link_to_translation:`zh_CN:[中文]`
.. _ble-mesh-terminology-role:
.. list-table:: Table 1 ESP-BLE-MESH Terminology - Role
:widths: 10 40 60
:header-rows: 1
* - Term
- Official Definition
- Detailed Explanation
* - Unprovisioned Device
- A device that is not a member of a mesh network is known as an unprovisioned device.
- Examples: lighting devices, temperature control devices, manufacturing equipments and electric doors, etc.
* - Node
- A node is a provisioned device.
- The role of unprovisioned device will change to node after being provisioned to ESP-BLE-MESH network. Nodes (such as lighting devices, temperature control devices, manufacturing equipments, and electric doors) are devices that can send, receive, or relay messages in ESP-BLE-MESH network, and they can optionally support one or more subnets.
* - Relay Node
- A node that supports the Relay feature and has the Relay feature enabled is known as a Relay node.
- Relay nodes can receive and resend ESP-BLE-MESH messages, so the messages can be transferred further. Users can decide whether or not to enable forwarding function of nodes according to nodes' status. Messages can be relayed for multiple times, and each relay is considered as a "hop". Messages can hop up to 126 times, which is enough for message transmission in a wide area.
* - Proxy Node
- A node that supports the Proxy feature and has the Proxy feature enabled is known as a Proxy node.
- Proxy nodes receive messages from one bearer (it generally includes advertising bearer and GATT bearer) and resend it from another one. The purpose is to connect communication equipments that only support GATT bearer to ESP-BLE-MESH network. Generally, mobile apps need a Proxy node to access Mesh network. Without Proxy nodes, mobile apps cannot communicate with members in Mesh network.
* - Friend Node
- A node that supports the Friend feature, has the Friend feature enabled, and has a friendship with a node that supports the Low Power feature is known as a Friend node.
- Friend node, like the backup of Low Power node (LPN), can store messages that are sent to Low Power node and security updates; the stored information will be transferred to Low Power node when Low Power node needs it. Low Power node must establish "friendship" with another node that supports the Friend Feature to reduce duty cycle of its receiver, thus power consumption of Low Power node can be reduced. Low Power node needs to find a Friend node to establish a friendship with it. The process involved is called "friendship establishment". Cooperation between Low Power node and Friend nodes enables Low Power node to schedule the use of the radio, thus Low Power node can receive messages at an appropriate or lower frequency without the need of keeping listening. Low Power node will poll Friend node to see if there is new message.
* - Low Power Node
- A node that supports the Low Power feature and has a friendship with a node that supports the Friend feature is known as a Low Power node.
- By polling, Low Power node gets information from Friend node, such as messages, security updates, and etc.
* - Provisioner
- A node that is capable of adding a device to a mesh network.
- The device that can provision unprovisioned devices is called a Provisioner. This process usually needs to be implemented through an app that is typically provided by the product manufacturer and can be used on a gateway, a smartphone, tablet or other carriers.
.. _ble-mesh-terminology-composition:
.. list-table:: Table 2 ESP-BLE-MESH Terminology - Composition
:widths: 10 40 60
:header-rows: 1
* - Term
- Official Definition
- Detailed Explanation
* - State
- A value representing a condition of an element that is exposed by an element of a node.
- Each node in a ESP-BLE-MESH network has an independent set of state values that indicate certain states of the device, like brightness, and color of lighting device. Change of state value will lead to change of the physical state of devices. For example, changing the on/off state of a device is actually turning on/off the device.
* - Model
- A model defines the basic functionality of a node.
- A node may contain multiple models, and each model defines basic functionalities of nodes, like the states needed by the nodes, the messages controlling the states, and actions resulted from messages handling. The function implementation of the nodes is based on models, which can be divided into SIG Model and Vendor Model, with the former defined by SIG and latter defined by users.
* - Element
- An addressable entity within a device.
- A node can contain one or more elements, with each having a unicast address and one or more models, and the models contained by the same element must not be the same.
* - Composition Data State
- The Composition Data state contains information about a node, the elements it includes, and the supported models.
- By reading the value of the Composition Data state, users can know basic information of the node, such as the number of elements, and the models in each element. Provisioner gets this message to further provision the device, such as configuring subscription address and publishing address of nodes.
.. _ble-mesh-terminology-features:
.. list-table:: Table 3 ESP-BLE-MESH Terminology - Features
:widths: 10 40 60
:header-rows: 1
* - Term
- Official Definition
- Detailed Explanation
* - Low Power Feature
- The ability to operate within a mesh network at significantly reduced receiver duty cycles only in conjunction with a node supporting the Friend feature.
- Low Power feature reduces power consumption of nodes. When a Low Power node is searching for a Friend node, and there are multiple Friend nodes nearby, it selects the most suitable Friend node through algorithm.
* - Friend Feature
- The ability to help a node supporting the Low Power feature to operate by storing messages destined for those nodes.
- By enabling friend feature, the node can help to store information for Low Power node. The nodes enabled with friend feature may cause more power and memory consumption.
* - Relay Feature
- The ability to receive and retransmit mesh messages over the advertising bearer to enable larger networks.
- The relay feature enables ESP-BLE-MESH messages to hop among nodes for multiple times, and the transmission distance can exceed the range of direct radio transmission between two nodes, thereby covering the entire network. When a node is enabled with the relay feature to relay messages, it only relays the messages of its own subnet, and does not relay the messages of other subnets. The data integrity will not be considered when the node enabled with relay feature relays segmented messages. The node would relay every segmented message once it receives one rather than waiting for the complete message.
* - Proxy Feature
- The ability to receive and retransmit mesh messages between GATT and advertising bearers.
- The purpose of the proxy feature is to allow nodes without an advertising bearer to access the ESP-BLE-MESH network. The proxy feature is typically used in nodes that need to connect to mobile apps.
.. _ble-mesh-terminology-provisioning:
.. list-table:: Table 4 ESP-BLE-MESH Terminology - Provisioning
:widths: 10 40 60
:header-rows: 1
* - Term
- Official Definition
- Detailed Explanation
* - PB-ADV
- PB-ADV is a provisioning bearer used to provision a device using Generic Provisioning PDUs over the advertising channels.
- PB-ADV transfers packets generated during the provisioning process over the advertising channels. This way can only be used for provisioning when provisioner and unprovisioned device both support PB-ADV.
* - PB-GATT
- PB-GATT is a provisioning bearer used to provision a device using Proxy PDUs to encapsulate Provisioning PDUs within the Mesh Provisioning Service.
- PB-GATT uses connection channels to transfer packets generated during the provisioning process. If an unprovisioned device wants to be provisioned through this method, it needs to implement the related Mesh Provisioning Service. Unprovisioned devices which don't implement such service cannot be provisioned into mesh network through PB-GATT bearer.
* - Provisioning
- Provisioning is a process of adding an unprovisioned device to a mesh network, managed by a Provisioner.
- The process of provisioning turns the "unprovisioned device" into a "node", making it a member of the ESP-BLE-MESH network.
* - Authentication Method
- Authentication is a step during the provisioning of nodes.
- There are four authentication methods for unprovisioned devices: Output OOB, Input OOB, Static OOB, and No OOB.
* - Input OOB
- Input Out-of-Band
- For example, a Provisioner generates and displays a random number, and then prompts users to take appropriate actions to input the random number into the unprovisioned device. Taking lighting switch as an example, users can press the button for several times in a certain period of time to input the random number displayed on the Provisioner. Authentication method of the Input OOB is similar to that of Output OOB, but the role of the device is reversed.
* - Output OOB
- Output Out-of-Band
- For example, an unprovisioned device will choose a random number and output the number in a way that is compatible with its functionality. If the unprovisioned device is a bulb, it can flash a specified number of times. If the unprovisioned device has an LCD screen, the random number can display as a multi-digit value. Users who start provisioning should input the observed number to authenticate the unprovisioned device.
* - Static OOB
- Static Out-of-Band
- Authentication method of Static OOB: use Static OOB information. Use 0 as Static OOB information if No OOB information is needed. Use Static OOB information to authenticate devices which are going through provisioning if OOB information is needed.
* - No OOB
- No Out-of-Band
- Authentication method of No OOB: Set the value of the Static OOB field to 0. Using this way is like not authenticating the unprovisioned devices.
.. _ble-mesh-terminology-address:
.. list-table:: Table 5 ESP-BLE-MESH Terminology - Address
:widths: 10 40 60
:header-rows: 1
* - Term
- Official Definition
- Detailed Explanation
* - Unassigned Address
- This is a special address type, with a value of 0x0000. Its use indicates that an Element has not yet been configured or had a Unicast Address assigned to it.
- The addresses owned by elements which has not been configured yet or no address has been allocated are unassigned addresses. These elements will not be used for messages transfer because they have no fixed address. Unassigned address is recommended to set as the value of the address before setting the address of user code.
* - Unicast Address
- A unicast address is a unique address allocated to each element.
- During provisioning, the Provisioner will assign a unicast address to each element of node within the life cycle of the nodes in the network. A unicast address may appear in the source/destination address field of a message. Messages sent to a unicast address can only be processed by the element that owns the unicast address.
* - Virtual Address
- A virtual address represents a set of destination addresses. Each virtual address logically represents a Label UUID, which is a 128-bit value that does not have to be managed centrally.
- Associated with specific UUID labels, a virtual address may serve as the publishing or subscription address of the model. A UUID label is a 128-bit value associated with elements of one or more nodes. For virtual addresses, the 15th and 14th bits are set to 1 and 0 respectively; bits from 13th to 0 are set to hash values (providing 16384 hash values). The hash is a derivation of the Label UUID. To use subscribing elements to check the full 128-bit UUID is very inefficient while hash values provide a more efficient way to determine which elements that which messages are finally sent to.
* - Group Address
- A group address is an address that is programmed into zero or more elements
- Group address is another kind of multicast address in the ESP-BLE-MESH network, which is usually used to group nodes. A message sent to the all-proxies address shall be processed by the primary element of all nodes that have the proxy functionality enabled. A message sent to the all-friends address shall be processed by the primary element of all nodes that have the friend functionality enabled. A message sent to the all-relays address shall be processed by the primary element of all nodes that have the relay functionality enabled. A message sent to the all-nodes address shall be processed by the primary element of all nodes.
.. _ble-mesh-terminology-security:
.. list-table:: Table 6 ESP-BLE-MESH Terminology - Security
:widths: 10 40 60
:header-rows: 1
* - Term
- Official Definition
- Detailed Explanation
* - Device Key (DevKey)
- There is also a device key, which is a special application key that is unique to each node, is known only to the node and a Configuration Client, and is used to secure communications between the node and a Configuration Client.
- The device key enables you to provision the devices, configure the nodes. The device key is used to encrypt Configuration Messages, i.e. the message transferred between the Provisioner and the node when the device is configured.
* - Application Key (AppKey)
- Application keys are used to secure communications at the upper transport layer.
- Application key is used for decryption of application data before delivering application data to application layer and encryption of them during the delivery of application layer. Some nodes in the network have a specific purpose and can restrict access to potentially sensitive data based on the needs of the application. With specific application keys, these nodes are associated with specific applications. Generally speaking, the fields using different application keys include security (access control of buildings, machine rooms and CEO offices), lighting (plant, exterior building and sidewalks) and HVAC systems. Application keys are bound to Network keys. This means application keys are only used in a context of a Network key they are bound to. An application key shall only be bound to a single Network key.
* - Master Security Material
- The master security material is derived from the network key (NetKey) and can be used by other nodes in the same network. Messages encrypted with master security material can be decoded by any node in the same network.
- The corresponding friendship messages encrypted with the friendship security material: 1. Friend Poll, 2. Friend Update, 3. Friend Subscription List, add/delete/confirm, 4. The Stored Messages" sent by friend nodes to Low Power node. The corresponding friendship messages encrypted with the master security material: 1. Friend Clear, 2. Friend Clear Confirm. Based on the setup of the applications, the messages sent from the Low Power node to the friend nodes will be encrypted with the friendship security material or master security material, with the former being used by the messages transmitted between Low Power node and friend nodes and the latter being used by other network messages.
.. _ble-mesh-terminology-message:
.. list-table:: Table 7 ESP-BLE-MESH Terminology - Message
:widths: 10 40 60
:header-rows: 1
* - Term
- Official Definition
- Detailed Explanation
* - Reassembly / Segmentation
- Segmentation and reassembly (SAR) is a method of communication network, which is divided into small units before transmitting packets and reassembled in a proper order at the communication receiving end.
- The lower transport layer will automatically segment the message whose size is too big. The receiving end will return a response message, and the transmitting end will send the data packet again that the receiving end does not receive according to the response message. This is automatically completed by the lower transport layer. Unsegmented messages have at most 15 bytes, of which 4 bytes are transMIC, so the remaining is 11 bytes; in the case of segmentation, there are 12 valid bytes in the first several packets, and 8 in the last one. Special case: A shorter packet requires mandatory segmentation from lower transport layer, in which case the valid byte is 8 bytes.
* - Unacknowledged / Acknowledged
- There are two types of messages: Unacknowledged or Acknowledged
- Based on the whether or not the receiving end needs to send the response message, the messages sent are divided into two kinds. The sending end should set the maximum number of retransmission.
.. _ble-mesh-terminology-foundation-models:
.. list-table:: Table 8 ESP-BLE-MESH Terminology - Foundation Models
:widths: 10 40 60
:header-rows: 1
* - Term
- Official Definition
- Detailed Explanation
* - Configuration Server Model
- This model is used to represent a mesh network configuration of a device.
- The node must contain the Configuration Server Model, which is responsible for maintaining configuration-related states. The states that Configuration Server Model maintains include: NetKey List, AppKey List, Model to AppKey List, Node Identity, Key Refresh Phase, Heartbeat Publish, Heartbeat Subscription, Network Transmit, Relay Retransmit etc.
* - Configuration Client Model
- The model is used to represent an element that can control and monitor the configuration of a node.
- The Configuration Client Model uses messages to control the state maintained by the Configuration Server Model. The Provisioner must contain the Configuration Client Model, with which the configuration messages, like Configuration Composition Data Get can be sent.
* - Health Server Model
- This model is used to represent a mesh network diagnostics of a device.
- The Health Server Model is primarily used by devices to check their states and see if there is an error. The states maintained by Health Server model include: Current Fault, Registered Fault, Health Period, and Attention Timer.
* - Health Client Model
- The model is used to represent an element that can control and monitor the health of a node.
- The Health Client Model uses messages to control the state maintained by the Health Server Model. The model can get the self-test information of other nodes through the message "Health Fault Get".
.. _ble-mesh-terminology-network-management:
.. list-table:: Table 9 ESP-BLE-MESH Terminology - Network Management
:widths: 10 40 60
:header-rows: 1
* - Term
- Official Definition
- Detailed Explanation
* - Key Refresh procedure
- This procedure is used when the security of one or more network keys and/or one or more of the application keys has been compromised or could be compromised.
- Key Refresh Procedure is used to update network key and application key of ESP-BLE-MESH network. Key Refresh Procedure is used when the security of one or more network keys and/or one or more application keys is threatened or potentially threatened. Keys are usually updated after some nodes in the network are removed.
* - IV (Initialisation Vector) Update Procedure
- A node can also use an IV Update procedure to signal to peer nodes that it is updating the IV Index.
- The IV Update procedure is used to update the value of ESP-BLE-MESH network's IV Index. This value is related to the random number required for message encryption. To ensure that the value of the random number is not repeated, this value is periodically incremented. IV Index is a 32-bit value and a shared network resource. For example, all nodes in a mesh network share the same IV Index value. Starting from 0x00000000, the IV Index increments during the IV Update procedure and maintained by a specific process, ensuring the IV Index shared in the mesh network is the same. This can be done when the node believes that it has the risk of exhausting its sequence number, or when it determines that another node is nearly exhausting its sequence number. Note: The update time must not be less than 96 hours. It can be triggered when a secure network beacon is received, or when the node determines that its sequence number is greater than a certain value.
For more terms, please see: `ESP-BLE-MESH Glossary of Terms <https://www.bluetooth.com/bluetooth-technology/topology-options/le-mesh/mesh-glossary/>`_.

View File

@@ -30,6 +30,7 @@ API Guides
RF Calibration <RF_calibration>
WiFi Driver <wifi>
ESP-MESH <mesh>
ESP-BLE-MESH <esp-ble-mesh/ble-mesh-index>
BluFi <blufi>
External SPI-connected RAM <external-ram>
Linker Script Generation <linker-script-generation>

View File

@@ -0,0 +1,154 @@
ESP-BLE-MESH
============
With various features of ESP-BLE-MESH, users can create a managed flooding mesh network for several
scenarios, such as lighting, sensor and etc.
For an ESP32 to join and work on a ESP-BLE-MESH network, it must be provisioned firstly. By provisioning,
the ESP32, as an unprovisioned device, will join the ESP-BLE-MESH network and become a ESP-BLE-MESH node,
communicating with other nodes within or beyond the radio range.
Apart from ESP-BLE-MESH nodes, inside ESP-BLE-MESH network, there is also ESP32 that works as ESP-BLE-MESH
Provisioner, which could provision unprovisioned devices into ESP-BLE-MESH nodes and configure the nodes
with various features.
For information how to start using ESP32 and ESP-BLE-MESH, please see the Section :ref:`getting-started-with-ble-mesh`. If you are interested in information on ESP-BLE-MESH architecture, including some details of software implementation, please see Section :doc:`../../api-guides/esp-ble-mesh/ble-mesh-architecture`.
Application Examples and Demos
------------------------------
Please refer to Sections :ref:`esp-ble-mesh-examples` and :ref:`esp-ble-mesh-demo-videos`.
API Reference
-------------
ESP-BLE-MESH APIs are divided into the following parts:
* `ESP-BLE-MESH Definitions`_
* `ESP-BLE-MESH Core API Reference`_
* `ESP-BLE-MESH Models API Reference`_
ESP-BLE-MESH Definitions
------------------------
This section contains only one header file, which lists the following items of ESP-BLE-MESH.
* ID of all the models and related message opcodes
* Structs of model, element and Composition Data
* Structs of used by ESP-BLE-MESH Node/Provisioner for provisioning
* Structs used to transmit/receive messages
* Event types and related event parameters
.. include:: /_build/inc/esp_ble_mesh_defs.inc
ESP-BLE-MESH Core API Reference
-------------------------------
This section contains ESP-BLE-MESH Core related APIs, which can be used to initialize ESP-BLE-MESH
stack, provision, send/publish messages, etc.
This API reference covers six components:
* `ESP-BLE-MESH Stack Initialization`_
* `Reading of Local Data Information`_
* `Low Power Operation (Updating)`_
* `Send/Publish Messages, add Local AppKey, etc.`_
* `ESP-BLE-MESH Node/Provisioner Provisioning`_
* `ESP-BLE-MESH GATT Proxy Server`_
ESP-BLE-MESH Stack Initialization
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. include:: /_build/inc/esp_ble_mesh_common_api.inc
Reading of Local Data Information
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. include:: /_build/inc/esp_ble_mesh_local_data_operation_api.inc
Low Power Operation (Updating)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. include:: /_build/inc/esp_ble_mesh_low_power_api.inc
Send/Publish Messages, add Local AppKey, etc.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. include:: /_build/inc/esp_ble_mesh_networking_api.inc
ESP-BLE-MESH Node/Provisioner Provisioning
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. include:: /_build/inc/esp_ble_mesh_provisioning_api.inc
ESP-BLE-MESH GATT Proxy Server
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. include:: /_build/inc/esp_ble_mesh_proxy_api.inc
ESP-BLE-MESH Models API Reference
---------------------------------
This section contains ESP-BLE-MESH Model related APIs, event types, event parameters, etc.
There are six categories of models:
* `Configuration Client/Server Models`_
* `Health Client/Server Models`_
* `Generic Client/Server Models`_
* `Sensor Client/Server Models`_
* `Time and Scenes Client/Server Models`_
* `Lighting Client/Server Models`_
.. note::
Definitions related to Server Models are being updated, and will be released soon.
Configuration Client/Server Models
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. include:: /_build/inc/esp_ble_mesh_config_model_api.inc
Health Client/Server Models
^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. include:: /_build/inc/esp_ble_mesh_generic_model_api.inc
Generic Client/Server Models
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. include:: /_build/inc/esp_ble_mesh_health_model_api.inc
Sensor Client/Server Models
^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. include:: /_build/inc/esp_ble_mesh_lighting_model_api.inc
Time and Scenes Client/Server Models
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. include:: /_build/inc/esp_ble_mesh_sensor_model_api.inc
Lighting Client/Server Models
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. include:: /_build/inc/esp_ble_mesh_time_scene_model_api.inc

View File

@@ -9,7 +9,7 @@ Bluetooth API
Bluetooth LE <bt_le>
Bluetooth Classic <classic_bt>
NimBLE <nimble/index>
ESP-BLE-MESH <esp-ble-mesh>
ESP-IDF currently supports two host stacks. The Bluedroid based stack (default) supports classic Bluetooth as well as BLE. On the other hand, Apache NimBLE based stack is BLE only. For users to make a
* For usecases involving classic Bluetooth as well as BLE, Bluedroid should be used.

View File

@@ -0,0 +1,388 @@
ESP-BLE-MESH 架构
=================
:link_to_translation:`en:[English]`
本文档将介绍 ESP-BLE-MESH 的架构概览、架构实现和辅助程序。
- ESP-BLE-MESH 架构概览
- 描述了 ESP-BLE-MESH 架构的 5 大部分及每个部分的功能。
- ESP-BLE-MESH 架构实现
- 描述了 ESP-BLE-MESH 文件的基本功能、文件与 ESP-BLE-MESH 架构的对应关系及文件间调用的接口。
- ESP-BLE-MESH 辅助程序
- 描述了 ESP-BLE-MESH 的辅助程序,比如 Mesh 网络管理Mesh 特性等。
1. ESP-BLE-MESH 架构概览
------------------------
目前ESP-BLE-MESH 已经实现了 Mesh Profile 的大多数功能及 Mesh Model 规范中定义的所有 Client Model。未支持的功能/模型尚在开发中,会尽快提供。 ESP-BLE-MESH 已通过 Bluetooth SIG 蓝牙技术联盟的 `认证 <https://launchstudio.bluetooth.com/ListingDetails/76255>`__
.. figure:: ../../../_static/esp-ble-mesh-architecture.png
:align: center
图 1.1 ESP-BLE-MESH 架构图
ESP-BLE-MESH 架构主要由以下 5 大部分组成:
- ``Mesh 协议栈``
- ``Mesh Networking`` 负责 BLE Mesh 设备的网络消息处理等。
- ``Mesh Provisioning`` 负责 BLE Mesh 设备的启动配置流程。
- ``Mesh Models`` 负责实现 SIG 定义的模型。
- ``网络管理``
- 负责实现网络管理程序,包括节点删除程序、网络索引 (IV Index) 恢复程序等。
- ``特性``
- 包括 BLE Mesh 特性,如低功耗特性、好友特性、中继特性等。
- ``Mesh 承载层``
- 包括 ``广播承载层````GATT 承载层``。承载层对于 ESP-BLE-MESH 协议栈至关重要,因为协议栈基于蓝牙低功耗技术构建而成,其必须利用承载层通过 BLE 广播通道和连接通道进行数据传输。
- ``应用程序``
- 基于 ESP-BLE-MESH 协议栈和 ``Mesh Models``
- 通过调用 API 和处理事件,``Applications`` 实现了与 ESP-BLE-MESH 协议栈中的 ``Mesh Networking````Mesh Provisioning`` 的交互,也实现了与 ``Mesh Models`` 中一系列模型的交互。
1.1 Mesh 协议栈
---------------
1.1.1 Mesh Networking
^^^^^^^^^^^^^^^^^^^^^
协议栈架构中的 ``Mesh Networking`` 实现了如下功能:
- Mesh 网络中节点间的通讯。
- Mesh 网络中消息的加解密。
- Mesh 网络资源的管理,如网络秘钥 (NetKey)、网络索引等。
- Mesh 网络消息的分包与重组。
- 消息在不同模型间的模型映射。
- 更多功能,请参见 :doc:`ble-mesh-feature-list`
``Mesh Networking`` 功能的实现是基于层级结构的。每一层的功能如表 1.1 所示:
.. list-table:: 表 1.1 Mesh Networking 框架描述
:widths: 40 150
:header-rows: 1
* - 层级
- 功能
* - 接入层
- 接入层定义应用程序数据的格式,还对上层传输层对数据包的加密和解密进行定义和控制。
* - 上层传输层
- 上层传输层对接入层进出的应用数据进行加密、解密和认证,同时也处理被称为 “传输控制消息”的特殊消息,这种消息包括了与“友谊”和心跳包相关的消息。
* - 底层传输层
- 底层传输层处理 PDU 的分包和重组。
* - 网络层
- 网络层定义网络消息的地址类型和格式,实现设备的中继功能。
1.1.2 Mesh Provisioning
^^^^^^^^^^^^^^^^^^^^^^^
协议栈架构中的 ``Mesh Provisioning`` 实现了如下功能:
- 对未配网设备的配网。
- Mesh 网络资源的分配 (单播地址、网络索引和网络秘钥)。
- 配网期间对 4 种验证方法的支持。
- 更多功能,请参见 :doc:`ble-mesh-feature-list`
``Mesh Provisioning`` 功能的实现是基于层级结构的。每一层的功能如表 1.2 所示:
.. list-table:: 表 1.2 Mesh Provisioning 框架描述
:widths: 40 150
:header-rows: 1
* - 层级
- 功能
* - Provisioning PDUs
- 通过配网协议处理不同层级的 Provisioning PDUs。
* - Generic Provisioning PDU/Proxy PDU
- 使用 Generic Provisioning 层或代理协议层将 Provisioning PDU 传输到未配网的设备。
* - PB-ADV/PB-GATT
- 这些层级定义了 Provisioning PDUs 作为可分包和重组的消息进行传输的方式。
* - Advertising/Provisioning Service
- Provisioning bearer 定义了会话建立的方式,该方式用来将 Generic Provisioning 层的传输包传送到设备。
1.1.3 Mesh Models
^^^^^^^^^^^^^^^^^
协议栈架构中的 ``Mesh Models`` 实现了如下功能:
- Configuration Client/Server Models
- Health Client/Server Models
- Generic Client/Server Models
- Sensor Client/Server Models
- Time and Scenes Client/Server Models
- Lighting Client/Server Models
每一层的功能如表 1.3 所示:
.. list-table:: 表 1.3 Mesh Models 框架描述
:widths: 40 150
:header-rows: 1
* - 层级
- 功能
* - 模型层
- 模型层实现用于标准化典型用户场景操作的模型,包括 Generic Client/Server Models、Sensor Client/Server Models、Time and Scenes Client/Server Models、Lighting Client/Server Models 和若干自定义模型。
* - 基础模型层
- 基础模型层实现与 ESP-BLE-MESH 网络配置、管理和自我诊断等相关的模型。
1.2 Mesh 网络管理
-----------------
``网络管理`` 实现了如下功能:
- 节点移除程序:用于将节点从网络中移除。
- 网络索引恢复程序:用于恢复节点的网络索引。
- 网络索引更新程序:用于更新节点的网络索引。
- 秘钥更新程序:用于更新节点的网络秘钥、应用秘钥 (AppKey) 等。
- 网络创建程序:用于创建 mesh 网络。
- NVS 存储器:用于存储节点的网络信息。
1.3 Mesh 特性
-------------
``特性`` 包括以下几项:
- 低功耗特性:用于降低节点的能耗。
- 好友特性:用于为低功耗节点存储消息。
- 中继特性:用于中继/转发节点通过广播承载层收到的网络 PDU.
- Proxy Server/Client 是代理协议中的两个节点角色,其使节点可以通过面向连接的承载层收发 Network PDUs、mesh beacons、代理配置消息和 Provisioning PDU。
1.4 Mesh 承载层
---------------
协议栈框架中的 ``承载层`` 负责 ESP-BLE-MESH 协议栈和低功耗蓝牙核心协议间的数据传输。
``承载层`` 可视为是基于蓝牙低功耗核心协议的载体层,其实现了 ESP-BLE-MESH 协议栈数据的接收和传输。
.. list-table:: 表 1.3 Mesh 承载层描述
:widths: 40 150
:header-rows: 1
* - 层级
- 功能
* - GATT 承载层
- GATT 承载层使用代理协议通过 GATT 连接在两个设备之间发送和接收 ``Proxy PDUs``
* - 广播承载层
- 使用广播承载层时,必须使用低功耗蓝牙广播通道来发送 mesh 数据包, 数据包中的 AD Type 需要设置为 mesh 数据包的类型。
1.5 Mesh ``应用层``
--------------------
协议栈框架图中的 ``应用层`` 通过调用 ESP-BLE-MESH 协议栈提供的 API 并处理协议栈上报的事件来实现相应的功能,有一些常见应用,比如网关、照明等。
应用层和 ``API / 事件`` 之间的交互
- 应用层调用 API
- 调用配网相关的 API 进行配网。
- 调用模型相关的 API 发送消息。
- 调用设备属性相关的 API 获取设备的本地信息。
- 应用层处理事件
应用层的设计基于事件设计,事件将参数传输给应用层。事件主要分为两大类。
- 调用 API 完成的事件。
- 比如接收消息的节点。
- 协议栈主动上报给应用层的事件。
- 协议栈主动上报的事件。
- 模型主动上报的事件。
- 事件通过应用层注册的回调函数进行上报,同时回调函数中也会包含对事件的相应处理。
``API /事件`` 与 ESP-BLE-MESH 协议栈的交互
- 用户使用的 API 主要调用``Mesh Networking````Mesh Provisioning````Mesh Models`` 提供的函数。
- ``API /事件`` 和协议栈的交互不会跨越协议栈的层级进行操作。比如 API 不会调用 ``Network Layer`` 相关的函数。
2. ESP-BLE-MESH 架构实现
------------------------
ESP-BLE-MESH 架构的设计和实现是基于层级和模块的。具体而言,第 2.1 节Mesh 网络的实现),第 2.2 节Mesh 配网实现)和第 2.3 节Mesh 层级实现)基于层级思想,第 2.4 节(网格模型的实现)基于模块思想。
- **层级思想**: 基于层级思想,网络架构根据 Mesh Profile Specification 中指定的层级设计而成。每层都有独特的文件,文件包括该层的 API 等。具体设计如图 2.1 所示。
- **模块思想**: 每个文件实现一个独立的功能,供其它程序调用。
.. figure:: ../../../_static/esp-ble-mesh-interface.png
:align: center
图 2.1 ESP-BLE-MESH 架构实现图
ESP-BLE-MESH 架构采用分层的方式进行设计,数据包的处理所经过的层级顺序是固定的,也就是数据包的处理过程会形成一个 ``消息流``。因此,我们可以从图 2.1 的协议栈接口图中看到消息流。
2.1 Mesh 协议栈的实现
---------------------
2.1.1 Mesh Networking 实现
^^^^^^^^^^^^^^^^^^^^^^^^^^
``Mesh Networking`` 中的文件列表和每个文件实现的功能如表 2.1 所示:
.. list-table:: 表 2.1 Mesh Networking 文件描述
:widths: 40 150
:header-rows: 1
* - 文件
- 功能
* - :component_file:`access.c <bt/esp_ble_mesh/mesh_core/access.c>`
- BLE Mesh 接入层
* - :component_file:`transport.c <bt/esp_ble_mesh/mesh_core/transport.c>`
- BLE Mesh 底层/上层传输层
* - :component_file:`net.c <bt/esp_ble_mesh/mesh_core/net.c>`
- BLE Mesh 网络层
* - :component_file:`adv.c <bt/esp_ble_mesh/mesh_core/adv.c>`
- 用于发送 BLE Mesh 广播包的任务,一个用于处理收到的广播包的回调以及用于分配 adv 缓冲区的 API
2.1.2 Mesh Provisioning 实现
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
由于 Node/Provisioner 共存的限制Mesh Provisioning 的实现分为两大模块。
实现 Node 启动配置的特定文件如表 2.2 所示:
.. list-table:: 表 2.2 Mesh Provisioning节点文件描述
:widths: 40 150
:header-rows: 1
* - 文件
- 功能
* - :component_file:`prov.c <bt/esp_ble_mesh/mesh_core/prov.c>`
- BLE Mesh 节点配网 (PB-ADV & PB-GATT)
* - :component_file:`proxy.c <bt/esp_ble_mesh/mesh_core/proxy.c>`
- BLE Mesh 节点代理相关功能
* - :component_file:`beacon.c <bt/esp_ble_mesh/mesh_core/beacon.c>`
- 用于处理 BLE Mesh Beacon 的 API
实现 Provisioner 配置功能的特定文件如表 2.3 所示:
.. list-table:: 表 2.3 Mesh Provisioning (Provisioner) 文件描述
:widths: 40 150
:header-rows: 1
* - 文件
- 功能
* - :component_file:`provisioner_prov.c <bt/esp_ble_mesh/mesh_core/provisioner_prov.c>`
- BLE Mesh Provisioner 配置入网 (PB-ADV & PB-GATT)
* - :component_file:`provisioner_proxy.c <bt/esp_ble_mesh/mesh_core/provisioner_proxy.c>`
- BLE Mesh 代理客户端相关功能
* - :component_file:`provisioner_beacon.c <bt/esp_ble_mesh/mesh_core/provisioner_beacon.c>`
- BLE Mesh Provisioner 接收 Unprovisioned Device Beacon
2.1.3 Mesh Models 实现
^^^^^^^^^^^^^^^^^^^^^^
Mesh Models 用于实现节点中所包含的模型的具体功能。服务器模型主要用于维护节点状态。客户端模型主要用于获取和修改节点状态。
.. list-table:: Table 2.4 Mesh Models 文件描述
:widths: 40 150
:header-rows: 1
* - 文件
- 功能
* - :component_file:`cfg_cli.c <bt/esp_ble_mesh/mesh_core/cfg_cli.c>`
- 发送 Configuration Client 消息,接收相应应答消息
* - :component_file:`cfg_srv.c <bt/esp_ble_mesh/mesh_core/cfg_srv.c>`
- 接收 Configuration Client 消息,发送适当应答消息
* - :component_file:`health_cli.c <bt/esp_ble_mesh/mesh_core/health_cli.c>`
- 发送 Health Client 消息,接收相应应答消息
* - :component_file:`health_srv.c <bt/esp_ble_mesh/mesh_core/health_srv.c>`
- 接收 Health Client 消息,发送适当应答消息
* - :component_file:`client_common.c <bt/esp_ble_mesh/mesh_models/client/client_common.c>`
- BLE Mesh 模型相关操作
* - :component_file:`generic_client.c <bt/esp_ble_mesh/mesh_models/client/generic_client.c>`
- 发送 BLE Mesh Generic Client 消息,接收相应应答消息
* - :component_file:`lighting_client.c <bt/esp_ble_mesh/mesh_models/client/lighting_client.c>`
- 发送 BLE Mesh Lighting Client 消息,接收相应应答消息
* - :component_file:`sensor_client.c <bt/esp_ble_mesh/mesh_models/client/sensor_client.c>`
- 发送 BLE Mesh Sensor Client 消息,接收相应应答消息
* - :component_file:`time_scene_client.c <bt/esp_ble_mesh/mesh_models/client/time_scene_client.c>`
- 发送 BLE Mesh Time Scene Client 消息,接收相应应答消息
2.2 Mesh Bearers 实现
^^^^^^^^^^^^^^^^^^^^^
Mesh Bearers 在实现时充分考虑了可移植性。当 ESP-BLE-MESH 协议栈需要移植到其它平台时,用户只需要修改 :component_file:`mesh_bearer_adapt.c <bt/esp_ble_mesh/mesh_core/mesh_bearer_adapt.c>` 就能移植成功。
.. list-table:: 表 2.5 Mesh Bearers 文件描述
:widths: 40 150
:header-rows: 1
* - 文件
- 功能
* - :component_file:`mesh_bearer_adapt.c <bt/esp_ble_mesh/mesh_core/mesh_bearer_adapt.c>`
- BLE Mesh 承载层适配文件。此文件提供用于接收和发送 BLE Mesh ADV 和 GATT 相关数据包的接口。
.. note::
:component_file:`mesh_bearer_adapt.c <bt/esp_ble_mesh/mesh_core/mesh_bearer_adapt.c>` 是对 Mesh 网络框架中 ``Advertising Bearer````GATT Bearer`` 的实现。
2.3 Mesh Applications 实现
^^^^^^^^^^^^^^^^^^^^^^^^^^
我们提供了一系列用于客户开发的应用示例,用户可以基于 :ref:`esp-ble-mesh-examples` 开发产品。
3. ESP-BLE-MESH 辅助程序
-------------------------
辅助程序指的是 ESP-BLE-MESH 协议栈中可选的功能。辅助程序的设计通常通过 :ref:`CONFIG_BLE_MESH` 来实现代码的裁剪。
3.1 特性
^^^^^^^^
- 低功耗
- 好友
- 中继
- 代理客户端/代理服务器
3.2 网络管理
^^^^^^^^^^^^
- 节点移除程序
- 网络索引恢复程序
- 网络索引更新程序
- 秘钥更新程序
- 网络创建程序
- NVS 存储器
3.3 辅助程序实现
^^^^^^^^^^^^^^^^
采用独立模块的设计主要考虑到两个因素:
- 该模块不具备分层实现的条件,其实现可以完全独立,不需要依赖其它模块。
- 模块中的函数会被反复使用到,因此最好设计成独立模块。独立模块如表 3.1 所示:
.. list-table:: 表 3.1 模块文件描述
:widths: 40 150
:header-rows: 1
* - 文件
- 功能
* - :component_file:`lpn.c <bt/esp_ble_mesh/mesh_core/lpn.c>`
- BLE Mesh 低功耗功能
* - :component_file:`friend.c <bt/esp_ble_mesh/mesh_core/friend.c>`
- BLE Mesh 好友功能
* - :component_file:`net.c <bt/esp_ble_mesh/mesh_core/net.c>`
- BLE Mesh 中继功能、网络创建、网络索引更新程序、网络索引恢复程序、秘钥更新程序相关功能
* - :component_file:`proxy.c <bt/esp_ble_mesh/mesh_core/proxy.c>`
- BLE Mesh 代理服务器相关功能
* - :component_file:`provisioner_proxy.c <bt/esp_ble_mesh/mesh_core/provisioner_proxy.c>`
- BLE Mesh 代理客户端相关功能
* - :component_file:`settings.c <bt/esp_ble_mesh/mesh_core/settings.c>`
- BLE Mesh 节点 NVS 存储器功能
* - :component_file:`mesh_main.c <bt/esp_ble_mesh/mesh_core/mesh_main.c>`
- BLE Mesh 节点移除相关功能

View File

@@ -0,0 +1 @@
.. include:: ../../../en/api-guides/esp-ble-mesh/ble-mesh-faq.rst

View File

@@ -0,0 +1 @@
.. include:: ../../../en/api-guides/esp-ble-mesh/ble-mesh-feature-list.rst

View File

@@ -0,0 +1,276 @@
************
ESP-BLE-MESH
************
:link_to_translation:`en:[English]`
概述
=====
蓝牙 mesh 网络实现了无线设备的“多对多”通讯,其可用于建立包含大量设备的网络。
设备能将数据中继至不在初始设备无线电覆盖范围内的其他设备。这样mesh 网络就能够覆盖非常大的物理区域并且囊括大量设备。Mesh 网络非常适用于楼宇自动化、传感器网络和其他物联网解决方案,这些情景下数以十计、百计、千计的设备需要与其他设备进行安全可靠的通信。
蓝牙 mesh 并非无线通信技术,而是一种网络技术。该技术基于一种无线通讯协议栈,即低功耗蓝牙。
ESP-BLE-MESH 基于 Zephyr 蓝牙 Mesh 协议栈的顶端,其实现支持设备配网和节点控制,同时也实现了代理、中继、低功耗和朋友等节点功能。
有关 ESP-BLE-MESH 架构实现的信息,请参见 :doc:`ble-mesh-architecture`;有关各自 API 的信息,请参见 :doc:`ESP-BLE-MESH API Reference <../../api-reference/bluetooth/esp-ble-mesh>`
ESP-BLE-MESH 的实现和认证基于最新的 `Mesh Profile v1.0.1 <https://www.bluetooth.org/docman/handlers/downloaddoc.ashx?doc_id=457092>`_ 。有关 ESP-BLE-MESH 认证的细节,请参考 `此处 <https://launchstudio.bluetooth.com/ListingDetails/94304>`_
.. note::
如果您在寻找 ESP32 基于 Wi-Fi 的 mesh 方案,请查阅乐鑫的另一款产品 ESP-MESH。更多相关信息及文档请参见:doc:`ESP-MESH <../../api-reference/network/esp_mesh>`
.. _getting-started-with-ble-mesh:
ESP-BLE-MESH 快速入门
=====================
该章节旨在帮助您基于乐鑫的 ESP32 开发板搭建 ESP-BLE-MESH 网络。
我们将会展示如何搭建并运行一个包含 3 个节点的小型 ESP-BLE-MESH 网络,其中包含设备配网、节点配置,以及向特定节点上的 Generic OnOff Server Model 发送开关灯命令。
如果您是第一次接触 ESP-IDF请参见 esp-idf :doc:../../get-started/index 来设置开发环境,编译、烧写和运行示例应用程序。
硬件及软件准备
--------------
硬件:
* 3 块 ESP32 开发板,请参见 :ref:`options <get-started-ble-mesh-check-hardware>`
* 连接开发板的 USB 线。
* ESP-IDF 开发环境。
* 运行 Android 或 iOS 的手机或平板。
软件:
* 下载至 ESP32 开发板的示例应用 :example:`bluetooth/esp_ble_mesh/ble_mesh_node`
* 手机 App: **nRF Mesh** Android 或 iOS 版本。除 nRF Mesh 的 App以下 App 也支持 ESP-BLE-MESH
- `EspBleMesh <https://github.com/EspressifApp/EspBLEMeshForAndroid/releases/tag/v1.0.0>`_ Android App
- Silicon Labs Android 或 iOS App
安装
----
以下详细步骤可指导您完成安装过程。
.. _get-started-ble-mesh-check-hardware:
步骤 1. 检查硬件
"""""""""""""""""
`ESP32-DevKitC`_`ESP-WROVER-KIT`_ 开发板均支持 ESP-BLE-MESH。您可以通过 menuconfig: :code:`idf.py menuconfig` > ``Example Configuration`` > ``Board selection for ESP-BLE-MESH`` 选择特定的开发板。
.. note::
如果您打算使用 `ESP32-DevKitC`_ 开发板,请将 RGB 灯焊接至 GPIO 管脚 25、26 和 27。
步骤 2. 配置软件
""""""""""""""""
进入 :example:`bluetooth/esp_ble_mesh/ble_mesh_node` 示例文件夹,运行 :code:`idf.py menuconfig` 选择所使用的开发板,然后运行 :code:`idf.py build` 编译示例。
步骤 3. 下载应用
"""""""""""""""""
:example:`bluetooth/esp_ble_mesh/ble_mesh_node` 示例编译成功后,用户可以运行 :code:`idf.py flash` 将编译生成的二进制文件下载至 3 块开发板中。
当开发板上电后RGB 灯会变为 **绿色**
.. figure:: ../../../_static/ble-mesh-device-power-on.png
:align: center
ESP-BLE-MESH 设备上电
步骤 4. 设备配网
"""""""""""""""""
在该章节中,我们将使用 **nRF Mesh Android** App 演示如何配网设备。用户也可以从 App Store 下载其 iOS 版本。
4.1 扫描 (scanner)
^^^^^^^^^^^^^^^^^^
扫描 (Scanner) 是 nRF Mesh App 搜索蓝牙通信范围内未配网设备的功能。打开 App点击底部的扫描按钮 **Scanner**。App 就会开始扫描设备,很快,我们便可在屏幕上看到 3 个未配网设备。
.. figure:: ../../../_static/ble-mesh-scanner.png
:align: center
:height: 370
nRF Mesh - 扫描
4.2 识别
^^^^^^^^^^^^
用户可以选择任何一个未配网设备,此时 App 会尝试和该设备建立连接。连接成功(有时可能需要尝试多次),且发现相应的 ESP-BLE-MESH GATT 服务后,用户可以在屏幕中看到识别按钮 **IDENTIFY**。IDENTIFY 操作告诉用户哪个设备将被配网。
.. note::
IDENTIFY 需要设备侧的支持,然后才能用来识别当前正在配网的设备。当前如果点击识别按钮 **IDENTIFY**,除了串口输出的 log在当前的 example 中设备侧不会有其他现象。
点击识别按钮 **IDENTIFY** 后,用户可以看到配网按钮 **PROVISION**
.. figure:: ../../../_static/ble-mesh-identify-provision.png
:align: center
:height: 370
nRF Mesh - 识别 - 配网
4.3 配网
^^^^^^^^^
点击配网按钮 **PROVISION**App 会开始配网设备。当设备配网成功后,开发板上的 RGB 灯会熄灭,此时 App 会执行以下几个步骤:
1. 和该节点(设备配网后成为节点)断开连接
2. 尝试和该节点重新建立连接
3. 连接成功并且发现了相应的 ESP-BLE-MESH GATT 服务
4. 获取节点的 Composition Data 并且给该节点添加 AppKey
当以上所有的步骤完成后,节点初始配置完成. 此时点击 **OK**,用户可以看见节点的单播地址分配成功,并且其 Composition Data 也被成功解析.
.. figure:: ../../../_static/ble-mesh-config-complete.png
:align: center
:height: 370
nRF Mesh - 配置完成
有时在上述步骤 2 中App 可能与节点连接失败。这种情况下,用户点击 **OK** 后可以看到节点只有单播地址被成功分配Composition data 并没有被成功获取。此时用户需要点击右上角的连接按钮 **CONNECT**,屏幕上会显示原先配网的节点,用户需要选择该节点并与其建立连接。
.. figure:: ../../../_static/ble-mesh-initial-config-fail.png
:align: center
:height: 370
nRF Mesh - 初始配置失败
连接成功后App 会显示获取 Composition Data 以及添加 AppKey 的按钮。
.. figure:: ../../../_static/ble-mesh-reconnect-initial-config.png
:align: center
:height: 370
nRF Mesh - 重连 - 初始配置
如果该设备是 App 配网的第二个或第三个节点,此时点击连接按钮 **CONNECT** 后,用户可以在屏幕中看到 2 个或 3 个节点。这种情况下,用户可以选择其中的任何一个节点建立连接,连接成功后可以返回至主界面选择需要配置的节点。
这里给出了一个 3 个节点的示例。
* 左侧图片表示第三个设备成功配网,但是 App 没有和其成功建立连接。当 App 尝试去重新连接第三个节点时,界面上会出现 3 个节点。
* 右侧图片表示和节点成功建立连接后App 显示这 3 个节点的信息。用户可以看到 App 已经获取了第一个和第二个节点的 Composition Data但是对于第三个节点只有单播地址被成功分配而节点的 Composition Data 未知。
.. figure:: ../../../_static/ble-mesh-reconnect-three.png
:align: center
:height: 370
nRF Mesh - 重连 - 3 个节点
4.4 配置
^^^^^^^^^
当成功配网和初始配置完成后,用户可以配置节点的其余信息,例如将 AppKey 绑定至每个元素 (element) 的每个模型 (model) 中、设置模型的发布信息等。
下图展示了如何将 AppKey 绑定至 Primary Element 中的 Generic OnOff Server Model 上。
.. figure:: ../../../_static/ble-mesh-model-bind-appkey.png
:align: center
:height: 370
nRF Mesh - Model Bind AppKey
.. note::
用户不需要将 AppKey 绑定至 Configuration Server Model因为该模型使用 DevKey 在 Upper Transport Layer 中对消息进行加密。
Step 5. 运行网络
"""""""""""""""""
当 3 个元素中的 Generic OnOff Server Models 均成功绑定 AppKey 后,用户可以使用 App 开关 RBG 灯。
:example:`bluetooth/esp_ble_mesh/ble_mesh_node` 示例中,第一个 Generic OnOff Server Model 用来控制 **红色**,第二个用来控制 **绿色**,同时第三个用来控制 **蓝色**.
.. figure:: ../../../_static/ble-mesh-generic-onoff.png
:align: center
:height: 370
nRF Mesh - 通用开关控制
下图展示了打开了不同色灯的开发板。
.. figure:: ../../../_static/ble-mesh-three-nodes-on.png
:align: center
3 个上电的 ESP-BLE-MESH 节点
.. note::
对于 **nRF Mesh** iOS App [version 1.0.4]当节点包含超过一个元素时App 表现不正确。如果用户尝试打开或者关闭第 2 个或第 3 个 Generic OnOff Server ModelApp 会将相应的消息发送至第 1 个 Generic OnOff Server Model。
.. _esp-ble-mesh-examples:
ESP-BLE-MESH 示例
===================
* :example:`ESP-BLE-MESH 节点 <bluetooth/esp_ble_mesh/ble_mesh_node/tutorial/Ble_Mesh_Node_Example_Walkthrough.md>` - 展示了将 ESP-BLE-MESH 作为拥有 Configuration Server model 和 Generic OnOff Server model 的节点设备的用法。然后ESP-BLE-MESH Provisioner 可以配网设备,控制表示开/关状态的 RGB 灯,示例请见 :example:`example code <bluetooth/esp_ble_mesh/ble_mesh_node>`
* :example:`ESP-BLE-MESH 客户端模型 <bluetooth/esp_ble_mesh/ble_mesh_client_model/tutorial/ble_mesh_client_model.md>` - 展示了 Generic OnOff Client model 如何在节点内工作。节点拥有 Configuration Server model、Generic OnOff Server model 和 Generic OnOff Client model示例请见:example:`example code <bluetooth/esp_ble_mesh/ble_mesh_client_model>`
* :example:`ESP-BLE-MESH Provisioner <bluetooth/esp_ble_mesh/ble_mesh_provisioner/tutorial/Ble_Mesh_Provisioner_Example_Walkthrough.md>` - 展示了设备如何充当 ESP-BLE-MESH Provisioner 以配网设备。Provisioner 拥有 Configuration Server model、Configuration Client model 和 Generic OnOff Client model示例请见 :example:`example code <bluetooth/esp_ble_mesh/ble_mesh_provisioner>`
* ESP-BLE-MESH 快速配网 - :example:`Client <bluetooth/esp_ble_mesh/ble_mesh_fast_provision/ble_mesh_fast_prov_client/tutorial/ble_mesh_fast_provision_client.md>`:example:`Server <bluetooth/esp_ble_mesh/ble_mesh_fast_provision/ble_mesh_fast_prov_server/tutorial/ble_mesh_fast_provision_server.md>` - 该示例用于演示快速配网。配网 100 个设备费时不超过 60 秒,示例请见::example:`example client code <bluetooth/esp_ble_mesh/ble_mesh_fast_provision/ble_mesh_fast_prov_client>`:example:`example server code <bluetooth/esp_ble_mesh/ble_mesh_fast_provision/ble_mesh_fast_prov_server>`
* :example:`Wi-Fi 和 ESP-BLE-MESH 共存 <bluetooth/esp_ble_mesh/ble_mesh_wifi_coexist/tutorial/ble_mesh_wifi_coexist.md>` - 该示例用于演示 Wi-Fi 和 ESP-BLE-MESH 共存的功能。简而言之,用户可在运行 ESP-BLE-MESH 时使用 Wi-Fi示例请见 :example:`example code <bluetooth/esp_ble_mesh/ble_mesh_wifi_coexist>`
* ESP-BLE-MESH 节点控制台 - 该演示实现 ESP-BLE-MESH 节点的基本功能。在演示中Provisioner 可以扫描、验证节点,节点可以回复 Provisioner 的获取/设置消息,示例请见::example:`example node code <bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_node>`:example:`example provisioner code <bluetooth/esp_ble_mesh/ble_mesh_console/ble_mesh_provisioner>`
.. _esp-ble-mesh-demo-videos:
ESP-BLE-MESH 演示视频
======================
* `Provisioning of ESP-BLE-MESH nodes using Smartphone App <http://download.espressif.com/BLE_MESH/Docs4Customers/esp-ble-mesh-demo.mp4>`_
* `Espressif Fast Provisioning using ESP-BLE-MESH App <http://download.espressif.com/BLE_MESH/BLE_Mesh_Demo/V0.4_Demo_Fast_Provision/ESP32_BLE_Mesh_Fast_Provision.mp4>`_
* `Espressif ESP-BLE-MESH and Wi-Fi Coexistence <http://download.espressif.com/BLE_MESH/BLE_Mesh_Demo/V0.5_Demo_Coexistence/ESP_BLE_MESH_%26_WIFI_Coexistence.mp4>`_
ESP-BLE-MESH 常见问题手册
=========================
* :ref:`ble-mesh-faq-provisioner-development`
* :ref:`ble-mesh-faq-node-development`
* :ref:`ble-mesh-faq-ble-mesh-and-wi-fi-coexistence`
* :ref:`ble-mesh-faq-fast-provisioning`
* :ref:`ble-mesh-faq-log-help`
* :ref:`ble-mesh-faq-example-help`
* :ref:`ble-mesh-faq-others`
相关文档
========
.. toctree::
:maxdepth: 1
ble-mesh-feature-list
ble-mesh-architecture
ble-mesh-faq
ble-mesh-terminology
蓝牙 SIG 文档
-------------
- `BLE Mesh Profile Specification <https://www.bluetooth.org/docman/handlers/downloaddoc.ashx?doc_id=457092>`_
- `BLE Mesh Model Specification <https://www.bluetooth.org/docman/handlers/downloaddoc.ashx?doc_id=457091>`_
- `An Intro to Bluetooth Mesh Part 1 <http://blog.bluetooth.com/an-intro-to-bluetooth-mesh-part1>`_ / `Part 2 <http://blog.bluetooth.com/an-intro-to-bluetooth-mesh-part2>`__
- `The Fundamental Concepts of Bluetooth Mesh Networking, Part 1 <http://blog.bluetooth.com/the-fundamental-concepts-of-bluetooth-mesh-networking-part-1>`_ / `Part 2 <http://blog.bluetooth.com/the-fundamental-concepts-of-bluetooth-mesh-networking-part-2>`__
- `Bluetooth Mesh Networking: Friendship <http://blog.bluetooth.com/bluetooth-mesh-networking-series-friendship>`_
- `Management of Devices in a Bluetooth Mesh Network <http://blog.bluetooth.com/management-of-devices-bluetooth-mesh-network>`_
- `Bluetooth Mesh Security Overview <http://blog.bluetooth.com/bluetooth-mesh-security-overview>`_
- `Provisioning a Bluetooth Mesh Network Part 1 <http://blog.bluetooth.com/provisioning-a-bluetooth-mesh-network-part-1>`_ / `Part 2 <http://blog.bluetooth.com/provisioning-a-bluetooth-mesh-network-part-2>`__
.. _ESP32-DevKitC: https://www.espressif.com/en/products/hardware/esp32-devkitc/overview
.. _ESP-WROVER-KIT: https://www.espressif.com/en/products/hardware/esp-wrover-kit/overview

View File

@@ -0,0 +1,221 @@
ESP-BLE-MESH Terminology
========================
.. _ble-mesh-terminology-role:
:link_to_translation:`en:[English]`
.. list-table:: 表 1 ESP-BLE-MESH 术语 - 身份
:widths: 10 40 60
:header-rows: 1
* - 术语
- 官方定义
- 详细说明
* - 未配网设备
- "A device that is not a member of a mesh network is known as an unprovisioned device."
- 示例:照明装置、温控设备、制造设备和电动门等。
* - 节点
- "A node is a provisioned device."
- 经配网加入 ESP-BLE-MESH 网络后,未配网设备的身份转变成节点。节点(如照明装置、温控设备、制造设备和电动门)是指能在蓝牙 ESP-BLE-MESH 网络中发送、接收或中继消息的设备,且节点可以选择性地支持一个或多个子网。
* - 中继节点
- "A node that supports the Relay feature and has the Relay feature enabled is known as a Relay node."
- 中继节点接收并中继 ESP-BLE-MESH 消息,因此消息可以传输得更远。用户可以根据节点的状态来决定是否使能节点的中继功能。消息可以中继多次,每次中继为“一跳”,消息最多可有 126 跳,足以让消息在广阔的区域内传输。
* - 代理节点
- "A node that supports the Proxy feature and has the Proxy feature enabled is known as a Proxy node."
- 代理节点从一个承载层(通常包括广播承载层和 GATT 承载层)接收消息,并通过另一个承载层重新发送消息。其目的是将只支持 GATT 承载层的通讯设备接入到 ESP-BLE-MESH 网络中。通常而言,手机 App 需要一个代理节点才能接入 Mesh 网络。没有代理节点,手机 App 无法与 Mesh 网络中成员通信。
* - 好友节点
- "A node that supports the Friend feature, has the Friend feature enabled, and has a friendship with a node that supports the Low Power feature is known as a Friend node."
- 好友节点相当于低功耗节点LPN的备份可存储发往低功耗节点的消息及安全更新信息当低功耗节点需要这些存储的信息时这些信息便会被传输至低功耗节点。低功耗节点必须与支持好友特性的另一节点建立“友谊”以减少其接收器的占空比从而降低低功耗节点的功耗。低功耗节点需要找到好友节点与其建立友谊关系其中涉及的过程称为“友谊建立”。低功耗节点与好友节点的搭配可让低功耗节点规划对无线电的使用从而以适当或较低的频率接收消息无需保持收听状态。低功耗节点会轮询好友节点以查看是否有新的消息。
* - 低功耗节点
- "A node that supports the Low Power feature and has a friendship with a node that supports the Friend feature is known as a Low Power node."
- 低功耗节点通过轮询从好友节点获取信息,比如消息、安全更新等。
* - 启动配置设备(以下称为 Provisioner
- "A node that is capable of adding a device to a mesh network."
- 能够配网未配网设备的设备称为启动配置设备。这一流程通常需要通过产品制造商的提供的 App 来实现,并可在网关、智能手机、平板电脑和其他载体上使用。
.. _ble-mesh-terminology-composition:
.. list-table:: 表 2 ESP-BLE-MESH 术语 - 节点构成
:widths: 10 40 60
:header-rows: 1
* - 术语
- 官方定义
- 详细说明
* - 状态
- "A value representing a condition of an element that is exposed by an element of a node."
- ESP-BLE-MESH 网络中的每台设备都具有一组独立的状态值,表示设备的某些状态,比如照明设备的亮度、颜色等状态。更改状态值会修改设备本身的物理状态,比如更改设备的开关状态值实际是在打开或关闭设备。
* - 模型
- "A model defines the basic functionality of a node."
- 一个节点可能包含多个模型,而每个模型定义了节点的基本功能,比如节点所需要的状态、控制状态的消息以及处理消息所产生的动作等。节点功能的实现是基于模型的,模型可分为 SIG 模型和自定义模型,前者由 SIG 定义,而后者由用户定义。
* - 元素
- "An addressable entity within a device."
- 一个节点可以包含一个或多个元素,每个元素都有一个单播地址和一个或多个模型,并且同一元素所包含的模型不可以出现重复。
* - 节点构成状态
- "The Composition Data state contains information about a node, the elements it includes, and the supported models."
- 通过读取节点构成状态的值用户可以了解节点的基本信息比如元素的数量及每个元素中的模型。Provisioner 通过获取这个消息对设备进一步配置,比如配置节点的订阅地址与发布地址。
.. _ble-mesh-terminology-features:
.. list-table:: 表 3 ESP-BLE-MESH 术语 - 特性
:widths: 10 40 60
:header-rows: 1
* - 术语
- 官方定义
- 详细说明
* - 低功耗特性
- "The ability to operate within a mesh network at significantly reduced receiver duty cycles only in conjunction with a node supporting the Friend feature."
- 低功耗功能可降低节点的功耗。当低功耗节点寻找好友节点、且附近有多个好友节点时,它会通过算法选择最适合的好友节点。
* - 好友特性
- "The ability to help a node supporting the Low Power feature to operate by storing messages destined for those nodes."
- 通过使能好友特性,节点可以帮助存储低功耗节点的信息。使能了好友特性的节点可能会产生更大的功耗和内存消耗。
* - 中继特性
- "The ability to receive and retransmit mesh messages over the advertising bearer to enable larger networks."
- 中继特性能让 ESP-BLE-MESH 的消息在节点之间实现多次跳跃,传输距离可超过两个节点之间直接进行无线电传输的范围,从而覆盖整个网络。使能了中继特性的节点中继消息时,只中继其所在子网的消息,不中继其它子网的消息。使能了中继特性的节点中继分段消息时不考虑数据的完整性。节点每收到一条分段消息便直接中继,不会等待收到完整的消息。
* - 代理特性
- "The ability to receive and retransmit mesh messages between GATT and advertising bearers."
- 代理特性的目的是允许不具备广播承载层的节点访问 ESP-BLE-MESH 网络。代理特性通常为需要和手机 App 连接的节点所用。
.. _ble-mesh-terminology-provisioning:
.. list-table:: 表 4 ESP-BLE-MESH 术语 - 配置入网
:widths: 10 40 60
:header-rows: 1
* - 术语
- 官方定义
- 详细说明
* - PB-ADV
- "PB-ADV is a provisioning bearer used to provision a device using Generic Provisioning PDUs over the advertising channels."
- PB-ADV 通过广播通道传输配网过程中产生的数据包。只有 Provisioner 和未配网设备都支持 PB-ADV 时才可使用这种方法进行配网。
* - PB-GATT
- "PB-GATT is a provisioning bearer used to provision a device using Proxy PDUs to encapsulate Provisioning PDUs within the Mesh Provisioning Service."
- PB-GATT 通过连接通道传输配网过程中产生的数据包。如果未配网设备想使用此方式进行配网,其需要实现相关的 Mesh Provisioning Service。未实现此服务的未配网设备不能通过 PB-GATT 承载层配网接入 mesh 网络。
* - 配置入网
- "Provisioning is a process of adding an unprovisioned device to a mesh network, managed by a Provisioner."
- 经过配网,“未配网设备”的身份转变为“节点”,成为 ESP-BLE-MESH 网络中的一员。
* - 认证方式
- "Authentication is a step during the provisioning of nodes."
- 未配网设备有四种认证方法:输入带外 (Input OOB)、输出带外 (Output OOB)、静态带外 (Static OOB) 和无带外 (No OOB)。
* - 输入带外 (Input OOB)
- Input Out-of-Band
- 比如Provisioner 生成并显示随机数,然后提示用户采取适当操作将随机数输入未配网的设备中。以照明开关为例,用户可以在一定时间内数次按下按钮,以这种形式输入 Provisioner 端显示的随机数。输入带外认证方法与输出带外的认证方法类似,但设备的角色相反。
* - 输出带外 (Output OOB)
- Output Out-of-Band
- 比如,未配网设备会选择一个随机数,并通过与其功能兼容的方式输出该数字。如果未配网设备是一个灯泡,则其能够闪烁指定的次数。如果未配网设备有 LCD 屏幕,则可以将随机数显示为多位数值。启动 Provisioner 的用户需要输入观察到的数字,来认证未配网的设备。
* - 静态带外 (Static OOB)
- Static Out-of-Band
- 静态 OOB 的认证方法:使用静态 OOB 信息。如果需要使用无 OOB 信息,请将静态 OOB 字段赋值为 0。如果需要使用 OOB 信息,请使用静态 OOB 信息认证正在配网的设备。
* - 无带外 (No OOB)
- No Out-of-Band
- 无 OOB 的认证方法:将“静态 OOB”字段赋值为 0。采用这种方式相当于不认证未配网的设备。
.. _ble-mesh-terminology-address:
.. list-table:: 表 5 ESP-BLE-MESH 术语 - 地址
:widths: 10 40 60
:header-rows: 1
* - 术语
- 官方定义
- 详细说明
* - 未分配地址
- "This is a special address type, with a value of 0x0000. Its use indicates that an Element has not yet been configured or had a Unicast Address assigned to it."
- 未配置的元素地址或未分配的元素地址都称为未分配地址。鉴于这些元素没有固定的地址,它们不会用于消息的传输。建议在设置用户代码的地址之前,将该地址的值设为未分配地址。
* - 单播地址
- "A unicast address is a unique address allocated to each element."
- 在配网期间Provisioner 会给网络中处于生命周期内节点的每个元素分配一个单播地址。单播地址可能会出现在消息的源/目标地址字段中。发送到单播地址的消息只能由拥有该单播地址的元素进行处理。
* - 虚拟地址
- "A virtual address represents a set of destination addresses. Each virtual address logically represents a Label UUID, which is a 128-bit value that does not have to be managed centrally."
- 虚拟地址与特定的 UUID 标签相关联可以用作模型的发布地址或订阅地址。UUID 标签是与一个或多个节点的元素相关联的 128 位值。虚拟地址的第 15 位和第 14 位分别设置为 1 和 0。从第 13 位到第 0 位设置为散列值(提供 16384 个散列值)。散列是 UUID 标签的派生。使用订阅元素检查完整的 128 位 UUID 十分低效,而散列值提供了一种更有效的方法来确定最终将哪些消息发送到哪些元素。
* - 群组地址
- "A group address is an address that is programmed into zero or more elements."
- 群组地址是 ESP-BLE-MESH 网络中的另一种多播地址,通常用于将节点进行分组。发送到 all-proxies 地址的信息应由启用了代理功能的所有节点的主要元素处理。 发送到 all-friends 地址的消息应由启用了好友功能的所有节点的主要元素处理。 发送到 all-relays 地址的消息应由启用了中继功能的所有节点的主要元素处理。 发送到 all-nodes 地址的消息应由所有节点的主要元素处理。
.. _ble-mesh-terminology-security:
.. list-table:: 表 6 ESP-BLE-MESH 术语 - 安全
:widths: 10 40 60
:header-rows: 1
* - 术语
- 官方定义
- 详细说明
* - 设备密钥 (DevKey)
- "There is also a device key, which is a special application key that is unique to each node, is known only to the node and a Configuration Client, and is used to secure communications between the node and a Configuration Client."
- 设备密钥让您能够配网未配网设备、配置节点。设备密钥用来加密配置信息,即配置设备时 Provisioner 和节点之间传输的消息。
* - 应用密钥 (AppKey)
- "Application keys are used to secure communications at the upper transport layer."
- 应用密钥用于应用数据传递至应用层过程中对应用数据的解密,和应用层下发过程中对数据的加密。网络中的一些节点有特定的用途,并且可以根据应用程序的需求对一些潜在敏感数据的访问进行限制。通过特定的应用密钥,这些节点与特定应用程序相关联。通常而言,使用不同应用密钥的领域有安全(楼宇门禁、机房门禁和 CEO 办公室门禁)、照明(工厂、外部楼宇和人行道)和 HVAC 系统。应用密钥绑定在网络密钥上,这意味着应用密钥仅在绑定网络密钥的情况下使用。每一个应用密钥仅可绑定到一个网络密钥。
* - 主安全资料
- "The master security material is derived from the network key (NetKey) and can be used by other nodes in the same network. Messages encrypted with master security material can be decoded by any node in the same network. "
- 使用好友安全材料加密的相应友谊消息有1. 好友轮询 (Friend Poll)2. 好友更新 (Friend Update)3. 好友订阅列表 (Friend Subscription List),添加/删除/确认4. 好友节点发送到低功耗节点的“已存储消息”使用主安全材料加密的相应友谊消息有1. 好友清除 (Friend Clear)2. 好友清除确认 (Friend Clear Confirm)。根据应用程序的设置,从低功耗节点发送到好友节点的消息会使用友谊安全材料或主安全材料进行加密,前者用于低功耗节点与好友节点之间的消息传输,而后者用于其他网络消息。
.. _ble-mesh-terminology-message:
.. list-table:: 表 7 ESP-BLE-MESH 术语 - 消息
:widths: 10 40 60
:header-rows: 1
* - 术语
- 官方定义
- 详细说明
* - 重组 / 分包
- "Segmentation and reassembly (SAR) is a method of communication network, which is divided into small units before transmitting packets and reassembled in a proper order at the communication receiving end."
- 底层传输层会自动分包过大的消息。接收端会回复一条应答消息,根据应答消息,发送端会重新向接收端发送其未接收到的数据包。这些都是底层传输层自动完成的。未分包的消息最多携带 15 个字节,其中 4 个字节是 transMIC所以剩余 11 个字节;在分包的情况下,前面的包中每包有 12 个有效字节,最后一个包中有 8 个有效字节。特殊情况:一个较短的包需要底层传输端强制分包,这种情况下有 8 个有效字节。
* - 无应答 / 有应答
- "There are two types of messages: Unacknowledged or Acknowledged."
- 根据接收端是否需要发送应答消息,发送的消息可分为两种。发送端需要设置最大重传次数。
.. _ble-mesh-terminology-foundation-models:
.. list-table:: 表 8 ESP-BLE-MESH 术语 - 基础模型
:widths: 10 40 60
:header-rows: 1
* - 术语
- 官方定义
- 详细说明
* - Configuration Server Model
- "This model is used to represent a mesh network configuration of a device."
- 节点必须包含 Configuration Server Model其负责维护配置相关的状态。Configuration Server Model 维护的状态包含:网络密钥名单 (NetKey List)、应用密钥名单 (AppKey List)、模型绑定的应用密钥名单 (Model to AppKey List)、节点身份 (Node Identity)、密钥更新阶段 (Key Refresh Phase)、心跳消息发布 (Heartbeat Publish)、心跳消息订阅 (Heartbeat Subscription)、网络传输 (Network Transmit) 和中继重传 (Relay Retransmit) 等。
* - Configuration Client Model
- "The model is used to represent an element that can control and monitor the configuration of a node."
- Configuration Client Model 通过消息控制 Configuration Server Model 维护的状态。Provisioner 必须包含 Configuration Client Model有了该模型才可发送 "Configuration Composition Data Get" 等配置消息。
* - Health Server Model
- "This model is used to represent a mesh network diagnostics of a device."
- Health Server Model 主要用于设备检查自身状态查看自身是否发生错误。Health Server model 维护的状态包含:当前故障 (Current Fault)、已登记故障 (Registered Fault)、健康周期 (Health Period) 和关注计时器 (Attention Timer)。
* - Health Client Model
- "The model is used to represent an element that can control and monitor the health of a node."
- Health Client Model 通过消息控制 Health Server Model 维护的状态。该模型可通过消息 “Health Fault Get” 获取其他节点的自检信息。
.. _ble-mesh-terminology-network-management:
.. list-table:: 表 9 ESP-BLE-MESH 术语 - 网络管理
:widths: 10 40 60
:header-rows: 1
* - 术语
- 官方定义
- 详细说明
* - 密钥更新程序
- "This procedure is used when the security of one or more network keys and/or one or more of the application keys has been compromised or could be compromised."
- 密钥更新程序用于更新 ESP-BLE-MESH 网络的网络密钥和应用密钥。当一个或多个网络密钥和/或一个或多个应用密钥的安全受到威胁或可能受到威胁时,会启动密钥更新程序。通常而言,在网络中某些节点移除后可以进行密钥更新。
* - IV 更新程序
- "A node can also use an IV Update procedure to signal to peer nodes that it is updating the IV Index."
- IV 更新程序用于更新 ESP-BLE-MESH 网络的 IV Index 的值这个值和消息加密时所需的随机数相关。为了保证随机数的值不重复所以将这个值定期增加。IV Index 是一个 32 位的值,是一种共享网络资源,比如一个 mesh 网中的所有节点共享一个 IV Index 值。IV Index 从 0x00000000 开始,在 IV 更新过程中递增,并由特定的进程维护,以保证整个 Mesh 网内共享一个 IV Index。当节点认为它有耗尽其序列号的风险或它确定另一个节点即将耗尽其序列号时可以启动该程序。注意每次的更新时间不得低于 96 小时。节点接收到 secure network beacon 或者确定自己的序列号大于特定值时,会触发 IV 更新程序。
官方定义摘自 `ESP-BLE-MESH Glossary of Terms <https://www.bluetooth.com/bluetooth-technology/topology-options/le-mesh/mesh-glossary/>`_.
查看更多术语,也请参照上述网址。

View File

@@ -30,6 +30,7 @@ API 指南
RF Calibration <RF_calibration>
WiFi Driver <wifi>
ESP-MESH <mesh>
ESP-BLE-MESH <esp-ble-mesh/ble-mesh-index>
BluFi <blufi>
External SPI-connected RAM <external-ram>
链接脚本生成机制 <linker-script-generation>

View File

@@ -0,0 +1 @@
.. include:: ../../../en/api-reference/bluetooth/esp-ble-mesh.rst

View File

@@ -63,11 +63,11 @@ static void initialize_console(void)
esp_vfs_dev_uart_set_tx_line_endings(ESP_LINE_ENDINGS_CRLF);
/* Install UART driver for interrupt-driven reads and writes */
ESP_ERROR_CHECK( uart_driver_install(CONFIG_ESP_CONSOLE_UART_NUM,
ESP_ERROR_CHECK( uart_driver_install(CONFIG_CONSOLE_UART_NUM,
256, 0, 0, NULL, 0) );
/* Tell VFS to use UART driver */
esp_vfs_dev_uart_use_driver(CONFIG_ESP_CONSOLE_UART_NUM);
esp_vfs_dev_uart_use_driver(CONFIG_CONSOLE_UART_NUM);
/* Initialize the console */
esp_console_config_t console_config = {

View File

@@ -66,11 +66,11 @@ static void initialize_console(void)
esp_vfs_dev_uart_set_tx_line_endings(ESP_LINE_ENDINGS_CRLF);
/* Install UART driver for interrupt-driven reads and writes */
ESP_ERROR_CHECK( uart_driver_install(CONFIG_ESP_CONSOLE_UART_NUM,
ESP_ERROR_CHECK( uart_driver_install(CONFIG_CONSOLE_UART_NUM,
256, 0, 0, NULL, 0) );
/* Tell VFS to use UART driver */
esp_vfs_dev_uart_use_driver(CONFIG_ESP_CONSOLE_UART_NUM);
esp_vfs_dev_uart_use_driver(CONFIG_CONSOLE_UART_NUM);
/* Initialize the console */
esp_console_config_t console_config = {

View File

@@ -44,6 +44,14 @@
#define APP_KEY_IDX 0x0000
#define APP_KEY_OCTET 0x12
#define MSG_1_OCTET(msg, offset) (msg[offset])
#define MSG_2_OCTET(msg, offset) (msg[offset + 1] << 8 | msg[offset])
static uint16_t primary_addr;
static uint8_t match[2] = {0xec, 0xa6};
static uint8_t dev_uuid[16];
/* The following is BLE Mesh tx/rx test related context */
#define MSG_TIMEOUT 200000 /* msg resend interval */
#define MSG_INTERVAL 1000000 /* msg send interval */
#define MSG_MAX_RESEND 3 /* max resend count */
@@ -59,6 +67,7 @@ static uint32_t msg_index;
static struct {
uint8_t resend;
bool acked;
int64_t time;
} __attribute__((packed)) msg_record[MSG_TEST_COUNT];
/* Used to indicate the transaction number in the current message */
static uint16_t trans_num;
@@ -66,12 +75,10 @@ static bool retrans_timer_start;
static void example_start_retransmit_timer(void);
static void example_start_interval_timer(void);
static SemaphoreHandle_t test_mutex;
static SemaphoreHandle_t tx_rx_mutex;
static uint8_t match[2] = {0xec, 0xa6};
static uint8_t dev_uuid[16];
/* The following is BLE Mesh deinit test flag */
bool example_deinit_test;
static uint16_t primary_addr;
typedef struct {
uint8_t uuid[16];
@@ -79,9 +86,9 @@ typedef struct {
uint8_t elem_num;
uint8_t onoff;
uint8_t tid;
} esp_ble_mesh_node_info_t;
} example_ble_mesh_node_info_t;
static esp_ble_mesh_node_info_t nodes[CONFIG_BLE_MESH_MAX_PROV_NODES] = {
static example_ble_mesh_node_info_t nodes[CONFIG_BLE_MESH_MAX_PROV_NODES] = {
[0 ... (CONFIG_BLE_MESH_MAX_PROV_NODES - 1)] = {
.unicast = ESP_BLE_MESH_ADDR_UNASSIGNED,
.elem_num = 0,
@@ -89,7 +96,7 @@ static esp_ble_mesh_node_info_t nodes[CONFIG_BLE_MESH_MAX_PROV_NODES] = {
}
};
static struct esp_ble_mesh_key {
static struct example_ble_mesh_key {
uint16_t net_idx;
uint16_t app_idx;
uint8_t app_key[16];
@@ -202,7 +209,7 @@ static esp_err_t example_ble_mesh_store_node_info(const uint8_t uuid[16], uint16
return ESP_FAIL;
}
static esp_ble_mesh_node_info_t *example_ble_mesh_get_node_info(uint16_t unicast)
static example_ble_mesh_node_info_t *example_ble_mesh_get_node_info(uint16_t unicast)
{
size_t i;
@@ -221,7 +228,7 @@ static esp_ble_mesh_node_info_t *example_ble_mesh_get_node_info(uint16_t unicast
}
static esp_err_t example_ble_mesh_set_msg_common(esp_ble_mesh_client_common_param_t *common,
esp_ble_mesh_node_info_t *node,
example_ble_mesh_node_info_t *node,
esp_ble_mesh_model_t *model, uint32_t opcode)
{
if (!common || !node || !model) {
@@ -270,7 +277,7 @@ static esp_err_t prov_complete(int node_idx, const esp_ble_mesh_octet16_t uuid,
{
esp_ble_mesh_client_common_param_t common = {0};
esp_ble_mesh_cfg_client_get_state_t get = {0};
esp_ble_mesh_node_info_t *node = NULL;
example_ble_mesh_node_info_t *node = NULL;
char name[10];
int err;
@@ -433,13 +440,51 @@ static void example_ble_mesh_provisioning_cb(esp_ble_mesh_prov_cb_event_t event,
}
}
static void example_ble_mesh_parse_node_comp_data(const uint8_t *data, uint16_t length)
{
uint16_t cid, pid, vid, crpl, feat;
uint16_t loc, model_id, company_id;
uint8_t nums, numv;
uint16_t offset;
size_t i;
cid = MSG_2_OCTET(data, 0);
pid = MSG_2_OCTET(data, 2);
vid = MSG_2_OCTET(data, 4);
crpl = MSG_2_OCTET(data, 6);
feat = MSG_2_OCTET(data, 8);
offset = 10;
ESP_LOGW(TAG, "***************** Composition Data Start *****************");
ESP_LOGI(TAG, "* CID 0x%04x, PID 0x%04x, VID 0x%04x, CRPL 0x%04x, Features 0x%04x *", cid, pid, vid, crpl, feat);
for (; offset < length; ) {
loc = MSG_2_OCTET(data, offset);
nums = MSG_1_OCTET(data, offset + 2);
numv = MSG_1_OCTET(data, offset + 3);
offset += 4;
ESP_LOGI(TAG, "* Loc 0x%04x, NumS 0x%02x, NumV 0x%02x *", loc, nums, numv);
for (i = 0; i < nums; i++) {
model_id = MSG_2_OCTET(data, offset);
ESP_LOGI(TAG, "* SIG Model ID 0x%04x *", model_id);
offset += 2;
}
for (i = 0; i < numv; i++) {
company_id = MSG_2_OCTET(data, offset);
model_id = MSG_2_OCTET(data, offset + 2);
ESP_LOGI(TAG, "* Vendor Model ID 0x%04x, Company ID 0x%04x *", model_id, company_id);
offset += 4;
}
}
ESP_LOGW(TAG, "****************** Composition Data End ******************");
}
static void example_ble_mesh_config_client_cb(esp_ble_mesh_cfg_client_cb_event_t event,
esp_ble_mesh_cfg_client_cb_param_t *param)
{
esp_ble_mesh_client_common_param_t common = {0};
esp_ble_mesh_cfg_client_set_state_t set = {0};
esp_ble_mesh_cfg_client_get_state_t get = {0};
esp_ble_mesh_node_info_t *node = NULL;
example_ble_mesh_node_info_t *node = NULL;
esp_err_t err;
if (param->error_code) {
@@ -458,6 +503,11 @@ static void example_ble_mesh_config_client_cb(esp_ble_mesh_cfg_client_cb_event_t
if (param->params->opcode == ESP_BLE_MESH_MODEL_OP_COMPOSITION_DATA_GET) {
ESP_LOGI(TAG, "composition data %s", bt_hex(param->status_cb.comp_data_status.composition_data->data,
param->status_cb.comp_data_status.composition_data->len));
example_ble_mesh_parse_node_comp_data(param->status_cb.comp_data_status.composition_data->data,
param->status_cb.comp_data_status.composition_data->len);
esp_ble_mesh_provisioner_store_node_comp_data(param->params->ctx.addr,
param->status_cb.comp_data_status.composition_data->data,
param->status_cb.comp_data_status.composition_data->len);
example_ble_mesh_set_msg_common(&common, node, config_client.model, ESP_BLE_MESH_MODEL_OP_APP_KEY_ADD);
set.app_key_add.net_idx = prov_key.net_idx;
set.app_key_add.app_idx = prov_key.app_idx;
@@ -508,8 +558,8 @@ static void example_ble_mesh_config_client_cb(esp_ble_mesh_cfg_client_cb_event_t
example_ble_mesh_set_msg_common(&common, node, config_client.model, ESP_BLE_MESH_MODEL_OP_MODEL_APP_BIND);
set.model_app_bind.element_addr = node->unicast;
set.model_app_bind.model_app_idx = prov_key.app_idx;
set.model_app_bind.model_id = ESP_BLE_MESH_MODEL_ID_GEN_ONOFF_SRV;
set.model_app_bind.company_id = CID_NVAL;
set.model_app_bind.model_id = ESP_BLE_MESH_VND_MODEL_ID_TEST_SRV;
set.model_app_bind.company_id = CID_ESP;
err = esp_ble_mesh_config_client_set_state(&common, &set);
if (err) {
ESP_LOGE(TAG, "%s: Config Model App Bind failed", __func__);
@@ -524,14 +574,26 @@ static void example_ble_mesh_config_client_cb(esp_ble_mesh_cfg_client_cb_event_t
}
}
static void example_test_lock(void)
static void example_tx_rx_mutex_create(void)
{
xSemaphoreTake(test_mutex, portMAX_DELAY);
if (!tx_rx_mutex) {
tx_rx_mutex = xSemaphoreCreateMutex();
assert(tx_rx_mutex);
}
}
static void example_test_unlock(void)
static void example_tx_rx_lock(void)
{
xSemaphoreGive(test_mutex);
if (tx_rx_mutex) {
xSemaphoreTake(tx_rx_mutex, portMAX_DELAY);
}
}
static void example_tx_rx_unlock(void)
{
if (tx_rx_mutex) {
xSemaphoreGive(tx_rx_mutex);
}
}
static void example_ble_mesh_custom_model_cb(esp_ble_mesh_model_cb_event_t event,
@@ -551,20 +613,23 @@ static void example_ble_mesh_custom_model_cb(esp_ble_mesh_model_cb_event_t event
if (msg_record[msg_index].resend == 0) {
/* If send successfully in the first time, start the interval timer */
example_start_interval_timer();
msg_record[msg_index].time = esp_timer_get_time();
}
}
break;
case ESP_BLE_MESH_CLIENT_MODEL_RECV_PUBLISH_MSG_EVT:
example_test_lock();
example_tx_rx_lock();
if (param->client_recv_publish_msg.opcode == ESP_BLE_MESH_VND_MODEL_OP_TEST_STATUS) {
uint16_t value = *(uint16_t *)param->client_recv_publish_msg.msg;
ESP_LOGI(TAG, "%d %d %d", msg_index, value, trans_num);
if (value == trans_num && retrans_timer_start == true) {
msg_record[msg_index].acked = true;
esp_timer_stop(retransmit_timer);
int64_t time = esp_timer_get_time();
msg_record[msg_index].time = time - msg_record[msg_index].time;
}
}
example_test_unlock();
example_tx_rx_unlock();
break;
default:
break;
@@ -584,13 +649,13 @@ static void example_start_interval_timer(void)
static void retransmit_timer_callback(void* arg)
{
example_test_lock();
example_tx_rx_lock();
retrans_timer_start = false;
if (msg_record[msg_index].acked == false &&
msg_record[msg_index].resend < MSG_MAX_RESEND) {
example_ble_mesh_send_test_msg(true);
}
example_test_unlock();
example_tx_rx_unlock();
}
static void interval_timer_callback(void* arg)
@@ -604,6 +669,7 @@ static void interval_timer_callback(void* arg)
* received corresponding response.
*/
uint32_t no_ack_count = 0;
int64_t total_time = 0;
size_t i, j, k;
for (i = 0; i < sizeof(compare); i++) {
@@ -619,17 +685,22 @@ static void interval_timer_callback(void* arg)
count[k]++;
if (msg_record[i * MSG_TEST_UNIT + j].resend == MSG_MAX_RESEND &&
msg_record[i * MSG_TEST_UNIT + j].acked == false) {
/* If msg is not acked, use 1s for its time */
msg_record[msg_index].time = 1000000;
no_ack_count++;
}
break;
}
}
total_time += msg_record[msg_index].time;
}
ESP_LOGW(TAG, "Send messages the %d time", i);
ESP_LOGW(TAG, "Send messages the %d time, total %lldus, average %lldus", i, total_time, total_time / MSG_TEST_UNIT);
ESP_LOGW(TAG, "0-resend %d, 1-resend %d, 2-resend %d, 3-resend %d, 3-resend-no-ack %d",
count[0], count[1], count[2], count[3], no_ack_count);
ESP_LOG_BUFFER_HEX("log", msg_record, MSG_TEST_COUNT * sizeof(msg_record[0]));
bzero(count, sizeof(count));
no_ack_count = 0;
total_time = 0;
}
return;
}
@@ -638,6 +709,7 @@ static void interval_timer_callback(void* arg)
++trans_num;
msg_record[msg_index].resend = 0;
msg_record[msg_index].acked = false;
msg_record[msg_index].time = 0;
example_ble_mesh_send_test_msg(false);
}
@@ -766,21 +838,6 @@ void ble_mesh_start(void)
board_init();
#if 0
err = nvs_flash_init();
if (err == ESP_ERR_NVS_NO_FREE_PAGES) {
ESP_ERROR_CHECK(nvs_flash_erase());
err = nvs_flash_init();
}
ESP_ERROR_CHECK(err);
err = bluetooth_init();
if (err) {
ESP_LOGE(TAG, "esp32_bluetooth_init failed (err %d)", err);
return;
}
#endif
esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_ADV, ESP_PWR_LVL_P9);
ESP_LOGI(TAG, "tx power level %d", esp_ble_tx_power_get(ESP_BLE_PWR_TYPE_ADV));
@@ -800,10 +857,8 @@ void ble_mesh_start(void)
ESP_ERROR_CHECK(esp_timer_create(&retransmit_timer_args, &retransmit_timer));
ESP_ERROR_CHECK(esp_timer_create(&interval_timer_args, &interval_timer));
test_mutex = xSemaphoreCreateMutex();
if (test_mutex == NULL) {
ESP_LOGE(TAG, "Failed to create test_mutex");
}
example_tx_rx_mutex_create();
board_led_operation(LED_R, LED_ON);
}