Send large amount of data through BLE with pc-ble-driver-py

Hi,

I'm using nRF52840 BLE Dongle to connect and perform bonding to a custom target.

The connection and bonding are working but I need to write a token (lenght=291) to a characteristic and got error "NRF_ERROR_SD_RPC_SEND".

From what I understand, The MTU can't be updated over 247. Is that correct ? Is there a way to update MTU, making possible the transfer of large amount of data ?

Or is there other way to perform the data transfer with adapter.write_cmd or adapter.write_req ?

I followed some example on the github but without any success...

Note: Running on Windows 10, with python=3.10.11 and pc-ble-driver-py=0.17.0

Any help is welcome !

Best regards,

Antoine

  • HI there,

    The maximum practical MTU size for the   using pc-ble-driver-py is around 247 bytes, which is less than your 291-byte token. 
    MTU Limitation
    Your understanding is largely correct: the maximum configurable MTU size with the standard Nordic SoftDevice and pc-ble-driver-py setup is typically 247 bytes. This limit is due to underlying BLE packet structure and SoftDevice serialization constraints. Therefore, you cannot send a 291-byte payload in a single ATT packet. 
    Solution: Data Fragmentation
    To transfer a token of 291 bytes, you need to fragment (split) the data into smaller chunks that fit within the negotiated MTU size and send them sequentially. The receiving device must then reassemble these chunks. 
    Here is how you can implement this approach using adapter.write_req or adapter.write_cmd:
    • Determine the maximum payload size: After connecting and negotiating the MTU, you need to know the maximum number of data bytes you can send per write operation. This is typically MTU - 3 bytes (3 bytes are used for the ATT command header).
    • Split the data: Divide your 291-byte token into chunks of this maximum payload size.
    • Send sequentially: Use a loop to send each chunk to the characteristic. adapter.write_req ensures reliable delivery with responses, while adapter.write_cmd (write without response) is faster but less reliable (you'd need to handle flow control, like waiting for a BLE_GATTS_EVT_HVN_TX_COMPLETE event, if sending many packets in quick succession). For a single large token, write_req might be simpler.
    • Reassemble on the target: The custom target device's firmware must be designed to receive these fragmented writes and concatenate them into the original 291-byte token.   

    While the exact implementation depends on your existing code structure, here's a conceptual outline:

    python
    # Assuming 'adapter' is your BLEAdapter instance and 'conn_handle' is the connection handle
    # and 'char_handle' is the handle of your characteristic
    
    token = b"..." # Your 291-byte token as bytes
    
    # The maximum payload size will be the negotiated MTU size minus 3 bytes for overhead.
    # You can typically determine this after the connection and MTU exchange.
    # Let's assume a max payload size of 244 bytes for this example.
    max_payload_size = 244 
    
    # Split the token into chunks
    chunks = [token[i:i + max_payload_size] for i in range(0, len(token), max_payload_size)]
    
    for chunk in chunks:
        try:
            # Use adapter.write_req for a reliable transfer
            adapter.write_req(conn_handle, char_handle, chunk)
            print(f"Sent chunk of size {len(chunk)}")
        except Exception as e:
            print(f"Error sending chunk: {e}")
            # Handle the error, possibly NRF_ERROR_SD_RPC_SEND again if something is wrong with the chunking
            break
    
    # The target device will receive multiple write events and combine the data.

    HTH

    GL :-) PJ V

  • Hi PJ,

    Thank you for the details response !

    I tried your code sample and it does the correct job ! But unfortunately, the target does't not handle chunk for token...

    I have few last questions:

    - So there is no possible update of pc-ble-driver-py package to increase the MTU ?

    - What the error NRF_ERROR_SD_RPC_SEND means ? Because it occurs when trying to send the 291 bytes lenght data. but it's not the same error as invalid lenght

    Anyway, thank for your response, it's clear for my issue !

    Best regards,

    Antoine

  • Hi there,

    So it is the same error just higher up from the SoftDevice...AFAIK there is NO 291 byte possible MTU Fingers crossed

    the target would need some code to handle the chunks, maybe something like they do in I2S ?

    HTH

    GL :-) PJ V

  • Hi PJ,

    Okay, all clear for me, thank you for the reply !

    I'm going to try to perform my tests with bleak python package or check if a firmware update to receive chunk is possible.

    Best regards,

    Antoine

Related