This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

sd_ble_gatts_rw_authorize_reply() multiple client reading characteristic

Hi,

I'm developing a star network with one Server and up to 20 Clients (nrf52840 with S140). The Server holds a large configuration blob (>8kB) which needs to be sent to each Client that connects to it. I don't really want to deal with flow control on the App layer, handling each Client's progress of getting the blob, keeping records of ATT_MTU, sending HVX indication etc...

It would be better to have it done on the Client side, reading the characteristic for as long as it needs to. I read about GATT READ /w Authorization and my question is two-fold:

  1. Can I utilize the full range of the uint16_t offset and read from the characteristic up to 64kB? Even so if the characteristic size is only 32 byte or that the MAX ATT size is 512 bytes? I would feed the values on the Server side when I get BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST in the reply by giving the requested offset, pointer to the large config array and the length, which is ATT_MTU-1.
  2. What happens when all 20 connections are trying to do the same? Are READ REPLIES update the attribute value table and corrupt the fragments that the other Clients were meant to be given? Are there any race condition on the Characteristic value, or every reply is only meant to the client that requested it and the SoftDevice keeps track of each connection handle's offsets and lengths etc...?

Thank you in advance!

Best Regards,

Roland

EDIT:
I quickly made my characteristic able to handle rd_auth and had the following experience. Here is the code:

static void on_rw_auth_req(ble_obu_t * p_obu, ble_evt_t const * p_ble_evt)
{
	ret_code_t err_code;
	ble_gatts_evt_read_t ble_evt_read = p_ble_evt->evt.gatts_evt.params.authorize_request.request.read;

	if (p_ble_evt->evt.gatts_evt.params.authorize_request.type == BLE_GATTS_AUTHORIZE_TYPE_READ) {
		ble_gatts_rw_authorize_reply_params_t reply = {
			.type = BLE_GATTS_AUTHORIZE_TYPE_READ,
			.params.read.gatt_status = BLE_GATT_STATUS_SUCCESS,
			.params.read.offset = ble_evt_read.offset,
			.params.read.p_data = test_array,
			.params.read.update = 1,
			.params.read.len = 22
		};

		NRF_LOG_DEBUG("handle: %04X, offset=%i; data_def_handles.value_handle: %04X",
		                    ble_evt_read.handle,
		                    ble_evt_read.offset,
							p_obu->data_def_handles.value_handle);
		
		err_code = sd_ble_gatts_rw_authorize_reply(p_ble_evt->evt.gatts_evt.conn_handle, &reply);
		if (err_code != NRF_SUCCESS) {
			NRF_LOG_ERROR("sd_ble_gatts_rw_authorize_reply() error: %i", err_code);
		}
	}
}

For the test, it just mechanically gives back a test array pre-filled with values with the requested offset and fixed length. I am using nRF Connect mobile to initiate GATT READ. In SEGGER ES, I'm monitoring the outcome through the RTT, here is the result:

<info> app: Link 0 accepted the connection parameters
<debug> nrf_ble_gatt: Peer on connection 0x0 requested a data length of 27 bytes.
<debug> nrf_ble_gatt: Updating data length to 27 on connection 0x0.
<debug> nrf_ble_gatt: Data length updated to 27 on connection 0x0.
<debug> nrf_ble_gatt: max_rx_octets: 27
<debug> nrf_ble_gatt: max_tx_octets: 27
<debug> nrf_ble_gatt: max_rx_time: 328
<debug> nrf_ble_gatt: max_tx_time: 1363
<info> app: Data length is set to 27 on link 0
<debug> ble_obu: handle: 002C, offset=0; data_def_handles.value_handle: 002C
<debug> ble_obu: handle: 002C, offset=22; data_def_handles.value_handle: 002C
<debug> ble_obu: handle: 002C, offset=44; data_def_handles.value_handle: 002C
<debug> ble_obu: handle: 002C, offset=66; data_def_handles.value_handle: 002C
<debug> ble_obu: handle: 002C, offset=88; data_def_handles.value_handle: 002C
<debug> ble_obu: handle: 002C, offset=110; data_def_handles.value_handle: 002C
<error> ble_obu: sd_ble_gatts_rw_authorize_reply() error: 7

It seems that the process is working until the last offset + 22 is exceeding my BLE_OBU_MAX_DATA_LEN macro, which equals to 128 - 1 - 2 = 125. in the sdk_config.h, the NRF_SDH_BLE_GATT_MAX_MTU_SIZE is set to 128. Does this mean that a long characteristic can be never read beyond this length and since the MAX ATT SIZE is 510ish for the nRF52840, that is the absolute limit for the long read operation?

Can I not make the characteristic somewhat transparent, forcing the SoftDevice to give back fragments of data and not taking these limitations into consideration?

Parents
  • It seems that the process is working until the last offset + 22 is exceeding my BLE_OBU_MAX_DATA_LEN macro, which equals to 128 - 1 - 2 = 125. in the sdk_config.h, the NRF_SDH_BLE_GATT_MAX_MTU_SIZE is set to 128. Does this mean that a long characteristic can be never read beyond this length and since the MAX ATT SIZE is 510ish

    That is correct, and that is from the Bluetooth core specification. The blob size cannot be greater than 512 (external link).

Reply
  • It seems that the process is working until the last offset + 22 is exceeding my BLE_OBU_MAX_DATA_LEN macro, which equals to 128 - 1 - 2 = 125. in the sdk_config.h, the NRF_SDH_BLE_GATT_MAX_MTU_SIZE is set to 128. Does this mean that a long characteristic can be never read beyond this length and since the MAX ATT SIZE is 510ish

    That is correct, and that is from the Bluetooth core specification. The blob size cannot be greater than 512 (external link).

Children
No Data
Related