BLE mesh : Failed to publish & Out of network adv

Hi,

I am using sensor observer sample to get the data from sensor sample. However, I notice the power consuption is too high. I have look thourgh the forum and found  this technique to reduce the power consumtion. I write one driver for this tehcnique.

After I flash my board, it can work well for around 30s and then will have "<err> bt_mesh_access: Failed to publish (err -105) <err> bt_mesh_transport: Out of network advs" and cannot print "People count is %". I also notice that the Bluetooth Mesh: Sensor can still be trigger and generate data correctly.

Here is my code:

model handler

/*
 * Copyright (c) 2020 Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
 */

#include <zephyr/bluetooth/bluetooth.h>
#include <bluetooth/mesh/models.h>
#include "model_handler.h"
#include "nus_handler.h" 
#include "pm.h" 

#define GET_DATA_INTERVAL 999

static struct k_work_delayable get_data_work;

/* 传感器客户端回调函数 - 只处理People Count */
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) {
        //printk("People count is %s\n", bt_mesh_sensor_ch_str(value));
         const char *count_str = bt_mesh_sensor_ch_str(value);
        printk("People count is %s\n", count_str);

        /* 更新 NUS 模块中的 people count 字符串 */
        nus_update_people_count(count_str);
        pre_sleep();

    }
}

/* 简化的传感器客户端处理程序 */
static const struct bt_mesh_sensor_cli_handlers bt_mesh_sensor_cli_handlers = {
    .data = sensor_cli_data_cb,
};

static struct bt_mesh_sensor_cli sensor_cli =
    BT_MESH_SENSOR_CLI_INIT(&bt_mesh_sensor_cli_handlers);

/* 数据获取工作处理函数 - 只请求People Count */
static void get_data(struct k_work *work)
{   
        post_sleep();
        if (!bt_mesh_is_provisioned()) {
            k_work_schedule(&get_data_work, K_MSEC(GET_DATA_INTERVAL));
            return;
        }
    
        int 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);
        }
        
        k_work_schedule(&get_data_work, K_MSEC(GET_DATA_INTERVAL));
    
    
    // set_pm_state();
}

/* 健康服务回调(保留基本功能) */
static void attention_on(const struct bt_mesh_model *mod) {}
static void attention_off(const struct bt_mesh_model *mod) {}

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(&get_data_work, get_data);
    k_work_schedule(&get_data_work, K_MSEC(GET_DATA_INTERVAL));
    
    return &comp;
}

pm.c

#include "pm.h" 
#include <zephyr/device.h>
#include <zephyr/pm/pm.h>
#include <zephyr/pm/device.h>
#include <zephyr/bluetooth/mesh.h>



// void set_pm_state()
// {
//     struct pm_state_info info =
//     {
//         .exit_latency_us  = 0,
//         .min_residency_us = 0,
//         .state            = PM_STATE_SUSPEND_TO_RAM,
//         .substate_id      = 0,
//     };
//     pm_device_action_run(CPU_ID, &info);
// }

void pre_sleep()
{
    bt_mesh_prov_disable(BT_MESH_PROV_GATT | BT_MESH_PROV_ADV);    // disabling provisioning bearer
    bt_mesh_suspend();                                             // turn off mesh
}

void post_sleep()
{
    bt_mesh_resume();                                              // turn on mesh
    bt_mesh_prov_enable(BT_MESH_PROV_GATT | BT_MESH_PROV_ADV);     // enabling provisioning bearer
}

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=y
CONFIG_BT_EXT_ADV_MAX_ADV_SET=9
# 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=9
CONFIG_BT_MAX_CONN=9
CONFIG_BT_BUF_CMD_TX_COUNT=30

#为了调试加的
CONFIG_LOG=y
#CONFIG_LOG_DEFAULT_LEVEL=4

Thank you for your time!

