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

Not receiving Notifications/Indications in the central events handler [nRF52832 - s132]

Hello,

Let me introduce you to the issue:

I am working on a custom firmware for a custom hardware, based on the nRF52832 and SD S132, as a central which need to connect to an already implemented peripheral device and write, read and receive indications/notifications from it.

I am developing on Keil 5.0 and I have the PCA10040 for development/testing purposes.

So the main issue here is that in the central part, after I connect successfully, discover services and characteristics with VS (vendor specific) UUIDs, I enable the notifications/indications for a characteristic, and when I write an encrypted value to that characteristic, I never receive the notifications/indication the peripheral sends as response.

Different points to consider:

  • I mention both notifications and indications as the peripheral sends the same information on either of them when enabled. 
  • The peripheral works properly, as I developed an Android APP for testing purposes and the notifications/indications are received correctly.
  • The encryption method on the central is working properly. Results are compared with the Android APP. Also, when writing the encrypted value to the peripheral, this processes the right "physical" task, but the notification (as response) from it it is never received.

Once I am connected to the peripheral and all the services and characteristics I need are discovered, I enable the notifications on CCCD handle using the code:

err_code = ble_peripheral_char_notif_enable(p_custom_srv_c);
APP_ERROR_CHECK(err_code);

And the ''ble_peripheral_char_notif_enable()" function is:

uint32_t ble_peripheral_char_notif_enable(ble_custom_srv_c_t * evt)
{
	VERIFY_PARAM_NOT_NULL(evt);

    if ( (evt->conn_handle == BLE_CONN_HANDLE_INVALID)
       ||(evt->handles[BLE_CUSTOM_SRV_C_CHAR_CCCD] == BLE_GATT_HANDLE_INVALID)
       )
    {
        return NRF_ERROR_INVALID_STATE;
    }
    return cccd_configure(evt->conn_handle, evt->handles[BLE_CUSTOM_SRV_C_CHAR_CCCD], true);
}

So above I check if my handles for CCCD and connection are OK. This works properly. (*the handles value is a structure which keeps all the handles for services and characteristics).

Then the cccd_configure function looks like:

static uint32_t cccd_configure(uint16_t conn_handle, uint16_t cccd_handle, bool enable)
{

	uint8_t buf[BLE_CCCD_VALUE_LEN];

    buf[0] = enable ? BLE_GATT_HVX_INDICATION : 0;
    buf[1] = 0;

    ble_gattc_write_params_t const write_params =
    {
        .write_op = BLE_GATT_OP_WRITE_REQ,
        .flags    = BLE_GATT_EXEC_WRITE_FLAG_PREPARED_WRITE,
        .handle   = cccd_handle,
        .offset   = 0,
        .len      = BLE_CCCD_VALUE_LEN,
        .p_value  = (uint8_t *)buf
    };

    return sd_ble_gattc_write(conn_handle, &write_params);
}

After calling the above function, I successfully receive the event BLE_GATTC_EVT_WRITE_RSP for my char_type -> BLE_CUSTOM_SRV_C_CHAR_CCCD.

No error until here so I suppose my events handler works well.

Now, I write a characteristic with an encrypted value, and the Peripheral receives it properly (as it moves a servo motor as it should) but I never receive anything on the BLE_GATTC_EVT_HVX as I should as a response from it.

This is how my events handler looks like:

static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
{
    uint16_t conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
    uint16_t role        = ble_conn_state_role(conn_handle);
	
    if (role == BLE_GAP_ROLE_PERIPH || ble_evt_is_advertising_timeout(p_ble_evt))
    {
        on_ble_peripheral_evt(p_ble_evt);
    }
    else if ((role == BLE_GAP_ROLE_CENTRAL))
    {

        ble_custom_srv_on_ble_evt(p_ble_evt, &m_custom_srv_c);
        ble_dis_c_on_ble_evt(p_ble_evt, &m_dis_c);
        on_ble_central_evt(p_ble_evt);
    }
}

which forwards the events to my custom handler:

