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

How to create characteristics with different UUIDs?

Hi everyone,
my colleague developed a firmware using Arduino Nano 33 BLE and PlatformIO. Now I have to rewrite the code using Segger Embedded Studio. The problem is in the declaration of the characteristics of a service. There are in fact two characteristics that have different base UUIDs.

My colleague added these characteristics using the following code:

//Battery Service
BLEService Battery_service("72050700-df73-4f35-8e62-965e9d019cb3");

    BLEStringCharacteristic Battery_SerialID("72050701-df73-4f35-8e62-965e9d019cb3", BLERead, 17);
    BLEStringCharacteristic Battery_Hardware_rev("72050702-df73-4f35-8e62-965e9d019cb3", BLERead, 12);
    BLEStringCharacteristic Battery_Firmware_rev("72050703-df73-4f35-8e62-965e9d019cb3", BLERead, 12);
    BLEUnsignedCharCharacteristic Battery_charge("72050704-df73-4f35-8e62-965e9d019cb3", BLERead | BLENotify);
    BLEShortCharacteristic Battery_temperature("72050705-df73-4f35-8e62-965e9d019cb3", BLERead | BLENotify);
    BLEUnsignedCharCharacteristic Battery_health("72050706-df73-4f35-8e62-965e9d019cb3", BLERead);
    BLEUnsignedShortCharacteristic Battery_cycles("72050707-df73-4f35-8e62-965e9d019cb3", BLERead);
    BLEUnsignedCharCharacteristic Battery_warning("72050708-df73-4f35-8e62-965e9d019cb3", BLERead | BLEWrite);
    BLEUnsignedCharCharacteristic Battery_settings("72050709-df73-4f35-8e62-965e9d019cb3", BLERead | BLEWrite);

//Authentication Service
BLEService Autentication_service("00000001-0000-4f35-8e62-965e9d019cb3");

    BLEUnsignedShortCharacteristic KeyA("00000001-0001-4f35-8e62-965e9d019cb3", BLERead);
    BLEUnsignedShortCharacteristic KeyB("00000001-0002-4f35-8e62-965e9d019cb3", BLERead | BLEWrite);
...

//Battery Service --> Add Characteristics
Bluetooth::Battery_service.addCharacteristic(Battery_SerialID);
Bluetooth::Battery_service.addCharacteristic(Battery_Hardware_rev);
Bluetooth::Battery_service.addCharacteristic(Battery_Firmware_rev);
Bluetooth::Battery_service.addCharacteristic(Battery_charge);
Bluetooth::Battery_service.addCharacteristic(Battery_temperature);
Bluetooth::Battery_service.addCharacteristic(Battery_health);
Bluetooth::Battery_service.addCharacteristic(Battery_cycles);
Bluetooth::Battery_service.addCharacteristic(Battery_warning);
Bluetooth::Battery_service.addCharacteristic(Battery_settings);

//Authentication Service
Bluetooth::Autentication_service.addCharacteristic(KeyA);
Bluetooth::Autentication_service.addCharacteristic(KeyB);
    

I know well how to implement the battery service and its characteristics using Segger Embedded Studio.

In fact, the characteristics of the battery have a UUID that respects the 7205xxxx-df73-4f35-8e62-965e9d019cb3 structure. As indicated in this guide.

The authentication service, on the other hand, has two characteristics that do not respect the aforementioned structure.

How do I add these two characteristics?

Thanks so much.

