This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

service data advertisement and 128 uuid

Hi,

I searched through the devzone but I cannot find a answer on this question but the question has been asked before. Some background. I have a working solution from another vendor and I want to switch to Nordic. In this solution I use service data to advertise our product including some data about the product. I am now looking in the SDK to see how I can implement this with Nordic. Ok, so the ble_advdata_service_data_t structure needs a uint16_t for de uuid. I use 128 bits uuid's. I can add them with sd_ble_uuid_vs_add. This returns a UUID type. Now the question is. How do I match the UUID type return from sd_ble_uuid_vs_add to the service_uuid field in ble_advdata_service_data_t structure.

Cheers, Marcel

Parents
  • FormerMember
    0 FormerMember

    In order to add "Service data" with 128 bit UUID to the advertising data, a few modifications to the code in the SDK has to be made. Below are the modifications I did. I used SDK 7.1.0, and tested with ble_app_hrs.

    Note 1: This is not a general solution, it just shows how "service data" with a 128 bit UUID can be added.

    Note 2: remember that 31 bytes is the maximum payload in an advertising packet.

    ble_advdata.h: ble_advdata_service_data_t has to be modified to handle 128 bit UUID:

    /**@brief Service data structure. */
    typedef struct
    {
        ble_uuid128_t                  service_uuid;                  /**< Service UUID. */ 
        uint8_array_t                  data;                          /**< Additional service data. */
    } ble_advdata_service_data_t;
    

    app_util.h: An encoding function for a 128 bit UUID has to be added:

    /**@brief Function for encoding a 128 bit UUID value.
     *
     * @param[in]   value            Value to be encoded.
     * @param[out]  p_encoded_data   Buffer where the encoded data is to be written.
     *
     * @return      Number of bytes written.
     */
    
    static __INLINE uint8_t uint128_encode(ble_uuid128_t value, uint8_t * p_encoded_data)
    {
        p_encoded_data[0] =  (uint8_t) value.uuid128[0];
        p_encoded_data[1] =  (uint8_t) value.uuid128[1];
        p_encoded_data[2] =  (uint8_t) value.uuid128[2];
        p_encoded_data[3] =  (uint8_t) value.uuid128[3];
        p_encoded_data[4] =  (uint8_t) value.uuid128[4];
        p_encoded_data[5] =  (uint8_t) value.uuid128[5];
        p_encoded_data[6] =  (uint8_t) value.uuid128[6];
        p_encoded_data[7] =  (uint8_t) value.uuid128[7];
        p_encoded_data[8] =  (uint8_t) value.uuid128[8];
        p_encoded_data[9] =  (uint8_t) value.uuid128[9];
        p_encoded_data[10] = (uint8_t) value.uuid128[10];
        p_encoded_data[11] = (uint8_t) value.uuid128[11];
        p_encoded_data[12] = (uint8_t) value.uuid128[12];
        p_encoded_data[13] = (uint8_t) value.uuid128[13];
        p_encoded_data[14] = (uint8_t) value.uuid128[14];
        p_encoded_data[15] = (uint8_t) value.uuid128[15];
    
        return 16;
    }
    

    ble_advdata.c: The service_data_encode(..) function has to be modified to encode the 128 bit UUID.

     static uint32_t service_data_encode(const ble_advdata_t * p_advdata,
                                        uint8_t             * p_encoded_data,
                                        uint8_t             * p_len)
    {
        uint8_t i;
    
        // Check parameter consistency.
        if (p_advdata->p_service_data_array == NULL)
        {
            return NRF_ERROR_INVALID_PARAM;
        }
    
        for (i = 0; i < p_advdata->service_data_count; i++)
        {
            ble_advdata_service_data_t * p_service_data;
            uint8_t                      data_size;
    
            p_service_data = &p_advdata->p_service_data_array[i];
            data_size      = 16 + p_service_data->data.size; // sizeof(uint16_le_t) + p_service_data->data.size;
    
            // Encode Length and AD Type.
            p_encoded_data[(*p_len)++] = 1 + data_size;
            p_encoded_data[(*p_len)++] = BLE_GAP_AD_TYPE_SERVICE_DATA_128BIT_UUID; //BLE_GAP_AD_TYPE_SERVICE_DATA;
    
            // Encode service UUID.
            //(*p_len) += uint16_encode(p_service_data->service_uuid, &p_encoded_data[*p_len]);
        
            (*p_len) += uint128_encode(p_service_data->service_uuid, &p_encoded_data[*p_len]); // added for encoding of 128 bit uuid.
        
            // Encode additional service data.
            if (p_service_data->data.size > 0)
            {
                if (p_service_data->data.p_data == NULL)
                {
                    return NRF_ERROR_INVALID_PARAM;
                }
                memcpy(&p_encoded_data[*p_len], p_service_data->data.p_data, p_service_data->data.size);
                (*p_len) += p_service_data->data.size;
            }
        }
    
        return NRF_SUCCESS;
    }
    

    main.c: I made the device name short and added "service data" in advertising_init(..):

    In order to make sure that the advertising data didn't exceed 31 bytes, I change the device name to something short:

    #define DEVICE_NAME                          "H"         
    

    I changed advertising_init(..) to the following:

    /**@brief Function for initializing the Advertising functionality.
     *
     * @details Encodes the required advertising data and passes it to the stack.
     *          Also builds a structure to be passed to the stack when starting advertising.
     */
    static void advertising_init(void)
    {
        uint32_t      err_code;
        ble_advdata_t advdata;
        uint8_t       flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
    
        uint8_t       service_data[3] = {1,2,3};
        uint8_t       service_data_len = sizeof(service_data)/sizeof(service_data[0]);
    
     
         ble_uuid128_t   service128bit_uuid = {{0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00, 0x11,
                                     0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99}};                                 
                                     
        ble_advdata_service_data_t service_data_struct;
    
        ble_uuid_t adv_uuids[] =
        {
            {BLE_UUID_HEART_RATE_SERVICE,         BLE_UUID_TYPE_BLE},
            {BLE_UUID_BATTERY_SERVICE,            BLE_UUID_TYPE_BLE},
            {BLE_UUID_DEVICE_INFORMATION_SERVICE, BLE_UUID_TYPE_BLE}
        };
    
        // Build and set advertising data.
        memset(&advdata, 0, sizeof(advdata));
    
        advdata.name_type               = BLE_ADVDATA_FULL_NAME;
        advdata.include_appearance      = true;
        advdata.flags.size              = sizeof(flags);
        advdata.flags.p_data            = &flags;
        //advdata.uuids_complete.uuid_cnt = sizeof(adv_uuids) / sizeof(adv_uuids[0]);
        //advdata.uuids_complete.p_uuids  = adv_uuids;
    
        advdata.p_service_data_array = &service_data_struct;    
        advdata.p_service_data_array->service_uuid = service128bit_uuid;
        advdata.p_service_data_array->data.p_data = service_data;
        advdata.p_service_data_array->data.size   = service_data_len;
        advdata.service_data_count = 1;
    
        err_code = ble_advdata_set(&advdata, NULL);
        APP_ERROR_CHECK(err_code);
    
        // Initialize advertising parameters (used when starting advertising).
        memset(&m_adv_params, 0, sizeof(m_adv_params));
    
        m_adv_params.type        = BLE_GAP_ADV_TYPE_ADV_IND;
        m_adv_params.p_peer_addr = NULL;                           // Undirected advertisement.
        m_adv_params.fp          = BLE_GAP_ADV_FP_ANY;
        m_adv_params.interval    = APP_ADV_INTERVAL;
        m_adv_params.timeout     = APP_ADV_TIMEOUT_IN_SECONDS;
    }
    
