Advertising Payload format on BLE

This blog is to describe more details on the advertising payload.

The Packet data unit for the advertising channel (called the Advertising Channel PDU) includes a 2-byte header and a variable payload from 6 to 37 bytes. The actual length of the payload is defined by the 6-bit Length field in the header of the Advertising Channel PDU.

https://www.argenox.com/library/bluetooth-low-energy/ble-advertising-primer/

ble advertising payload format的图片搜寻结果

Flags Advertising Data Type

This packet has data type 0x01 indicating various flags. The length is 2 because there are two bytes, the data type and the actual flag value. The flag value has several bits indicating the capabilities of the iBeacon:

  • Bit 0 – Indicates LE Limited Discoverable Mode
  • Bit 1 – Indicates LE General Discoverable Mode
  • Bit 2 – Indicates whether BR/EDR is supported. This is used if your iBeacon is Dual Mode device
  • Bit 3 – Indicates whether LE and BR/EDR Controller operates simultaneously
  • Bit 4 – Indicates whether LE and BR/EDR Host operates simultaneously

Most iBeacons are single mode devices BR/EDR is not used. For iBeacons, General discoverability mode is used.

After Channel Selection Algorithm 2 (introduced at BT 5.0), the RFU would split into RFU and ChSel.

ble advertising payload format的图片搜寻结果

Scan Response

The advertisement packet has 31 data bytes available for you to use. Due to the limited payload of the Advertising particular on the 128-bit UUID, you can choose to use scan responses. Scan response would have extra 31 data bytes available.

The Scan Response packet has the same packet format as the advertisement, with the exception of the type on the higher layer indicating it’s a scan response instead of an advertisement. So your scan response can provide the device name or other services you didn’t mention in the advertising packet.

Core Specification Supplement

This part defines the basic data types used for Extended Inquiry Response (EIR), Advertising Data (AD), Scan Response Data (SRD), Additional Controller Advertising Data (ACAD), and OOB data blocks. Additional data types may be defined in profile specifications.

Corresponding GAP Advertising and Scan Response Data format in ble_gap.h

EXAMPLES on some common used GAP advertising data format

This example is to fill up advertising payload with Manufacturer specific data (maximum length = 0x25). All the others such as device name, 128 uuid , TX power can be filled up at the scan response payload.

Advertising Data (Flags)

LengthData TypeAdvertising Mode
0x020x010x06 (00000110B)

Manufacturer Specify Data

LengthData TypeCompany IDManufacturer Specific Data
0x1B (27)0xFF0x00590x0001C0111111CC64F00A0B0C0D0E0F101112131415161718
Manufacturer Specific Data (offset)TypeValue / Data
0Header of Manufacturer Payload0x01
1-7MAC Address0xCC, 0x11, 0x11, 0x11, 0x11, 0xC0
8Battery Value in %0x64 (100%)
9Measured RSSI Value0xF0
10 – 24Other Value0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
0x16, 0x17, 0x18

TX Power

LengthData TypeTX Power Level
020x0A0xFC (-4 dBm)

Slave Connection Interval Range

LengthData TypeMinimumMaximum
0x050x120x0006 (7.5ms)0x0014 (25ms)

Service UUIDs (Complete UUID 128 bit)

LengthData TypeUUID
0x11 (17)0x070x6E400001-B5A3-F393-E0A9-E50E24DCCA9E

Scan Response Data with UUID 128 bit (NUS)

Device Name

LengthData TypeComplete Local Name
0x0C (12)0x09Nordic_UART (0x4E6F726469635F55415254)

Without using the ble_advertising module (reduce the RAM / FLASH size usage), we can directly call the softdevice device API to set up the advertising payload.

static void advertising_init(void)
{
        uint32_t err_code;
        uint16_t len_advdata = BLE_GAP_ADV_MAX_SIZE;
        uint16_t len_scandata = BLE_GAP_ADV_MAX_SIZE;

        ble_gap_addr_t device_mac_addr;

        uint16_t actual_device_name_length = MAXIMUM_DEVICE_NAME_LENGTH;

        m_hardcode_enc_advdata[0] = 0x02;
        m_hardcode_enc_advdata[1] = BLE_GAP_AD_TYPE_FLAGS;
        m_hardcode_enc_advdata[2] = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
        m_hardcode_enc_advdata[3] = 0x1B; // Maximum payload of the manufacturer specific data
        m_hardcode_enc_advdata[4] = BLE_GAP_AD_TYPE_MANUFACTURER_SPECIFIC_DATA;
        m_hardcode_enc_advdata[5] = 0x59; // Company Identier
        m_hardcode_enc_advdata[6] = 0x00;
        m_hardcode_enc_advdata[7] = APP_MANU_HEADER;
       
        err_code = sd_ble_gap_addr_get(&device_mac_addr);
        APP_ERROR_CHECK(err_code);

        memcpy(&m_hardcode_enc_advdata[8], device_mac_addr.addr, BLE_GAP_ADDR_LEN);
        if (strlen(DEVICE_NAME) > MAXIMUM_DEVICE_NAME_LENGTH)
        {
            NRF_LOG_ERROR("Length of device name %s is exceeded the limit %d", (char *)DEVICE_NAME,  MAXIMUM_DEVICE_NAME_LENGTH);
            APP_ERROR_CHECK(NRF_ERROR_INVALID_PARAM);
        }
        /* Get GAP device name and length. */
        m_hardcode_enc_scandata[0] = 0x11;  /* length = 17 , UUID 128 */
        m_hardcode_enc_scandata[1] = BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_COMPLETE; 

        memcpy(&m_hardcode_enc_scandata[2], nus_base_uuid, sizeof(nus_base_uuid));
        len_scandata = 2 + sizeof(nus_base_uuid);
        err_code = sd_ble_gap_device_name_get(&m_hardcode_enc_scandata[20], &actual_device_name_length);
        APP_ERROR_CHECK(err_code);
        m_hardcode_enc_scandata[18] = actual_device_name_length+1;
        m_hardcode_enc_scandata[19] = BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME;
        len_scandata += 2 + actual_device_name_length;

        //err_code = sd_ble_gap_adv_data_set(m_enc_advdata, len_advdata, NULL, 0);
        err_code = sd_ble_gap_adv_data_set(m_hardcode_enc_advdata, len_advdata, m_hardcode_enc_scandata, len_scandata);
        APP_ERROR_CHECK(err_code);
}

static uint32_t advertising_start(void)
{

        uint32_t err_code;
        ble_gap_adv_params_t adv_params =
            {
                .type = BLE_GAP_ADV_TYPE_ADV_IND,
                .p_peer_addr = NULL,
                .fp = BLE_GAP_ADV_FP_ANY,
                .interval = APP_ADV_INTERVAL,
                .timeout = APP_ADV_TIMEOUT_IN_SECONDS,
            };

        err_code = sd_ble_gap_adv_start(&adv_params, APP_BLE_CONN_CFG_TAG);
        APP_ERROR_CHECK(err_code);

        return err_code;
}

2 thoughts on “Advertising Payload format on BLE

  1. Usually I don’t learn post on blogs, but I would
    like to say that this write-up very pressured me to check
    out and do so! Your writing taste has been amazed me. Thanks, quite nice post.

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.