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

128-bit Characteristic UUID not based on Service UUID

Hi Nordic Team,

What I want to achieve is to add a service with a custom 128-bit UUID that has about 4 characteristics with a completely different 128-bit UUIDs that are NOT based on the service UUID ?

Is that possible ? If so, how can I implement that? I'm using SDK12.2.0 on nRF51822.

Many thanks in advance.

Kind Regards, Ayman.

Parents Reply Children
  • It is fairly easy to do. You just need to add a new 128-bit UUID to the BLE stack table and then add a service/characteristic with that UUID.

    // To add a service
    // Declare 16-bit service and 128-bit base UUIDs and add them to BLE stack table
    ret_code_t	err_code;
    ble_uuid_t	service_uuid;
    
    BLE_UUID_BLE_ASSIGN(service_uuid, your_16_bit_uuid);
    
    ble_uuid128_t base_uuid = YOUR_CUSTOM_128_BIT_UUID;
    
    // Add the UUID to the BLE stack
    err_code = sd_ble_uuid_vs_add(&base_uuid, &service_uuid.type);
    APP_ERROR_CHECK(err_code);
    
    // Add your service
    err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY,
                                        &service_uuid,
                                        &service_handle);
    APP_ERROR_CHECK(err_code);
    

    // To add a characteristic
    // Add a custom characteristic UUID
    ret_code_t err_code;
    ble_uuid_t char_uuid;
    BLE_UUID_BLE_ASSIGN(char_uuid, your_16_bit_uuid);
    
    ble_uuid128_t base_uuid = YOUR_CUSTOM_128_BIT_UUID;
    
    // Add the UUID to the BLE stack
    err_code = sd_ble_uuid_vs_add(&base_uuid, &char_uuid.type);
    APP_ERROR_CHECK(err_code);
    
    [Initialize all attribute metadata and stuff]
    [Copy from any example]
    
    // Add our new characteristic to the service
    err_code = sd_ble_gatts_characteristic_add(service_handle,
                                               &char_md,
                                               &attr_char_value,
                                               &custom_char_handles);
    APP_ERROR_CHECK(err_code);

  • I am having exactly this problem; my code is essentially the same as above.  I don't know what I am doing wrong.

    What is happening is that the UUID of the data characteristic is the same as the UUID of the service.

    Here is what I am trying to achieve:

    Instead, I'm getting this:

    What am I doing wrong?

    Here is an excerpt of my code:

    #define BLE_UUID_SCS_SERVICE 0x0e04	/**< UUID of the SCS service */
    #define BLE_UUID_SCS_DATA    0xb607	/**< UUID of the data characteristic */
    
    typedef struct ble_scs_s ble_scs_t;
    
    /**@brief   Nordic UART Service structure.
     *
     * @details This structure contains status information related to the service.
     */
    struct ble_scs_s
    {
        uint8_t service_uuid_type;				/**< UUID type for SCS service base UUID */
        uint8_t data_uuid_type;					/**< UUID type for SCS data base UUID. */
        uint16_t service_handle;				/**< Handle for SCS service (as provided by the SoftDevice). */
        ble_gatts_char_handles_t service_handles;	/**< service characteristic handles */
        ble_gatts_char_handles_t data_handles;	    /**< data characteristic handles */
        uint16_t conn_handle;					/**< Handle of current connection */
        bool is_notification_enabled;			/**< Variable to indicate if the peer has enabled notification of the RX characteristic.*/
        ble_scs_data_handler_t data_handler;	/**< Event handler to be called for handling received data. */
    };
    
    static ble_uuid128_t const m_scs_base_uuid128 =
    {
    	{
    	   	0x17, 0x76, 0x6f, 0xcf, 0x10, 0x88, 0xbc, 0xb5,
    	   	0x6d, 0x4a, 0x61, 0xc2, 0x04, 0x0e, 0xbf, 0xe6
       	}
    };
    
    static ble_uuid128_t const m_scs_data_txchar_uuid128 =
    {
    	{
    	   	0x0d, 0xee, 0x3e, 0x5f, 0x8d, 0x2e, 0xfd, 0x97,
    	   	0x82, 0x4f, 0xe8, 0xf5, 0x07, 0xb6, 0x25, 0xc7
       	}
    };
    
    
    /**@brief Add data characteristic.
     *
     * @param[in] p_scs       SCS Service structure.
     * @param[in] p_scs_init  Information needed to initialize the service.
     *
     * @return NRF_SUCCESS on success, otherwise an error code.
     */
    static uint32_t scs_data_char_add(ble_scs_t *p_scs, ble_scs_init_t const *p_scs_init)
    {
        /**@snippet [Adding proprietary characteristic to the SoftDevice] */
        ble_gatts_char_md_t char_md;
        ble_gatts_attr_md_t cccd_md;
        ble_gatts_attr_t attr_char_value;
        ble_uuid_t char_uuid;
        ble_gatts_attr_md_t attr_md;
    	uint8_t initial_data[20];
    
    	BLE_UUID_BLE_ASSIGN(char_uuid, BLE_UUID_SCS_DATA);
        VERIFY_SUCCESS(sd_ble_uuid_vs_add(&m_scs_data_txchar_uuid128, &p_scs->data_uuid_type));
    
        memset(&cccd_md, 0, sizeof(cccd_md));
        BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm);
        BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.write_perm);
        cccd_md.vloc = BLE_GATTS_VLOC_STACK;
    
        memset(&char_md, 0, sizeof(char_md));
        char_md.char_props.write  = 1;
        char_md.char_props.indicate = 1;
        char_md.p_char_pf = NULL;
        char_md.p_user_desc_md = NULL;
        char_md.p_cccd_md = &cccd_md;
        char_md.p_sccd_md = NULL;
    
        memset(&attr_md, 0, sizeof(attr_md));
        BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm);
        BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm);
        attr_md.vloc = BLE_GATTS_VLOC_STACK;
        attr_md.rd_auth = 0;
        attr_md.wr_auth = 0;
        attr_md.vlen = 1;
    
        memset(&attr_char_value, 0, sizeof(attr_char_value));
    	memset(initial_data, 0, sizeof(initial_data));
        attr_char_value.p_uuid = &char_uuid;
        attr_char_value.p_attr_md = &attr_md;
        attr_char_value.init_len = sizeof(initial_data);
        attr_char_value.init_offs = 0;
        attr_char_value.max_len = sizeof(initial_data);
    	attr_char_value.p_value = initial_data;
    
        return sd_ble_gatts_characteristic_add(p_scs->service_handle,
                                               &char_md,
                                               &attr_char_value,
                                               &p_scs->data_handles);
    }
    
    
    uint32_t ble_scs_init(ble_scs_t *p_scs, ble_scs_init_t const *p_scs_init)
    {
        ble_uuid_t ble_uuid;
    
        VERIFY_PARAM_NOT_NULL(p_scs);
        VERIFY_PARAM_NOT_NULL(p_scs_init);
    
        // Initialize the service structure.
        p_scs->conn_handle = BLE_CONN_HANDLE_INVALID;
        p_scs->data_handler = p_scs_init->data_handler;
        p_scs->is_notification_enabled = false;
    
        /**@snippet [Adding proprietary Service to the SoftDevice] */
        // Add a custom base UUID.
    	BLE_UUID_BLE_ASSIGN(ble_uuid, BLE_UUID_SCS_SERVICE);
        VERIFY_SUCCESS(sd_ble_uuid_vs_add(&m_scs_base_uuid128, &p_scs->service_uuid_type));
    
        // Add the service.
        VERIFY_SUCCESS(sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY,
    											&ble_uuid,
    										   	&p_scs->service_handle));
    
        // Add the data characteristic.
        VERIFY_SUCCESS(scs_data_char_add(p_scs, p_scs_init));
    
        return NRF_SUCCESS;
    }
    
    

    Thanks for any help you can give.

    --ken

  • Your problem is that you're passing different UUIDs to sd_ble_uuid_vs_add().

    Try changing 

    VERIFY_SUCCESS(sd_ble_uuid_vs_add(&m_scs_data_txchar_uuid128, &p_scs->data_uuid_type));

    to

    VERIFY_SUCCESS(sd_ble_uuid_vs_add(&m_scs_data_txchar_uuid128, &char_uuid.type));
    p_scs->data_uuid_type = char_uuid.type;

  • Andy,

    You are right, that was a bug (a vestige of previous attempts to solve this).  Thanks.

    Unfortunately, that doesn't fix the problem though.

    I am still getting the same UUID for the data characteristic as the service.

    --ken

  • I'm pretty sure that should have solved it. Try turning off and on airplane mode on your phone, or try rebooting it altogether. I know for a fact that iOS caches BLE services and characteristics and this cache is cleared in those cases. If you're on Android I'm not so sure how you can do that, but try something similar.

Related