Android-BLE-Library
Android-BLE-Library copied to clipboard
Is there any way to decrease or bypass Service Discovery?
Hi Android-Ble-Library developers,
I tried to illustrate the communication diagram between a BLE Device and an Android device when I tried to send the data (with my observations). And I have a question: First of all, I am trying to make a connection as fast as possible but there is something wrong with this. Service Discovery is taking too much time sometimes (5-8 seconds), and sometimes less (2-3 seconds)and it still is too much.
- Is there any way to decrease or bypass Service Discovery?
- Is there any way to cache Gatt Services?
- If there are fewer services and characteristics, will it help reduce service discovery? like this:
Service | Characteristic Size |
---|---|
Service 1 | 1 |
It might be because our services and characteristics sizes are big:
Service | Characteristic Size |
---|---|
Service 1 | 4 |
Service 2 | 1 |
Service 3 | 1 |
Service 4 | 1 |
Service 5 | 5 |
Service 6 | 1 |
So I splited the services and charactersitics on BleManager
classes and if I need a use some service I create by what I needed in BleManager
.
With example 2 classes:
class Manager1(
context: Context,
private val scope: CoroutineScope
) : BleManager(context) {
private var characteristic1: BluetoothGattCharacteristic? = null
private var characteristic2: BluetoothGattCharacteristic? = null
private var characteristic3: BluetoothGattCharacteristic? = null
private var characteristic4: BluetoothGattCharacteristic? = null
private var characteristic5: BluetoothGattCharacteristic? = null
private val data: MutableStateFlow<CommunicationData> =
MutableStateFlow(CommunicationData())
val dataHolder = ConnectionObserverAdapter<CommunicationData>()
init {
connectionObserver = dataHolder
data.onEach {
dataHolder.setValue(it)
}.launchIn(scope)
}
override fun getMinLogPriority(): Int = Log.VERBOSE
override fun initialize() {
requestMtu(500).enqueue()
setNotificationCallback(characteristicOnOff).with(dataCallback)
enableNotifications(characteristicOnOff).enqueue()
}
override fun isRequiredServiceSupported(gatt: BluetoothGatt): Boolean {
val service1: BluetoothGattService? =
gatt.getService(SERVICE_1_UUID)
if (service1!= null) {
characteristic1 =
service1.getCharacteristic(CHARACTERISTIC_UUID_1)
characteristic2 =
service1.getCharacteristic(CHARACTERISTIC_UUID_2)
characteristic3 =
service1.getCharacteristic(CHARACTERISTIC_UUID_3)
characteristic4 =
service1.getCharacteristic(CHARACTERISTIC_UUID_4)
}
val service6: BluetoothGattService? =
gatt.getService(SERVICE_6_UUID)
if (service6!= null) {
characteristic5 =
service6.getCharacteristic(CHARACTERISTIC_UUID_6)
}
return characteristis1 != null && characteristic2 = null...
}
override fun onServicesInvalidated() {
characteristic1 = null
characteristic2 = null
characteristic3 = null
characteristic4 = null
characteristic5 = null
}
fun sendCommand(command: Boolean) {
val commandData = if (command) Command.SOME else Command.SOME
val request: WriteRequest =
writeCharacteristic(
characteristic,
commandData.data,
BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE
)
request.with(dataCallback).enqueue()
}
...
private val dataCallback = ...
}
class Manager2(
context: Context,
private val scope: CoroutineScope
) : BleManager(context) {
private var characteristic: BluetoothGattCharacteristic? = null
private val data: MutableStateFlow<CommunicationData> =
MutableStateFlow(CommunicationData())
val dataHolder = ConnectionObserverAdapter<CommunicationData>()
init {
connectionObserver = dataHolder
data.onEach {
dataHolder.setValue(it)
}.launchIn(scope)
}
override fun getMinLogPriority(): Int = Log.VERBOSE
override fun initialize() {
setNotificationCallback(characteristicOnOff).with(dataCallback)
enableNotifications(characteristicOnOff).enqueue()
sendCommand()
}
override fun isRequiredServiceSupported(gatt: BluetoothGatt): Boolean {
val service2: BluetoothGattService? =
gatt.getService(SERVICE_2_UUID)
if (service2!= null) {
characteristic =
service2.getCharacteristic(CHARACTERISTIC_UUID_2)
}
return characteristic != null
}
override fun onServicesInvalidated() {
characteristic = null
}
fun sendCommand() {
val data = byteArrayOf(
1.convertByte(),
0,
0,
0
)
val request: WriteRequest =
writeCharacteristic(
characteristic,
data,
BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE
)
request.with(dataCallback).enqueue()
}
private val dataCallback = ...
}
sequenceDiagram
actor User
participant Android
participant Bluetooth Gatt
participant BLEDevice
User->>Android: userAction()
activate Android
Android-)Bluetooth Gatt: connect()
Android-)Bluetooth Gatt: sendData() when connect()
activate Bluetooth Gatt
Bluetooth Gatt->>BLEDevice: connect()
BLEDevice-->>Bluetooth Gatt: onConnectionUpdated()
loop
Bluetooth Gatt-->>Android: onDeviceConnecting()
BLEDevice-->>Bluetooth Gatt: onConnectionUpdated()
opt optional
BLEDevice-xAndroid:connectionFailed()
end
end
BLEDevice-->>Bluetooth Gatt: onDeviceConnected()
Bluetooth Gatt-->>Android: onDeviceConnected()
Bluetooth Gatt->>BLEDevice: discoverServices()
Note over Bluetooth Gatt, BLEDevice: Takes too much time
BLEDevice-->Bluetooth Gatt: Services Handshake
Bluetooth Gatt -->> Android: onSearchComplete()
deactivate Bluetooth Gatt
Bluetooth Gatt->>BLEDevice:setCharacteristicNotification()
Bluetooth Gatt->>BLEDevice:setCharacteristicNotification()
BLEDevice-->>Bluetooth Gatt: onConnectionUpdated()
Bluetooth Gatt-->>Android:onDeviceReady()
Bluetooth Gatt->>BLEDevice:sendData()
BLEDevice-->>Bluetooth Gatt:dataResponse()
Bluetooth Gatt-->>Android:dataResponse()
Android-->>User:notifiyAboutAction()
activate Android
Android-->>Android:Wait User action for 5 seconds
Android->>Bluetooth Gatt: sendDisconnect()
deactivate Android
Bluetooth Gatt->>BLEDevice: sendDisconnect()
Bluetooth Gatt-->>Android:onDeviceDisconnecting()
BLEDevice-->Bluetooth Gatt: Disconnect Handshake
activate Bluetooth Gatt
Bluetooth Gatt-->>Android:onDeviceDisconnected()
deactivate Bluetooth Gatt
Example 1
15:27:50.489 selectedDevices E C8:F0:9E:A0:82:5A
15:27:50.789 BluetoothGatt D onClientConnectionState() - status=133 clientIf=9 device=C8:F0:9E:A0:82:5A
15:27:51.796 BluetoothGatt D close()
15:27:51.796 BluetoothGatt D unregisterApp() - mClientIf=9
15:27:52.003 BluetoothGatt D connect() - device: C8:F0:9E:A0:82:5A, auto: false
15:27:52.003 BluetoothGatt D registerApp()
15:27:52.004 BluetoothGatt D registerApp() - UUID=d0bc6014-4436-43c5-99a8-0073d2c2618d
15:27:52.010 BluetoothGatt D onClientRegistered() - status=0 clientIf=9
15:27:52.026 BLE-CONNECTION D onDeviceConnecting()
15:27:52.298 BluetoothGatt D onClientConnectionState() - status=133 clientIf=9 device=C8:F0:9E:A0:82:5A
15:27:53.318 BluetoothGatt D close()
15:27:53.319 BluetoothGatt D unregisterApp() - mClientIf=9
15:27:53.527 BluetoothGatt D connect() - device: C8:F0:9E:A0:82:5A, auto: false
15:27:53.527 BluetoothGatt D registerApp()
15:27:53.529 BluetoothGatt D registerApp() - UUID=102aee31-2fe8-4170-8163-abe0ee0ef581
15:27:53.539 BluetoothGatt D onClientRegistered() - status=0 clientIf=9
15:27:53.580 BLE-CONNECTION D onDeviceConnecting()
15:27:53.827 BluetoothGatt D onClientConnectionState() - status=133 clientIf=9 device=C8:F0:9E:A0:82:5A
15:27:54.855 BluetoothGatt D close()
15:27:54.855 BluetoothGatt D unregisterApp() - mClientIf=9
15:27:55.065 BluetoothGatt D connect() - device: C8:F0:9E:A0:82:5A, auto: false
15:27:55.066 BluetoothGatt D registerApp()
15:27:55.067 BluetoothGatt D registerApp() - UUID=da8be66d-7352-4c29-be54-2da42fd3310f
15:27:55.074 BluetoothGatt D onClientRegistered() - status=0 clientIf=9
15:27:55.078 BLE-CONNECTION D onDeviceConnecting()
15:27:55.248 BluetoothGatt D onClientConnectionState() - status=0 clientIf=9 device=C8:F0:9E:A0:82:5A
15:27:55.265 BLE-CONNECTION D onDeviceConnected()
15:27:55.566 BluetoothGatt D discoverServices() - device: C8:F0:9E:A0:82:5A
15:27:55.704 BluetoothGatt D onConnectionUpdated() - Device=C8:F0:9E:A0:82:5A interval=6 latency=0 timeout=500 status=0
15:27:56.530 BluetoothGatt D onSearchComplete() = Device=C8:F0:9E:A0:82:5A Status=0
15:27:56.540 BluetoothGatt D setCharacteristicNotification() - uuid: 47421404-f259-11ec-b939-0242ac120002 enable: true
15:27:56.571 BluetoothGatt D setCharacteristicNotification() - uuid: 47421402-f259-11ec-b939-0242ac120002 enable: true
15:27:56.591 BluetoothGatt D onConnectionUpdated() - Device=C8:F0:9E:A0:82:5A interval=30 latency=0 timeout=500 status=0
15:27:56.636 BLE-CONNECTION D onDeviceReady()
15:27:56.670 onDataSent E 1B000000
... /*Disconnects after 7 seconds*/
15:28:01.908 BluetoothGatt D cancelOpen() - device: C8:F0:9E:A0:82:5A
15:28:01.916 BLE-CONNECTION D onDeviceDisconnecting()
15:28:01.928 BluetoothGatt D onClientConnectionState() - status=0 clientIf=9 device=C8:F0:9E:A0:82:5A
15:28:01.936 BluetoothGatt D refresh() - device: C8:F0:9E:A0:82:5A
15:28:01.942 BluetoothGatt D close()
15:28:01.942 BluetoothGatt D unregisterApp() - mClientIf=9
15:28:01.954 BLE-CONNECTION D onDeviceDisconnected(), reason: 0
Example 2
15:28:04.279 BLE-CONNECTION D onDeviceConnecting()
15:28:04.279 BluetoothGatt D connect() - device: C8:F0:9E:A0:82:5A, auto: false
15:28:04.279 BluetoothGatt D registerApp()
15:28:04.280 BluetoothGatt D registerApp() - UUID=ded3b352-53d5-42d7-8c1a-893afb323eff
15:28:04.284 BluetoothGatt D onClientRegistered() - status=0 clientIf=9
15:28:04.389 selectedDevices E C8:F0:9E:A0:82:5A
15:28:04.625 BluetoothGatt D onClientConnectionState() - status=133 clientIf=9 device=C8:F0:9E:A0:82:5A
15:28:05.639 BluetoothGatt D close()
15:28:05.640 BluetoothGatt D unregisterApp() - mClientIf=9
15:28:05.845 BluetoothGatt D connect() - device: C8:F0:9E:A0:82:5A, auto: false
15:28:05.845 BluetoothGatt D registerApp()
15:28:05.846 BluetoothGatt D registerApp() - UUID=b7ff9713-afbb-43b8-9693-ea25745d6b72
15:28:05.852 BluetoothGatt D onClientRegistered() - status=0 clientIf=9
15:28:05.854 BLE-CONNECTION D onDeviceConnecting()
15:28:06.103 BluetoothGatt D onClientConnectionState() - status=0 clientIf=9 device=C8:F0:9E:A0:82:5A
15:28:06.142 BLE-CONNECTION D onDeviceConnected()
15:28:06.435 BluetoothGatt D discoverServices() - device: C8:F0:9E:A0:82:5A
15:28:06.616 BluetoothGatt D onConnectionUpdated() - Device=C8:F0:9E:A0:82:5A interval=6 latency=0 timeout=500 status=0
15:28:07.550 BluetoothGatt D onSearchComplete() = Device=C8:F0:9E:A0:82:5A Status=0
15:28:07.561 BluetoothGatt D setCharacteristicNotification() - uuid: 47421404-f259-11ec-b939-0242ac120002 enable: true
15:28:07.592 BluetoothGatt D onConnectionUpdated() - Device=C8:F0:9E:A0:82:5A interval=30 latency=0 timeout=500 status=0
15:28:07.666 BluetoothGatt D setCharacteristicNotification() - uuid: 47421402-f259-11ec-b939-0242ac120002 enable: true
15:28:07.745 BLE-CONNECTION D onDeviceReady()
15:28:07.765 onDataSent E 27000000
15:28:07.911 onDataReceived E 0027AC2345
... /*Disconnects after 7 seconds*/
15:28:13.028 BluetoothGatt D cancelOpen() - device: C8:F0:9E:A0:82:5A
15:28:13.032 BluetoothGatt D onClientConnectionState() - status=19 clientIf=9 device=C8:F0:9E:A0:82:5A
15:28:13.036 BLE-CONNECTION D onDeviceDisconnecting()
15:28:13.067 BluetoothGatt D refresh() - device: C8:F0:9E:A0:82:5A
15:28:13.070 BluetoothGatt D close()
15:28:13.071 BluetoothGatt D unregisterApp() - mClientIf=9
15:28:13.081 BLE-CONNECTION D onDeviceDisconnected(), reason: 2