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);
}
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
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.
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.
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++;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With