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

Custom Service Data UUID

Hi!

I am trying to add service data to my scan response service data for a custom service. I am unsure of how to set the UUID correctly for this.

UUID declaration:

#define TIMECODE_SERVICE_UUID_BASE                 \
  { 0x8B, 056, 0x74, 0xC2, 0x14, 0x2D, 0xFA, 0xA4, \
    0x94, 0x41, 0x73, 0x30, 0xDA, 0x19, 0xE1, 0x3F }

#define TIMECODE_SERVICE_UUID 0x01
#define TIMECODE_DEVICE_NAME_CHARACTERISTIC_UUID 0x02

Where I set the UUID for the service:

  // Add Custom Service UUID
  ble_uuid128_t base_uuid = {TIMECODE_SERVICE_UUID_BASE};
  err_code = sd_ble_uuid_vs_add(&base_uuid, &p_timecode_service->uuid_type);
  VERIFY_SUCCESS(err_code);

  ble_uuid.type = p_timecode_service->uuid_type;
  ble_uuid.uuid = TIMECODE_SERVICE_UUID;

  // Add the Custom Service
  err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &ble_uuid, &p_timecode_service->service_handle);
  VERIFY_SUCCESS(err_code);

Setting the response service data:

  static ble_advdata_t new_response_data;
  ble_advdata_service_data_t service_data;
  uint8_array_t data_array;

  uint8_t data[] = {device_state_flags, device_state_color};

  data_array.p_data = data;
  data_array.size = sizeof(data);

  service_data.service_uuid = TIMECODE_SERVICE_UUID;
  service_data.data = data_array;

  memset(&new_response_data, 0, sizeof(new_response_data));
  new_response_data.p_service_data_array = &service_data;
  new_response_data.service_data_count = 1;

  err_code = ble_advertising_advdata_update(&m_advertising, &new_advertising_data, &new_response_data);
  APP_ERROR_CHECK(err_code);

This runs correctly, but the service UUID in the service data is the exact same as "TIMECODE_SERVICE_UUID" (0x0001). How do I combine this with the base UUID to set it to the actual service UUID (3fe10001-3073-4194-a4fa-2d14c2742e8b)? I've tried searching the documentation as well as these help forms and haven't found anything that is different from what I'm currently doing.

  • Hi,

    Note that the service UUID is formed by the UUID base, but byte 13 and 14 of the UUID is formed by the 2 bytes of the service UUID.

    E.g. for the NUS service,
    The BASE is {{0x9E, 0xCA, 0xDC, 0x24, 0x0E, 0xE5, 0xA9, 0xE0, 0x93, 0xF3, 0xA3, 0xB5, 0x00, 0x00, 0x40, 0x6E}} 
    and the 2 byte UUID for the NUS service is 0x0001

    The complete NUS service UUID will then be 0x9E, 0xCA, 0xDC, 0x24, 0x0E, 0xE5, 0xA9, 0xE0, 0x93, 0xF3, 0xA3, 0xB5, 0x01, 0x00, 0x40, 0x6E

    Byte 13 and 14 in your TIMECODE_SERVICE_UUID_BASE, "0xDA, 0x19,", is therefore ignored.

    Also note that in your TIMECODE_SERVICE_UUID_BASE, your second byte, 056, is not defined as hex value.

  • Thanks , good catch with the 056 -> 0x56. :)

    Sorry, I don't think I phrased my question correctly. I'm aware that the base ID is the base for all bytes except 13 and 14 bytes, which are replaced by the two bytes for each specific service or characteristic (in my case TIMECODE_SERVICE_UUID, though I now realize from your example that I should be setting it to 0x0001 for consistency). What I don't understand is how to pass that value to service_data.service_uuid.

    For example, with the code above, service_data.service_uuid = TIMECODE_SERVICE_UUID will return 00000001-0000-1000-8000-00805f9b34fb (according to the Bluetooth library on my phone app I am working on), the Bluetooth base ID with my TIMECODE_SERVICE_UUID (0x0001). I need it to be my custom service ID (3fe10001-3073-4194-a4fa-2d14c2742e8b, which is TIMECODE_SERVICE_UUID using TIMECODE_SERVICE_UUID_BASE as the base).

    Is this possible? Or am I misunderstanding how service data sends the ID (eg. it it always 2 bytes, as the expected value for p_service_data_array.service_uuid is uint16_t)? Or maybe the ID I posted above is how the app library I am using on my phone interprets the service ID in the service data?

  • When advertising what 128 bit service UUID you have, it's usually done like this (from ble_app_uart example), by putting it into the "Service UUID" field.

    static void advertising_init(void)
    {
        uint32_t               err_code;
        ble_advertising_init_t init;
    
        memset(&init, 0, sizeof(init));
    
        init.advdata.name_type          = BLE_ADVDATA_FULL_NAME;
        init.advdata.include_appearance = false;
        init.advdata.flags              = BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE;
    
        init.srdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);
        init.srdata.uuids_complete.p_uuids  = m_adv_uuids;
    
        init.config.ble_adv_fast_enabled  = true;
        init.config.ble_adv_fast_interval = APP_ADV_INTERVAL;
        init.config.ble_adv_fast_timeout  = APP_ADV_DURATION;
        init.evt_handler = on_adv_evt;
    
        err_code = ble_advertising_init(&m_advertising, &init);
        APP_ERROR_CHECK(err_code);
    
        ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG);
    }

    where

    static ble_uuid_t m_adv_uuids[]          =                                          /**< Universally unique service identifier. */
    {
        {BLE_UUID_NUS_SERVICE, NUS_SERVICE_UUID_TYPE}
    };

    You are instead trying to put your 128bit service UUID in the "Service Data" field.

    Looking at the Bluetooth Core Specification Supplement, this is described like this:

    Unfortunately, in the BLE advertising module in the SDK, we have only implemented support for 16-bit UUIDs when it comes to Service Data. Sorry for this inconvenience.

  • Thank you! I am already using what you showed (setting uuids_complete.p_uuids with my custom service ID).

    Unfortunately, in the BLE advertising module in the SDK, we have only implemented support for 16-bit UUIDs when it comes to Service Data. Sorry for this inconvenience.

    Ah thank you, that answers my question. I guess I should either use the manufacture data or just use the service data with a generic ID.

Related