Android: Sending Data >20 Bytes by Ble

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

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

Android: Sending data 20 bytes by BLE

BLE allows you transfer maximum of 20 bytes.

If you want to send more than 20 bytes, you should define array byte[] to contain how many packets you want.

Following example worked fine if you want to send less than 160 characters (160 bytes).

p/s : Let edit following as you want. Do not follow me exactly.

Actually, when we are using BLE, mobile side and firmware side need to set up the Key (ex. 0x03 ...) to define the connection gate among both sides.

The idea is :

  • When we continue to transfer packets, not is the last one. The gate is byte[1] = 0x01.

  • If we send the last one, The gate is byte[1] = 0x00.

The data contruction (20 bytes):

1 - Byte 1 - Define the Gate ID : ex. Message gate ID byte[0] = 0x03.

2 - Byte 2 - Define the recognization : Is the last packet 0x00 or continue sending packets 0x01.

3 - Byte 3 (Should be 18 bytes after eliminating Byte 1 & Byte 2) - Attach the message content in here.

please understand my logic before reading the code below.

Below is an example of sending a Message with many packets, each packet is an array of size 20 bytes.

private void sendMessage(BluetoothGattCharacteristic characteristic, String CHARACTERS){
byte[] initial_packet = new byte[3];
/**
* Indicate byte
*/
initial_packet[0] = BLE.INITIAL_MESSAGE_PACKET;
if (Long.valueOf(
String.valueOf(CHARACTERS.length() + initial_packet.length))
> BLE.DEFAULT_BYTES_VIA_BLE) {
sendingContinuePacket(characteristic, initial_packet, CHARACTERS);
} else {
sendingLastPacket(characteristic, initial_packet, CHARACTERS);
}
}

private void sendingContinuePacket(BluetoothGattCharacteristic characteristic,
byte[] initial_packet, String CHARACTERS){
/**
* TODO If data length > Default data can sent via BLE : 20 bytes
*/
// Check the data length is large how many times with Default Data (BLE)
int times = Byte.valueOf(String.valueOf(
CHARACTERS.length() / BLE.DEFAULT_BYTES_IN_CONTINUE_PACKET));

Log.i(TAG, "CHARACTERS.length() " + CHARACTERS.length());
Log.i(TAG, "times " + times);

// TODO
// 100 : Success
// 101 : Error
byte[] sending_continue_hex = new byte[BLE.DEFAULT_BYTES_IN_CONTINUE_PACKET];
for (int time = 0; time <= times; time++) {
/**
* Wait second before sending continue packet
*/
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}

if (time == times) {
Log.i(TAG, "LAST PACKET ");

/**
* If you do not have enough characters to send continue packet,
* This is the last packet that will be sent to the band
*/

/**
* Packet length byte :
*/
/**
* Length of last packet
*/
int character_length = CHARACTERS.length()
- BLE.DEFAULT_BYTES_IN_CONTINUE_PACKET*times;

initial_packet[1] = Byte.valueOf(String.valueOf(character_length
+ BLE.INITIAL_MESSAGE_PACKET_LENGTH));
initial_packet[2] = BLE.SENDING_LAST_PACKET;

Log.i(TAG, "character_length " + character_length);

/**
* Message
*/
// Hex file
byte[] sending_last_hex = new byte[character_length];

// Hex file : Get next bytes
for (int i = 0; i < sending_last_hex.length; i++) {
sending_last_hex[i] =
CHARACTERS.getBytes()[sending_continue_hex.length*time + i];
}

// Merge byte[]
byte[] last_packet =
new byte[character_length + BLE.INITIAL_MESSAGE_PACKET_LENGTH];
System.arraycopy(initial_packet, 0, last_packet,
0, initial_packet.length);
System.arraycopy(sending_last_hex, 0, last_packet,
initial_packet.length, sending_last_hex.length);

// Set value for characteristic
characteristic.setValue(last_packet);
} else {
Log.i(TAG, "CONTINUE PACKET ");
/**
* If you have enough characters to send continue packet,
* This is the continue packet that will be sent to the band
*/
/**
* Packet length byte
*/
int character_length = sending_continue_hex.length;

/**
* TODO Default Length : 20 Bytes
*/
initial_packet[1] = Byte.valueOf(String.valueOf(
character_length + BLE.INITIAL_MESSAGE_PACKET_LENGTH));

/**
* If sent data length > 20 bytes (Default : BLE allow send 20 bytes one time)
* -> set 01 : continue sending next packet
* else or if after sent until data length < 20 bytes
* -> set 00 : last packet
*/
initial_packet[2] = BLE.SENDING_CONTINUE_PACKET;
/**
* Message
*/
// Hex file : Get first 17 bytes
for (int i = 0; i < sending_continue_hex.length; i++) {
Log.i(TAG, "Send stt : "
+ (sending_continue_hex.length*time + i));

// Get next bytes
sending_continue_hex[i] =
CHARACTERS.getBytes()[sending_continue_hex.length*time + i];
}

// Merge byte[]
byte[] sending_continue_packet =
new byte[character_length + BLE.INITIAL_MESSAGE_PACKET_LENGTH];
System.arraycopy(initial_packet, 0, sending_continue_packet,
0, initial_packet.length);
System.arraycopy(sending_continue_hex, 0, sending_continue_packet,
initial_packet.length, sending_continue_hex.length);

// Set value for characteristic
characteristic.setValue(sending_continue_packet);
}

// Write characteristic via BLE
mBluetoothGatt.writeCharacteristic(characteristic);
}
}

public boolean writeCharacteristic(BluetoothGattCharacteristic characteristic,
String data) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return false;
}

if (ActivityBLEController.IS_FIRST_TIME) {
/**
* In the first time,
* should send the Title
*/
byte[] merge_title = sendTitle(data);

// Set value for characteristic
characteristic.setValue(merge_title);

// Write characteristic via BLE
mBluetoothGatt.writeCharacteristic(characteristic);

// Reset
ActivityBLEController.IS_FIRST_TIME = false;

return true;
} else {
/**
* In the second time,
* should send the Message
*/
if (data.length() <= BLE.LIMIT_CHARACTERS) {
sendMessage(characteristic, data);

// Reset
ActivityBLEController.IS_FIRST_TIME = true;

return true;
} else {
// Typed character
typed_character = data.length();

return false;
}
}
}

How to split and send data 20 bytes for BLE in Xamarin forms?

You can try and send the data in multiple chunks each having a maximum size of 20.
This example sends the first chunk of 20 bytes, then another one with the remaining 7.

            byte[] senddata = Encoding.ASCII.GetBytes("Hi1290004847846767627723676");
int start = 0;
while (start < senddata.Length)
{
int chunkLength = Math.Min(20, senddata.Length - start);
byte[] chunk = new byte[chunkLength];
Array.Copy(senddata, start, chunk, 0, chunkLength);
await writeBuf.WriteAsync(chunk);
start += 20;
}

Edits:

  • Removed comment which was copy & pasted

Notify transmission is complete over 20 bytes onCharactersitcChanged BLE

Use https://developer.android.com/reference/android/bluetooth/BluetoothGatt.html#requestMtu(int) to attempt to increase the MTU. The notification maximum size is MTU - 3.

There is no procedure defined in the Bluetooth standard to "tell when all bytes have been received" nor "request more data". That is application specific.



Related Topics



Leave a reply



Submit