void ble_custom_srv_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context)
{
    ble_custom_srv_c_t * p_ble_custom_srv_c = (ble_custom_srv_c_t *) p_context;

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

    if (p_ble_custom_srv_c->conn_handle == BLE_CONN_HANDLE_INVALID)
    {
        return;
    }

    switch (p_ble_evt->header.evt_id)
    {
		case BLE_GATTC_EVT_HVX:
            on_hvx(p_ble_custom_srv_c, p_ble_evt);
            break;
				
        case BLE_GATTC_EVT_READ_RSP:
            on_read_rsp(p_ble_custom_srv_c, p_ble_evt);
            break;

        case BLE_GAP_EVT_DISCONNECTED:
            on_disconnected(p_ble_custom_srv_c, p_ble_evt);
            break;
            
		case BLE_GATTC_EVT_WRITE_RSP:
			on_write_rsp(p_ble_custom_srv_c, p_ble_evt);
			break;
			
        default:
            // No implementation needed.
            break;
    }
}

All the above cases are triggered properly when needed, except the HVX one.

I have also tried to read the CCCD value from the central side after enabling notifications/indications as seen on this post, but without success. The values are never, 0x0000, 0x0001, or 0x0002, but something like 0x20007723.

Furthermore, I have tried to compile and run different central examples from the SDK on my PCA10040 but without success, it never goes past "ble_stack_init()" from the main func.

Any idea on what am I doing wrong? Any advice on what I should test?

Thanks in advance for your help and sorry for the long question.

BR,

  • HI Gabriel, 

    would you be able to provide a sniffer trace of the on-air data between the nRF52 central and the peripheral? This way we would be able to check whether the nRF52 is correctly enabling notifcations by writting to the CCCD of the characteristic on the peripheral side. 

    Best regards

    Bjørn

  • Hi Björn, thank you for your reply and sorry for my late answer. I did not really knew I could see the connection packets, but only the advertising ones (noobie me...) with the sniffer.

    Now, and after comparing with the Android connection, I saw different issues I am trying to fix. This is one of them:

    As you can see, the mentioned service is the default "Device Information 0x180a" and the characteristic is my custom one. This is obviously not right as my characteristic is in a custom service with UUID: 00035b0358e607dd021a08123a000300. This causes a "Malformed Packet".

    The problem comes from the discovery event handler, where at some point I forward the events at both my custom event handler and the default event handler for default characteristics and services, and somewhere over there the handles for each service and characteristics are overlapped.

    I will isolate the connection to handle only my custom service, and if this doesn't fix the issue I will reply again here.

    Thanks again for the hint.

    BR,

  • Happy to help. :) Just post a comment here if you're still having issues. 

    Bjørn

  • I am not able to understand where the 0x180a UUID is assigned. I isolated my code and commented everything related to generic services and characteristics, and I still got it. Also, where does that service come from when enabling the CCCD? The only parameters there are conn_handle and write_params:

    static uint32_t cccd_configure(uint16_t conn_handle, uint16_t cccd_handle, bool enable)
    {
    
    	uint8_t buf[BLE_CCCD_VALUE_LEN];
    
        buf[0] = enable ? BLE_GATT_HVX_INDICATION : 0;
        buf[1] = 0;
    
        ble_gattc_write_params_t const write_params =
        {
            .write_op = BLE_GATT_OP_WRITE_REQ,
            .flags    = BLE_GATT_EXEC_WRITE_FLAG_PREPARED_WRITE,
            .handle   = cccd_handle,
            .offset   = 0,
            .len      = BLE_CCCD_VALUE_LEN,
            .p_value  = (uint8_t *)buf
        };
    
        return sd_ble_gattc_write(conn_handle, &write_params);
    }

    Where

    conn_handle: 0x0000
    cccd_handle: 0x0019

    Are the right ones.

    The handle on the sniffer should look like this (when enabled with nRF Connect APP):

    BR,

  • Hi Gabriel, 

    Gabriel C. said:
    I am not able to understand where the 0x180a UUID is assigned. I isolated my code and commented everything related to generic services and characteristics, and I still got it.

    Is this on the peripheral device or the central device? Or is the central device also a peripheral device at the same time? If its the latter, can you post the services_init() function as well as the code where you define your custom service and its characteristics, i.e. where you call sd_ble_gatts_service_add and characteristic_add(which in turn calls sd_ble_gatts_characteristic_add) ?

    Gabriel C. said:
    Also, where does that service come from when enabling the CCCD?

     No quite sure what you mean here. The cccd_configure is a function that writes to the CCCD of characteristic on the peripheral that the central want to receive notifications/indications from. 

    Best regards

    Bjørn

Related