Working with BLE Android 4.3 how to write characteristics? - android

I am working on a BLE project (Android application) using Android 4.3 API, i have used sample BLE app it is only reading characteristics in DeviceControlActivity.activity, but i want to write characteristics and send it to BLE chip on clicking a button. How can I write data on chip cc2540 .. Basically i don't know the step by step procedure to write characteristics.
write i can only see the name and id of device with following piece of code in DeviceControlActivity
private final ExpandableListView.OnChildClickListener servicesListClickListner =
new ExpandableListView.OnChildClickListener() {
#Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition,
int childPosition, long id) {
if (mGattCharacteristics != null) {
final BluetoothGattCharacteristic characteristic =
mGattCharacteristics.get(groupPosition).get(childPosition);
final int charaProp = characteristic.getProperties();
if ((charaProp | BluetoothGattCharacteristic.PROPERTY_READ) > 0) {
// If there is an active notification on a characteristic, clear
// it first so it doesn't update the data field on the user interface.
if (mNotifyCharacteristic != null) {
mBluetoothLeService.setCharacteristicNotification(
mNotifyCharacteristic, false);
mNotifyCharacteristic = null;
}
mBluetoothLeService.readCharacteristic(characteristic);
showDialog("reading");
}
if ((charaProp | BluetoothGattCharacteristic.PROPERTY_WRITE) > 0) {
// If there is an active notification on a characteristic, clear
// it first so it doesn't update the data field on the user interface.
if (mNotifyCharacteristic != null) {
mBluetoothLeService.setCharacteristicNotification(
mNotifyCharacteristic, false);
mNotifyCharacteristic = null;
}
mBluetoothLeService.writeCharacteristic(characteristic);
showDialog("writing");
//characteristic.setValue(bytes);
//characteristic.setValue("testing");
//characteristic.setWriteType(BluetoothGattCharacteristic.PERMISSION_WRITE);
}
if ((charaProp | BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) {
mNotifyCharacteristic = characteristic;
mBluetoothLeService.setCharacteristicNotification(
characteristic, true);
}
byte[] value = {0x00, (byte) (0xB9) , 0x0D, (byte) (0x90), 0x2F};
if(!characteristic.setValue(value))
{
Log.w(TAG, "Couldn't set characteristic's local value");
//return;
}
characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
/*if(!writeCharacteristic.writeCharacteristic(characteristic))
{
Log.w(TAG, "Couldn't write characteristic");
}*/
return true;
}
return false;
}
};

The following code is write characteristic using byte[] data:
public boolean writeCharacteristic(){
//check mBluetoothGatt is available
if (mBluetoothGatt == null) {
Log.e(TAG, "lost connection");
return false;
}
BluetoothGattService Service = mBluetoothGatt.getService(your Services);
if (Service == null) {
Log.e(TAG, "service not found!");
return false;
}
BluetoothGattCharacteristic charac = Service
.getCharacteristic(your characteristic);
if (charac == null) {
Log.e(TAG, "char not found!");
return false;
}
byte[] value = new byte[1];
value[0] = (byte) (21 & 0xFF);
charac.setValue(value);
boolean status = mBluetoothGatt.writeCharacteristic(charac);
return status;
}

Please note that the logic OR in:
if ((charaProp | BluetoothGattCharacteristic.PROPERTY_READ) > 0)" in the original post should be a logic AND for the permission check to work. Same for the second charaProp comparison. Otherwise bot statements are true regardless of the actual permission flag.

