是的,在 ESP32 BLE Mesh 网关中,可以通过 ESP-IDF 提供的 BLE Mesh API 获取自身的组网地址(即节点的单播地址)。以下是详细说明和代码示例,帮助您实现这一功能。
背景知识
- 单播地址(Unicast Address):在 BLE Mesh 网络中,每个节点在组网(配网)过程中都会被分配一个唯一的单播地址,用于标识该节点。
- 元素(Element):节点由一个或多个元素组成,主元素(Primary Element)通常位于索引 0 的位置,节点的单播地址就是主元素的地址。
获取自身单播地址的方法
方法一:使用配置服务器模型
配置服务器模型(Configuration Server Model)是每个节点默认包含的模型,可以通过它获取节点的单播地址。
代码示例:
#include "esp_ble_mesh_common_api.h"
#include "esp_ble_mesh_config_model_api.h"
// 声明配置服务器模型实例
extern esp_ble_mesh_cfg_srv_t config_server;
void get_own_unicast_address(void)
{
uint16_t unicast_addr = config_server.model->element->element_addr;
printf("节点的单播地址:0x%04X\n", unicast_addr);
}
说明:
config_server
是配置服务器模型的实例,通过它可以访问所属元素的地址。element_addr
即为元素的地址,也就是节点的单播地址。
方法二:通过元素获取
可以直接获取节点的主元素,然后读取其地址。
代码示例:
#include "esp_ble_mesh_common_api.h"
void get_own_unicast_address(void)
{
// 获取索引为 0 的主元素
esp_ble_mesh_elem_t *element = esp_ble_mesh_find_element(0);
if (element != NULL)
{
uint16_t unicast_addr = element->element_addr;
printf("节点的单播地址:0x%04X\n", unicast_addr);
}
else
{
printf("未找到主元素\n");
}
}
说明:
esp_ble_mesh_find_element(0)
用于获取索引为 0 的元素,即主元素。- 如果成功获取元素,则其
element_addr
即为节点的单播地址。
方法三:在配网完成事件中获取
在节点完成配网(Provisioning)后,会触发相应的事件,可以在事件回调中获取分配的单播地址。
代码示例:
#include "esp_ble_mesh_defs.h"
void ble_mesh_provisioning_callback(esp_ble_mesh_prov_cb_event_t event,
esp_ble_mesh_prov_cb_param_t *param)
{
switch (event)
{
case ESP_BLE_MESH_NODE_PROV_COMPLETE_EVT:
{
uint16_t unicast_addr = param->node_prov_complete.addr;
printf("配网完成,节点的单播地址:0x%04X\n", unicast_addr);
break;
}
// 处理其他事件
default:
break;
}
}
void app_main(void)
{
// 注册配网回调函数
esp_ble_mesh_register_prov_callback(ble_mesh_provisioning_callback);
// 初始化 BLE Mesh(省略初始化代码)
// ...
}
说明:
- 当节点完成配网后,会触发
ESP_BLE_MESH_NODE_PROV_COMPLETE_EVT
事件。 - 在事件参数
param->node_prov_complete
中包含了节点的单播地址addr
。
注意事项
- 确保节点已完成配网:只有在节点成功加入 BLE Mesh 网络后,才能获取有效的单播地址。
- 元素索引:如果您的节点包含多个元素,可以根据元素索引获取对应元素的地址。
- 回调注册:在使用配网完成事件获取地址时,确保已正确注册配网回调函数。
完整示例代码
以下是一个完整的示例,展示如何在应用中获取节点的单播地址。
#include <stdio.h>
#include "esp_ble_mesh_common_api.h"
#include "esp_ble_mesh_config_model_api.h"
#include "esp_ble_mesh_defs.h"
// 配置服务器模型实例
esp_ble_mesh_cfg_srv_t config_server = {
.relay = ESP_BLE_MESH_RELAY_DISABLED,
// 其他配置参数
};
// 元素描述
esp_ble_mesh_model_t root_models[] = {
ESP_BLE_MESH_MODEL_CFG_SRV(&config_server),
// 其他模型
};
esp_ble_mesh_elem_t elements[] = {
ESP_BLE_MESH_ELEMENT(0, root_models, ESP_BLE_MESH_MODEL_NONE),
// 如果有其他元素,在此添加
};
esp_ble_mesh_comp_t composition = {
.cid = 0xFFFF, // 公司 ID
.elements = elements,
.element_count = ARRAY_SIZE(elements),
};
// 配网参数
esp_ble_mesh_prov_t provision = {
// 配网参数配置
// ...
};
// 配网回调函数
void ble_mesh_provisioning_callback(esp_ble_mesh_prov_cb_event_t event,
esp_ble_mesh_prov_cb_param_t *param)
{
switch (event)
{
case ESP_BLE_MESH_NODE_PROV_COMPLETE_EVT:
{
uint16_t unicast_addr = param->node_prov_complete.addr;
printf("配网完成,节点的单播地址:0x%04X\n", unicast_addr);
break;
}
default:
break;
}
}
void app_main(void)
{
// 初始化 NVS(必要时)
// ...
// 注册配网回调
esp_ble_mesh_register_prov_callback(ble_mesh_provisioning_callback);
// 初始化 BLE Mesh 核心堆栈
esp_ble_mesh_init(&provision, &composition);
// 启动 BLE Mesh 功能
esp_ble_mesh_node_prov_enable(ESP_BLE_MESH_PROV_ADV | ESP_BLE_MESH_PROV_GATT);
// 获取自身单播地址
get_own_unicast_address();
// 其他应用逻辑
// ...
}
// 获取自身单播地址的函数
void get_own_unicast_address(void)
{
uint16_t unicast_addr = config_server.model->element->element_addr;
printf("节点的单播地址:0x%04X\n", unicast_addr);
}
总结
- 获取自身组网地址:可以通过配置服务器模型、元素信息或配网完成事件获取节点的单播地址。
- 确保正确初始化和注册回调:在获取地址前,确保 BLE Mesh 堆栈已正确初始化,必要的回调函数已注册。
- 应用场景:获取自身的单播地址对于调试、日志记录或实现特定的网络逻辑非常有用。
如果您在实现过程中遇到任何问题,或者需要进一步的帮助,请随时提问!