bt_le_scan of node in Mesh network


Martin <ma@...>
 

Hi,
I am wondering if (and how) it is possible to fire off a bt_le_scan
(scan for nearby devices) from a Zephyr OS device which is a node in a
BLE mesh network at the same time.
From my current research I have found out that timing possibly is
important (and that Nordic provides a Timeslot API), but I did not
find a timing API or suchlike in the Zephyr OS documentation..

Could someone point me into the right direction?

Thanks!
Martin


Chettimada, Vinayak Kariappa
 

Hi Martin,

Adding Johan.

The controller does not support multiple scan state instances. This is something in the works.

Mesh stack implementation utilizes standard BT 4.0+ controller features, and no proprietary implementations are present in Zephyr.

That said, there are plans to add Mesh vendor specific extensions, some investigatory work was done before but postposed for later implementation:
https://github.com/zephyrproject-rtos/zephyr/pull/5500

Regards,
Vinayak

-----Original Message-----
From: <devel@...> on behalf of Martin <ma@...>
Date: Friday, 12 October 2018 at 2:44 PM
To: "devel@..." <devel@...>
Subject: [Zephyr-devel] bt_le_scan of node in Mesh network

Hi,
I am wondering if (and how) it is possible to fire off a bt_le_scan
(scan for nearby devices) from a Zephyr OS device which is a node in a
BLE mesh network at the same time.
From my current research I have found out that timing possibly is
important (and that Nordic provides a Timeslot API), but I did not
find a timing API or suchlike in the Zephyr OS documentation..

Could someone point me into the right direction?

Thanks!
Martin


Julian, LEDCity.ch
 

Hi Martin,
We needed the same functionality that you are describing.

After some analysis of the BT Mesh subsystem in the Zephryr, we came to the same conclusion as Vinayak. The Mesh system is using the BT 4 features to receive packages itself, i.e. the Mesh subsystem starts scanning with bt_le_scan on initialization and registeres its own callback (bt_mesh_scan_cb in Zephyr/subsys/bluetooth/host/mesh/adv.c). The system does not allow a second (concurrent) call of bt_le_scan.

Hence, the only option is a small adaptation of  the Zephyr source.
The Mesh scan callback only recognises Mesh specific scan packages and ignores the rest. Introducing an extra callback enabled us to receive all scan packages that are ignored by Mesh (see code snipped below).

Best,
Julian

Here is a code snippet of our adaptations of adv.c starting on line 253:
///////////////////changes here
//callback function pointer to be set from project code
void (*bt_mesh_scan_unprocressed_nonconn_ad_cb)(const bt_addr_le_t *addr, s8_t rssi,
        struct net_buf_simple *buf, u8_t type_from_buf, u8_t data_len) = NULL;
/////////////////

static void bt_mesh_scan_cb(const bt_addr_le_t *addr, s8_t rssi,
                u8_t adv_type, struct net_buf_simple *buf)
{
    if (adv_type != BT_LE_ADV_NONCONN_IND) {
        return;
    }

    BT_DBG("len %u: %s", buf->len, bt_hex(buf->data, buf->len));

    while (buf->len > 1) {
        struct net_buf_simple_state state;
        u8_t len, type;

        len = net_buf_simple_pull_u8(buf);
        /* Check for early termination */
        if (len == 0) {
            return;
        }

        if (len > buf->len) {
            BT_WARN("AD malformed");
            return;
        }

        net_buf_simple_save(buf, &state);

        type = net_buf_simple_pull_u8(buf);

        buf->len = len - 1;

        switch (type) {
        case BT_DATA_MESH_MESSAGE:
            bt_mesh_net_recv(buf, rssi, BT_MESH_NET_IF_ADV);
            break;
#if defined(CONFIG_BT_MESH_PB_ADV)
        case BT_DATA_MESH_PROV:
            bt_mesh_pb_adv_recv(buf);
            break;
#endif
        case BT_DATA_MESH_BEACON:
            bt_mesh_beacon_recv(buf);
            break;
///////////////////changes here
        default:
            if (bt_mesh_scan_unprocressed_nonconn_ad_cb != NULL)       
                bt_mesh_scan_unprocressed_nonconn_ad_cb(addr,rssi,buf,type,len-1);
            break;
/////////////////
        }

        net_buf_simple_restore(buf, &state);
        net_buf_simple_pull(buf, len);
    }
}


Martin <ma@...>
 

Hi!
Thanks, this looks exactly like what I was looking for. Even seems to
be easier than the NRF52 SDK-approach with the timing API.

Best Regards,
Martin
Am Mo., 15. Okt. 2018 um 08:25 Uhr schrieb <julian.schneider@...>:


Hi Martin,
We needed the same functionality that you are describing.

After some analysis of the BT Mesh subsystem in the Zephryr, we came to the same conclusion as Vinayak. The Mesh system is using the BT 4 features to receive packages itself, i.e. the Mesh subsystem starts scanning with bt_le_scan on initialization and registeres its own callback (bt_mesh_scan_cb in Zephyr/subsys/bluetooth/host/mesh/adv.c). The system does not allow a second (concurrent) call of bt_le_scan.

Hence, the only option is a small adaptation of the Zephyr source.
The Mesh scan callback only recognises Mesh specific scan packages and ignores the rest. Introducing an extra callback enabled us to receive all scan packages that are ignored by Mesh (see code snipped below).

Best,
Julian

Here is a code snippet of our adaptations of adv.c starting on line 253:
///////////////////changes here
//callback function pointer to be set from project code
void (*bt_mesh_scan_unprocressed_nonconn_ad_cb)(const bt_addr_le_t *addr, s8_t rssi,
struct net_buf_simple *buf, u8_t type_from_buf, u8_t data_len) = NULL;
/////////////////

static void bt_mesh_scan_cb(const bt_addr_le_t *addr, s8_t rssi,
u8_t adv_type, struct net_buf_simple *buf)
{
if (adv_type != BT_LE_ADV_NONCONN_IND) {
return;
}

BT_DBG("len %u: %s", buf->len, bt_hex(buf->data, buf->len));

while (buf->len > 1) {
struct net_buf_simple_state state;
u8_t len, type;

len = net_buf_simple_pull_u8(buf);
/* Check for early termination */
if (len == 0) {
return;
}

if (len > buf->len) {
BT_WARN("AD malformed");
return;
}

net_buf_simple_save(buf, &state);

type = net_buf_simple_pull_u8(buf);

buf->len = len - 1;

switch (type) {
case BT_DATA_MESH_MESSAGE:
bt_mesh_net_recv(buf, rssi, BT_MESH_NET_IF_ADV);
break;
#if defined(CONFIG_BT_MESH_PB_ADV)
case BT_DATA_MESH_PROV:
bt_mesh_pb_adv_recv(buf);
break;
#endif
case BT_DATA_MESH_BEACON:
bt_mesh_beacon_recv(buf);
break;
///////////////////changes here
default:
if (bt_mesh_scan_unprocressed_nonconn_ad_cb != NULL)
bt_mesh_scan_unprocressed_nonconn_ad_cb(addr,rssi,buf,type,len-1);
break;
/////////////////
}

net_buf_simple_restore(buf, &state);
net_buf_simple_pull(buf, len);
}
}