The following code is write characteristic using string data in utf-8 format:
public void writeCharacteristic(BluetoothGattCharacteristic characteristic,
String data) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
Log.i(TAG, "characteristic " + characteristic.toString());
try {
Log.i(TAG, "data " + URLEncoder.encode(data, "utf-8"));
characteristic.setValue(URLEncoder.encode(data, "utf-8"));
// TODO
mBluetoothGatt.writeCharacteristic(characteristic);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
Hope it helps!

public boolean writeCharacteristic(byte value[],int type){
//check mBluetoothGatt is available
if (mBluetoothGatt == null) {
Log.e(TAG, "lost connection");
return false;
}
BluetoothGattService Service = mBluetoothGatt.getService(UUID_SIMPLESERVICE);
if (Service == null) {
Log.e(TAG, "service not found!");
//////////NO service found...........
return false;
}
BluetoothGattCharacteristic charac1 = null;
boolean status1 = false;
if(type==1) {
charac1 = Service.getCharacteristic(UUID_PORT1);
charac1.setValue(value);
status1 = mBluetoothGatt.writeCharacteristic(charac1);
Log.v("________BLESERVICE____", "___WRITE CHARATERISTICS STATUS:_________"+status1);
onReliableWriteCompleted(status1);
}
if (charac1 == null) {
Log.e(TAG, "char not found!");
return false;
}
Log.v("___TYPE___","______________________"+type);
return status1;
}

Related

BLE GATT onCharacteristicChanged not called after subscribe to notification

After subscribe notification immediate write command doesn't work. I have to restart server device and auto connect to existing ble instance to get result.
Notification enable code:
public boolean setCharacteristicNotification(BluetoothGattCharacteristic characteristic,
boolean enabled) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return false;
}
mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
System.out.println("descriptor length----" + characteristic.getDescriptors().size());
// This is specific to Heart Rate Measurement.
if (UUID_HEART_RATE_MEASUREMENT.equals(characteristic.getUuid())) {
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"));
System.out.println("descriptor--" + Arrays.toString(descriptor.getValue()));
System.out.println("characteristic value--" + Arrays.toString(descriptor.getCharacteristic().getValue()));
descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
return mBluetoothGatt.writeDescriptor(descriptor);
}
return false;
}
and here is my write command code:
public void writeCustomCharacteristic(String value) {
this.value = "";
this.command = value;
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("65333333-a115-11e2-9e9a-0800200ca100"));
if (mCustomService == null) {
Log.w(TAG, "Custom BLE Service not found");
return;
}
/*get the read characteristic from the service*/
BluetoothGattCharacteristic mWriteCharacteristic = mCustomService.getCharacteristic(UUID.fromString("65333333-a115-11e2-9e9a-0800200ca101"));
mWriteCharacteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
mWriteCharacteristic.setValue(value.getBytes());
if (!mBluetoothGatt.writeCharacteristic(mWriteCharacteristic)) {
Log.w(TAG, "Failed to write characteristic");
}
System.out.println("BluetoothLeService.writeCustomCharacteristic------->" + value);
}
Before write any characteristic , delay for few sec . Bcz it takes time to execute.
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
#Override
public void run() {
mBluetoothGatt.writeDescriptor(RTS_CCCD); //for descriptor
// or
mBluetoothGatt.readCharacteristic(brspInfo); //for read
//or
mBluetoothGatt.writeCharacteristic(brspInfo); //for write
}
}, 500);
Here you get more explaination

Reading value of characteristic after connecting to service Bluetooth Low Energy Android

