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

CUSTOM BLE SERVICE : READ WRITE RESPONSE

Hi, I am creating custom ble service.there i need to perform

1. character   -  READ , NOTIF

2. character   -  WRITE READ

3. character  -   READ,WRITE, NOTIF

I achieved - WRITE.  but i am unable to read the response

Here i upload the example code that i have used.

IF THE BUTTON PRESSED  value 0x01 . if released 0x00.

when the NOTIF enabled it works perfect. but when i want to read the current data if the notif in disabled it shows " ERROR 2 : GATT READ NOT PERMITTED "

static void on_connect(ble_uis_t * p_uis, ble_evt_t const * p_ble_evt)
{
    p_uis->conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
}

static void on_disconnect(ble_uis_t * p_uis, ble_evt_t const * p_ble_evt)
{
    UNUSED_PARAMETER(p_ble_evt);
    p_uis->conn_handle = BLE_CONN_HANDLE_INVALID;
}

static void on_write(ble_uis_t * p_uis, ble_evt_t const * p_ble_evt)
{
    ble_gatts_evt_write_t const * p_evt_write = &p_ble_evt->evt.gatts_evt.params.write;
    

    if ( (p_evt_write->handle == p_uis->button_char_handles.cccd_handle) &&
         (p_evt_write->len == 2) )
    {
        ble_device_evt_t    evt;

        if (ble_srv_is_notification_enabled(p_evt_write->data))
        {
            p_uis->is_button_notif_enabled = true;
            evt.evt_type = BLE_DEVICE_EVT_NOTIFICATION_ENABLED;
           
        }
        else
        {
            p_uis->is_button_notif_enabled = false;
            evt.evt_type = BLE_DEVICE_EVT_NOTIFICATION_DISABLED;
        }
        evt.conn_handle = p_ble_evt->evt.gatts_evt.conn_handle;
         p_uis->evt_handler(p_uis, &evt);
    }
    else
    {
        // Do Nothing. This event is not relevant for this service.
    }
}


void ble_uis_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context)
{
    ble_uis_t * p_uis = (ble_uis_t *) p_context;

    if ((p_uis == NULL) || (p_ble_evt == NULL))
    {
        return;
    }

    switch (p_ble_evt->header.evt_id)
    {
        case BLE_GAP_EVT_CONNECTED:
            on_connect(p_uis, p_ble_evt);
            NRF_LOG_INFO("BLE UI connected\r\n");
            break;

        case BLE_GAP_EVT_DISCONNECTED:
            on_disconnect(p_uis, p_ble_evt);
            break;

        case BLE_GATTS_EVT_WRITE:
            on_write(p_uis, p_ble_evt);
            break;

        case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST:
            on_authorize_req(p_uis, p_ble_evt);
            break;

        default:
            // No implementation needed.
            break;
    }
}
static uint32_t button_char_add(ble_uis_t * p_uis, const ble_uis_init_t * p_uis_init)
{
    ble_gatts_char_md_t char_md;
    ble_gatts_attr_md_t cccd_md;
    ble_gatts_attr_t    attr_char_value;
    ble_uuid_t          ble_uuid;
    ble_gatts_attr_md_t attr_md;
    uint8_t            init_value = 0;
    init_value  =   p_uis_init->charge;

    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.read   = 1;
   // char_md.char_props.write  = 1;
    char_md.char_props.notify = 1;
    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         = &cccd_md;
    char_md.p_sccd_md         = NULL;

    ble_uuid.type = p_uis->uuid_type;
    ble_uuid.uuid = BLE_CHARGE_CHAR;

    memset(&attr_md, 0, sizeof(attr_md));

    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&attr_md.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&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(uint8_t);
    attr_char_value.init_offs    = 0;
    attr_char_value.max_len      = sizeof(uint8_t);
    attr_char_value.p_value      = ((uint8_t *)(&init_value));
    

    return sd_ble_gatts_characteristic_add(p_uis->service_handle,
                                          &char_md,
                                          &attr_char_value,
                                          &p_uis->button_char_handles);
}


