I am using an android device with Android 5.1 (Bluetooth 4.0) and a MCU Board which has Bluetooth 4.2.
On my MCU side i am updating my Gatt Characteristic in a Loop just to make sure, that i know if the data i am writing inside is consistent. before i am writing it inside the gatt database i am using a crc check.
on my android side i just have a thread which reads the characteristic out of that gatt database and directly after that i have the same crc but it seems like 50% of the values are corrupt (which doesn't make sense from my side).
i know that the data i am writing in my gatt database is correct so i guess the issue is with reading the characteristic several times in a thread.
i've already tried to read the characteristic via notifications on my android side but the bluetoothleservice is never jumping into the OnCharacteristicChanged callback.
my characteristic update Looks like this
tmpGatt.readCharacteristic(characteristic);
and the characteristic is filtered by the uuid before
for(int i = 0; i<Services.size(); i++){
Characteristics = Services.get(i).getCharacteristics();
for(int c=0;c < Characteristics.size();c++){
UUID myUUID = Characteristics.get(c).getUuid();
if(myUUID.toString().equals("354a1b8e-7597-11e6-8b77-86f30ca893d3")){
characteristic = Characteristics.get(c);
//refExternalData.getRefBluetoothGatt().readCharacteristic(characteristic);
descriptor = characteristic.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"));
Log.i("BLE", "Characteristic " + myUUID.toString() + " found");
}
}
}
so do i Need to do anything Special to re-read the gattcharacteristic?
Did you follow the procedures at https://developer.android.com/guide/topics/connectivity/bluetooth-le.html#notification in order to enable notifications?
When you issue readCharacteristic, you are not allowed to issue a new readCharacteristic until you have got the onCharacteristicRead. Or actually you are not allowed to send ANY new request (readCharacteristic, writeCharacteristic, readDescriptor, writeDescriptor) until a previous request has completed. This is because there may only be one outstanding GATT request at a time and there is no internal queue.
Related
I've a bluetooth gatt service and two channels to write
bluetoothGattService = gatt?.getService(UUID.fromString(ble_gatt_service_uuid))
mTxCharacteristic1 = bluetoothGattService.getCharacteristic(UUID.fromString(txCharacteristics1))
mTxCharacteristic2 = bluetoothGattService.getCharacteristic(UUID.fromString(txCharacteristics2))
Now I have onCharacteristicsRead(), onCharacteristicsWrite(), and onCharacteristicsChange()
I connected with the ble device
When I write on mTxCharacteristic1 characteristic then ble works well
But whenever I write on mTxCharacteristic2 characteristic then ble gets DISCONNECTED
// function1
mTxCharacteristic1.writeType = BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE
mTxCharacteristic1.value = chunk
gatt.writeCharacteristic(mTxCharacteristic1)
//function 2
mTxCharacteristic2.writeType = BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT
mTxCharacteristic2.value = chunk
gatt.writeCharacteristic(mTxCharacteristic2)
How to resolve this?
Everytime it is getting disconnected whenever I send data using 2nd characteristics, I'm only able to connect with ble again only when I restart my android device.
I tried:
gatt.beginReliableWrite()
gatt.setCharacteristicNotification(characteristic1,true)
gatt.writeCharacteristic(characteristic1)
gatt.executeReliableWrite()
gatt.beginReliableWrite()
gatt.setCharacteristicNotification(characteristic2,true)
gatt.writeCharacteristic(characteristic2)
gatt.executeReliableWrite()
nrf connect app showing (TX(1) and unknown_characteristic(2))
still getting the same disconnected with gatt server issue with state 133.
Just made this simple writeCharacteristics instead of reliableWrite on doing this disconnection and no repairing issue resolved
gatt.writeCharacteristic(characteristic1)
gatt.writeCharacteristic(characteristic2)
I was have 8 byte of packet data where I sent null which I found on debugging
expected was 19 byte array and I was sending only 11 packets (8 missed)
due to this it was giving me error and getting disconnected with state code 133
Following is my reliable gatt characteristic reliable write function and byte array byte1 is having value more than 20 bytes.
private void beginReliableWriteToGattServer(BluetoothDevice device, UUID serviceUUID,UUID charUUID, byte[] byte1){
if(mGatt != null){
BluetoothGattService service = mGatt.getService(serviceUUID);
if(service != null){
BluetoothGattCharacteristic gattCharacteristic = service.getCharacteristic(charUUID);
if(gattCharacteristic != null){
Logger.d(TAG, "BeginReliable Write="+mGatt.beginReliableWrite());
gattCharacteristic.setValue(byte1);
mGatt.writeCharacteristic(gattCharacteristic);
Logger.d(TAG, "ExecuteReliable Write="+mGatt.executeReliableWrite());
}
}
}
}
Below are write Gatt characteristic logs
BeginReliable Write=true
ExecuteReliable Write=false
D/Bluetooth_GATTCallBack: onCharacteristicWrite 17
First, you can't have multiple GATT requests outstanding at the same time. Since both writeCharacteristic and executeReliableWrite are requests to the peer device (beginReliableWrite is not a request but only sets a flag in Android's BLE stack that the following writes are "reliable writes"), you need to first wait for the onCharacteristicWrite until you are allowed to send executeReliableWrite.
Now, regarding error code 17, I assume this corresponds to the ATT error code Insufficient Resources 0x11. To handle that you need to check why the peripheral sends that error code.
You should also know that Android has a design bug that reliable writes aren't really reliable. The protocol is that the data is first sent to the server, then the server sends the same data back to the client. According to the GATT specification, the client must then verify that the received data is equal to the sent data, otherwise it must abort. Unfortunately that info gets lost between the C and Java layer in Android's Bluetooth stack so there is no way to verify this.
My Android app is made as a BLE central device. I have a device which is peripheral. I want to send some data from Android app to peripheral device without any request from the peripheral. Can I achieve this ?
In my peripheral device to write data i am using below code :
BluetoothGattCharacteristic charac = Service
.getCharacteristic(UUID.fromString(SampleGattAttributes.LOCAL_TIME));
byte[] value = new byte[1];
String valuetosend = "data from client to server";
value = valuetosend.getBytes();
charac.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
charac.setValue(value);
Log.d("BluetoothLeservice::","Write Status:" + charac.getValue());
boolean status = mBluetoothGatt.writeCharacteristic(charac);
Do I have to do in the same way for central also? Any reference links would be helpful.
I think the process is same, you have to write data to the particular characteristic and service. You should know the value of the characteristic and service. In your case it is SampleGattAttributes.LOCAL_TIME.
I am trying to write data by using the blow code, successfully received on the target.
boolean status = mBluetoothGatt.writeCharacteristic(characteristic);
byte[] value = new byte[1];
value[0] = (byte)inputvalue;
characteristic.setValue(value);
if (value.length <20){
boolean status = mBluetoothGatt.writeCharacteristic(characteristic);
Log.d("send Status ******- : ", String.valueOf(status));
}
But, When I am trying the write the multiple times can't send the data.
Also tried to send with a 2 second delay then, it is working fine.
How can I do it with out a delay
BLE on Android is asynchronous and notoriously difficult to work with. Typically you have to wait for the first GATT operation to complete before you can perform follow up GATT operation (which is why it works when you add a delay).
I would recommend you checkout this project from Nordic semiconductor which includes a nice queue processor that makes BLE manageable. https://github.com/NordicSemiconductor/puck-central-android
I am implement the connection between Android and BLE? like Anti-lost or finder , After android phone has connected to the BLE device , phone read the RSSI of BLE device every second.
If the RSSI of BLE device is lower than RSSI threshold , it deem Out of Range. For example: Threshold is -70 , and the current RSSI of device is -80.
When app is deem Out of Range. it send the message to the BLE every 5 second. But it always disconnect after few times. I uses the following code to send the message to the BLE device.
BluetoothGattService HelloService = Gatt.getService(HELLO_SERVICE_UUID);
if(HelloService == null) {
Log.d(TAG, "HelloService not found!");
return;
}
//If the Service is not null , try to get the characteristic.
BluetoothGattCharacteristic Characteristic = HelloService.getCharacteristic(UUID_HELLO_CHARACTERISTIC);
if(Characteristic == null) {
Log.d(TAG, "Characteristic not found!");
return;
}
Gatt.setCharacteristicNotification(Characteristic, true);
Characteristic.setValue(text, BluetoothGattCharacteristic.FORMAT_UINT8, 0);
Gatt.writeCharacteristic(Characteristic);
Log.d(TAG, "StepCount Characteristic End!");
The above code is correct , the BLE can receive the message. But the BLE device will disconnect after few second. It seems do more than one thing in a short time is burden to BLE device.
The question is: How to make the connection more stable between Android and BLE ?.
Some suggestions:
Don't use notifications if you can avoid it. Based on personal experience with some phones in some environments notifications can stop working and appear to cause general instability. Try to do periodic reads instead.
Only do a read or write once you have received a callback to BluetoothGattCallback.onCharacteristicWrite() or BluetoothGattCallback.onCharacteristicRead() for the previous read or write.
More generally, never do two things at once, whether that be scanning, connecting, reading, writing, whatever. You should serialize all operations using a job queue, only popping from that queue when the previous job completes (or fails).
In almost-out-of-range scenarios like you're talking about, operations can take a long time to complete, longer than 5 seconds sometimes. So doing another operation in 5 seconds or less you're effectively "stomping" the previous operation. However, operations can also never return with a callback in these cases, so you do have to implement a timeout. I use 10 seconds. Beyond that, the operation failed.