I have the Adafruit Feather M0 Bluefruit LE.
I'm encountering the same issue as these two posts:
https://forums.adafruit.com/viewtopic.php?t=122349
https://forums.adafruit.com/viewtopic.php?f=22&t=155690
I created a custom BLE GATT service on the microcontroller side, but it never shows up on the Android app side.
Custom Service with a custom UUID is as follows in my setup function:
// Add the Custom Service definition
Serial.println(F("Adding Custom Service definition "));
success = ble.sendCommandWithIntReply( F("AT+GATTADDSERVICE=UUID128=dc-5d-81-73-dc-73-4f-11-b0-54-57-14-55-15-b3-b2"), &hrmServiceId);
if (! success) {
error(F("Could not add Custom service"));
}
Then I adapted the sample BluetoothLeGatt application provided by Android and listed out all service UUIDs found. Relevant code in BluetoothLeService.java is as follows:
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
List<BluetoothGattService> gattServices = getSupportedGattServices();
for (BluetoothGattService gattService : gattServices) {
Log.i(TAG, "Service UUID Found: " + gattService.getUuid().toString());
}
} else {
Log.w(TAG, "onServicesDiscovered received: " + status);
}
}
The Logcat output lists the following UUIDs that were found:
2023-01-31 18:15:37.677 30616-30678/com.example.android.bluetoothlegatt I/BluetoothLeService: Service UUID Found: 00001800-0000-1000-8000-00805f9b34fb
2023-01-31 18:15:37.678 30616-30678/com.example.android.bluetoothlegatt I/BluetoothLeService: Service UUID Found: 00001801-0000-1000-8000-00805f9b34fb
2023-01-31 18:15:37.678 30616-30678/com.example.android.bluetoothlegatt I/BluetoothLeService: Service UUID Found: 00001530-1212-efde-1523-785feabcd123
2023-01-31 18:15:37.678 30616-30678/com.example.android.bluetoothlegatt I/BluetoothLeService: Service UUID Found: 0000180a-0000-1000-8000-00805f9b34fb
2023-01-31 18:15:37.678 30616-30678/com.example.android.bluetoothlegatt I/BluetoothLeService: Service UUID Found: 6e400001-b5a3-f393-e0a9-e50e24dcca9e
2023-01-31 18:15:37.678 30616-30678/com.example.android.bluetoothlegatt I/BluetoothLeService: Service UUID Found: ee0c2080-8786-40ba-ab96-99b91ac981d8
My Custom service UUID is never discovered.
I've tested it on two separate microcontrollers of the same model-- same issue comes up both times.
Any suggestions on what is going on or where to troubleshoot?
Related
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.
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());
}
Fetch android secondary bluetooth gatt service from bluetooth android API's.
Currently below is the code where we fetch ble services :
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
List<BluetoothGattService> gattServices = mBluetoothGatt.getServices();
Log.e("onServicesDiscovered", "Services count: "+gattServices.size());
BluetoothGattService bleServ = mBluetoothGatt.getService(UUID.fromString("22222222-0000-0000-0000-000000000000"));
for (BluetoothGattService gattService : gattServices) {
String serviceUUID = gattService.getUuid().toString();
Log.e("onServicesDiscovered", "Service uuid "+serviceUUID);
}
} else {
Log.w(TAG, "onServicesDiscovered received: " + status);
}
}
Even tried fetching exclusively the secondary service but it returns null object :
BluetoothGattService bleServ = mBluetoothGatt.getService(UUID.fromString("22222222-0000-0000-0000-000000000000"));
Can someone point any pointers how to search secondary ble service in Android.
You should use this method: https://developer.android.com/reference/android/bluetooth/BluetoothGattService.html#getIncludedServices() on a primary service.
After launch a BLUETOOTH server written in c.
https://github.com/RyanGlScott/BluetoothTest/blob/master/C%20BlueZ%20Server/bluez_server.c
This is the output of the command sdptool browse local:
....other services....
Service Name: AVRCP CT
Service RecHandle: 0x10005
Service Class ID List:
"AV Remote" (0x110e)
Protocol Descriptor List:
"L2CAP" (0x0100)
PSM: 23
"AVCTP" (0x0017)
uint16: 0x103
Profile Descriptor List:
"AV Remote" (0x110e)
Version: 0x0100
/*MY SERVICE!!!*/
Service Name: Armatus Bluetooth server
Service Description: A HERMIT server that interfaces with the Armatus Android app
Service Provider: Armatus
Service RecHandle: 0x10006
Service Class ID List:
"Serial Port" (0x1101)
Protocol Descriptor List:
"L2CAP" (0x0100)
"RFCOMM" (0x0003)
Channel: 3
Profile Descriptor List:
"Serial Port" (0x1101)
Version: 0x0100
....other services....
I'am trying to find this service using an Android app
// Create a BroadcastReceiver for ACTION_FOUND
private final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
// Whenever a remote Bluetooth device is found
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
// Get the BluetoothDevice object from the Intent
BluetoothDevice bluetoothDevice =
intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// Add the name and address to an array adapter to show in a ListView
adapter.add(bluetoothDevice.getName() + "\n"
+ bluetoothDevice.getAddress());
if (bluetoothDevice.getName().equals("mint-0")) {
Log.d("tagmint0","bene bene");
try {
ParcelUuid[] uuids = (ParcelUuid[]) bluetoothDevice.getUuids();
for (ParcelUuid uuid : uuids) {
Log.d("x", "mintUUIDxx: " + uuid.getUuid().toString() + "\n");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
};
My question is, why my android application is not able to find my service even if it is visible using the command sdptool browse local?
This is the android application output
mintUUIDxx: 0000111e-0000-1000-8000-00805f9b34fb
mintUUIDxx: 00001105-0000-1000-8000-00805f9b34fb
mintUUIDxx: 00001106-0000-1000-8000-00805f9b34fb
mintUUIDxx: 0000112d-0000-1000-8000-00805f9b34fb
mintUUIDxx: 0000110e-0000-1000-8000-00805f9b34fb
mintUUIDxx: 00001112-0000-1000-8000-00805f9b34fb
mintUUIDxx: 0000111f-0000-1000-8000-00805f9b34fb
mintUUIDxx: 00000000-0000-1000-8000-00805f9b34fb
As you can see it doesn't contains the server uuid. Can someone explain me why?
bluetoothDevice.getUuids();
This method does not start a service discovery procedure to retrieve the UUIDs from the remote device. Instead, the local cached copy of the service UUIDs are returned.
Use fetchUuidsWithSdp() instead. This method perform a service discovery on the remote device to get the UUIDs supported.
if you have used the same git code then looks like you have mention different UUID in android.
In you bluez_server.c
uint32_t svc_uuid_int[] = { 0x01110000, 0x00100000, 0x80000080, 0xFB349B5F };
And android output
mintUUIDxx: 0000111e-0000-1000-8000-00805f9b34fb
Give a try by changing that line in bluez_server.c with this
uint32_t svc_uuid_int[] = { 0x0000111e, 0x00001000, 0x80000080, 0x5f9b34fb };
In my app , i am passng the UUID number of the hearing aid service as in the BLE sample from google i.e. 0000a00-0000-1000-8000-00805f9b34fb
But the getservice returns null means that the service is not supported by the BluetoothGatt .
Why is this happening , can anybody please help me .
You have to first discover all services for the given device per documentation.
This function requires that service discovery has been completed for the given device.
http://developer.android.com/reference/android/bluetooth/BluetoothGatt.html#getService(java.util.UUID)
#Override
// New services discovered
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
BluetoothGattService mBluetoothGattService = mBluetoothGatt.getService(UUID.fromString(serviceUUID));
if (mBluetoothGattService != null) {
Log.i(TAG, "Service characteristic UUID found: " + mBluetoothGattService.getUuid().toString());
} else {
Log.i(TAG, "Service characteristic not found for UUID: " + serviceUUID);
}
}
Or you can just run a search
for (BluetoothGattService gattService : gattServices) {
Log.i(TAG, "Service UUID Found: " + gattService.getUuid().toString());
}
Try doing a full discover[1] of the remote database and then iterate through the services. Maybe you've got the UUID wrong.
[1] http://developer.android.com/reference/android/bluetooth/BluetoothGatt.html#discoverServices()
Your UUID is also wrong. It should be 0000a00X-0000-1000-8000-00805f9b34fb, not 0000a00-0000-1000-8000-00805f9b34fb