This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

CAF BLE state BT connection limit

Hi,

I am currently developing an application around the CAF BLE state and advertising components.

My setup consists of a nRF9160DK that uses the nRF52840 onboard for BLE. 

The components themselves work mostly OK, but I run into a problem with the following assertion found in ble_state.c:367:

BUILD_ASSERT(!IS_ENABLED(CONFIG_BT_PERIPHERAL) ||
		     (ARRAY_SIZE(active_conn) == 1));

My application does the following two things:

- Advertise so that a device can connect

- Be a central so that I can scan for advertising packets from other BLE sensors. I will never connect, I just need to be able to parse the advertisement data.

So in my prj.conf I have the following lines:

#
# Copyright (c) 2019 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#

# General config
CONFIG_NEWLIB_LIBC=y
CONFIG_ASSERT=y
CONFIG_REBOOT=y

# Enable Bluetooth stack and libraries
CONFIG_BT=y
#CONFIG_BT_GATT_CLIENT=y
#CONFIG_BT_GATT_DM=y
#CONFIG_BT_LL_SOFTDEVICE=y

# Bluetooth general settings 
CONFIG_BT_DIS=y # device information service
CONFIG_BT_SMP=y
CONFIG_BT_MAX_CONN=2
CONFIG_BT_MAX_PAIRED=4

# Bluetooth appearance
CONFIG_BT_PERIPHERAL=y
CONFIG_BT_DEVICE_NAME="nRF Device"
CONFIG_BT_DEVICE_APPEARANCE=1856

# Enable bonding
# CONFIG_BT_SETTINGS=y
# CONFIG_FLASH=y
# CONFIG_FLASH_PAGE_LAYOUT=y
# CONFIG_FLASH_MAP=y
# CONFIG_NVS=y
# CONFIG_SETTINGS=y
# CONFIG_SETTINGS_NVS=y

# Enable the BMS service
CONFIG_BT_BMS=y

# Heap and stacks
CONFIG_HEAP_MEM_POOL_SIZE=65536
CONFIG_MAIN_STACK_SIZE=65536

# Configuration required by Event Manager
CONFIG_EVENT_MANAGER=y
CONFIG_LINKER_ORPHAN_SECTION_PLACE=y
CONFIG_REBOOT=y

## Config related to CAF (common application framework)
CONFIG_CAF=y
CONFIG_CAF_BLE_STATE=y
# CONFIG_CAF_BLE_BOND_SUPPORTED=y

# CAF BLE ADVERTISING
CONFIG_CAF_BLE_ADV=y
CONFIG_CAF_BLE_ADV_DEF_PATH="ble_adv_def.h"
#CONFIG_CAF_BLE_ADV_PM_EVENTS=y
CONFIG_CAF_BLE_ADV_DIRECT_ADV=n
CONFIG_CAF_BLE_ADV_FAST_ADV=y

# CAF debug
CONFIG_CAF_BLE_ADV_LOG_LEVEL_DBG=y
CONFIG_CAF_BLE_STATE_LOG_LEVEL_DBG=y

## Logger configuration
CONFIG_LOG=y
CONFIG_LOG_DEFAULT_LEVEL=4
CONFIG_LOG_BACKEND_UART=y
CONFIG_LOG_STRDUP_BUF_COUNT=10
CONFIG_BOOT_BANNER=n

## HC-SR04
CONFIG_SENSOR=y
CONFIG_GPIO=y
CONFIG_HC_SR04=y

# ultrasonic service, CONFIG_BT_L2CAP_TX_BUF_COUNT needed?
CONFIG_BT_L2CAP_TX_BUF_COUNT=5 

# Required for Bluetooth HCI to external nRF52840
CONFIG_NRF_SW_LPUART=y
CONFIG_NRF_SW_LPUART_INT_DRIVEN=y

CONFIG_UART_2_ASYNC=y
CONFIG_UART_2_INTERRUPT_DRIVEN=n
CONFIG_UART_2_NRF_HW_ASYNC=y
CONFIG_UART_2_NRF_HW_ASYNC_TIMER=2

CONFIG_BT_H4=y
CONFIG_BT_WAIT_NOP=y
CONFIG_BT_GATT_CLIENT=y
CONFIG_BT_GATT_DM=y

CONFIG_UART_INTERRUPT_DRIVEN=y

# ultrasonic service, CONFIG_BT_L2CAP_TX_BUF_COUNT needed?
CONFIG_BT_L2CAP_TX_BUF_COUNT=5 

# Enable scanning
CONFIG_BT_SCAN=y
CONFIG_BT_CENTRAL=y
CONFIG_BT_GATT_CLIENT=y

# Allow for bigger packets to include all TPMS in one packet
CONFIG_BT_USER_DATA_LEN_UPDATE=y
CONFIG_BT_L2CAP_TX_MTU=253
CONFIG_BT_BUF_CMD_TX_SIZE=255
CONFIG_BT_BUF_ACL_RX_SIZE=251

Since I have both CONFIG_BT_PERIPHERAL and CONFIG_BT_CENTRAL, zephyr requies CONFIG_BT_MAX_CONN to be at least 2, I guess because it reserves a connection for the internal central as well? Although from the peripheral point of view I only require one 'connection' to an external central at a time. 

Is there a way around this build assert or am I stuck?

I have uncommented the lines from ble_state.c and now the application 'works' but I doubt this is the right way.

Kind regards,

