I am using Zephyr to create a program that integrates BLE Mesh and NUS. My goal is to use a sensor_client to read data from a sensor_server, and then send the data, via peripheral_uart, to an external central_uart device after reading it. I referred to the official examples, including sensor_client, sensor_server, peripheral_uart, and ble_peripheral_lbs_coex, and developed the final program using NCS 2.9 on an nRF52833. My code shows below
main.c
/*
* Copyright (c) 2020 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/
/** @file
* @brief Nordic mesh sensor observer sample
*/
#include <zephyr/bluetooth/bluetooth.h>
#include <bluetooth/mesh/models.h>
#include <bluetooth/mesh/dk_prov.h>
#include <dk_buttons_and_leds.h>
#include "model_handler.h"
#include "nus_handler.h"//头文件
static void bt_ready(int err)
{
if (err) {
printk("Bluetooth init failed (err %d)\n", err);
return;
}
printk("Bluetooth initialized\n");
err = dk_leds_init();
if (err) {
printk("Initializing LEDs failed (err %d)\n", err);
return;
}
err = dk_buttons_init(NULL);
if (err) {
printk("Initializing buttons failed (err %d)\n", err);
return;
}
err = bt_mesh_init(bt_mesh_dk_prov_init(), model_handler_init());
if (err) {
printk("Initializing mesh failed (err %d)\n", err);
return;
}
if (IS_ENABLED(CONFIG_SETTINGS)) {
settings_load();
}
/* This will be a no-op if settings_load() loaded provisioning info */
bt_mesh_prov_enable(BT_MESH_PROV_ADV | BT_MESH_PROV_GATT);
printk("Mesh initialized\n");
/* 初始化 NUS handler */
err = nus_handler_init();
if (err) {
printk("NUS handler initialization failed (err %d)\n", err);
return;
}
printk("NUS handler initialized\n");
}
int main(void)
{
int err;
printk("Initializing...\n");
err = bt_enable(bt_ready);
if (err) {
printk("Bluetooth init failed (err %d)\n", err);
}
return 0;
}
model_handler.c
/*
* Copyright (c) 2020 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/
#include <zephyr/bluetooth/bluetooth.h>
#include <bluetooth/mesh/models.h>
#include <dk_buttons_and_leds.h>
#include "model_handler.h"
#define GET_DATA_INTERVAL 10000
#define GET_DATA_INTERVAL_QUICK 3000
#define MOTION_TIMEOUT K_SECONDS(60)
static bool is_occupied;
static struct k_work_delayable motion_timeout_work;
static void motion_timeout(struct k_work *work)
{
is_occupied = false;
printk("Area is now vacant.\n");
}
// static void sensor_cli_data_cb(struct bt_mesh_sensor_cli *cli,
// struct bt_mesh_msg_ctx *ctx,
// const struct bt_mesh_sensor_type *sensor,
// const struct bt_mesh_sensor_value *value)
// {
// enum bt_mesh_sensor_value_status status;
// if (sensor->id == bt_mesh_sensor_present_dev_op_temp.id) {
// printk("Chip temperature: %s\n", bt_mesh_sensor_ch_str(value));
// } else if (sensor->id == bt_mesh_sensor_presence_detected.id) {
// int64_t presence_detected = 0;
// status = bt_mesh_sensor_value_to_micro(value, &presence_detected);
// if (!bt_mesh_sensor_value_status_is_numeric(status)) {
// printk("Warning: unexpected behaviour during conversion of presence "
// "detected value (%d)\n",
// status);
// return;
// }
// if (!!presence_detected) {
// printk("Presence detected\n");
// } else {
// printk("No presence detected\n");
// }
// } else if (sensor->id ==
// bt_mesh_sensor_time_since_presence_detected.id) {
// int64_t time_since_presence_detected = 0;
// status = bt_mesh_sensor_value_to_micro(value, &time_since_presence_detected);
// if (status == BT_MESH_SENSOR_VALUE_UNKNOWN) {
// printk("Unknown last presence detected\n");
// } else if (!time_since_presence_detected) {
// printk("Presence detected, or under 1 second since presence detected\n");
// } else {
// printk("%s second(s) since last presence detected\n",
// bt_mesh_sensor_ch_str(value));
// }
// } else if (sensor->id == bt_mesh_sensor_present_amb_light_level.id) {
// printk("Ambient light level: %s\n", bt_mesh_sensor_ch_str(value));
// } else if (sensor->id == bt_mesh_sensor_motion_sensed.id) {
// int64_t motion_sensed = 0;
// status = bt_mesh_sensor_value_to_micro(value, &motion_sensed);
// if (!bt_mesh_sensor_value_status_is_numeric(status)) {
// printk("Warning: unexpected behaviour during conversion of motion sensed "
// "value (%d)\n",
// status);
// return;
// }
// if (!!motion_sensed) {
// is_occupied = true;
// printk("Motion detected (%s %%). Area is occupied.\n",
// bt_mesh_sensor_ch_str(value));
// k_work_cancel_delayable(&motion_timeout_work);
// } else {
// if (is_occupied) {
// printk("No current motion detected. Area is still occupied.\n");
// k_work_reschedule(&motion_timeout_work, MOTION_TIMEOUT);
// } else {
// printk("No motion detected. Area is vacant.\n");
// }
// }
// } else if (sensor->id == bt_mesh_sensor_time_since_motion_sensed.id) {
// int64_t time_since_motion_sensed = 0;
// status = bt_mesh_sensor_value_to_micro(value, &time_since_motion_sensed);
// if (status == BT_MESH_SENSOR_VALUE_UNKNOWN) {
// printk("Unknown last motion sensed\n");
// } else if (!time_since_motion_sensed) {
// printk("Motion sensed, or under 1 second since motion sensed\n");
// } else {
// printk("%s second(s) since last motion sensed\n",
// bt_mesh_sensor_ch_str(value));
// }
// } else if (sensor->id == bt_mesh_sensor_people_count.id) {
// printk("People count is %s\n", bt_mesh_sensor_ch_str(value));
// }
// }
static void sensor_cli_data_cb(struct bt_mesh_sensor_cli *cli,
struct bt_mesh_msg_ctx *ctx,
const struct bt_mesh_sensor_type *sensor,
const struct bt_mesh_sensor_value *value)
{
if (sensor->id == bt_mesh_sensor_people_count.id) {
// 打印 People Count 数据
printk("People count is %s\n", bt_mesh_sensor_ch_str(value));
}
}
static void sensor_cli_series_entry_cb(
struct bt_mesh_sensor_cli *cli, struct bt_mesh_msg_ctx *ctx,
const struct bt_mesh_sensor_type *sensor, uint8_t index, uint8_t count,
const struct bt_mesh_sensor_series_entry *entry)
{
printk("Relative runtime in %s", bt_mesh_sensor_ch_str(&entry->value[1]));
printk(" to %s degrees: ", bt_mesh_sensor_ch_str(&entry->value[2]));
printk("%s percent\n", bt_mesh_sensor_ch_str(&entry->value[0]));
}
static void sensor_cli_setting_status_cb(struct bt_mesh_sensor_cli *cli,
struct bt_mesh_msg_ctx *ctx,
const struct bt_mesh_sensor_type *sensor,
const struct bt_mesh_sensor_setting_status *setting)
{
printk("Sensor ID: 0x%04x, Setting ID: 0x%04x\n", sensor->id, setting->type->id);
for (int chan = 0; chan < setting->type->channel_count; chan++) {
printk("\tChannel %d value: %s\n", chan,
bt_mesh_sensor_ch_str(&(setting->value[chan])));
}
}
static void sensor_cli_desc_cb(struct bt_mesh_sensor_cli *cli, struct bt_mesh_msg_ctx *ctx,
const struct bt_mesh_sensor_info *sensor)
{
printk("Descriptor of sensor with ID 0x%04x:\n", sensor->id);
printk("\ttolerance: { positive: %d negative: %d }\n",
sensor->descriptor.tolerance.positive, sensor->descriptor.tolerance.negative);
printk("\tsampling type: %d\n", sensor->descriptor.sampling_type);
}
static const struct bt_mesh_sensor_cli_handlers bt_mesh_sensor_cli_handlers = {
.data = sensor_cli_data_cb,
.series_entry = sensor_cli_series_entry_cb,
.setting_status = sensor_cli_setting_status_cb,
.sensor = sensor_cli_desc_cb,
};
static struct bt_mesh_sensor_cli sensor_cli =
BT_MESH_SENSOR_CLI_INIT(&bt_mesh_sensor_cli_handlers);
static struct k_work_delayable get_data_work;
// static void get_data(struct k_work *work)
// {
// if (!bt_mesh_is_provisioned()) {
// k_work_schedule(&get_data_work, K_MSEC(GET_DATA_INTERVAL));
// return;
// }
// static uint32_t sensor_idx;
// int err;
// /* Only one message can be published at a time. Swap sensor after each timeout. */
// switch (sensor_idx++) {
// case (0): {
// err = bt_mesh_sensor_cli_get(
// &sensor_cli, NULL, &bt_mesh_sensor_present_dev_op_temp,
// NULL);
// if (err) {
// printk("Error getting chip temperature (%d)\n", err);
// }
// break;
// }
// case (1): {
// err = bt_mesh_sensor_cli_series_entries_get(
// &sensor_cli, NULL,
// &bt_mesh_sensor_rel_runtime_in_a_dev_op_temp_range, NULL, NULL,
// NULL, NULL);
// if (err) {
// printk("Error getting relative chip temperature data (%d)\n", err);
// }
// break;
// }
// case (2): {
// err = bt_mesh_sensor_cli_get(
// &sensor_cli, NULL, &bt_mesh_sensor_time_since_presence_detected,
// NULL);
// if (err) {
// printk("Error getting time since presence detected (%d)\n", err);
// }
// break;
// }
// case (3): {
// err = bt_mesh_sensor_cli_get(
// &sensor_cli, NULL, &bt_mesh_sensor_present_amb_light_level, NULL);
// if (err) {
// printk("Error getting ambient light level (%d)\n", err);
// }
// break;
// }
// case (4): {
// err = bt_mesh_sensor_cli_get(&sensor_cli, NULL,
// &bt_mesh_sensor_time_since_motion_sensed, NULL);
// if (err) {
// printk("Error getting time since motion detected (%d)\n", err);
// }
// break;
// }
// case (5): {
// err = bt_mesh_sensor_cli_get(&sensor_cli, NULL, &bt_mesh_sensor_people_count, NULL);
// if (err) {
// printk("Error getting people count (%d)\n", err);
// }
// break;
// }
// }
// if (sensor_idx % 6) {
// k_work_schedule(&get_data_work, K_MSEC(GET_DATA_INTERVAL_QUICK));
// } else {
// k_work_schedule(&get_data_work, K_MSEC(GET_DATA_INTERVAL));
// sensor_idx = 0;
// }
// }
static void get_data(struct k_work *work)
{
if (!bt_mesh_is_provisioned()) {
k_work_schedule(&get_data_work, K_MSEC(GET_DATA_INTERVAL));
return;
}
int err;
/* 只获取 people count 数据 */
err = bt_mesh_sensor_cli_get(&sensor_cli, NULL, &bt_mesh_sensor_people_count, NULL);
if (err) {
printk("Error getting people count (%d)\n", err);
} else {
printk("Requesting people count data...\n");
}
/* 定时任务,保持轮询获取 people count */
k_work_schedule(&get_data_work, K_MSEC(GET_DATA_INTERVAL));
}
static const int temp_ranges[][2] = {
{ 0, 100 },
{ 10, 20 },
{ 22, 30 },
{ 40, 50 },
};
static const int presence_motion_threshold[] = { 0, 25, 50, 75, 100 };
static int setting_set_int(const struct bt_mesh_sensor_type *sensor_type,
const struct bt_mesh_sensor_type *setting_type,
const int *values)
{
struct bt_mesh_sensor_value sensor_vals[CONFIG_BT_MESH_SENSOR_CHANNELS_MAX];
int err;
for (int i = 0; i < setting_type->channel_count; i++) {
err = bt_mesh_sensor_value_from_micro(setting_type->channels[i].format,
values[i] * 1000000LL, &sensor_vals[i]);
if (err) {
return err;
}
}
return bt_mesh_sensor_cli_setting_set(&sensor_cli, NULL, sensor_type,
setting_type, sensor_vals, NULL);
}
static void button_handler_cb(uint32_t pressed, uint32_t changed)
{
if (!bt_mesh_is_provisioned()) {
return;
}
static uint32_t temp_idx;
static uint32_t motion_threshold_idx;
int err;
if (pressed & changed & BIT(0)) {
err = bt_mesh_sensor_cli_setting_get(&sensor_cli, NULL,
&bt_mesh_sensor_present_dev_op_temp,
&bt_mesh_sensor_dev_op_temp_range_spec, NULL);
if (err) {
printk("Error getting range setting (%d)\n", err);
}
}
if (pressed & changed & BIT(1)) {
err = setting_set_int(&bt_mesh_sensor_present_dev_op_temp,
&bt_mesh_sensor_dev_op_temp_range_spec,
temp_ranges[temp_idx++]);
if (err) {
printk("Error setting range setting (%d)\n", err);
}
temp_idx = temp_idx % ARRAY_SIZE(temp_ranges);
}
if (pressed & changed & BIT(2)) {
err = bt_mesh_sensor_cli_desc_get(&sensor_cli, NULL,
&bt_mesh_sensor_present_dev_op_temp, NULL);
if (err) {
printk("Error getting sensor descriptor (%d)\n", err);
}
}
if (pressed & changed & BIT(3)) {
err = setting_set_int(&bt_mesh_sensor_presence_detected,
&bt_mesh_sensor_motion_threshold,
&presence_motion_threshold[motion_threshold_idx++]);
if (err) {
printk("Error setting motion threshold setting (%d)\n", err);
}
motion_threshold_idx = motion_threshold_idx % ARRAY_SIZE(presence_motion_threshold);
}
}
static struct button_handler button_handler = {
.cb = button_handler_cb,
};
/* Set up a repeating delayed work to blink the DK's LEDs when attention is
* requested.
*/
static struct k_work_delayable attention_blink_work;
static bool attention;
static void attention_blink(struct k_work *work)
{
static int idx;
const uint8_t pattern[] = {
BIT(0) | BIT(1),
BIT(1) | BIT(2),
BIT(2) | BIT(3),
BIT(3) | BIT(0),
};
if (attention) {
dk_set_leds(pattern[idx++ % ARRAY_SIZE(pattern)]);
k_work_reschedule(&attention_blink_work, K_MSEC(30));
} else {
dk_set_leds(DK_NO_LEDS_MSK);
}
}
static void attention_on(const struct bt_mesh_model *mod)
{
attention = true;
k_work_reschedule(&attention_blink_work, K_NO_WAIT);
}
static void attention_off(const struct bt_mesh_model *mod)
{
/* Will stop rescheduling blink timer */
attention = false;
}
static const struct bt_mesh_health_srv_cb health_srv_cb = {
.attn_on = attention_on,
.attn_off = attention_off,
};
static struct bt_mesh_health_srv health_srv = {
.cb = &health_srv_cb,
};
BT_MESH_HEALTH_PUB_DEFINE(health_pub, 0);
static struct bt_mesh_elem elements[] = {
BT_MESH_ELEM(1,
BT_MESH_MODEL_LIST(BT_MESH_MODEL_CFG_SRV,
BT_MESH_MODEL_HEALTH_SRV(&health_srv,
&health_pub),
BT_MESH_MODEL_SENSOR_CLI(&sensor_cli)),
BT_MESH_MODEL_NONE),
};
static const struct bt_mesh_comp comp = {
.cid = CONFIG_BT_COMPANY_ID,
.elem = elements,
.elem_count = ARRAY_SIZE(elements),
};
const struct bt_mesh_comp *model_handler_init(void)
{
k_work_init_delayable(&attention_blink_work, attention_blink);
k_work_init_delayable(&get_data_work, get_data);
k_work_init_delayable(&motion_timeout_work, motion_timeout);
dk_button_handler_add(&button_handler);
k_work_schedule(&get_data_work, K_MSEC(GET_DATA_INTERVAL));
return ∁
}
nus_handler.c
#include "nus_handler.h"
#include <zephyr/types.h>
#include <zephyr/sys/printk.h>
#include <zephyr/bluetooth/gatt.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/sys/byteorder.h>
#include <zephyr/types.h>
#include <stddef.h>
#include <zephyr/sys/printk.h>
#include <zephyr/sys/byteorder.h>
#include <zephyr/kernel.h>
#include <zephyr/drivers/gpio.h>
#include <soc.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/hci.h>
#include <zephyr/bluetooth/conn.h>
#include <zephyr/bluetooth/uuid.h>
#include <bluetooth/services/nus.h>
#include <dk_buttons_and_leds.h>
#define DEVICE_NAME CONFIG_BT_DEVICE_NAME
#define DEVICE_NAME_LEN (sizeof(CONFIG_BT_DEVICE_NAME) - 1)
static struct bt_conn *current_conn;
static struct k_work_delayable send_work;
static struct bt_le_ext_adv *nus_adv; // 独立的扩展广告实例
static const char cmd_str[] = "123456789";
static uint8_t nus_conn_id = BT_ID_DEFAULT;
/* Advertising配置 */
static const struct bt_data ad[] = {
BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
};
static const struct bt_data sd[] = {
BT_DATA_BYTES(BT_DATA_UUID128_ALL, BT_UUID_NUS_VAL),
};
/* 蓝牙连接回调函数 */
static void connected(struct bt_conn *conn, uint8_t err)
{
if (err) {
printk("Connection failed (err 0x%02x)\n", err);
return;
}
printk("Connected\n");
current_conn = bt_conn_ref(conn); // 保存连接引用
}
static void disconnected(struct bt_conn *conn, uint8_t reason)
{
printk("Disconnected (reason 0x%02x)\n", reason);
if (current_conn) {
bt_conn_unref(current_conn); // 释放连接引用
current_conn = NULL;
}
}
/* 定义连接回调结构 */
BT_CONN_CB_DEFINE(conn_callbacks) = {
.connected = connected,
.disconnected = disconnected,
};
/* 数据发送工作处理 */
static void send_work_handler(struct k_work *work)
{
if (current_conn) {
int err = bt_nus_send(current_conn, cmd_str, sizeof(cmd_str) - 1);
if (err == -ENOMEM) {
printk("Failed to send NUS data: Out of memory (err %d)\n", err);
} else if (err) {
printk("Failed to send NUS data (err %d)\n", err);
} else {
printk("Sent: %s\n", cmd_str);
}
} else {
printk("No active connection, skipping send\n");
}
// 定时调度下一次发送任务
k_work_schedule(&send_work, K_SECONDS(5));
}
/* NUS回调函数 */
static void bt_receive_cb(struct bt_conn *conn, const uint8_t *const data, uint16_t len)
{
printk("Received data: %.*s\n", len, data);
}
/* NUS回调结构 */
static struct bt_nus_cb nus_cb = {
.received = bt_receive_cb,
};
/* 初始化扩展广告 */
static int init_extended_advertising(void)
{
int err;
size_t id_count = 0xFF;
struct bt_le_adv_param adv_params = *BT_LE_ADV_CONN;
/* 检查当前标识符数量 */
(void)bt_id_get(NULL, &id_count);
if (id_count < CONFIG_BT_ID_MAX) {
int id = bt_id_create(NULL, NULL);
if (id < 0) {
printk("Unable to create a new identity for NUS (err %d). Using the default one.\n", id);
nus_conn_id = BT_ID_DEFAULT;
} else {
nus_conn_id = id;
printk("Created a new identity for NUS: %d\n", nus_conn_id);
}
} else {
nus_conn_id = BT_ID_DEFAULT;
printk("Recovered identity for NUS: %d\n", nus_conn_id);
}
// struct bt_le_adv_param adv_params = {
// // .options = BT_LE_ADV_OPT_EXT_ADV | BT_LE_ADV_OPT_CONNECTABLE, // 启用扩展广告并支持连接
// // .interval_min = BT_GAP_ADV_FAST_INT_MIN_2,
// // .interval_max = BT_GAP_ADV_FAST_INT_MAX_2,
// // .peer = NULL, // 无特定目标设备
// // .sid = 0, // 广播实例ID
// .id = nus_conn_id,
// };
adv_params.id = nus_conn_id;
/* 创建扩展广告实例 */
err = bt_le_ext_adv_create(&adv_params, NULL, &nus_adv);
if (err) {
printk("Failed to create extended advertising instance (err %d)\n", err);
return err;
}
/* 设置广告和扫描响应数据 */
err = bt_le_ext_adv_set_data(nus_adv, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd));
if (err) {
printk("Failed to set extended advertising data (err %d)\n", err);
return err;
}
printk("Extended advertising instance created\n");
return 0;
}
/* 启动扩展广告 */
static int start_extended_advertising(void)
{
int err;
err = bt_le_ext_adv_start(nus_adv, BT_LE_EXT_ADV_START_DEFAULT);
if (err) {
printk("Failed to start extended advertising (err %d)\n", err);
return err;
}
printk("Extended advertising started\n");
return 0;
}
/* 初始化NUS服务的入口函数 */
int nus_handler_init(void)
{
int err;
/* 初始化NUS服务 */
err = bt_nus_init(&nus_cb);
if (err) {
printk("Failed to initialize NUS (err %d)\n", err);
return err;
}
printk("NUS service initialized\n");
/* 初始化扩展广告 */
err = init_extended_advertising();
if (err) {
return err;
}
/* 启动扩展广告 */
err = start_extended_advertising();
if (err) {
return err;
}
/* 初始化定时发送任务 */
k_work_init_delayable(&send_work, send_work_handler);
k_work_schedule(&send_work, K_SECONDS(5)); // 每 5 秒发送一次数据
printk("NUS Handler initialized\n");
return 0;
}
project config
# # Copyright (c) 2020 Nordic Semiconductor ASA # # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause # CONFIG_NCS_SAMPLES_DEFAULTS=y # Deferred logging helps improve LPN power consumption # when friendship is established. CONFIG_LOG_MODE_DEFERRED=y # General configuration CONFIG_NCS_APPLICATION_BOOT_BANNER_STRING="Mesh Sensor Observer" #CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 在后面加了个大的 CONFIG_FLASH=y CONFIG_FLASH_MAP=y # Flash shell module uses 8k of RAM for testing buffers, disable to save RAM CONFIG_FLASH_SHELL=n CONFIG_NVS=y CONFIG_NVS_LOOKUP_CACHE=y CONFIG_SETTINGS=y CONFIG_SETTINGS_NVS_NAME_CACHE=y CONFIG_HWINFO=y CONFIG_DK_LIBRARY=y CONFIG_PM_SINGLE_IMAGE=y CONFIG_PM_PARTITION_SIZE_SETTINGS_STORAGE=0x8000 CONFIG_SOC_FLASH_NRF_PARTIAL_ERASE=y CONFIG_CBPRINTF_FP_SUPPORT=y # Bluetooth configuration CONFIG_BT=y CONFIG_BT_DEVICE_NAME="Mesh Sensor Observer" CONFIG_BT_L2CAP_TX_BUF_COUNT=8 CONFIG_BT_OBSERVER=y CONFIG_BT_PERIPHERAL=y CONFIG_BT_SETTINGS=y # Disable unused Bluetooth features CONFIG_BT_CTLR_LE_ENC=n CONFIG_BT_PHY_UPDATE=n CONFIG_BT_CTLR_CHAN_SEL_2=n CONFIG_BT_CTLR_MIN_USED_CHAN=n CONFIG_BT_CTLR_PRIVACY=n # Bluetooth Mesh configuration CONFIG_BT_MESH=y CONFIG_BT_MESH_RELAY=y CONFIG_BT_MESH_FRIEND=y CONFIG_BT_MESH_TX_SEG_MAX=24 CONFIG_BT_MESH_RX_SEG_MAX=16 CONFIG_BT_MESH_PB_GATT=y CONFIG_BT_MESH_GATT_PROXY=y CONFIG_BT_MESH_PROXY_USE_DEVICE_NAME=y CONFIG_BT_MESH_DK_PROV=y CONFIG_BT_MESH_SUBNET_COUNT=2 CONFIG_BT_MESH_APP_KEY_COUNT=3 CONFIG_BT_MESH_MODEL_KEY_COUNT=3 CONFIG_BT_MESH_CRPL=32 CONFIG_BT_MESH_MSG_CACHE_SIZE=64 CONFIG_BT_MESH_SHELL=y # Bluetooth Mesh models CONFIG_BT_MESH_SENSOR_CLI=y CONFIG_LOG_BACKEND_RTT=n #我加的我加的 CONFIG_BT_NUS=y # CONFIG_FLASH_PAGE_LAYOUT=y CONFIG_BT_EXT_ADV_MAX_ADV_SET=6 # CONFIG_BT_BUF_ACL_RX_SIZE=27 # CONFIG_BT_BUF_ACL_TX_SIZE=27 # CONFIG_BT_BUF_ACL_TX_COUNT=10 # CONFIG_BT_BUF_EVT_RX_COUNT=10 # CONFIG_BT_BUF_EVT_DISCARDABLE_SIZE=58 # CONFIG_HEAP_MEM_POOL_SIZE=4096 # CONFIG_MAIN_STACK_SIZE=2048 # CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 CONFIG_BT_ID_MAX=2 CONFIG_BT_MAX_CONN=3
However, I encountered an issue: despite maintaining the logic and structure of the ble_peripheral_lbs_coex code entirely, I am unable to initialize advertising, and I frequently receive errors such as 'no BUFFER', 'no context', and 'No more contexts.'
*** Booting Mesh Sensor Observer v2.9.0-99e1dd02b3a7 ***
*** Using nRF Connect SDK v2.9.0-7787b2649840 ***
*** Using Zephyr OS v3.7.99-1f8f3dc29142 ***
Initializing...
[00:00:00.008,209] <inf> fs_nvs: 8 Sectors of 4096 bytes
[00:00:00.008,209] <inf> fs_nvs: alloc wra: 0, fe8
[00:00:00.008,239] <inf> fs_nvs: data wra: 0, 0
[00:00:00.008,575] <inf> bt_sdc_hci_driver: SoftDevice Controller build revision:
2d 79 a1 c8 6a 40 b7 3c f6 74 f9 0b 22 d3 c4 80 |-y..j@.< .t.."...
74 72 82 ba |tr..
[00:00:00.012,512] <inf> bt_hci_core: HW Platform: Nordic Semiconductor (0x0002)
[00:00:00.012,542] <inf> bt_hci_core: HW Variant: nRF52x (0x0002)
[00:00:00.012,603] <inf> bt_hci_core: Firmware: Standard Bluetooth controller (0x00) Version 45.41337 Build 3074452168
[00:00:00.012,939] <inf> bt_hci_core: No ID address. App must call settings_load()
Bluetooth initialized
[00:00:00.271,362] <inf> bt_hci_core: Identity: CC:E6:9E:65:8E:2C (random)
[00:00:00.271,392] <inf> bt_hci_core: HCI: version 6.0 (0x0e) revision 0x106b, manufacturer 0x0059
[00:00:00.271,423] <inf> bt_hci_core: LMP: version 6.0 (0x0e) subver 0x106b
[00:00:00.277,465] <inf> bt_mesh_provisionee: Device UUID: 0bc7df6f-43c0-4ca9-b438-2090bc3fc356
Mesh initialized
NUS service initialized
Recovered identity for NUS: 0
Failed to create extended advertising instance (err -12)
NUS handler initialization failed (err -12)
Could you let me know if my approach is correct? Is it possible to integrate NUS with BLE Mesh? Alternatively, is there another way to achieve similar functionality? I have not found relevant examples online and look forward to your response : )