after the connection is established I want to read the value from the characteristic and save the value in a byte array.
Here is my function for the reading inside my BluetoothLeService:
public byte[] readWhiteAndIntensityCharacteristic() {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return null;
}
/*check if the service is available on the device*/
BluetoothGattService mCustomService = mBluetoothGatt.getService(UUID.fromString(UuidAdresssService));
if (mCustomService == null) {
Log.w(TAG, "Custom BLE Service not found");
return null;
}
/*get the read characteristic from the service*/
BluetoothGattCharacteristic mReadCharacteristic = mCustomService.getCharacteristic(UUID.fromString(UuidAdresssWhiteAndIntensityCharastic));
byte[] messageByte = mReadCharacteristic.getValue();
if (messageByte != null && messageByte.length > 0) {
final StringBuilder stringBuilder = new StringBuilder(messageByte.length);
for (byte byteChar : messageByte)
stringBuilder.append(String.format("%02X", byteChar));
s = "0x" + stringBuilder.toString();
Log.v("Scan Activity", s);
if (mBluetoothGatt.readCharacteristic(mReadCharacteristic) == false) {
Log.w(TAG, "Failed to read characteristic");
}
}
return messageByte;
}
This function get called inside my DeviceControlActivity:
public void getStartUpValue(){
Log.w(TAG, "Reading completed");}
if(mBluetoothLeService.readWhiteAndIntensityCharacteristic() == null)
{
Log.w(TAG, "FAILED Reading value failed");
}
startValue = mBluetoothLeService.readWhiteAndIntensityCharacteristic();
Log.w(TAG, "Reading completed");
}
I call the getStartUpValue function after the connection is established.
private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) {
mConnected = true;
updateConnectionState(R.string.connected);
invalidateOptionsMenu();
} else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) {
mConnected = false;
updateConnectionState(R.string.disconnected);
invalidateOptionsMenu();
clearUI();
} else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) {
// Show all the supported services and characteristics on the user interface.
mBluetoothLeService.getSupportedGattServices();
getStartUpValue();
} else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) {
displayData(intent.getStringExtra(BluetoothLeService.EXTRA_DATA));
}
}
};
The reading is failing everytime but sending values to the characteristic is no problem.
How can I fix this problem?
The solution is: mBluetoothGatt.readCharacteristic(mReadCharacteristic)
After the reading is finished a callback will be called.
Thanks to Andrew Vovk

get array value from bluetooth low energy fff2 characteristic on Java

I need to get value from fff2 characteristic.
Its characteristic only return 01 or 00
How to get its value?
this is example value that I want.
public boolean readCharacteristic(){
//check mBluetoothGatt is available
if (bluetoothGatt == null) {
Log.e(TAG, "lost connection");
return false;
}
BluetoothGattService Service = bluetoothGatt.getService(UUID.fromString("0000fff0-0000-1000-8000-00805f9b34fb"));
if (Service == null) {
Log.e(TAG, "service not found!");
return false;
}
BluetoothGattCharacteristic charac = Service
.getCharacteristic(UUID.fromString("0000fff2-0000-1000-8000-00805f9b34fb"));
if (charac == null) {
Log.e(TAG, "char not found!");
return false;
}
final byte[] data = charac.getValue(); // return null
String s2 = new String(data);
Log.i("READ", s2);
boolean status = true;
return status;
}
thanks..
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
byte[] data = characteristic.getValue();
}
}
Convert the byte array to Hex format if required.
Hope this is helpful.

Bluetooth BLE service returns status = 10 at onCharacteristicRead

I try to read some configurations from a device I'm connected to, but on the callback - onCharacteristicRead the parameter status=10.
I noticed that status == 0 meas BluetoothGatt.GATT_SUCCESS.
WHAT DOES 10 STANDS FOR????
My code is as follows:
public boolean read(byte[] bytes, String action) {
// is copied from android website example
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return false;
}
BluetoothGattService mCC2540_service = mBluetoothGatt.getService(UUID.fromString(mCC2540_SERVICE_UUID));
if (mCC2540_service == null){
Log.e(TAG, "mCC2540_service == null");
return false;
}
BluetoothGattCharacteristic bluetoothGattCharacteristic = mCC2540_service.getCharacteristic(UUID.fromString("0000fffc-0000-1000-8000-00805f9b34fb"));
bluetoothGattCharacteristic.setValue(bytes);
if ((bluetoothGattCharacteristic.getProperties() | BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) {
mBluetoothGatt.setCharacteristicNotification(bluetoothGattCharacteristic, true);
}
boolean status = mBluetoothGatt.readCharacteristic(bluetoothGattCharacteristic);
Log.d(TAG, "read() command sent");
return status;
}

how to update the battery level for every 5seconds in ble in android