Reply
  • FormerMember
    0 FormerMember

    In order to add "Service data" with 128 bit UUID to the advertising data, a few modifications to the code in the SDK has to be made. Below are the modifications I did. I used SDK 7.1.0, and tested with ble_app_hrs.

    Note 1: This is not a general solution, it just shows how "service data" with a 128 bit UUID can be added.

    Note 2: remember that 31 bytes is the maximum payload in an advertising packet.

    ble_advdata.h: ble_advdata_service_data_t has to be modified to handle 128 bit UUID:

    /**@brief Service data structure. */
    typedef struct
    {
        ble_uuid128_t                  service_uuid;                  /**< Service UUID. */ 
        uint8_array_t                  data;                          /**< Additional service data. */
    } ble_advdata_service_data_t;
    

    app_util.h: An encoding function for a 128 bit UUID has to be added:

    /**@brief Function for encoding a 128 bit UUID value.
     *
     * @param[in]   value            Value to be encoded.
     * @param[out]  p_encoded_data   Buffer where the encoded data is to be written.
     *
     * @return      Number of bytes written.
     */
    
    static __INLINE uint8_t uint128_encode(ble_uuid128_t value, uint8_t * p_encoded_data)
    {
        p_encoded_data[0] =  (uint8_t) value.uuid128[0];
        p_encoded_data[1] =  (uint8_t) value.uuid128[1];
        p_encoded_data[2] =  (uint8_t) value.uuid128[2];
        p_encoded_data[3] =  (uint8_t) value.uuid128[3];
        p_encoded_data[4] =  (uint8_t) value.uuid128[4];
        p_encoded_data[5] =  (uint8_t) value.uuid128[5];
        p_encoded_data[6] =  (uint8_t) value.uuid128[6];
        p_encoded_data[7] =  (uint8_t) value.uuid128[7];
        p_encoded_data[8] =  (uint8_t) value.uuid128[8];
        p_encoded_data[9] =  (uint8_t) value.uuid128[9];
        p_encoded_data[10] = (uint8_t) value.uuid128[10];
        p_encoded_data[11] = (uint8_t) value.uuid128[11];
        p_encoded_data[12] = (uint8_t) value.uuid128[12];
        p_encoded_data[13] = (uint8_t) value.uuid128[13];
        p_encoded_data[14] = (uint8_t) value.uuid128[14];
        p_encoded_data[15] = (uint8_t) value.uuid128[15];
    
        return 16;
    }
    

    ble_advdata.c: The service_data_encode(..) function has to be modified to encode the 128 bit UUID.

     static uint32_t service_data_encode(const ble_advdata_t * p_advdata,
                                        uint8_t             * p_encoded_data,
                                        uint8_t             * p_len)
    {
        uint8_t i;
    
        // Check parameter consistency.
        if (p_advdata->p_service_data_array == NULL)
        {
            return NRF_ERROR_INVALID_PARAM;
        }
    
        for (i = 0; i < p_advdata->service_data_count; i++)
        {
            ble_advdata_service_data_t * p_service_data;
            uint8_t                      data_size;
    
            p_service_data = &p_advdata->p_service_data_array[i];
            data_size      = 16 + p_service_data->data.size; // sizeof(uint16_le_t) + p_service_data->data.size;
    
            // Encode Length and AD Type.
            p_encoded_data[(*p_len)++] = 1 + data_size;
            p_encoded_data[(*p_len)++] = BLE_GAP_AD_TYPE_SERVICE_DATA_128BIT_UUID; //BLE_GAP_AD_TYPE_SERVICE_DATA;
    
            // Encode service UUID.
            //(*p_len) += uint16_encode(p_service_data->service_uuid, &p_encoded_data[*p_len]);
        
            (*p_len) += uint128_encode(p_service_data->service_uuid, &p_encoded_data[*p_len]); // added for encoding of 128 bit uuid.
        
            // Encode additional service data.
            if (p_service_data->data.size > 0)
            {
                if (p_service_data->data.p_data == NULL)
                {
                    return NRF_ERROR_INVALID_PARAM;
                }
                memcpy(&p_encoded_data[*p_len], p_service_data->data.p_data, p_service_data->data.size);
                (*p_len) += p_service_data->data.size;
            }
        }
    
        return NRF_SUCCESS;
    }
    

    main.c: I made the device name short and added "service data" in advertising_init(..):

    In order to make sure that the advertising data didn't exceed 31 bytes, I change the device name to something short:

    #define DEVICE_NAME                          "H"         
    

    I changed advertising_init(..) to the following:

    /**@brief Function for initializing the Advertising functionality.
     *
     * @details Encodes the required advertising data and passes it to the stack.
     *          Also builds a structure to be passed to the stack when starting advertising.
     */
    static void advertising_init(void)
    {
        uint32_t      err_code;
        ble_advdata_t advdata;
        uint8_t       flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
    
        uint8_t       service_data[3] = {1,2,3};
        uint8_t       service_data_len = sizeof(service_data)/sizeof(service_data[0]);
    
     
         ble_uuid128_t   service128bit_uuid = {{0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00, 0x11,
                                     0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99}};                                 
                                     
        ble_advdata_service_data_t service_data_struct;
    
        ble_uuid_t adv_uuids[] =
        {
            {BLE_UUID_HEART_RATE_SERVICE,         BLE_UUID_TYPE_BLE},
            {BLE_UUID_BATTERY_SERVICE,            BLE_UUID_TYPE_BLE},
            {BLE_UUID_DEVICE_INFORMATION_SERVICE, BLE_UUID_TYPE_BLE}
        };
    
        // Build and set advertising data.
        memset(&advdata, 0, sizeof(advdata));
    
        advdata.name_type               = BLE_ADVDATA_FULL_NAME;
        advdata.include_appearance      = true;
        advdata.flags.size              = sizeof(flags);
        advdata.flags.p_data            = &flags;
        //advdata.uuids_complete.uuid_cnt = sizeof(adv_uuids) / sizeof(adv_uuids[0]);
        //advdata.uuids_complete.p_uuids  = adv_uuids;
    
        advdata.p_service_data_array = &service_data_struct;    
        advdata.p_service_data_array->service_uuid = service128bit_uuid;
        advdata.p_service_data_array->data.p_data = service_data;
        advdata.p_service_data_array->data.size   = service_data_len;
        advdata.service_data_count = 1;
    
        err_code = ble_advdata_set(&advdata, NULL);
        APP_ERROR_CHECK(err_code);
    
        // Initialize advertising parameters (used when starting advertising).
        memset(&m_adv_params, 0, sizeof(m_adv_params));
    
        m_adv_params.type        = BLE_GAP_ADV_TYPE_ADV_IND;
        m_adv_params.p_peer_addr = NULL;                           // Undirected advertisement.
        m_adv_params.fp          = BLE_GAP_ADV_FP_ANY;
        m_adv_params.interval    = APP_ADV_INTERVAL;
        m_adv_params.timeout     = APP_ADV_TIMEOUT_IN_SECONDS;
    }
    
Children
Related