BluetoothLE sending pakets > 20 bytes

41 Views Asked by At

I realize there are several posts asking this question, but I can't seem to solve this problem with the provided answers.

Here is what I am doing: in an existing app that was used with different scanners via bluetooth before, I want to integrate a new scanner. It uses bluetooth LE and with previous scanners everything worked fine. The new scanner requires me to send pakets > 20 bytes.

As I understand from the other posts, there are two ways to accomplish this.

  1. increase the mtu
  2. split the message into sub packets <= 20 bytes and send them individually

Increasing the MTU: in my gatt callback onConnectionStateChange I check if the connection was established and then call

gatt.requestMtu(100);

In the gatt callback onMtuChanged the new mtu is 100, so the scanner has accepted the request.

When I try to write a large packet to the characteristic (with gatt.writeCharacteristic(...)), it returns true. But the scanner sends a response, that tells me that the write has failed. My guess at this point is, that either the scanner does not really handle the large packet properly or the message itself has invalid content. This is something I am trying to clarify with the scanner's support but I got no feedback yet.

Splitting the packet:

I tried this option as well. Splitting the message into smaller parts like this

int packetSize = 20;
int numPackets = (int) Math.ceil(packetData.length / 20.0);
int remainingPacketSize = (int) packetData.length % packetSize;

int numBytesAlreadyUsed = 0;

for (int i = 0; i < numPackets; i++) {

    Thread.sleep(1000);
    if (i == numPackets - 1)  // last packet part
    {
         packetSize = remainingPacketSize;
    }
    byte[] data = new byte[packetSize];

    for (int j = 0; j < packetSize; j++) {
         data[j] = packetData[numBytesAlreadyUsed];
         numBytesAlreadyUsed++;
    } 
...
}

I tried two different variants of this.

Variant 1:

In my app I am using a queuing mechanism to make sure the messages are only sent, after onCharacteristicWrite was received. So I enqueued the sub pakets one after the other to make sure that the gatt's onCharacteristicWrite gets triggered. Problem is, that the scanner, after it received the first message, does not send any response, so the gatt.onCharacteristicWrite does not get triggered. After a while the scanner runs into a timeout waiting for the next sub packet which results in it treating the first paket as complete (which it is not) and responding with a message indicating that the write was not successful.

Variant 2:

I enqueue only on request which includes the loop and the calls to gatt.writeCharacteristic(...) for the different sub packets. Since this is not waiting for onCharacteristicWrite before sending the next sub packet, the sub packets do not get sent at all. In the BluetoothGatt, writeCharacteristic(...) always returns false, because mDeviceBusy is still true.

synchronized (mDeviceBusyLock) {
    if (mDeviceBusy) return false;
    mDeviceBusy = true;
}

As a conslusion, I think changing the mtu should work and would be the cleanest way. But for the splitting of packets, is there any way to send write messages without waiting for responses? Using the WRITE_TYPE_NO_RESPONSE seems to be ignored. Are there other options to solve this problem?

0

There are 0 best solutions below