Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to send more than 20 bytes data over ble in android?

I am trying to send more than 33 bytes using simple loops, Is anybody has idea how to send more than 20 bytes data over android ble.

if(!mConnected) return;
        for (int i = 0; i<str.length;i++) {
            if(str[i] == str[str.length -1]){
                 val = str[i]+"\n";
            }else {
                val = str[i] + "_";
            }
            System.out.println(val);
            mBluetoothLeService.WriteValue(val);
        }
like image 465
Nik Avatar asked May 08 '15 18:05

Nik


4 Answers

Sending more than 20 bytes via BLE is easily achievable by splitting your data into 20 byte packets and implementing a short delay (i.e. using sleep()) between sending each packet.

Here's a short snippet of code from a project I'm working on that takes data in the form of byte[] and splits it into an array of the same, ( byte[][] ), in 20 byte chunks, and then sends it to another method that transmits each packet one by one.

    int chunksize = 20;
    byte[][] packets = new byte[packetsToSend][chunksize]; 
    int packetsToSend = (int) Math.ceil( byteCount / chunksize);

    for(int i = 0; i < packets.length; i++) {
        packets[i] = Arrays.copyOfRange(source,start, start + chunksize);
        start += chunksize;
    }

    sendSplitPackets(packets);

Here are two other very good explanations of how to achieve this:

(Stackoverflow) Android: Sending data >20 bytes by BLE

(Nordic Semi) Dealing Large Data Packets Through BLE

like image 57
Brock Amhurst Avatar answered Oct 18 '22 02:10

Brock Amhurst


You can send more than 20 bytes of data without breaking into chunks and including a delay. Every characteristics you are trying to write has an MTU value assigned. It's number of bytes you can write in one time. During the connection MTU values are exchanged and you can write those many bytes at a time. You can increase the mtu value on the server side (Max 512 bytes) and send that much bytes in one go.

For Android, you might want to request mtu manually after connecting with the server using

requestMtu(int mtu)

This is return true or false based on the mtu value you send. It will give a callback to onMtuChanged where Android device and server negotiate the maximum possible MTU value.

onMtuChanged (BluetoothGatt gatt, int mtu, int status)

and you can set MTU value in this function and can send more than 20 bytes in one go.

like image 29
HelloWorld Avatar answered Oct 18 '22 03:10

HelloWorld


Some embedded bluetooth LE implementations limit the size of a characteristic to be 20 bytes. I know that the Laird BL600 series does this. This is limitation of the Laird module, even though the BLE spec calls for the max length to be longer. Other embedded BLE solutions have similar limits. I suspect this is the limitation that you are encountering.

like image 41
Rob Gorman Avatar answered Oct 18 '22 03:10

Rob Gorman


Instead of using sleep for every chunk, i just found a better and efficient way for my application to send more than 20 bit data.

The packets will be send after onCharacteristicWrite() triggered. i just found out this method will be triggered automatically after peripheral device (BluetoothGattServer) sends a sendResponse() method.

firstly we have to transform the packet data into chunk with this function:

public void sendData(byte [] data){
    int chunksize = 20; //20 byte chunk
    packetSize = (int) Math.ceil( data.length / (double)chunksize); //make this variable public so we can access it on the other function

    //this is use as header, so peripheral device know ho much packet will be received.
    characteristicData.setValue(packetSize.toString().getBytes());
    mGatt.writeCharacteristic(characteristicData);
    mGatt.executeReliableWrite();

    packets = new byte[packetSize][chunksize];
    packetInteration =0;
    Integer start = 0;
    for(int i = 0; i < packets.length; i++) {
        int end = start+chunksize;
        if(end>data.length){end = data.length;}
        packets[i] = Arrays.copyOfRange(data,start, end);
        start += chunksize;
    }

after our data ready, so i put my iteration on this function:

@Override
    public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
        if(packetInteration<packetSize){
        characteristicData.setValue(packets[packetInteration]);
        mGatt.writeCharacteristic(characteristicData);
            packetInteration++;
        }
    }
like image 40
Doni Avatar answered Oct 18 '22 02:10

Doni