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

AN36 modifications

I want to add to lbs service battery service(bas) as well. One of the changes is in the advertising_init() function:


static void advertising_init(void)
{
    uint32_t      err_code;
    ble_advdata_t advdata;
    uint8_t       flags = BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE;
    
    ble_uuid_t adv_uuids[] = 
    {
        {BLE_UUID_BATTERY_SERVICE, m_lbs.uuid_type},
        {LBS_UUID_SERVICE, m_lbs.uuid_type}
    };

    // 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;
    
    err_code = ble_advdata_set(&advdata, NULL);
    APP_ERROR_CHECK(err_code);
}

As a result I have NRF_ERROR_DATA_SIZE I did use blood pressure service as an example. What did I miss?

Thank you.

  • This is what I ended up with:

    
    static void advertising_init(void)
    {
        uint32_t      err_code;
        ble_advdata_t advdata, scanrsp;
        uint8_t       flags = BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE;
        
        // YOUR_JOB: Use UUIDs for service(s) used in your application.
        ble_uuid_t adv_uuids[] = 
        {
            {BLE_UUID_BATTERY_SERVICE, BLE_UUID_TYPE_BLE},
            {LBS_UUID_SERVICE, m_lbs.uuid_type}
        };
    
        // 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;
    
        memset(&scanrsp, 0, sizeof(scanrsp));
        scanrsp.uuids_complete.uuid_cnt = sizeof(adv_uuids) / sizeof(adv_uuids[0]);
        scanrsp.uuids_complete.p_uuids  = adv_uuids;
        
        err_code = ble_advdata_set(&advdata, &scanrsp);
        APP_ERROR_CHECK(err_code);
    }
    
    

    Does this mean that because of implementation of SD110 x.uuids_complete can not be splitted between advdata and scanrsp?

  • You can get any kind of advertisement and scan response data you want, by just using sd_ble_gap_adv_data_set() directly if ble_advdata doesn't allow you to do what you want. In that case, you must however do the parsing and data setup yourself.

    Based on my understanding of the spec however, I don't think it would normally be legal to have uuids_complete split between advertisement data and scan response. The reason is that each packet should be valid in itself, but if you have only some services in a field marked as uuid_complete, your field doesn't actually contain what the type implies. If you want to share the list between the packets, I'd therefore recommend you to use more_available.

    (In your case this is somewhat different, since you have one 128-bit UUID and one 16-bit UUID, so you could probably achieve what you want and be compliant by having the type of fields be different (see Core specification, Volume 3, Part C, table 18.2), but this seems to be a corner case.)

  • Dear Ole,

    Thank you very much for your help, support and patience. Could you please add more details and extend this paragraph:

    Based on my understanding of the spec however, I don't think it would normally be legal to have uuids_complete split between advertisement data and scan response. The reason is that each packet should be valid in itself, but if you have only some services in a field marked as uuid_complete, your field doesn't actually contain what the type implies. If you want to share the list between the packets, I'd therefore recommend you to use more_available.

    What confuses me is if I do have a proprietary device with some unique service(s) but also want to have same defined services like the battery, temperature, proximity. The list can become lengthy and may not fit, so how to do it the right way?

    Thank you.

  • Each field in the advertisement and scan response packets have a type, and when you use the complete UUID list as type, I'd say that you are required to actually have all services in this exact field. If you have one field in the advertisement packet which have the complete type, and one field in the scan response with the complete type, neither of them are actually complete, and I'd hence say that you don't fulfill the specification.

    This is exactly why you have the more available type, and are also not required to have all services in the advertisement packet. I'd normally recommend you to have the primary service of the device in the advertisement, and leave out all others. In some cases you may have multiple equally important services, and if so, you may need/want to split them between the advertisement and scan response, but then by using the more available type for both fields.

  • I need more time to read books/specs, examples of actual implementation and personal experience to digest what you've been saying... In any rate AN36 is a pretty good starting point and of course it could be and should be better but so far this is the best tutorial already. Hope that our discussion will help it to become even better.

    My regards, Boris.

Related