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

how can i do a new characteristic ( all new 128bit-uuid )Under the same service

how can i do a new characteristic ( all new 128bit-uuid )Under the same service

this is i try use nrf connect to do this , i hop add new different from NUS servic ( only change 16bit uuid ) , how can i do?

have any example ?

thankes ~

sdk15.3 / nrf52810 / s112_v6.1.1

  • Hi,

    I'm not entirely sure if I understand what you mean. Do you want to make a custom service with characteristics under the same service?

    I suggest you have a look at these two tutorials:

    ble-services-a-beginners-tutorial

    ble-characteristics-a-beginners-tutorial 

  • thank you , i find this link 

    https://devzone.nordicsemi.com/f/nordic-q-a/19291/128-bit-characteristic-uuid-not-based-on-service-uuid

    try to do this

    Can you help me check this?
    have any wrong?

    ble_nus_128.h

    /**
     * Copyright (c) 2012 - 2019, Nordic Semiconductor ASA
     *
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without modification,
     * are permitted provided that the following conditions are met:
     *
     * 1. Redistributions of source code must retain the above copyright notice, this
     *    list of conditions and the following disclaimer.
     *
     * 2. Redistributions in binary form, except as embedded into a Nordic
     *    Semiconductor ASA integrated circuit in a product or a software update for
     *    such product, must reproduce the above copyright notice, this list of
     *    conditions and the following disclaimer in the documentation and/or other
     *    materials provided with the distribution.
     *
     * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
     *    contributors may be used to endorse or promote products derived from this
     *    software without specific prior written permission.
     *
     * 4. This software, with or without modification, must only be used with a
     *    Nordic Semiconductor ASA integrated circuit.
     *
     * 5. Any software provided in binary form under this license must not be reverse
     *    engineered, decompiled, modified and/or disassembled.
     *
     * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
     * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
     * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     *
     */
    #include "sdk_common.h"
    #if NRF_MODULE_ENABLED(BLE_NUS)
    #include "ble.h"
    #include "ble_nus_128.h"
    #include "ble_srv_common.h"
    
    #define NRF_LOG_MODULE_NAME ble_nus
    #if BLE_NUS_CONFIG_LOG_ENABLED
    #define NRF_LOG_LEVEL       BLE_NUS_CONFIG_LOG_LEVEL
    #define NRF_LOG_INFO_COLOR  BLE_NUS_CONFIG_INFO_COLOR
    #define NRF_LOG_DEBUG_COLOR BLE_NUS_CONFIG_DEBUG_COLOR
    #else // BLE_NUS_CONFIG_LOG_ENABLED
    #define NRF_LOG_LEVEL       0
    #endif // BLE_NUS_CONFIG_LOG_ENABLED
    #include "nrf_log.h"
    NRF_LOG_MODULE_REGISTER();
    
    
    #define BLE_UUID_NUS_TX_CHARACTERISTIC 		0x16D2            /**< The UUID of the TX Characteristic. */
    #define BLE_UUID_NUS_RX_CHARACTERISTIC 		0x1614		        /**< The UUID of the RX Characteristic. */
    
    #define BLE_NUS_MAX_RX_CHAR_LEN        BLE_NUS_MAX_DATA_LEN /**< Maximum length of the RX Characteristic (in bytes). */
    #define BLE_NUS_MAX_TX_CHAR_LEN        BLE_NUS_MAX_DATA_LEN /**< Maximum length of the TX Characteristic (in bytes). */
    
    #define SERVICE_UUID_128BIT      			 {{0x55, 0xAA, 0x01, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x20, 0x00, 0x00, 0x23, 0x55}} /**< Used vendor specific UUID. */
    #define SERVICE_UUID_16BIT 	0x1234	   /**< The UUID of the RX Characteristic. */
    
    //characteristic UUID_128_BIT
    #define NUS_BASE_UUID                  {{0x65, 0x6E, 0x00, 0x00, 0x6E, 0x6F, 0x00, 0x00, 0xE7, 0x11, 0x00, 0x00, 0x00, 0x00, 0x69, 0x4B}} /**< Used vendor specific UUID. */
    #define NUS_BASE_UUID_2                {{0xBF, 0x67, 0x1A, 0x00, 0x00, 0x4B, 0x83, 0x9F, 0x00, 0x00, 0x8A, 0x8E, 0x00, 0x00, 0x00, 0x85}} /**< Used vendor specific UUID. */
    #define NUS_BASE_UUID_3                {{0x07, 0x00, 0x00, 0xC6, 0x40, 0x96, 0x43, 0x00, 0x00, 0x00, 0x00, 0xAB, 0x00, 0x00, 0x02, 0x00}} /**< Used vendor specific UUID. */
    #define NUS_BASE_UUID_4                {{0x99, 0x1F, 0xBC, 0x00, 0x00, 0x96, 0x00, 0x00, 0xFD, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}} /**< Used vendor specific UUID. */
    #define NUS_BASE_UUID_5                {{0xaa, 0x00, 0x00, 0xC6, 0x40, 0x00, 0x00, 0x87, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x02, 0x5D}} /**< Used vendor specific UUID. */
    
    //characteristic UUID_16_BIT
    #define UUID_NUS_RX_1 	0x1234	             	/**< The UUID of the RX Characteristic. */
    #define UUID_NUS_RX_2 	0x5678	             	/**< The UUID of the RX Characteristic. */
    #define UUID_NUS_RX_3 	0x9ABC	             	/**< The UUID of the RX Characteristic. */
    #define UUID_NUS_TX_3 	0xDEF0	             	/**< The UUID of the TX Characteristic. */
    
    
    ble_uuid128_t base_uuid = NUS_BASE_UUID_2;
    ble_uuid128_t base_uuid_1 = NUS_BASE_UUID_3;	
    ble_uuid128_t base_uuid_2 = NUS_BASE_UUID_4;	
    ble_uuid128_t base_uuid_3 = NUS_BASE_UUID_5;	
    
    /**@brief Function for handling the @ref BLE_GAP_EVT_CONNECTED event from the SoftDevice.
     *
     * @param[in] p_nus     Nordic UART Service structure.
     * @param[in] p_ble_evt Pointer to the event received from BLE stack.
     */
    static void on_connect(ble_nus_t * p_nus, ble_evt_t const * p_ble_evt)
    {
    		NRF_LOG_INFO("on_connect NUS")
    	
        ret_code_t                 err_code;
        ble_nus_evt_t              evt;
        ble_gatts_value_t          gatts_val;
        uint8_t                    cccd_value[2];
        ble_nus_client_context_t * p_client = NULL;
    
        err_code = blcm_link_ctx_get(p_nus->p_link_ctx_storage,
                                     p_ble_evt->evt.gap_evt.conn_handle,
                                     (void *) &p_client);
        if (err_code != NRF_SUCCESS)
        {
            NRF_LOG_ERROR("Link context for 0x%02X connection handle could not be fetched.",
                          p_ble_evt->evt.gap_evt.conn_handle);
        }
    
        /* Check the hosts CCCD value to inform of readiness to send data using the RX characteristic */
        memset(&gatts_val, 0, sizeof(ble_gatts_value_t));
        gatts_val.p_value = cccd_value;
        gatts_val.len     = sizeof(cccd_value);
        gatts_val.offset  = 0;
    
        err_code = sd_ble_gatts_value_get(p_ble_evt->evt.gap_evt.conn_handle,
                                          p_nus->rx_handles.cccd_handle,
                                          &gatts_val);
    
        if ((err_code == NRF_SUCCESS)     &&
            (p_nus->data_handler != NULL) &&
            ble_srv_is_notification_enabled(gatts_val.p_value))
        {
            if (p_client != NULL)
            {
                p_client->is_notification_enabled = true;
            }
    
            memset(&evt, 0, sizeof(ble_nus_evt_t));
            evt.type        = BLE_NUS_EVT_COMM_STARTED;
            evt.p_nus       = p_nus;
            evt.conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
            evt.p_link_ctx  = p_client;
    
            p_nus->data_handler(&evt);
        }
    }
    
    
    /**@brief Function for handling the @ref BLE_GATTS_EVT_WRITE event from the SoftDevice.
     *
     * @param[in] p_nus     Nordic UART Service structure.
     * @param[in] p_ble_evt Pointer to the event received from BLE stack.
     */
    static void on_write(ble_nus_t * p_nus, ble_evt_t const * p_ble_evt)
    {
    	
    		NRF_LOG_INFO("on_write NUS")
        ret_code_t                    err_code;
        ble_nus_evt_t                 evt;
        ble_nus_client_context_t    * p_client;
        ble_gatts_evt_write_t const * p_evt_write = &p_ble_evt->evt.gatts_evt.params.write;
    
        err_code = blcm_link_ctx_get(p_nus->p_link_ctx_storage,
                                     p_ble_evt->evt.gatts_evt.conn_handle,
                                     (void *) &p_client);
        if (err_code != NRF_SUCCESS)
        {
            NRF_LOG_ERROR("Link context for 0x%02X connection handle could not be fetched.",
                          p_ble_evt->evt.gatts_evt.conn_handle);
        }
    
        memset(&evt, 0, sizeof(ble_nus_evt_t));
        evt.p_nus       = p_nus;
        evt.conn_handle = p_ble_evt->evt.gatts_evt.conn_handle;
        evt.p_link_ctx  = p_client;
    
        if ((p_evt_write->handle == p_nus->tx_handles.cccd_handle) &&
            (p_evt_write->len == 2))
        {
            if (p_client != NULL)
            {
                if (ble_srv_is_notification_enabled(p_evt_write->data))
                {
                    p_client->is_notification_enabled = true;
                    evt.type                          = BLE_NUS_EVT_COMM_STARTED;
                }
                else
                {
                    p_client->is_notification_enabled = false;
                    evt.type                          = BLE_NUS_EVT_COMM_STOPPED;
                }
    
                if (p_nus->data_handler != NULL)
                {
                    p_nus->data_handler(&evt);
                }
    
            }
        }
        else if ((p_evt_write->handle == p_nus->rx_handles.value_handle) &&
                 (p_nus->data_handler != NULL))
        {
            evt.type                  = BLE_NUS_EVT_RX_DATA;
            evt.params.rx_data.p_data = p_evt_write->data;
            evt.params.rx_data.length = p_evt_write->len;
    
            p_nus->data_handler(&evt);
        }
    		
        else if ((p_evt_write->handle == p_nus->rx_2_handles.value_handle) &&
                 (p_nus->data_handler != NULL))
        {
            evt.type                  = BLE_NUS_EVT_RX_2_DATA;
            evt.params.rx_data.p_data = p_evt_write->data;
            evt.params.rx_data.length = p_evt_write->len;
    
            p_nus->data_handler(&evt);
        }		
    		
        else if ((p_evt_write->handle == p_nus->rx_3_handles.value_handle) &&
                 (p_nus->data_handler != NULL))
        {
            evt.type                  = BLE_NUS_EVT_RX_3_DATA;
            evt.params.rx_data.p_data = p_evt_write->data;
            evt.params.rx_data.length = p_evt_write->len;
    
            p_nus->data_handler(&evt);
        }		
    		
    		
        else
        {
            // Do Nothing. This event is not relevant for this service.
        }
    }
    
    
    /**@brief Function for handling the @ref BLE_GATTS_EVT_HVN_TX_COMPLETE event from the SoftDevice.
     *
     * @param[in] p_nus     Nordic UART Service structure.
     * @param[in] p_ble_evt Pointer to the event received from BLE stack.
     */
    static void on_hvx_tx_complete(ble_nus_t * p_nus, ble_evt_t const * p_ble_evt)
    {
        ret_code_t                 err_code;
        ble_nus_evt_t              evt;
        ble_nus_client_context_t * p_client;
    
        err_code = blcm_link_ctx_get(p_nus->p_link_ctx_storage,
                                     p_ble_evt->evt.gatts_evt.conn_handle,
                                     (void *) &p_client);
        if (err_code != NRF_SUCCESS)
        {
            NRF_LOG_ERROR("Link context for 0x%02X connection handle could not be fetched.",
                          p_ble_evt->evt.gatts_evt.conn_handle);
            return;
        }
    
        if (p_client->is_notification_enabled)
        {
            memset(&evt, 0, sizeof(ble_nus_evt_t));
            evt.type        = BLE_NUS_EVT_TX_RDY;
            evt.p_nus       = p_nus;
            evt.conn_handle = p_ble_evt->evt.gatts_evt.conn_handle;
            evt.p_link_ctx  = p_client;
    
            p_nus->data_handler(&evt);
        }
    }
    
    
    void ble_nus_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context)
    {
    		NRF_LOG_INFO("ble_nus_on_ble_evt NUS");
    
    
    		if ((p_context == NULL) || (p_ble_evt == NULL))
        {
            return;
        }
    
        ble_nus_t * p_nus = (ble_nus_t *)p_context;
    		
        switch (p_ble_evt->header.evt_id)
        {
            case BLE_GAP_EVT_CONNECTED:
                on_connect(p_nus, p_ble_evt);
                break;
    
            case BLE_GATTS_EVT_WRITE:
                on_write(p_nus, p_ble_evt);
                break;
    
            case BLE_GATTS_EVT_HVN_TX_COMPLETE:
                on_hvx_tx_complete(p_nus, p_ble_evt);
                break;
    
            default:
                // No implementation needed.
                break;
        }
    }
    
    
    uint32_t characteristic_add_128uuid(uint16_t                   service_handle,
    																	ble_add_char_params_t *    p_char_props,
    																	ble_gatts_char_handles_t * p_char_handle,
    																	uint8_t case_128uuid)
    {
        /**@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	service_uuid; 
        ble_gatts_attr_md_t attr_md;
    		ble_gatts_attr_md_t user_descr_attr_md;
    
    		BLE_UUID_BLE_ASSIGN(service_uuid, p_char_props->uuid);		
    
    		switch (case_128uuid)
        {
            case 0:
    					VERIFY_SUCCESS(sd_ble_uuid_vs_add(&base_uuid, &service_uuid.type));
    					break;
            case 1:
    					VERIFY_SUCCESS(sd_ble_uuid_vs_add(&base_uuid_1, &service_uuid.type));
    					break;				
            case 2:
    					VERIFY_SUCCESS(sd_ble_uuid_vs_add(&base_uuid_2, &service_uuid.type));
    					break;
            case 3:
    					VERIFY_SUCCESS(sd_ble_uuid_vs_add(&base_uuid_3, &service_uuid.type));
    					break;			
    		}	
    	
        memset(&attr_md, 0, sizeof(ble_gatts_attr_md_t));
        BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm);
        BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm);  
        attr_md.rd_auth 	=  (p_char_props->is_defered_read ? 1 : 0);
        attr_md.wr_auth 	=  (p_char_props->is_defered_write ? 1 : 0);	
        attr_md.vlen 			=	 (p_char_props->is_var_len ? 1 : 0);			
    		attr_md.vloc 			=  (p_char_props->is_value_user ? BLE_GATTS_VLOC_USER : BLE_GATTS_VLOC_STACK); //BLE_GATTS_VLOC_STACK;
    		
        memset(&char_md, 0, sizeof(ble_gatts_char_md_t));
    
    		if ((p_char_props->char_props.notify == 1)||(p_char_props->char_props.indicate == 1))
        {	
    		
    				memset(&cccd_md, 0, sizeof(ble_gatts_attr_md_t));
    				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;
    				char_md.p_cccd_md = &cccd_md;
    		}
        char_md.char_props     = p_char_props->char_props;		
        char_md.char_ext_props = p_char_props->char_ext_props;		
    			
    		memset(&attr_char_value, 0, sizeof(ble_gatts_attr_t));
    
        attr_char_value.p_uuid			= &service_uuid; 								
        attr_char_value.p_attr_md 	= &attr_md;
        attr_char_value.max_len 		= p_char_props->max_len;				
    
    
        if (p_char_props->p_init_value != NULL)
        {		
    			  attr_char_value.init_len  = p_char_props->init_len;			
    				attr_char_value.p_value = 	p_char_props->p_init_value;	
        }			
    		attr_char_value.init_offs = 0;		
    		
        if (p_char_props->p_user_descr != NULL)
        {
            memset(&user_descr_attr_md, 0, sizeof(ble_gatts_attr_md_t));
            char_md.char_user_desc_max_size = p_char_props->p_user_descr->max_size;
            char_md.char_user_desc_size     = p_char_props->p_user_descr->size;
            char_md.p_char_user_desc        = p_char_props->p_user_descr->p_char_user_desc;
    
            char_md.p_user_desc_md          = &user_descr_attr_md; 
    
    				BLE_GAP_CONN_SEC_MODE_SET_OPEN(&user_descr_attr_md.read_perm);
    				BLE_GAP_CONN_SEC_MODE_SET_OPEN(&user_descr_attr_md.write_perm);	
    
            user_descr_attr_md.rd_auth      = (p_char_props->p_user_descr->is_defered_read ? 1 : 0);
            user_descr_attr_md.wr_auth      = (p_char_props->p_user_descr->is_defered_write ? 1 : 0);
            user_descr_attr_md.vlen         = (p_char_props->p_user_descr->is_var_len ? 1 : 0);
            user_descr_attr_md.vloc         = (p_char_props->p_user_descr->is_value_user ? BLE_GATTS_VLOC_USER : BLE_GATTS_VLOC_STACK);
        }		
    
        if (p_char_props->p_presentation_format != NULL)
        {
            char_md.p_char_pf = p_char_props->p_presentation_format;  
        }	
    		char_md.p_sccd_md = NULL;
    
        return sd_ble_gatts_characteristic_add(service_handle,
                                               &char_md,
                                               &attr_char_value,
                                               p_char_handle);
    }
    
    
    uint32_t ble_nus_init(ble_nus_t * p_nus, ble_nus_init_t const * p_nus_init)
    {
        ret_code_t            err_code;
        ble_add_char_params_t add_char_params;	
    	
        VERIFY_PARAM_NOT_NULL(p_nus);
        VERIFY_PARAM_NOT_NULL(p_nus_init);
    
        // Initialize the service structure.
        p_nus->data_handler = p_nus_init->data_handler;
    
    ///////////////////////////////////////////////////////////////////////////
    
    		// To add a service
    		// Declare 16-bit service and 128-bit base UUIDs and add them to BLE stack table
    		ble_uuid_t	service_uuid;
    
    		BLE_UUID_BLE_ASSIGN(service_uuid, SERVICE_UUID_16BIT);
    
    		ble_uuid128_t base_uuid = SERVICE_UUID_128BIT;
    
    		// Add the UUID to the BLE stack
    		err_code = sd_ble_uuid_vs_add(&base_uuid, &service_uuid.type);
    		VERIFY_SUCCESS(err_code);
    
    		// Add your service
    		err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY,
    																				&service_uuid,
    																				&p_nus->service_handle);
    		VERIFY_SUCCESS(err_code);
    
        // Add the RX Characteristic.
        memset(&add_char_params, 0, sizeof(ble_add_char_params_t));
        add_char_params.uuid                     = UUID_NUS_RX_1;
        add_char_params.uuid_type                = p_nus->uuid_type;
        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;
        add_char_params.char_props.write         = 1;
        add_char_params.char_props.write_wo_resp = 1;
    //		add_char_params.is_value_user						 = 0;
    //		add_char_params.is_defered_read					 = 0;
    //		add_char_params.is_defered_write				 = 0;
    
        add_char_params.read_access  = SEC_OPEN;
        add_char_params.write_access = SEC_OPEN;
    
    		err_code = characteristic_add_128uuid(p_nus->service_handle, &add_char_params, &p_nus->rx_handles , 0);
        if (err_code != NRF_SUCCESS)
        {
            return err_code;
        }
    
        // Add the RX Characteristic.
        memset(&add_char_params, 0, sizeof(ble_add_char_params_t));
        add_char_params.uuid                     = UUID_NUS_RX_2;
        add_char_params.uuid_type                = p_nus->uuid_type;
        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;
        add_char_params.char_props.write         = 1;
        add_char_params.char_props.write_wo_resp = 1;
    //		add_char_params.is_value_user						 = 0;
    //		add_char_params.is_defered_read					 = 0;
    //		add_char_params.is_defered_write				 = 0;
    
        add_char_params.read_access  = SEC_OPEN;
        add_char_params.write_access = SEC_OPEN;
    
    		err_code = characteristic_add_128uuid(p_nus->service_handle, &add_char_params, &p_nus->rx_2_handles , 1);
        if (err_code != NRF_SUCCESS)
        {
            return err_code;
        }
    
        // Add the RX Characteristic.
        memset(&add_char_params, 0, sizeof(ble_add_char_params_t));
        add_char_params.uuid                     = UUID_NUS_RX_3;
        add_char_params.uuid_type                = p_nus->uuid_type;
        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;
        add_char_params.char_props.write         = 1;
        add_char_params.char_props.write_wo_resp = 1;
    //		add_char_params.is_value_user						 = 0;
    //		add_char_params.is_defered_read					 = 0;
    //		add_char_params.is_defered_write				 = 0;
    
        add_char_params.read_access  = SEC_OPEN;
        add_char_params.write_access = SEC_OPEN;
    
    		err_code = characteristic_add_128uuid(p_nus->service_handle, &add_char_params, &p_nus->rx_3_handles , 2);
        if (err_code != NRF_SUCCESS)
        {
            return err_code;
        }		
    
        // Add the TX Characteristic.
        /**@snippet [Adding proprietary characteristic to the SoftDevice] */
        memset(&add_char_params, 0, sizeof(ble_add_char_params_t));
        add_char_params.uuid              = UUID_NUS_TX_3;
        add_char_params.uuid_type         = p_nus->uuid_type;
        add_char_params.max_len           = BLE_NUS_MAX_TX_CHAR_LEN;
        add_char_params.init_len          = sizeof(uint8_t);
        add_char_params.is_var_len        = true;
        add_char_params.char_props.notify = 1;
    
        add_char_params.read_access       = SEC_OPEN;
        add_char_params.write_access      = SEC_OPEN;
        add_char_params.cccd_write_access = SEC_OPEN;
    
        return characteristic_add_128uuid(p_nus->service_handle, &add_char_params, &p_nus->tx_handles , 3 );
    		
    }
    
    uint32_t ble_nus_data_send(ble_nus_t * p_nus,
                               uint8_t   * p_data,
                               uint16_t  * p_length,
                               uint16_t    conn_handle)
    {
        ret_code_t                 err_code;
        ble_gatts_hvx_params_t     hvx_params;
        ble_nus_client_context_t * p_client;
    
        VERIFY_PARAM_NOT_NULL(p_nus);
    
        err_code = blcm_link_ctx_get(p_nus->p_link_ctx_storage, conn_handle, (void *) &p_client);
        VERIFY_SUCCESS(err_code);
    
        if ((conn_handle == BLE_CONN_HANDLE_INVALID) || (p_client == NULL))
        {
            return NRF_ERROR_NOT_FOUND;
        }
    
        if (!p_client->is_notification_enabled)
        {
            return NRF_ERROR_INVALID_STATE;
        }
    
        if (*p_length > BLE_NUS_MAX_DATA_LEN)
        {
            return NRF_ERROR_INVALID_PARAM;
        }
    
        memset(&hvx_params, 0, sizeof(hvx_params));
    
        hvx_params.handle = p_nus->tx_handles.value_handle;
        hvx_params.p_data = p_data;
        hvx_params.p_len  = p_length;
        hvx_params.type   = BLE_GATT_HVX_NOTIFICATION;
    
        return sd_ble_gatts_hvx(conn_handle, &hvx_params);
    }
    
    
    #endif // NRF_MODULE_ENABLED(BLE_NUS)
    

Related