Android - Getting null descriptors from a Characteristic - android

I am trying to interface with an Red Bear Labs nRF8001 Arduino Shield via Android Studio. I am succesfully able to send a command via Android and recieve it on my Arduino.
However I wish to read the response from my Arduino, using "OnCharacteristicChange" - however research showed a descriptor is required.
This is my code sample:
#Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
super.onServicesDiscovered(gatt, status);
if(status != BluetoothGatt.GATT_SUCCESS){
Log.i("BtServiceCallback","OnServicesDiscovered Failed!");
}
BluetoothGattService service = gatt.getService(RBLService.UUID_BLE_SHIELD_SERVICE);
BluetoothGattCharacteristic characteristic = service.getCharacteristic(RBLService.UUID_BLE_SHIELD_TX);
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UUID.fromString(RBLGattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
gatt.writeDescriptor(descriptor);
byte[] val = readSetPoint.getBytes();
characteristic.setValue(val);
gatt.setCharacteristicNotification(characteristic,true);
gatt.writeCharacteristic(characteristic);
Log.i("Sent = ", characteristic.getStringValue(0));
}
Whenever I try to create a descriptor from the characteristic, I get the following error:
java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.bluetooth.BluetoothGattDescriptor.setValue(byte[])' on a null object reference
at uk.ac.as988brighton.bluecontroller.MainActivity$1.onServicesDiscovered(MainActivity.java:160)
at android.bluetooth.BluetoothGatt$1.onSearchComplete(BluetoothGatt.java:286)
at android.bluetooth.IBluetoothGattCallback$Stub.onTransact(IBluetoothGattCallback.java:103)
at android.os.Binder.execTransact(Binder.java:573)
I am using the UUIDs from RBL's Github:
public static String CLIENT_CHARACTERISTIC_CONFIG = "00002902-0000-1000-8000-00805f9b34fb";
public static String BLE_SHIELD_TX = "713d0003-503e-4c75-ba94-3148f18d941e";
public static String BLE_SHIELD_RX = "713d0002-503e-4c75-ba94-3148f18d941e";
public static String BLE_SHIELD_SERVICE = "713d0000-503e-4c75-ba94-3148f18d941e";
I am unsure as to what is causing the null descriptor.
Edit
I have used different combinations for the descriptor - such as using
BluetoothGattDescriptor characteristic.getDescriptor(RBLService.UUID_BLE_SHIELD_TX);
But still receiving the same error.

It looks like you need to make sure you're naming things the same. Both your service and characteristic uuid are declared as BLE_SHIELD_SERVICE and BLE_SHIELD_TX but you're trying to access them with UUID_BLE_SHIELD_SERVICE and UUID_BLE_SHIELD_TX.
So change
BluetoothGattService service = gatt.getService(RBLService.UUID_BLE_SHIELD_SERVICE); to
BluetoothGattService service = gatt.getService(RBLService.BLE_SHIELD_SERVICE);
and
BluetoothGattCharacteristic characteristic = service.getCharacteristic(RBLService.UUID_BLE_SHIELD_TX); to
BluetoothGattCharacteristic characteristic = service.getCharacteristic(RBLService.BLE_SHIELD_TX);
and I believe it should work. Also make sure you are broadcasting those exact service and characteristic uuid's from your peripheral.
Good luck!

Related

Android BLE characteristics getValue is no any response?