Parents
  • Hello,

    I assume you are using the nRF5 SDK now? In that case, you will need to use sd_ble_uuid_vs_add() to add the base UUIDs for your characteristics. Below you can find a diff showing the changes I made to our UART service initialization (see UART/Serial Port Emulation over BLE) to make the RX characteristic have a different base UUID compared to the primary service.

    diff --git a/ble_nus.c b/ble_nus.c
    index ca77de6..b32772f 100644
    --- a/ble_nus.c
    +++ b/ble_nus.c
    @@ -244,12 +244,16 @@ void ble_nus_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context)
         }
     }
     
    +#define NUS_RX_BASE_UUID {0x80, 0xb9, 0xcb, 0x22, 0xd4, 0x47, 0x4b, 0x85, 0x8a, 0x4b, 0x88, 0x8e, 0x00, 0x00, 0x90, 0xf2}
    +
     
     uint32_t ble_nus_init(ble_nus_t * p_nus, ble_nus_init_t const * p_nus_init)
     {
         ret_code_t            err_code;
         ble_uuid_t            ble_uuid;
    +    uint8_t               uuid_tag;
         ble_uuid128_t         nus_base_uuid = NUS_BASE_UUID;
    +    ble_uuid128_t         nus_rx_base_uuid = NUS_RX_BASE_UUID;
         ble_add_char_params_t add_char_params;
     
         VERIFY_PARAM_NOT_NULL(p_nus);
    @@ -272,11 +276,15 @@ uint32_t ble_nus_init(ble_nus_t * p_nus, ble_nus_init_t const * p_nus_init)
                                             &p_nus->service_handle);
         /**@snippet [Adding proprietary Service to the SoftDevice] */
         VERIFY_SUCCESS(err_code);
    +    
    +
    +    err_code = sd_ble_uuid_vs_add(&nus_rx_base_uuid, &uuid_tag);
    +    VERIFY_SUCCESS(err_code);
     
         // Add the RX Characteristic.
         memset(&add_char_params, 0, sizeof(add_char_params));
         add_char_params.uuid                     = BLE_UUID_NUS_RX_CHARACTERISTIC;
    -    add_char_params.uuid_type                = p_nus->uuid_type;
    +    add_char_params.uuid_type                = uuid_tag;
         add_char_params.max_len                  = BLE_NUS_MAX_RX_CHAR_LEN;
         add_char_params.init_len                 = sizeof(uint8_t);
         add_char_params.is_var_len               = true;
    diff --git a/sdk_config.h b/sdk_config.h
    index 126fe8f..aa4b7ad 100644
    --- a/sdk_config.h
    +++ b/sdk_config.h
    @@ -11466,7 +11466,7 @@
     
     // <o> NRF_SDH_BLE_VS_UUID_COUNT - The number of vendor-specific UUIDs. 
     #ifndef NRF_SDH_BLE_VS_UUID_COUNT
    -#define NRF_SDH_BLE_VS_UUID_COUNT 1
    +#define NRF_SDH_BLE_VS_UUID_COUNT 2
     #endif
     
     // <q> NRF_SDH_BLE_SERVICE_CHANGED  - Include the Service Changed characteristic in the Attribute Table.

    Best regards,

    Vidar

  • Hi Vidar,
    thanks for your answer.
    I was able to reach my goal thanks to your help.
    I was able to add the characteristic but I can't read or write the characteristic. How do I enable reading and writing of the characteristic?
    I used the ble_gatts_char_md_t structure with the sd_ble_gatts_characteristic_add function. See code below:

        uint32_t authentications_service_key_a_add(ble_cus_t * p_cus, const ble_cus_init_t * p_cus_init)
        {
            uint32_t            err_code;
            ble_gatts_char_md_t char_md;
            ble_gatts_attr_t    attr_char_value;
            ble_uuid_t          ble_uuid;
            ble_gatts_attr_md_t attr_md;
    
            memset(&char_md, 0, sizeof(char_md));
    
            char_md.char_props.read   = 1;
            char_md.char_props.write  = 0;
            char_md.char_props.notify = 0; 
            char_md.p_char_user_desc  = NULL;
            char_md.p_char_pf         = NULL;
            char_md.p_user_desc_md    = NULL;
            char_md.p_cccd_md         = NULL; 
            char_md.p_sccd_md         = NULL;
    		
            ble_uuid.type = p_cus->uuid_type;
            ble_uuid.uuid = KEY_A_CHARACTERISTIC_UUID;
    
            memset(&attr_md, 0, sizeof(attr_md));
    
            attr_md.read_perm  = p_cus_init->custom_value_char_attr_md.read_perm;
            attr_md.write_perm = p_cus_init->custom_value_char_attr_md.write_perm;
            attr_md.vloc       = BLE_GATTS_VLOC_STACK;
            attr_md.rd_auth    = 0;
            attr_md.wr_auth    = 0;
            attr_md.vlen       = 0;
    
            memset(&attr_char_value, 0, sizeof(attr_char_value));
    
            attr_char_value.p_uuid    = &ble_uuid;
            attr_char_value.p_attr_md = &attr_md;
            attr_char_value.init_len  = sizeof(uint16_t);
            attr_char_value.init_offs = 0;
            attr_char_value.max_len   = sizeof(uint16_t);
    
            err_code = sd_ble_gatts_characteristic_add(p_cus->service_handle, &char_md,
                                                       &attr_char_value,
                                                       &p_cus->key_a_handles);
    
            return err_code;
        }

    The characteristic_add function does not have a parameter of type ble_gatts_char_md_t. How can I do?
    What is the difference between the characteristic_add function and the sd_ble_gatts_characteristic_add function?
    Thanks so much.

