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

S132: Is it possible to send an empty notification

My previous product uses an empty notification to indicate that a bulk transfer is finished. I attempted to send an empty notification but got error code 0x10 (NRF_ERROR_INVALID_FLAGS).

Is there a way to send an empty notification?

ble_gatts_hvx_params_t hvx_param =
{
    .type   = BLE_GATT_HVX_NOTIFICATION,
    .handle = p_ctx->bulkdata_handle,
    .p_data = data,
    .p_len  = &len,
};
hvx_param.p_len = 0;
err_code = sd_ble_gatts_hvx(p_ctx->conn_handle, &hvx_param);

[Edit]

No empty packet sent when p_data = NULL and p_len = 0.

image description

Example of an empty notification packet being sent by TI CC2540.

image description

[Edit 2]

Alright. Added print on TX_COMPLETE.

Heres the log at the end of the transfer. Its hard to tell if one of these completes correlates to the empty notification.

BULKDATA:INFO:on_tx_complete: 503
BULKDATA:INFO:on_tx_complete: 504
APP:INFO:Sent 10 KBytes
BULKDATA:INFO:on_tx_complete: 505
BULKDATA:INFO:Sent empty packet, error code: 0x0
APP:INFO:Finished.
BULKDATA:INFO:on_tx_complete: 506
BULKDATA:INFO:on_tx_complete: 507
BULKDATA:INFO:on_tx_complete: 508
BULKDATA:INFO:on_tx_complete: 509
BULKDATA:INFO:on_tx_complete: 510
BULKDATA:INFO:on_tx_complete: 511
BULKDATA:INFO:on_tx_complete: 512
BULKDATA:INFO:on_tx_complete: 513

I rebuilt without sending the empty packet and there does appear to be one less "on_tx_complete" after the Finished printout.

BULKDATA:INFO:on_tx_complete: 503
BULKDATA:INFO:on_tx_complete: 504
APP:INFO:Sent 10 KBytes
BULKDATA:INFO:on_tx_complete: 505
APP:INFO:Finished.
BULKDATA:INFO:on_tx_complete: 506
BULKDATA:INFO:on_tx_complete: 507
BULKDATA:INFO:on_tx_complete: 508
BULKDATA:INFO:on_tx_complete: 509
BULKDATA:INFO:on_tx_complete: 510
BULKDATA:INFO:on_tx_complete: 511
BULKDATA:INFO:on_tx_complete: 512

Next I modified the code to send only empty notifications. This is where things get weird. It appears that each notification is 9 bytes of 0xFF. 9 bytes happens to be the initial length of the characteristic however the characteristic is initialized to all zeros.

Char init code, generated by BDS:

ble_app_app_generic_data_rcv_t app_generic_data_rcv_initial_value = p_app_init->ble_app_app_generic_data_rcv_initial_value; 

ble_add_char_params_t add_app_generic_data_rcv_params;
memset(&add_app_generic_data_rcv_params, 0, sizeof(add_app_generic_data_rcv_params));

add_app_generic_data_rcv_params.uuid                = 0xFF25;
add_app_generic_data_rcv_params.uuid_type           = ble_uuid.type; 
add_app_generic_data_rcv_params.max_len             = NRF_BLE_GATT_MAX_MTU_SIZE;
add_app_generic_data_rcv_params.init_len            = app_generic_data_rcv_encode(&app_generic_data_rcv_initial_value, app_generic_data_rcv_encoded_value);
add_app_generic_data_rcv_params.p_init_value        = app_generic_data_rcv_encoded_value; 
add_app_generic_data_rcv_params.is_value_user       = 1; 
add_app_generic_data_rcv_params.char_props.notify   = 1; 
add_app_generic_data_rcv_params.char_props.write    = 1; 
add_app_generic_data_rcv_params.write_access        = SEC_OPEN; 
add_app_generic_data_rcv_params.cccd_write_access   = SEC_OPEN;
// 1 for variable length and 0 for fixed length.
add_app_generic_data_rcv_params.is_var_len          = 1;

err_code = characteristic_add(p_app->service_handle, &add_app_generic_data_rcv_params, &(p_app->app_generic_data_rcv_handles));

How did you setup your characteristic?

  • endnode, I'm not sure what you mean by ATT MTU but I am not receiving an empty notify packet on my client side.

    Since you suggested it, I fired up the ble sniffer and confirmed that I am not seeing the packet sent here either. I can see the last 20B notification which I received but no empty notification send. Note: I can't see to attach an image to a comment.

    Not sure what you mean by watching "in radio". Is there some way to get more detailed info from the S132 about what its doing?

  • No, sniffer is the right thing, I don't have any other magic tool. Notify is ATTribute layer method (command if you want), that's why I talk about ATT MTU. You can only update your original question or create answer, you cannot add images to the comment on this forum. So what you say is that by using code snippet pasted above you are able to issue sd_ble_gatts_hvx(...) with NULL pointer in p_data and 0 in p_len, you get NRF_SUCCESS as error code but you cannot see any Notification issued over BLE link, there are just empty LL PDUs exchanged every connection interval?

  • Thanks. Yes I added the picture to the original post. After the count pattern is finished sending there is supposed to be an empty notification packet sent.

  • Yes, I see it now. So the code sends 3 "full" packets and then empty one? I'm surprised that if you do so that there are no connection interval with several PDUs/MTUs exchanged. Or do you send it one by one after you receive BLE_EVT_TX_COMPLETE (or some equivalent)? Do you get this also when you send to the stack through SD API empty sd_ble_gatts_hvx?

  • So far I've copied the mtu throughput amts.c example and modified it slightly to send packets when a certain characteristic is written to.

    I was also surprised it was only sending one notification per connection event. I was expecting atleast 4, that was likely going to be my next problem to look at. The amts.c code has a while NRF_SUCCESS loop which keeps calling hvx() until it gets the NO_TX_PACKETS error so I'd have expected it to send more than just one per.

    Note that is just the bottom of the log, it sends about 10k of packets total for this test.

    "Do you get this also when you send to the stack through SD API empty sd_ble_gatts_hvx?" Whats SD API empty?

Related