I am trying to configure READ characteristic with notification attribute. At the moment I can see this characteristic on android app with properties READ and NOTIFY.
here is my device's uuid info :
UUID info
YES, I need to notification attribute first , then second I send command , that will be receive value, but ,
in fact , I don't receive any value , I don't even know what's wrong, here is my code :
public void onServicesDiscovered(BluetoothGatt gatt, int status){
if (status == gatt.GATT_SUCCESS){
runOnUiThread(new Runnable(){
public void run() {
BluetoothGattService gattService = gatt.getService(SERVICE_UUID);
if(gattService != null){
BluetoothGattCharacteristic gattCharacteristic = gattService.getCharacteristic(NOTIF_UUID);
if (gattCharacteristic != null ){
for (BluetoothGattDescriptor descriptor : gattCharacteristic.getDescriptors()){
descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
boolean sucess = gatt.writeDescriptor(descriptor);
}
gatt.setCharacteristicNotification(gattCharacteristic, true);
}
characteristic = gattService.getCharacteristic(WRITE_DATA);
if (characteristic != null){
sendCommand(characteristic, gatt); //send command
}
now , I have already send command , and it's return success , because onCharacteristicWrite() has response,
but onCharacteristicRead() and onCharacteristicChanged() is not any response? Why ?
which part I missing?
descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
instead of
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);

writeable characteristic for android custom ble service always returns write permission zero when discovered

I'm creating a custom BLE service on Android with a single characteristic that can be read/written. The code looks like this:
public static UUID MY_SERVICE = UUID.fromString("e0ec8d9c-5e4d-470a-b87f-64f433685301");
public static UUID MY_CHARACTERISTIC = UUID.fromString("e0ec8d9c-5e4d-470a-b87f-64f433685302");
/**
* Return a configured {#link BluetoothGattService} instance for the
* Custom Service.
*/
public static BluetoothGattService createCustomBleService() {
BluetoothGattService service = new BluetoothGattService(MY_SERVICE,
BluetoothGattService.SERVICE_TYPE_PRIMARY);
// Current Configuration characteristic
BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(MY_CHARACTERISTIC,
BluetoothGattCharacteristic.PROPERTY_READ | BluetoothGattCharacteristic.PROPERTY_WRITE,
BluetoothGattCharacteristic.PERMISSION_READ |BluetoothGattCharacteristic.PERMISSION_WRITE);
boolean serviceAdded = service.addCharacteristic(characteristic);
Log.i(TAG, "Building BLE service addCharacteristic returned "+serviceAdded);
return service;
}
The call to addCharacteristic(...) returns true. The service itself is created, can be advertised, and the service and its characteristic are discoverable by clients. Somewhere else in client side code, subsequent to a BLE scan that locates said service, the discovery code that runs looks like this:
for (BluetoothGattService service : gatt.getServices()) {
serviceUuid = service.getUuid().toString();
if( MY_SERVICE.toString().equals(serviceUuid) ) {
List<BluetoothGattCharacteristic> gattCharacteristics = service.getCharacteristics();
for( BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics ) {
characteristicUuid = gattCharacteristic.getUuid().toString();
Log.d(TAG, "onServicesDiscovered() - found characteristic uuid="+characteristicUuid);
int cProps = gattCharacteristic.getProperties();
Log.d(TAG, "onServicesDiscovered() - found characteristic properties "+cProps);
if ((( MY_CHARACTERISTIC.toString().equals(characteristicUuid) ))&&((cProps & BluetoothGattCharacteristic.PROPERTY_WRITE)>0)) {
writeCharacteristic(gatt,gattCharacteristic,"configStringLiteral");
}
}
}
}
When this service discovery code runs, as I mentioned, it finds the custom service and the characteristic that were defined. Any values I set for characteristic properties show up properly at the time of discovery on client side. The characteristic shows as writeable.
The problem is that characteristic write fails always even though the properties say its writable.
Has anyone seen this?... or perhaps I'm doing something dumb and have been looking at it too long.
(BTW the device hosting the custom service at runtime is a Samsung Galaxy 7 and the client is a Galaxy 6 ...or vice versa, same behavior)
Permission info is not sent over BLE when the services are discovered. Therfore the permission property should not be used for remote characteristics.
A client should inspect the characteristic property only to decide what can be done. If it receives an error saying for example encryption needed, the Bluetooth stack shall start encryption and then retry the request.
So, characteristic properties are the correct way to declare to a client what can be done with it. Characteristic permissions only tell the local GATT Server implementation how it should react to incoming GATT requests.

BLE Descriptor UUID

I'm new in the world of BLE, I am currently able to connect to the BLE module and I can communicate with it/receive Data by pressing a Button.
Now I want to use the Descriptor, but I don't exactly know how to define the required UUID. I only discovered that it is 0x2902.
I want to use the following Code:
BluetoothGattCharacteristic init_gatt=mConnectedGatt.getService(STATE_REQUEST_SERVICE_UUID).getCharacteristic(STATE_CHAR_UUID);
mConnectedGatt.setCharacteristicNotification(init_gatt,true);
BluetoothGattDescriptor descriptor=characteristic.getDescriptor(STATE_CHAR_UUID);
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mConnectedGatt.writeDescriptor(descriptor);
Can anyone tell me how I can create the UUID which is necessary for this line?
BluetoothGattDescriptor descriptor=characteristic.getDescriptor(STATE_CHAR_UUID);
If you're looking for creating a random UUID, you can do that like this:
if(uniqueId == null) {
uniqueId = UUID.randomUUID().toString();
}
You can actually log the list of device supported using:
for (BluetoothGattDescriptor descriptor:characteristic.getDescriptors()){
Log.e(TAG, "BluetoothGattDescriptor: "+descriptor.getUuid().toString());
}
BluetoothGattCharacteristic init_gatt=mConnectedGatt.getService(STATE_REQUEST_SERVICE_UUID).getCharacteristic(STATE_CHAR_UUID);
for (BluetoothGattDescriptor descriptor:characteristic.getDescriptors()){
Log.e(TAG, "BluetoothGattDescriptor: "+descriptor.getUuid().toString());
}
That's all I'm testing atm.
For the other Characteristic I'm Using, I got the hex Values which I have to write to the Characteristic by a collegue. In this case not

Android BLE BluetoothGattCharacteristic writing additional values

I want to write a command to a BluetoothGattCharacteristic with a parameter on it. I know how to write a command in bytes by setValue() method. But do not know how to write the parameter.
Here is an example of how to perform a BLE write:
public void writeValue(final String uuid, final byte[] value)
{
final BluetoothGattCharacteristic characteristic = getCharacteristic(bluetoothGatt, uuid);
characteristic.setValue(value);
bluetoothGatt.writeCharacteristic(characteristic);
}
The first argument of the method is a specified characteristic UUID of a service in your remote device
you want to access. The second argument is a byte Array you want to write to the characteristics of the remote device.

HM-10 Bluetooth Module - BLE 4.0 Keep Losing Connection

has anyone tried using HM-10 Bluetooth module?
I'm able to pair with it using an Android device and passing the pre-defined PIN. Based on the UART return, the pairing is successful (module returns OK+CONN - means a connection was established)
However, after a few seconds (2-3), the UART receives OK+LOST; means the connection was lost. Also, the LED starts blinking (normally, when a connection is active, it stays lit)
Is this normal behaviour for bluetooth in general or the HM-10 module.
This is the product's website: http://www.jnhuamao.cn/bluetooth.asp?ID=1
I'm not sure, but HM -10 don't support rfcom. It's mean that you must use GATT functionality for communication. Entity of BLE is usage of minimum data package as it possible, so BLE don't hold the connection all times and use something like statuses [attributes].
So, few code lines for example, how work with BLE:
1.
BluetoothAdapter mBluetoothAdapter = mBluetoothManager.getAdapter();
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(DEVICE_ADDR);
That's device initiation, the same like with simple bluetooth, where DEVICE_ADDR is the MAC of your BLE(how to find this address you can find in google or stack overflow, its trivial)
2.
BluetoothGattService mBluetoothGattService;
BluetoothGatt mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
#Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
if (newState == BluetoothProfile.STATE_CONNECTED) {
mBluetoothGatt.discoverServices();
}
}
#Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
List<BluetoothGattService> gattServices = mBluetoothGatt.getServices();
for(BluetoothGattService gattService : gattServices) {
if("0000ffe0-0000-1000-8000-00805f9b34fb".equals(gattService.getUuid().toString()))
{
mBluetoothGattService = gattService;
}
}
} else {
Log.d(TAG, "onServicesDiscovered received: " + status);
}
}
};
So, what this code mean: if u can see from this part of code, i describe how GATT service find. This service needed for "attribute" communication. gattService.getUuid() has few uuids for communication(4 in my module), some of them used for RX, some for TX etc. "0000ffe0-0000-1000-8000-00805f9b34fb" that is one of uuid that use for communication thats why i check it.
The final part of code is message sending:
BluetoothGattCharacteristic gattCharacteristic = mBluetoothGattService.getCharacteristic(UUID.fromString("0000ffe1-0000-1000-8000-00805f9b34fb"));
String msg = "HELLO BLE =)";
byte b = 0x00;
byte[] temp = msg.getBytes();
byte[] tx = new byte[temp.length + 1];
tx[0] = b;
for(int i = 0; i < temp.length; i++)
tx[i+1] = temp[i];
gattCharacteristic.setValue(tx);
mBluetoothGatt.writeCharacteristic(gattCharacteristic);
After sending message contain hold on and you can send another message or can close connection.
More info, you can find on https://developer.android.com/guide/topics/connectivity/bluetooth-le.html.
PS: MAC address of your module can find with ble scanner code or with AT cmd:
on my firmware AT+ADDR or AT+LADDR
About UUIDs usage: not sure, but in my case, i find it with next AT+UUID [Get/Set system SERVER_UUID] -> Response +UUID=0xFFE0, AT+CHAR [Get/Set system CHAR_UUID] - Response +CHAR=0xFFE1. Thats why i make conclusion that UUID which i must use fe "0000[ffe0/is 0xFFE0 from AT response]-0000-1000-8000-00805f9b34fb"

Categories

Resources