11package com.juul.kable
22
33import android.bluetooth.BluetoothDevice
4- import android.bluetooth.BluetoothGattCharacteristic
54import android.bluetooth.BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT
65import android.bluetooth.BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE
76import android.bluetooth.BluetoothGattDescriptor
@@ -70,9 +69,12 @@ public class AndroidPeripheral internal constructor(
7069 private val observers = Observers (this )
7170
7271 @Volatile
73- internal var platformServices: List <PlatformService >? = null
72+ private var _platformServices : List <PlatformService >? = null
73+ private val platformServices: List <PlatformService >
74+ get() = checkNotNull(_platformServices ) { " Services have not been discovered for $this " }
75+
7476 public override val services: List <DiscoveredService >?
75- get() = platformServices ?.map { it.toDiscoveredService() }
77+ get() = _platformServices ?.map { it.toDiscoveredService() }
7678
7779 @Volatile
7880 private var _connection : Connection ? = null
@@ -144,7 +146,7 @@ public class AndroidPeripheral internal constructor(
144146 connection.execute<OnServicesDiscovered > {
145147 discoverServices()
146148 }
147- platformServices = connection.bluetoothGatt
149+ _platformServices = connection.bluetoothGatt
148150 .services
149151 .map { it.toPlatformService() }
150152 }
@@ -206,37 +208,51 @@ public class AndroidPeripheral internal constructor(
206208 ): Flow <ByteArray > = observers.acquire(characteristic)
207209
208210 internal suspend fun startNotifications (characteristic : Characteristic ) {
209- val bluetoothGattCharacteristic = bluetoothGattCharacteristicFrom(characteristic)
210- connection.bluetoothGatt.setCharacteristicNotification(bluetoothGattCharacteristic, true )
211- writeConfigDescriptor(characteristic, ENABLE_NOTIFICATION_VALUE )
211+ val platformCharacteristic = platformServices.findCharacteristic(characteristic)
212+ connection
213+ .bluetoothGatt
214+ .setCharacteristicNotification(platformCharacteristic.bluetoothGattCharacteristic, true )
215+
216+ writeConfigDescriptor(platformCharacteristic, ENABLE_NOTIFICATION_VALUE )
212217 }
213218
214219 internal suspend fun stopNotifications (characteristic : Characteristic ) {
215- writeConfigDescriptor(characteristic, DISABLE_NOTIFICATION_VALUE )
216- val bluetoothGattCharacteristic = bluetoothGattCharacteristicFrom(characteristic)
217- connection.bluetoothGatt.setCharacteristicNotification(bluetoothGattCharacteristic, false )
220+ val platformCharacteristic = platformServices.findCharacteristic(characteristic)
221+ writeConfigDescriptor(platformCharacteristic, DISABLE_NOTIFICATION_VALUE )
222+
223+ val bluetoothGattCharacteristic = platformCharacteristic.bluetoothGattCharacteristic
224+ connection
225+ .bluetoothGatt
226+ .setCharacteristicNotification(bluetoothGattCharacteristic, false )
218227 }
219228
220229 private suspend fun writeConfigDescriptor (
221- characteristic : Characteristic ,
230+ characteristic : PlatformCharacteristic ,
222231 value : ByteArray
223232 ) {
224233 if (writeObserveDescriptor == Never ) return
225234
226- val descriptor = LazyDescriptor (
227- serviceUuid = characteristic.serviceUuid,
228- characteristicUuid = characteristic.characteristicUuid,
229- descriptorUuid = clientCharacteristicConfigUuid
230- )
231- val bluetoothGattDescriptor = bluetoothGattDescriptorOrNullFrom(descriptor)
235+ val bluetoothGattDescriptor = characteristic
236+ .descriptors
237+ .firstOrNull(clientCharacteristicConfigUuid)
238+ ?.bluetoothGattDescriptor
232239
233240 if (bluetoothGattDescriptor != null ) {
234241 write(bluetoothGattDescriptor, value)
235242 } else if (writeObserveDescriptor == Always ) {
236- error(" Unable to start observation for $characteristic , config descriptor not found." )
243+ val uuid = characteristic.characteristicUuid
244+ error(" Unable to start observation for characteristic $uuid , config descriptor not found." )
237245 }
238246 }
239247
248+ private fun bluetoothGattCharacteristicFrom (
249+ characteristic : Characteristic
250+ ) = platformServices.findCharacteristic(characteristic).bluetoothGattCharacteristic
251+
252+ private fun bluetoothGattDescriptorFrom (
253+ descriptor : Descriptor
254+ ) = platformServices.findDescriptor(descriptor).bluetoothGattDescriptor
255+
240256 override fun toString (): String = " Peripheral(bluetoothDevice=$bluetoothDevice )"
241257}
242258
@@ -250,57 +266,6 @@ private suspend fun Peripheral.suspendUntilDisconnected() {
250266 state.first { it is State .Disconnected }
251267}
252268
253- private fun AndroidPeripheral.bluetoothGattCharacteristicFrom (
254- characteristic : Characteristic ,
255- ): BluetoothGattCharacteristic {
256- val services = checkNotNull(platformServices) {
257- " Services have not been discovered for $this "
258- }
259-
260- val characteristics = services
261- .first { characteristic.serviceUuid == it.serviceUuid }
262- .characteristics
263- return characteristics
264- .first { characteristic.characteristicUuid == it.characteristicUuid }
265- .bluetoothGattCharacteristic
266- }
267-
268- private fun AndroidPeripheral.bluetoothGattDescriptorFrom (
269- descriptor : Descriptor ,
270- ): BluetoothGattDescriptor {
271- val services = checkNotNull(platformServices) {
272- " Services have not been discovered for $this "
273- }
274-
275- val characteristics = services
276- .first { descriptor.serviceUuid == it.serviceUuid }
277- .characteristics
278- val descriptors = characteristics
279- .first { descriptor.characteristicUuid == it.characteristicUuid }
280- .descriptors
281- return descriptors
282- .first { descriptor.descriptorUuid == it.descriptorUuid }
283- .bluetoothGattDescriptor
284- }
285-
286- private fun AndroidPeripheral.bluetoothGattDescriptorOrNullFrom (
287- descriptor : Descriptor ,
288- ): BluetoothGattDescriptor ? {
289- val services = checkNotNull(platformServices) {
290- " Services have not been discovered for $this "
291- }
292-
293- val characteristics = services
294- .firstOrNull { descriptor.serviceUuid == it.serviceUuid }
295- ?.characteristics
296- val descriptors = characteristics
297- ?.firstOrNull { descriptor.characteristicUuid == it.characteristicUuid }
298- ?.descriptors
299- return descriptors
300- ?.firstOrNull { descriptor.descriptorUuid == it.descriptorUuid }
301- ?.bluetoothGattDescriptor
302- }
303-
304269private val WriteType .intValue: Int
305270 get() = when (this ) {
306271 WithResponse -> WRITE_TYPE_DEFAULT
0 commit comments