static uint32_t led_char_add(ble_uis_t * p_uis, const ble_uis_init_t * p_uis_init)
{
    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  = 1;
    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_uis->uuid_type;
    ble_uuid.uuid = BLE_LED_CONFIG_CHAR;

    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    = 1;
    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(ble_uis_led_t);
    attr_char_value.init_offs    = 0;
    attr_char_value.max_len      = sizeof(ble_uis_led_t);;
    attr_char_value.p_value      = ((uint8_t *)(p_uis_init->p_init_led));


    return sd_ble_gatts_characteristic_add(p_uis->service_handle,
                                           &char_md,
                                           &attr_char_value,
                                           &p_uis->led_char_handles);
}


uint32_t ble_uis_init(ble_uis_t * p_uis, const ble_uis_init_t * p_uis_init)
{
    uint32_t   err_code;
    ble_uuid_t ble_uuid;

    // Initialize service structure.
    p_uis->conn_handle             = BLE_CONN_HANDLE_INVALID;
    p_uis->evt_handler             =  p_uis_init->evt_handler;
    p_uis->led_write_handler       = p_uis_init->led_write_handler;
   
    p_uis->is_button_notif_enabled = false;
    // Add service.
    ble_uuid128_t base_uuid = LSPOT_BASE_UUID;
    err_code = sd_ble_uuid_vs_add(&base_uuid, &p_uis->uuid_type);
    VERIFY_SUCCESS(err_code);

    ble_uuid.type = p_uis->uuid_type;
    ble_uuid.uuid = BLE_IO_SERVICE;

    err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &ble_uuid, &p_uis->service_handle);
    VERIFY_SUCCESS(err_code);

    // Add characteristics.
    err_code = button_char_add(p_uis, p_uis_init);
    VERIFY_SUCCESS(err_code);
 

    err_code = led_char_add(p_uis, p_uis_init);
    VERIFY_SUCCESS(err_code);

   

    return NRF_SUCCESS;
}


uint32_t ble_uis_on_button_change(ble_uis_t * p_uis, uint8_t buttons_state)
{
    ble_gatts_hvx_params_t params;
    uint16_t len = sizeof(buttons_state);

    VERIFY_PARAM_NOT_NULL(p_uis);

    if ((p_uis->conn_handle == BLE_CONN_HANDLE_INVALID) || (!p_uis->is_button_notif_enabled))
    {
        return NRF_ERROR_INVALID_STATE;
    }

    memset(&params, 0, sizeof(params));
    params.type = BLE_GATT_HVX_NOTIFICATION;
    params.handle = p_uis->button_char_handles.value_handle;
    params.p_data = (uint8_t *)(&buttons_state);
    params.p_len = &len;

    return sd_ble_gatts_hvx(p_uis->conn_handle, &params);
}

please check here what is the problem

static uint32_t button_char_add(ble_uis_t * p_uis, const ble_uis_init_t * p_uis_init)
{
    ble_gatts_char_md_t char_md;
    ble_gatts_attr_md_t cccd_md;
    ble_gatts_attr_t    attr_char_value;
    ble_uuid_t          ble_uuid;
    ble_gatts_attr_md_t attr_md;
    uint8_t            init_value = 0;
    init_value  =   p_uis_init->charge;

    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.read   = 1;
   // char_md.char_props.write  = 1;
    char_md.char_props.notify = 1;
    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         = &cccd_md;
    char_md.p_sccd_md         = NULL;

    ble_uuid.type = p_uis->uuid_type;
    ble_uuid.uuid = BLE_CHARGE_CHAR;

    memset(&attr_md, 0, sizeof(attr_md));

    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&attr_md.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&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(uint8_t);
    attr_char_value.init_offs    = 0;
    attr_char_value.max_len      = sizeof(uint8_t);
    attr_char_value.p_value      = ((uint8_t *)(&init_value));
    

    return sd_ble_gatts_characteristic_add(p_uis->service_handle,
                                          &char_md,
                                          &attr_char_value,
                                          &p_uis->button_char_handles);
}

NOTIF ENABLED :

WHEN READ BUTTON PRESSED:

Related