Reply
  • Hi Vidar,
    thanks for your answer.
    I was able to reach my goal thanks to your help.
    I was able to add the characteristic but I can't read or write the characteristic. How do I enable reading and writing of the characteristic?
    I used the ble_gatts_char_md_t structure with the sd_ble_gatts_characteristic_add function. See code below:

        uint32_t authentications_service_key_a_add(ble_cus_t * p_cus, const ble_cus_init_t * p_cus_init)
        {
            uint32_t            err_code;
            ble_gatts_char_md_t char_md;
            ble_gatts_attr_t    attr_char_value;
            ble_uuid_t          ble_uuid;
            ble_gatts_attr_md_t attr_md;
    
            memset(&char_md, 0, sizeof(char_md));
    
            char_md.char_props.read   = 1;
            char_md.char_props.write  = 0;
            char_md.char_props.notify = 0; 
            char_md.p_char_user_desc  = NULL;
            char_md.p_char_pf         = NULL;
            char_md.p_user_desc_md    = NULL;
            char_md.p_cccd_md         = NULL; 
            char_md.p_sccd_md         = NULL;
    		
            ble_uuid.type = p_cus->uuid_type;
            ble_uuid.uuid = KEY_A_CHARACTERISTIC_UUID;
    
            memset(&attr_md, 0, sizeof(attr_md));
    
            attr_md.read_perm  = p_cus_init->custom_value_char_attr_md.read_perm;
            attr_md.write_perm = p_cus_init->custom_value_char_attr_md.write_perm;
            attr_md.vloc       = BLE_GATTS_VLOC_STACK;
            attr_md.rd_auth    = 0;
            attr_md.wr_auth    = 0;
            attr_md.vlen       = 0;
    
            memset(&attr_char_value, 0, sizeof(attr_char_value));
    
            attr_char_value.p_uuid    = &ble_uuid;
            attr_char_value.p_attr_md = &attr_md;
            attr_char_value.init_len  = sizeof(uint16_t);
            attr_char_value.init_offs = 0;
            attr_char_value.max_len   = sizeof(uint16_t);
    
            err_code = sd_ble_gatts_characteristic_add(p_cus->service_handle, &char_md,
                                                       &attr_char_value,
                                                       &p_cus->key_a_handles);
    
            return err_code;
        }

    The characteristic_add function does not have a parameter of type ble_gatts_char_md_t. How can I do?
    What is the difference between the characteristic_add function and the sd_ble_gatts_characteristic_add function?
    Thanks so much.

Children
Related