I am developing an Android app that needs to read the Keyfob's Accelerometer data. Until now I've followed this tutorial: https://thenewcircle.com/s/post/1553/bluetooth_smart_le_android_tutorial
With it I was able to connect with the Keyfob, search for services and read some characteristics. The problem is when I try to enable the keyfob's Accelerometer, the bluetooth connection simply drops.
This is the code I use to try to enable the accelerometer:
private void enableAccelerometer(BluetoothGatt gatt){
BluetoothGattCharacteristic characteristic;
BluetoothGattService service;
Log.d(TAG, "ligando acelerometro");
service = gatt.getService(ACCELEROMETER_SERVICE);
if(service == null){
Log.d(TAG, "Not able to find the service");
}
else{
Log.d(TAG, "Service found");
characteristic = service.getCharacteristic(ENABLE_ACCELEROMETER);
if(characteristic == null){
Log.d(TAG, "Characteristic not found");
}
else{
characteristic.setValue(new byte[] {0x01});
if (!gatt.writeCharacteristic(characteristic)){
Log.d(TAG, "writing failed ");
}
else {
Log.d(TAG, "writing successful: ");
}
}
}
This method is called in the "onServicesDiscovered" callback function.
The Texas Instrument CC2540/41 Mini Development Kit User’s Guide states that to enable the accelerometer it is necessary to write "01" in the enable acceleromenter characteristic in the accelerometer serivce, that's what I am doing with this code.
The connection between the phone (LG G2 mini running Android 4.4.2) drops when I write:
characteristic.setValue(new byte[] {0x01});
I am sure it is this line that is making the connection drop, if I comment it out or simply try to write a string instead of a byte, the connection doesn't drop.
Does anyone have any idea what am I doing wrong?
Turns out that after a week I found a way to turn the accelerometer on. I still don't know why it is working only that way, but I just changed:
characteristic.setValue(new byte[] {0x01});
to
characteristic.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
I don't know what value is exactly inside the "BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE" constant, but it worked.
Related
I am implementing BLE in Android Studio. I have connected with the peripheral device ok. In my onServicesDiscovered method I want to analyze the services (and characteristics) and I get something like the following when I print out:
android.bluetooth.BluetoothGattService#41b6dd18
There is 4 services in the list and they all look similar except for the numbers at the end. How can I convert this to useful information. I have seen no reference to this format.
Thanks.
Try to read the uuid from the BluetoothGattService object.
You can find uuid of standard services on Bluetooth SIG website. If the uuid is not there (i.e. custom services), you should read the manual of the peripheral or reach out the peripheral maker.
That depends on what you consider "useful" information.
BLE works mostly like dictionary where you look up long numbers (characteristics) and get binary data, so without prior information about the device you're working on, there is not much you can see when you discover services.
That said, in the BLE docs, there is a method displayGattServices() which puts the discovered services info in an ExpandableListView, and here I changed it to print the UUIDs of services and characteristics to logcat instead.
Besides the UUIDs, you can use getProperties() to find out other characteristic properties such as the format of the characteristic data, or getPermissions() to see whether you can read or write the characteristic.
// Demonstrates how to iterate through the supported GATT
// Services/Characteristics.
private void displayGattServices(List<BluetoothGattService> gattServices) {
final String TAG = "BleServiceInfo";
if (gattServices == null) return;
String uuid;
String unknownServiceString = "Unknown service"
String unknownCharaString = "Unknown characteristic"
// Loops through available GATT Services.
for (BluetoothGattService gattService : gattServices) {
Log.d(TAG, "Service: " + gattService.getUuid().toString());
// Loops through available Characteristics.
for (BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) {
Log.d(TAG, "\tCharacteristic: " + gattCharacteristic.getUuid().toString());
}
}
}
Call this method from onServicesDisccovered() like this:
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
....
displayGattServices(gatt.getServices());
}
I am working with a BLE compatible health device (that can store Measurements) to read data using android app. I am able to scan services and setup indications on a particular characteristic that stores the readings. While I am able to listen for indications and obtain the values, the indications start from first reading saved on the device to the latest reading on the device, it takes a lot of time to get the latest value (especially as the device stores large number of values).
Is there a way I can get the latest reading first so I can stop reading further older values which are unnecessary for me.
Here is piece of the code relevant to enabling Indications for the desired characteristic.
public static final UUID CCCD = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
Boolean gattsetchar = gatt.setCharacteristicNotification(characteristic, true);
if (!gattsetchar){
Log.e(TAG, "set characteristic=" + gattsetchar);
}
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(CCCD);
if(descriptor != null){
if ((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_INDICATE) != 0) {
Log.d(TAG, "Enabling Indication");
descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
}
}
Boolean writeDes = mBluetoothGatt.writeDescriptor(descriptor);
Log.d(TAG, "Write Descriptor " + writeDes + " " + descriptor.getCharacteristic().getUuid());
I currently own a LilyPad Simblee BLE Board - RFD77101, with which I'm trying to establish a connection with a custom service that I am defining in arduino 1.6.5 IDE with the Simblee.customUUID command.
I later tried to get the service and the characteristic in Android Studio with the BluetoothleGatt sample code using the UUID I established previously.
The problem is when I connect to the Simblee the app fails to recognize the service and logs me the following error.
Custom BLE Service not found
The code is kinda long hence I am not posting all of it directly. If anyone has an idea as to a solution to my problem and need and part of code I am obviously more than glad to post it.
Thanks to anyone in advance.
This is the public void where I attempt to obtain the characteristic:
public void readCustomCharacteristic() {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
/*check if the service is available on the device*/
BluetoothGattService mCustomService = mBluetoothGatt.getService(UUID.fromString("fe84-0000-1000-8000-00805f9b34fb"));
if(mCustomService == null) {
Log.w(TAG, "Custom BLE Service not found");
return;
}
/*get the read characteristic from the service*/
BluetoothGattCharacteristic mReadCharacteristic = mCustomService.getCharacteristic(UUID.fromString("2d30c083-f39f-4ce6-923f-3484ea480596"));
if(!mBluetoothGatt.readCharacteristic(mReadCharacteristic)) {
Log.w(TAG, "Failed to read characteristic");
}
}
BluetoothGattService mCustomService = mBluetoothGatt.getService(UUID.fromString("fe84-0000-1000-8000-00805f9b34fb"));
The UUID you provided is not in correct format. According to the documentation, the part before first hyphen should consist of 4 hex octets (See the one you provided for characteristics) but you only got 2 here. You should add padding 0 in front like
BluetoothGattService mCustomService = mBluetoothGatt.getService(UUID.fromString("0000fe84-0000-1000-8000-00805f9b34fb"));
Edit : Missing a point here. Have you called mBluetoothGatt.discoverServices()?
I want to get the value of the HRM of an "A&D UA-651BLE" device.
this is what's written in the datasheet of this device to get the HRM value:
Set the application to pairing mode to start scanning.
Start pairing of A&D BLE device following each instruction manual.
At pairing mode, the application should set time and date and any other device settings
to A&D BLE device. After successful pairing, A&D BLE device shows “End” on the screen.
Take a measurement and finish the measurement, then A&D BLE device start BLE
connection with advertising. The application starts scanning with suitable interval so that
the application catches the advertising of A&D BLE device as soon as it can.
At initial connection or pairing, the Application set “2” to CCCD (Client Characteristic
Configuration Descriptor) so that A&D BLE device sends a measurement data with
Indication.
After A&D device recognizes to be set “2” to CCCD and to be synchronized time and date
within 5 seconds after connected, send the data with Indication.
If the timeout set CCCD and time and date is expired, A&D BLE device will not send data
and store the data in memory. The stored data in A&D BLE device can send next
successful connection.
this is my service 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);
}
}
and this is the method that read data:
final byte[] data = characteristic.getValue();
if (data != null && data.length > 0) {
final StringBuilder stringBuilder = new StringBuilder(data.length);
for(byte byteChar : data)
stringBuilder.append(String.format("%02X ", byteChar));
Log.e("HRM value",stringBuilder.toString());
dataComposition.put(characteristic.getUuid().toString(),stringBuilder.toString());
intent.putExtra(EXTRA_DATA,dataComposition);
}
the problem is that this code doesn't return any data !!
There's an Android Open Source Project example that does precisely this, easiest option would be to clone the android-BluetoothLeGatt code, build and compare it to your own. If you can't spot the difference / issue simply deploy both app's and step through both sets of code. Having some known working code will also help to rule out the possibility that the HRM is not functioning properly.
Do you have and example , i try this with equal device and i cant obtain the information y try with
public String response() {
if (mConnected) {
mBluetoothLeService.readCharacteristic(characteristica);
byte response[] = characteristica.getValue();
String respuesta = ReadBytes(response);
mBluetoothLeService.disconnect();
return respuesta;
} else {
return null;
}
}
I am trying to establish Bluetooth connection between an Android device with other mobile phone over Handsfree profile. I am using following code -
private static final UUID MY_UUID = UUID.fromString("0000111F-0000-1000-8000-00805F9B34FB"); // UUID for Hands free profile
// Some code...
// Get Bluetooth Adapter.
m_oBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
// Some code...
// For paired BT device, getting a connection established.
if(null != m_oBluetoothDevice)
{
if(BluetoothDevice.BOND_BONDED == m_oBluetoothDevice.getBondState())
{
try
{
m_oBluetoothSocket = m_oBluetoothDevice.createRfcommSocketToServiceRecord(MY_UUID);
m_oBluetoothSocket.connect();
Log.i(TAG, "Socket Connected");
}
catch(Exception e)
{
if(null != m_oBluetoothSocket)
{
Log.i(TAG, "Closing socket");
try
{
m_oBluetoothSocket.close();
}
catch (Exception e1)
{
Log.i(TAG, "Error while closing socket : " + e1.getMessage());
}
}
}
}
}
I can create RFCOMMSocket using this code.
Now I want to send AT commands based on Bluetooth Hands-Free profile. e.g. If other mobile phone receives a phone call, my Android device can reject this call by sending AT command- "+CHUP". I am not sure whether this is possible or not.
At this point, I am stuck. I have read Bluetooth APIs where I found -
BluetoothHeadset.ACTION_VENDOR_SPECIFIC_HEADSET_EVENT
Can we use this Intent for sending AT commands? Is this a proper way to send AT command based on Bluetooth Hands-Free profile? Please someone help me out and give me proper direction.
Any input from you all will be great help for me.
Thanks in advance.
You need to create InputStream and OutputStream so you can talk to the phone:
mmInStream = m_oBluetoothSocket.getInputStream();
mmOutStream = m_oBluetoothSocket.getOutputStream();
To setup the HFP connection you start to send:
mmOutStream.write("AT+BRSF=20\r".getBytes());
Where 20 is code for what you support of HFP.
And to read from the phone:
buffer = new byte[200];
mmInStream.read(buffer);
command = new String(buffer).trim();
So now you can talk beetwen the devices and you can read more about the Handsfree profile on https://www.bluetooth.org/docman/handlers/downloaddoc.ashx?doc_id=238193
Adding reference to AT commnads
http://forum.xda-developers.com/showthread.php?t=1471241
http://www.zeeman.de/wp-content/uploads/2007/09/ubinetics-at-command-set.pdf