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.
Related
I have a Garmin watch (Forerunner 25) which I use to connect with Garmin connect (Android app). For many reasons I would like to build my own custom app to track training. But I have not been able to do the following:
Connect android app with a bluetooth (Garmin) Watch for file transfer.
Retrieve a .fit file from the Watch via Bluetooth.
How would I be able to do this?
I have tried to connect the watch via a BluetoothSocket but have had no luck to connect it.
UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); //Standard SerialPortService ID
mSocket = mDevice.createRfcommSocketToServiceRecord(uuid);
mSocket.connect();
//Never reaches this part, the connection is unsuccessful
mOutputStream = mSocket.getOutputStream();
mInputStream = mSocket.getInputStream();
Not sure If any of this is correct but this is what I started with.
//Note: The device is not null before I try to connect.
// I can retrieve the name, the address ...
D/BluetoothUtils: isSocketAllowedBySecurityPolicy start : device null
W/BluetoothAdapter: getBluetoothService() called with no BluetoothManagerCallback
I know the .fit file is a bytefile so if anyone know how to convert it to a .csv file with all the information as: time, speed, length, elevation...
I have found the Fitparser for python but not anything for Android.
Is there any library for this?
Or how could I parse a .fit (bytefile) to .csv on my own?
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.
Reading the documentation, one would think that setCharacteristicNotification enables notifications for a BLE characteristic:
Enable or disable notifications/indications for a given
characteristic.
But this method doesn't seem to do this? Reading the BLE documentation on receiving BLE notifications, it turns out to be a multi-step process where you have to call this method and then write a file into a descriptor.
If this is the case, then what does setCharacteristicNotification by itself do?
The descriptor write is needed in order to tell the remote device to send notifications. setCharactersticNotification only tells the Bluetooth stack that it should forward any received notification to the app.
Interesting read at Why does setCharacteristicNotification() not actually enable notifications? . The answerers there dig through the source code and docs to find that:
"setCharacteristicNotification only prepares the local service to receive notifications."
I would suggest a wrapper function for set notifications, because, in addition to the documentation being not-so-clear, it is a confusing concept to enable notification reception locally as well as enable notification sending on the peripheral. I would suggest something like what the kind answerers at Enabling Bluetooth characteristic Notification in Android (Bluetooth Low Energy ) Not Working use:
public boolean setCharacteristicNotification(BluetoothGatt bluetoothGatt, BluetoothGattCharacteristic characteristic,boolean enable) {
Logger.d("setCharacteristicNotification");
bluetoothGatt.setCharacteristicNotification(characteristic, enable);
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(CHARACTERISTIC_UPDATE_NOTIFICATION_DESCRIPTOR_UUID);
descriptor.setValue(enable ? BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE : new byte[]{0x00, 0x00});
return bluetoothGatt.writeDescriptor(descriptor); //descriptor write operation successfully started?
}
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."