We developed a little hardware piece that works with Bluetooth Low Energy. When connecting from an Android 5, all services and their characteristics are discovered successfully.
However, we tried with 3 Android 6 devices, and even though the services are found correctly, their characteristics return null all the time.
I made sure the UUIDs are correct by logging all the discovered services, characteristics & descriptors.
Android 5:
service [uuid]:[00001801-0000-1000-8000-00805f9b34fb]
characteristic [uuid]:[00002a05-0000-1000-8000-00805f9b34fb]
service [uuid]:[00001800-0000-1000-8000-00805f9b34fb]
characteristic [uuid]:[00002a00-0000-1000-8000-00805f9b34fb]
characteristic [uuid]:[00002a01-0000-1000-8000-00805f9b34fb]
characteristic [uuid]:[00002aa6-0000-1000-8000-00805f9b34fb]
service [uuid]:[5765536d-0000-1000-8000-00805f9b34fb]
characteristic [uuid]:[00005765-0000-1000-8000-00805f9b34fb]
descriptor [uuid]:[00002902-0000-1000-8000-00805f9b34fb]
service [uuid]:[5765536e-0000-1000-8000-00805f9b34fb]
characteristic [uuid]:[00005764-0000-1000-8000-00805f9b34fb]
descriptor [uuid]:[00002902-0000-1000-8000-00805f9b34fb]
Android 6:
service [uuid]:[00001801-0000-1000-8000-00805f9b34fb]
characteristic [uuid]:[00002a05-0000-1000-8000-00805f9b34fb]
service [uuid]:[00001800-0000-1000-8000-00805f9b34fb]
characteristic [uuid]:[00002a00-0000-1000-8000-00805f9b34fb]
characteristic [uuid]:[00002a01-0000-1000-8000-00805f9b34fb]
characteristic [uuid]:[00002aa6-0000-1000-8000-00805f9b34fb]
service [uuid]:[5765536d-0000-1000-8000-00805f9b34fb]
service [uuid]:[5765536e-0000-1000-8000-00805f9b34fb]
Is there any known issue provoking this? I am using BluetoothAdapter and BluetoothLeScanner.
Thank you.
It worked on Android 6 after we changed the service UUID's from:
5765536d-0000-1000-8000-00805f9b34fb
5765536e-0000-1000-8000-00805f9b34fb
To:
3032454c-426b-7261-5074-72616d536557
3031454c-426b-7261-5074-72616d536557
It also worked when we reduced the UUID's size from 32bits to 16bits, this means, the first four digits being zero 0000XXXX.
Related
Can any one please help.
I am developing a Bluetooth Low Energy App
Works are done:
Devices Scan
Device Connection
Write to remote Device Raspberry Pi
The remote device has service id:
6e400001-b5a3-f393-e0a9-e50e24dcca9e
Write Strings is:
6e400002-b5a3-f393-e0a9-e50e24dcca9e
Notify String is:
6e400003-b5a3-f393-e0a9-e50e24dcca9e
All above custom services working well on IOS and on Android all done instead of listening to remote device notification.
I can write with:
gatt.writeCharacteristic(characteristicWrite);
I can enable notification with:
gatt.setCharacteristicNotification(characteristicNotify, true);
But when I try to fetch descriptor the descriptor is always null.
I tried:
UUID uuid = UUID.fromString("00000001-0000-1000-8000-00805f9b34fb");
BluetoothGattDescriptor descriptor =
characteristic.getDescriptor(uuid);
UUID uuid = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
BluetoothGattDescriptor descriptor =
characteristic.getDescriptor(uuid);
UUID uuid = convertFromInteger(0x2902); BluetoothGattDescriptor
descriptor = characteristic.getDescriptor(uuid);
UUID.fromString("6e400003-b5a3-f393-e0a9-e50e24dcca9e");
UUID.fromString("6e400002-b5a3-f393-e0a9-e50e24dcca9e");
UUID.fromString("6e400001-b5a3-f393-e0a9-e50e24dcca9e");
in all cases the descriptor is return null and I cannot set descriptor notification value.
The server guy told the descriptor value not configured on server device, same device working fine on IOS but on Android notification not receiving.
I tested same device with this app:
https://play.google.com/store/apps/details?id=no.nordicsemi.android.nrftoolbox
I can recieve notification with the help of this app.
Above app listening on:00002902-0000-1000-8000-00805f9b34fb for descriptor
But with same UUID I can not getting notification.
Sorry for my English.
I have found my answer after two days research.
Please see reference app for testing any BLE device.
The app change request MTU and then enable notification.
My steps to write and listen notification given below:
First I tired to request MTU and then write with notification value. After first try with the help of notification token the descriptor is written successfully.
After that step I can write and listen with given device.
My be any one facing same problem so please consider above given application and check application logs. Every step will be clear by given app.
BLE and Android, the more characteristics and services the more slowly
Following problem:
I’m working on a project with android (5.0+) and a Nordic BLE chip (NRF52832) to receive values from the chip on the android device.
(I don’t use third party packages)
Connect, readout the services and the characteristics works well and fast, but:
As soon as I set more characteristics (in 2 services) on notify, the values arrive the device very slow, for example:
Notify 1 characteristic = 50ms/value
Notify 1 service 6 characteristic = 150 – 200ms/value
Notify 2 service, 10 characteristics = 400-600ms/value`
RequestConnectionPriority won’t solve my case.
Does anyone have a solution statement or already a solution?
It is a know problem that using multiple services and characteristics can slow down the communication between a BLE center and a peripheral.
Furthermore, each characteristic has an overhead cost in terms of memory consumed on the device.
A solution to this problem is to minimize the number of characteristics you're using.
To do so, you could for instance use only one characteristic and dedicate one octet of the characteristic packet to storing the command id or info type you're sending or receiving from the device.
The same characteristic can then be used to send various command to your device, or to request various type of info from the device.
We are designing both a BLE device, and the mobile phone app to talk to it. We've defined a characteristic on the BLE device that has the properties
<properties write_no_response="true" notify="true" read="true" write="true" indicate="true"/>
Yes, it's overkill, we're in very early development.
The communication is working fine when I write to a characteristic on the device, but if I switch to Write Without Response:
m_characteristic.WriteType = GattWriteType.NoResponse;
m_characteristic.SetValue (bytes);
m_gatt.WriteCharacteristic (m_characteristic);
the call to WriteCharacteristic() fails.
1) Is it "legal" to have a characteristic that does both write_no_response and write?
2) Is it "legal" to switch from a regular write (GattWriteType.Default) to a write_no_response?
3) Is there any way to ask the BLE library why WriteCharacteristic() failed?
I'm trying to create an Android 5 (lollipop) app that acts as a Bluetooth Low Energy (BLE) peripheral. The app runs on a Nexus 9 which supports BLE peripheral mode. So far I've managed to advertise a service and allow another BLE device connect to it successfully. However, it is fails when trying to read the characteristic value.
I've checked that the characteristic has the read property and that the read permission is set.
When using the LightBlue iOS app (https://itunes.apple.com/gb/app/lightblue-bluetooth-low-energy/id557428110?mt=8) I manage to discover and connect to my Nexus and see the characteristic uuid but the value doesn't show.
Any help would be highly appreciated.
First check the characteristic data you are advertising in the peripheral mode usually there are three modes
BluetoothGattCharacteristic.PROPERTY_WRITE, BluetoothGattCharacteristic.PROPERTY_READ,
BluetoothGattCharacteristic.PROPERTY_NOTIFY;
and you can build characteristic with all modes using
BluetoothGattCharacteristic.PROPERTY_WRITE |BluetoothGattCharacteristic.PROPERTY_READ | BluetoothGattCharacteristic.PROPERTY_NOTIFY;
Once done look for onCharacteristicWriteRequest() in BluetoothGattServerCallback() that you gave while building characteristic. When central want to send data it can write data to the characteristic with WRITE mode and you will have onCharacteristicWriteRequest() callback method triggered at peripheral side and you will have data in byte[] and make sure send response using btGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, 0, null);
by checking the responseNeeded bool value in callback method. In this way the data is transferred from central to peripheral.
And to send data from peripheral to central use notification charatertertistc
BluetoothGattCharacteristic bgc = bluetoothGattService
.getCharacteristic(chartersticUUID);
bgc.setValue(bnd.data);
btGattServer.notifyCharacteristicChanged(centralbluetoothdevice, bgc, false);
.
The BluetoothLeGatt Android BLE example contains the following code:
public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic,
boolean enabled) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
// This is specific to Heart Rate Measurement.
if (UUID_HEART_RATE_MEASUREMENT.equals(characteristic.getUuid())) {
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
UUID.fromString(SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mBluetoothGatt.writeDescriptor(descriptor);
}
}
My question is basically, why is the marked code specific to Heart Rate Measurement? It seems like having a Client Characteristic Config Descriptor (CCCD) characteristic is the standard way to control characteristic notification, so why doesn't setCharacteristicNotification() take care of writing to it? And since it doesn't do that, what does setCharacteristicNotification() actually do?
I'm pretty new to BLE and there aren't any explanations of it on the internet that don't assume that you already understand it all! So don't assume I know what a CCCD or whatever is! It was difficult enough finding out what CCCD even stands for!
Edit: See also this answer which supports my understanding of CCCDs (and makes me continue to wonder why you have to write to them manually in Android when there is a function that looks like it should do that for you): https://devzone.nordicsemi.com/index.php/what-does-cccd-mean
I think is a litte bit late for give an answer but today I had the same doubt and I found a clear answer.
Using setCharacteristicNotification() you enable notification localy (on android device) and setting CCC descriptor to ENABLE_NOTIFICATION_VALUE you enable notification on ble peripheral. In fact for enabling CCC notification you have to use setValue() and writeDescriptor() that are methods used for writing characteristics (in this case characteristics descriptors) to remote device.
I found this on: http://processors.wiki.ti.com/index.php/SensorTag_User_Guide
Here is an excerpt from the O'Reilly book "Getting Started With Bluetooth Low Energy":
To enable notifications on Android, you normally have to locally
enable the notification for the particular characteristic you are
interested in.
Once that’s done, you also have to enable notifications on the peer
device by writing to the device’s client characteristic configuration
descriptor (CCCD)
I believe this answers your question.
So
mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
refers to the first part
and
mBluetoothGatt.writeDescriptor(descriptor);
refers to the 2nd.
For future peoples coming across this, here's the best answer I could find:
By writing to the Client Characteristic Config descriptor, you, the client, are telling the BLE server to switch configurations. (This made no sense to me either initially, but in english:)
This tells the BLE device to switch modes (configurations) to actively gather and report changes to this characteristic instead of changing and only reporting when requested.
It's poorly named, but digging through the docs it appears this is also going to be used for other possible characteristic changes that the client might request: hence the confusing name.
https://developer.bluetooth.org/gatt/descriptors/Pages/DescriptorViewer.aspx?u=org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml
This begs the question, why call BluetoothGatt.setCharacteristicNotification() if we're only going to duplicate our efforts by modifying the descriptor?! Digging through the BluetoothGatt source shows us that setCharacteristicNotification only prepares the local service to receive notifications, not to enable persistent updates.
I know it looks silly, but setting CCCD value is the only way you can tell the API whether you are going to turn on notification or indication.
Currently there is no setCharacteristicIndication. To enable indication, you have to call setCharacteristicNotification (confusing) and then write BluetoothGattDescriptor.ENABLE_INDICATION_VALUE to CCCD, similar to what you did to enable Notification.
All the other answers do not really answer the question.
My guess would be that the Android BLE team took the assumption an application could have more than one BluetoothGattCallback().
By splitting the notification enabling (and disabling) in two steps it would allow the BluetoothGattCallback observers to listen for GATT notification (only invoke setCharacteristicNotification()) - and leave only one BluetoothGattCallback implemention doing the write operations to the GATT server aka the BLE peripheral.
"The Client Characteristic Configuration descriptor defines how the characteristic may be configured by a specific client."