Parents
  • Hi, 

    What is your NCS version?

    it can work well for around 30s and then will have "<err> bt_mesh_access: Failed to publish (err -105) <err> bt_mesh_transport: Out of network advs"

    The error indicates a failure to publish a message likely due to insufficient network advertisement buffers from this line. Try to increase CONFIG_BT_MESH_ADV_BUF_COUNT.

    Regards,
    Amanda H.

  • Hi, I am using NCS 2.9.

    After I change the CONFIG_BT_MESH_ADV_BUF_COUNT to 30

    I will still got this error

    By the way, on this mesh device I still got a NUS service, does that affect this issue?

    And only when I add my power management code into the model_handler will I have this issue. If   bt_mesh_prov is always enable, this will be OK. Is there any way to clear ADV buffer after disable the mesh?

    Thank you so much for your help!

  • I have put this code in the original sample and will still have this issue, so the NUS service is not the problem.

    In addition I change the CONFIG_BT_MESH_ADV_BUF_COUNT to 256, Still cannot use. But I noticed when the CONFIG_BT_MESH_ADV_BUF_COUNT is higher, the time when data read stuck to error log is higher. (I do notice that people count will stop printing and after some time the error log happen).

    To make sure every bt_mesh_resume() and bt_mesh_suspend() work. My new code is:

    #include <zephyr/bluetooth/bluetooth.h>
    #include <bluetooth/mesh/models.h>
    #include "model_handler.h"
    #include "nus_handler.h" 
    #include "pm.h" 
    
    #define GET_DATA_INTERVAL 999
    
    static struct k_work_delayable get_data_work;
    BT_MESH_HEALTH_PUB_DEFINE(health_pub, 0);
    static bool mesh_suspended = false;
    
    
    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) {
            const char *count_str = bt_mesh_sensor_ch_str(value);
            printk("People count is %s\n", count_str);
            nus_update_people_count(count_str);
            if (!mesh_suspended) {
                int err = bt_mesh_suspend();
                if (err) {
                    printk("Error suspending mesh (%d)\n", err);
                } else {
                    mesh_suspended = true;
                }
            } else {
                printk("Mesh is not resumed, skipping suspend.\n");
            }
        }
    }
    
    
    static const struct bt_mesh_sensor_cli_handlers bt_mesh_sensor_cli_handlers = {
        .data = sensor_cli_data_cb,
    };
    
    static struct bt_mesh_sensor_cli sensor_cli =
        BT_MESH_SENSOR_CLI_INIT(&bt_mesh_sensor_cli_handlers);
    
    static void get_data(struct k_work *work)
    {   
        int err;
        if (!bt_mesh_is_provisioned()||(health_pub.addr == BT_MESH_ADDR_UNASSIGNED)) {
            k_work_schedule(&get_data_work, K_MSEC(GET_DATA_INTERVAL));
            return;
        }
    
        if (mesh_suspended) {
            err = bt_mesh_resume();
            if (err) {
                printk("Error resuming mesh (%d)\n", err);
                k_work_schedule(&get_data_work, K_MSEC(GET_DATA_INTERVAL));
                 return;
            }
            mesh_suspended = false;
        }
    
        /* 发送获取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);
            
        }
        
    
        k_work_schedule(&get_data_work, K_MSEC(GET_DATA_INTERVAL));
    }
    
    
    static void attention_on(const struct bt_mesh_model *mod) {}
    static void attention_off(const struct bt_mesh_model *mod) {}
    
    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,
    };
    
    
    
    
    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(&get_data_work, get_data);
        k_work_schedule(&get_data_work, K_MSEC(GET_DATA_INTERVAL));
        
        return &comp;
    }
    

    Could you please help me figure out this, thank you so much!

  • Hi, 

    From the team:

    Preliminary assesment shows the mesh stack code does not free up advertising memory slabs when mesh is suspended. This, the slabs keep getting consumed during suspend-resume cycles, eventually running out of ADV buffer pool. This requires a bug fix and we might need some time to fix it. 

    -Amanda H.

  • Thank you so much for your information. Could you please let me know when you solve this?

  • We cannot promise any schedule on Devzone. Sorry for the inconvenience.  

Reply Children
No Data
Related