Stef

  • - Be a central so that I can scan for advertising packets from other BLE sensors. I will never connect, I just need to be able to parse the advertisement data.

     If you just want the device to scan without connection, you should not configure it as a central. As mentioned in the ticket What is a client and server in BLE?, the central role has to do with establishing a connection. Instead you should configure it as an observer, which is the non-connecting variant of a central.

    I modified the sample ncs/zephyr/samples/bluetooth/central to make it operate as an observer. I used NCS v1.6.0, and here is the diff:

    diff --git a/samples/bluetooth/central/prj.conf b/samples/bluetooth/central/prj.conf
    index 3e36a99938..091c338db6 100644
    --- a/samples/bluetooth/central/prj.conf
    +++ b/samples/bluetooth/central/prj.conf
    @@ -1,2 +1,4 @@
     CONFIG_BT=y
    -CONFIG_BT_CENTRAL=y
    +CONFIG_BT_OBSERVER=y
    \ No newline at end of file
    diff --git a/samples/bluetooth/central/src/main.c b/samples/bluetooth/central/src/main.c
    index c2a164cccb..f58203f145 100644
    --- a/samples/bluetooth/central/src/main.c
    +++ b/samples/bluetooth/central/src/main.c
    @@ -14,49 +14,21 @@
     
     #include <bluetooth/bluetooth.h>
     #include <bluetooth/hci.h>
    -#include <bluetooth/conn.h>
     #include <bluetooth/uuid.h>
     #include <bluetooth/gatt.h>
     #include <sys/byteorder.h>
     
     static void start_scan(void);
     
    -static struct bt_conn *default_conn;
    -
     static void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type,
                             struct net_buf_simple *ad)
     {
            char addr_str[BT_ADDR_LE_STR_LEN];
            int err;
     
    -       if (default_conn) {
    -               return;
    -       }
    -
    -       /* We're only interested in connectable events */
    -       if (type != BT_GAP_ADV_TYPE_ADV_IND &&
    -           type != BT_GAP_ADV_TYPE_ADV_DIRECT_IND) {
    -               return;
    -       }
     
            bt_addr_le_to_str(addr, addr_str, sizeof(addr_str));
            printk("Device found: %s (RSSI %d)\n", addr_str, rssi);
    -
    -       /* connect only to devices in close proximity */
    -       if (rssi < -70) {
    -               return;
    -       }
    -
    -       if (bt_le_scan_stop()) {
    -               return;
    -       }
    -
    -       err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN,
    -                               BT_LE_CONN_PARAM_DEFAULT, &default_conn);
    -       if (err) {
    -               printk("Create conn to %s failed (%u)\n", addr_str, err);
    -               start_scan();
    -       }
     }
     
     static void start_scan(void)
    @@ -73,54 +45,6 @@ static void start_scan(void)
            printk("Scanning successfully started\n");
     }
     
    -static void connected(struct bt_conn *conn, uint8_t err)
    -{
    -       char addr[BT_ADDR_LE_STR_LEN];
    -
    -       bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    -
    -       if (err) {
    -               printk("Failed to connect to %s (%u)\n", addr, err);
    -
    -               bt_conn_unref(default_conn);
    -               default_conn = NULL;
    -
    -               start_scan();
    -               return;
    -       }
    -
    -       if (conn != default_conn) {
    -               return;
    -       }
    -
    -       printk("Connected: %s\n", addr);
    -
    -       bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
    -}
    -
    -static void disconnected(struct bt_conn *conn, uint8_t reason)
    -{
    -       char addr[BT_ADDR_LE_STR_LEN];
    -
    -       if (conn != default_conn) {
    -               return;
    -       }
    -
    -       bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    -
    -       printk("Disconnected: %s (reason 0x%02x)\n", addr, reason);
    -
    -       bt_conn_unref(default_conn);
    -       default_conn = NULL;
    -
    -       start_scan();
    -}
    -
    -static struct bt_conn_cb conn_callbacks = {
    -               .connected = connected,
    -               .disconnected = disconnected,
    -};
    -
     void main(void)
     {
            int err;
    @@ -133,7 +57,7 @@ void main(void)
     
            printk("Bluetooth initialized\n");
     
    -       bt_conn_cb_register(&conn_callbacks);
    +       //bt_conn_cb_register(&conn_callbacks);
     
            start_scan();
     }

  • Thanks for your quick reply, this clears some things up. I am relatively new to BLE so happy to learn new things.

    I am still a bit confused about the term 'scanning', since in my project I had set CONFIG_BT_SCAN=y, but this has a direct dependency on BT_CENTRAL=y. 

    Do you know if I can still use the scanning module (https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/include/bluetooth/scan.html) in my project?

    Since I had build my scanning code around this module and now the code will no longer build. Should I just use

     

    bt_le_scan_start()
    bt_le_scan_stop()

    directly? Or do you have a better suggestion?

    Again, many thanks

  • Check out the sample I attached, where I use the function bt_le_scan_start() without enabling CONFIG_BT_SCAN or CONFIG_BT_CENTRAL. 

    The function bt_le_scan_start() is declared in zephyr/include/bluetooth/bluetooth.h (not scan.h) and defined in zephyr/subsys/bluetooth/host/scan.c.

    The file zephyr/subsys/bluetooth/host/scan.c is intergrated into the project due to CONFIG_BT_OBSERVER: https://github.com/nrfconnect/sdk-zephyr/blob/v2.6.0-rc1-ncs1/subsys/bluetooth/host/CMakeLists.txt#L44-L47

  • But the scan library is needed if one wants to use scan filters, and that library needs CONFIG_BT_SCAN, which again needs CONFIG_BT_CENTRAL, and then we are back again to the build assert in the CAF module ble_state.c. Would it be possible to change that build assert test. I am using ncs 2.0.0

    I posted a new issue on devzone for this:  CAF BLE state module build assert when CONFIG_BT_PERIPHERAL and CONFIG_BT_CENTRAL is set  

Related