Nordic BLE Advertising Part I
Nordic has a good tutorial Bluetooth low energy Advertising, a beginner’s tutorial, and two guides of GAP advertising Part I and Part II. In this post, we will go through some of advertising features in details.
Device Name
In every Nordic example, the device name is a defined by define DEVICE_NAME
in
the code. There has been many posts (here) about how to change the device name.
However, the simplest I found was using the advertising module from this post,
only two steps:
- Set the new device name with
sd_ble_gap_device_name_set()
, - Call
ble_advertising_advdata_update()
to update the name part of the advertising packet.
The write permissions are set to the variable sec_mode using the
BLE_GAP_CONN_SEC_MODE_SET_OPEN()
macro. You many want to stop advertising
first to be safe, however, I have found that there’s no issue to just do it with
stop/restart. To make it even simpler, let advdata and srdata be global
variable, so you can update it anywhere including inside advertising_init()
and
don’t need to rebuild either data structure. There are, however, limitations
on the length of the device name.
TX Power
There are two aspects of TX power, one is for advertising to show TX power value, the other is to change the TX radio power. Though they are aligned in most cases, they have to be set individually.
To set advertising TX power, set m_advdata.p_tx_power_level = &m_tx_power
in
advertising_init()
or anywhere you wish to change. If it’s not in initialization,
then call ble_advertising_advdata_update()
again so it will appear in the
advertising packet. It comes handy if you already set advdata to global so
the internal buffer is there to be easily modified.
To set TX power of the radio, call sd_ble_gap_tx_power_set
function with a handle as described in this post:
- For advertising BLE_GAP_TX_POWER_ROLE_ADV, call
advertising_int()
first, so theadv_handle
is not empty:
sd_ble_gap_tx_power_set(BLE_GAP_TX_POWER_ROLE_ADV, m_advertising.adv_handle, level);
- For scanning BLE_GAP_TX_POWER_ROLE_SCAN_INIT, the connection handle is ignored:
sd_ble_gap_tx_power_set(BLE_GAP_TX_POWER_ROLE_ADV, BLE_CONN_HANDLE_INVALID, level);
- For connection BLE_GAP_TX_POWER_ROLE_CONN, use the specific connection handle from the connected event, which
can be found in
on_ble_evt()
function.
sd_ble_gap_tx_power_set(BLE_GAP_TX_POWER_ROLE_ADV, p_ble_evt->evt.gap_evt.conn_handle, level);
If nothing changed when a connection is established, the TX power during connection will inherit the power used in advertising or scanning.
UUID
In the service tutorial there’s a good section about the Universally Unique Identifier (UUID). There are two types, a short 16-bit Bluetooth SIG predefined UUID and a 128-bit vendor specific UUID for custom services and characteristics. One way to create a custom one is to use a random generator. In Nordic SDK, these two types are BLE_UUID_TYPE_BLE and BLE_UUID_TYPE_VENDOR_BEGIN.
You can add multiple services in the services_init()
method, we can also
include one (so that other services can be discovered once connected) or multiple
UUIDs (predefined or vendor specific) in the advertising packet. One thing
to pay attention to is the order they’ve been added, otherwise the advertising
services may get mixed up (see here and here).
Inside the function services_init()
, each service initialized and added to the
stack by sd_ble_uuid_vs_add()
, which normally resides in each service file. Then,
the main
calls the advertising_init()
to add each service UUIDs to the advertising
packet. For the advertised UUIDs correspond to the actual services, you have to
make sure each UUID points to the right sercie in the stack, e.g., if you have three
services DFU, our_service, and NUS initialized in this order in services_init()
,
you will need to specify them correspondingly:
static ble_uuid_t m_adv_uuids[] =
{
{BLE_UUID_OUR_SERVICE, BLE_UUID_TYPE_VENDOR_BEGIN+1},
{BLE_UUID_NUS_SERVICE, BLE_UUID_TYPE_VENDOR_BEGIN+2},
{BLE_UUID_DEVICE_INFORMATION_SERVICE, BLE_UUID_TYPE_BLE}
};
The TYPE is to tell if it’s a predefined or a vendor specific UUID, but they
all point to the first base UUID. In this case the first one is DFU, the second is
OUR_SERVICE and the third is NUS_SERVICE, thus BLE_UUID_TYPE_VENDOR_BEGIN+1
and BLE_UUID_TYPE_VENDOR_BEGIN+2
respectively.