in the following coding i am getting battery level of some percentage.but i want to call notify characteristics so that for every 5 to 10 secs it updates the percentage of battery.so please help me.the following is my device control activity,in this i coded as follows.
private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) {
displayData(intent.getStringExtra(BluetoothLeService.EXTRA_DATA));
}
}
};
and in the following method i am setting battery value and displaying in the value in percentage on image.
private void displayData(String data) {
Log.v("______________________No serives_______________",data );
if (data != null) {
mBluetoothLeService.setCharacteristicNotification(mNotifyCharacteristic, true);
battery.setText(data);
int x=Integer.parseInt(battery.getText().toString());
image_level.getLayoutParams().height = x*2;
}
else if (data==null)
battery.setText(data);
}
and the following is my ble service in this i add the set notification method wh
ich is as follows.
public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic,
boolean enabled) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
//For cube write
if (UUID_BatteryService.equals(characteristic.getUuid())) {
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
UUID.fromString(SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mBluetoothGatt.writeDescriptor(descriptor);
}
}
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
}
};
public boolean writeCharacteristic(BluetoothGattCharacteristic i){
//check mBluetoothGatt is available
if (mBluetoothGatt == null) {
Log.e(TAG, "lost connection");
return false;
}
BluetoothGattService Service = mBluetoothGatt.getService(UUID_BatteryService);
if (Service == null) {
Log.e(TAG, "service not found!");
//////////NO service found...........
return false;
}
boolean status = mBluetoothGatt.writeCharacteristic(i);
Log.e(TAG, "bluetooth write status"+status);
return status;
}
private void broadcastUpdate(final String action) {
final Intent intent = new Intent(action);
sendBroadcast(intent);
}
private void broadcastUpdate(final String action,
final BluetoothGattCharacteristic characteristic) {
final Intent intent = new Intent(action);
if(SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG_BATTERY.
toString().
equalsIgnoreCase(characteristic.getUuid().toString())) {
Log.v("_____________","in broadcastupdate..........");
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));
final int flag = characteristic.getProperties();
int format = -1;
if ((flag & 0x01) != 0) {
format = BluetoothGattCharacteristic.FORMAT_UINT16;
Log.d(TAG, " format UINT16.");
} else {
format = BluetoothGattCharacteristic.FORMAT_UINT8;
Log.d(TAG, " UINT8.");
}
int batterylevel = characteristic.getIntValue(format, 0);
intent.putExtra(EXTRA_DATA, String.valueOf(batterylevel));
//intent.putExtra(EXTRA_DATA,new String(data));
}
}
sendBroadcast(intent);
}
If I well understood your question, you will need a Timer in order to check you battery level regularly.
For instance, you could use this code after starting your device control activity, maybe at the end of the onServiceConnected method :
please put the timer at the end of onServiceConnected() method of mServiceConnection object
Timer timer = new Timer("batteryTimer");
TimerTask task = new TimerTask() {
#Override
public void run() {
mBluetoothLeService.getBattery();
}
};
timer.scheduleAtFixedRate(task, 0, 5000);
And do not forget to call timer.cancel() when the activity is finishing.
And in the service, you could put something like that :
public void getBattery() {
if (mBluetoothGatt == null) {
Log.e(TAG, "lost connection");
}
BluetoothGattService batteryService = mBluetoothGatt.getService(Battery_Service_UUID);
if(batteryService == null) {
Log.d(TAG, "Battery service not found!");
return;
}
BluetoothGattCharacteristic batteryLevel = batteryService.getCharacteristic(Battery_Level_UUID);
if(batteryLevel == null) {
Log.d(TAG, "Battery level not found!");
return;
}
mBluetoothGatt.readCharacteristic(batteryLevel);
}
It is an example which would need to be modified but that gives you an idea on how to do it.
Somebody already did access to the battery value in the link below :
How to get the battery level after connect to the BLE device?

Categories

Resources