Migration to latest BLEK (#132)

* Migration to latest BLEK

* Clean up
This commit is contained in:
Aleksander Nowakowski
2023-12-21 22:55:47 +01:00
committed by GitHub
parent 18ad3d97bb
commit 1004a561fd
28 changed files with 163 additions and 183 deletions

View File

@@ -33,7 +33,7 @@ plugins {
alias(libs.plugins.nordic.hilt) alias(libs.plugins.nordic.hilt)
} }
if (getGradle().getStartParameter().getTaskRequests().toString().contains("Release")){ if (getGradle().getStartParameter().getTaskRequests().toString().contains("Release")) {
apply(plugin = "com.google.gms.google-services") apply(plugin = "com.google.gms.google-services")
apply(plugin = "com.google.firebase.crashlytics") apply(plugin = "com.google.firebase.crashlytics")
} }
@@ -69,18 +69,14 @@ dependencies {
implementation(libs.nordic.uilogger) implementation(libs.nordic.uilogger)
implementation(libs.nordic.permissions.ble) implementation(libs.nordic.permissions.ble)
implementation(libs.nordic.analytics) implementation(libs.nordic.analytics)
implementation(libs.nordic.blek.client)
implementation(libs.androidx.lifecycle.runtime.compose)
implementation(libs.nordic.ble.common)
implementation(libs.nordic.ble.ktx)
implementation(libs.androidx.hilt.navigation.compose)
implementation(libs.androidx.compose.material.iconsExtended)
implementation(libs.androidx.core.ktx) implementation(libs.androidx.core.ktx)
implementation(libs.androidx.compose.material3) implementation(libs.androidx.compose.material3)
implementation(libs.androidx.compose.material.iconsExtended)
implementation(libs.androidx.activity.compose) implementation(libs.androidx.activity.compose)
implementation(libs.androidx.lifecycle.runtime.compose)
implementation(libs.nordic.blek.client) implementation(libs.androidx.hilt.navigation.compose)
} }

View File

@@ -39,12 +39,12 @@ android {
dependencies { dependencies {
implementation(libs.nordic.navigation) implementation(libs.nordic.navigation)
implementation(libs.nordic.blek.uiscanner)
implementation(libs.nordic.blek.uiscanner)
implementation(libs.nordic.blek.scanner) implementation(libs.nordic.blek.scanner)
implementation(libs.androidx.compose.material3)
implementation(libs.androidx.compose.material.iconsExtended) implementation(libs.androidx.compose.material.iconsExtended)
implementation(libs.androidx.core.ktx) implementation(libs.androidx.core.ktx)
implementation(libs.androidx.compose.material3)
implementation(libs.androidx.activity.compose) implementation(libs.androidx.activity.compose)
} }

View File

@@ -40,11 +40,8 @@ android {
dependencies { dependencies {
implementation(project(":lib_ui")) implementation(project(":lib_ui"))
implementation(libs.nordic.ble.common)
implementation(libs.nordic.ble.ktx)
implementation(libs.nordic.blek.uiscanner) implementation(libs.nordic.blek.uiscanner)
implementation(libs.nordic.blek.core) implementation(libs.nordic.blek.core)
implementation(libs.androidx.lifecycle.service) implementation(libs.androidx.lifecycle.service)

View File

@@ -65,7 +65,7 @@ abstract class NotificationService : LifecycleService() {
private fun startForegroundService() { private fun startForegroundService() {
// when the activity closes we need to show the notification that user is connected to the peripheral sensor // when the activity closes we need to show the notification that user is connected to the peripheral sensor
// We start the service as a foreground service as Android 8.0 (Oreo) onwards kills any running background services // We start the service as a foreground service as Android 8.0 (Oreo) onwards kills any running background services
val notification = createNotification(R.string.csc_notification_connected_message, 0) val notification = createNotification(R.string.csc_notification_connected_message)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForeground(NOTIFICATION_ID, notification) startForeground(NOTIFICATION_ID, notification)
} else { } else {
@@ -81,7 +81,7 @@ abstract class NotificationService : LifecycleService() {
// when the activity rebinds to the service, remove the notification and stop the foreground service // when the activity rebinds to the service, remove the notification and stop the foreground service
// on devices running Android 8.0 (Oreo) or above // on devices running Android 8.0 (Oreo) or above
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
stopForeground(true) stopForeground(STOP_FOREGROUND_REMOVE)
} else { } else {
cancelNotification() cancelNotification()
} }
@@ -92,9 +92,8 @@ abstract class NotificationService : LifecycleService() {
* *
* @param messageResId the message resource id. The message must have one String parameter,<br></br> * @param messageResId the message resource id. The message must have one String parameter,<br></br>
* f.e. `<string name="name">%s is connected</string>` * f.e. `<string name="name">%s is connected</string>`
* @param defaults
*/ */
private fun createNotification(messageResId: Int, defaults: Int): Notification { private fun createNotification(messageResId: Int): Notification {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
createNotificationChannel(CHANNEL_ID) createNotificationChannel(CHANNEL_ID)
} }
@@ -111,6 +110,7 @@ abstract class NotificationService : LifecycleService() {
.build() .build()
} }
@Suppress("SameParameterValue")
@RequiresApi(Build.VERSION_CODES.O) @RequiresApi(Build.VERSION_CODES.O)
private fun createNotificationChannel(channelName: String) { private fun createNotificationChannel(channelName: String) {
val channel = NotificationChannel( val channel = NotificationChannel(

View File

@@ -43,13 +43,13 @@ android {
dependencies { dependencies {
implementation(libs.nordic.uilogger) implementation(libs.nordic.uilogger)
implementation(libs.nordic.theme) implementation(libs.nordic.theme)
implementation(libs.nordic.logger)
implementation(libs.nordic.blek.client)
implementation(libs.androidx.compose.material3)
implementation(libs.androidx.compose.material.iconsExtended) implementation(libs.androidx.compose.material.iconsExtended)
implementation(libs.androidx.core.ktx) implementation(libs.androidx.core.ktx)
implementation(libs.androidx.compose.material3)
implementation(libs.androidx.activity.compose) implementation(libs.androidx.activity.compose)
implementation(libs.nordic.blek.client)
implementation(libs.nordic.logger)
} }

View File

@@ -40,6 +40,8 @@ android {
dependencies { dependencies {
implementation(libs.nordic.navigation) implementation(libs.nordic.navigation)
implementation(libs.nordic.blek.uiscanner) implementation(libs.nordic.blek.uiscanner)
implementation(libs.kotlinx.coroutines.core) implementation(libs.kotlinx.coroutines.core)
} }

View File

@@ -47,19 +47,17 @@ dependencies {
implementation(libs.nordic.blek.client) implementation(libs.nordic.blek.client)
implementation(libs.nordic.blek.profile) implementation(libs.nordic.blek.profile)
implementation(libs.nordic.blek.uiscanner)
implementation(libs.nordic.ble.common)
implementation(libs.nordic.ble.ktx)
implementation(libs.nordic.navigation) implementation(libs.nordic.navigation)
implementation(libs.nordic.theme) implementation(libs.nordic.theme)
implementation(libs.nordic.uilogger) implementation(libs.nordic.uilogger)
implementation(libs.nordic.blek.uiscanner)
implementation(libs.androidx.compose.material.iconsExtended)
implementation(libs.androidx.hilt.navigation.compose)
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.compose.material3) implementation(libs.androidx.compose.material3)
implementation(libs.androidx.compose.material.iconsExtended)
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.activity.compose) implementation(libs.androidx.activity.compose)
implementation(libs.androidx.lifecycle.service) implementation(libs.androidx.lifecycle.service)
implementation(libs.androidx.hilt.navigation.compose)
} }

View File

@@ -127,7 +127,7 @@ internal class BPSViewModel @Inject constructor(
logger = DefaultBleLogger.create(context, stringConst.APP_NAME, "BPS", device.address) logger = DefaultBleLogger.create(context, stringConst.APP_NAME, "BPS", device.address)
val client = ClientBleGatt.connect(context, device, logger = logger) val client = ClientBleGatt.connect(context, device, viewModelScope, logger = logger)
this@BPSViewModel.client = client this@BPSViewModel.client = client
client.connectionStateWithStatus client.connectionStateWithStatus

View File

@@ -45,22 +45,20 @@ dependencies {
implementation(project(":lib_ui")) implementation(project(":lib_ui"))
implementation(project(":lib_utils")) implementation(project(":lib_utils"))
implementation(libs.nordic.core)
implementation(libs.nordic.theme)
implementation(libs.nordic.uilogger)
implementation(libs.nordic.navigation)
implementation(libs.nordic.blek.uiscanner)
implementation(libs.nordic.blek.client) implementation(libs.nordic.blek.client)
implementation(libs.nordic.blek.profile) implementation(libs.nordic.blek.profile)
implementation(libs.nordic.ble.common) implementation(libs.androidx.compose.material3)
implementation(libs.nordic.ble.ktx)
implementation(libs.nordic.uilogger)
implementation(libs.nordic.theme)
implementation(libs.nordic.blek.uiscanner)
implementation(libs.nordic.navigation)
implementation(libs.nordic.core)
implementation(libs.androidx.hilt.navigation.compose)
implementation(libs.androidx.compose.material.iconsExtended) implementation(libs.androidx.compose.material.iconsExtended)
implementation(libs.androidx.core.ktx) implementation(libs.androidx.core.ktx)
implementation(libs.androidx.compose.material3)
implementation(libs.androidx.activity.compose) implementation(libs.androidx.activity.compose)
implementation(libs.androidx.lifecycle.service) implementation(libs.androidx.lifecycle.service)
implementation(libs.androidx.hilt.navigation.compose)
} }

View File

@@ -45,12 +45,12 @@ import kotlinx.coroutines.launch
import no.nordicsemi.android.cgms.data.CGMRecordWithSequenceNumber import no.nordicsemi.android.cgms.data.CGMRecordWithSequenceNumber
import no.nordicsemi.android.cgms.data.CGMServiceCommand import no.nordicsemi.android.cgms.data.CGMServiceCommand
import no.nordicsemi.android.kotlin.ble.client.main.callback.ClientBleGatt import no.nordicsemi.android.kotlin.ble.client.main.callback.ClientBleGatt
import no.nordicsemi.android.kotlin.ble.client.main.errors.GattOperationException
import no.nordicsemi.android.kotlin.ble.client.main.service.ClientBleGattCharacteristic import no.nordicsemi.android.kotlin.ble.client.main.service.ClientBleGattCharacteristic
import no.nordicsemi.android.kotlin.ble.client.main.service.ClientBleGattServices import no.nordicsemi.android.kotlin.ble.client.main.service.ClientBleGattServices
import no.nordicsemi.android.kotlin.ble.core.ServerDevice import no.nordicsemi.android.kotlin.ble.core.ServerDevice
import no.nordicsemi.android.kotlin.ble.core.data.GattConnectionState import no.nordicsemi.android.kotlin.ble.core.data.GattConnectionState
import no.nordicsemi.android.kotlin.ble.core.data.GattConnectionStateWithStatus import no.nordicsemi.android.kotlin.ble.core.data.GattConnectionStateWithStatus
import no.nordicsemi.android.kotlin.ble.core.errors.GattOperationException
import no.nordicsemi.android.kotlin.ble.profile.battery.BatteryLevelParser import no.nordicsemi.android.kotlin.ble.profile.battery.BatteryLevelParser
import no.nordicsemi.android.kotlin.ble.profile.cgm.CGMFeatureParser import no.nordicsemi.android.kotlin.ble.profile.cgm.CGMFeatureParser
import no.nordicsemi.android.kotlin.ble.profile.cgm.CGMMeasurementParser import no.nordicsemi.android.kotlin.ble.profile.cgm.CGMMeasurementParser
@@ -58,7 +58,6 @@ import no.nordicsemi.android.kotlin.ble.profile.cgm.CGMSpecificOpsControlPointPa
import no.nordicsemi.android.kotlin.ble.profile.cgm.CGMStatusParser import no.nordicsemi.android.kotlin.ble.profile.cgm.CGMStatusParser
import no.nordicsemi.android.kotlin.ble.profile.cgm.data.CGMErrorCode import no.nordicsemi.android.kotlin.ble.profile.cgm.data.CGMErrorCode
import no.nordicsemi.android.kotlin.ble.profile.cgm.data.CGMOpCode import no.nordicsemi.android.kotlin.ble.profile.cgm.data.CGMOpCode
import no.nordicsemi.android.kotlin.ble.profile.cgm.data.CGMSpecificOpsControlPointData
import no.nordicsemi.android.kotlin.ble.profile.gls.CGMSpecificOpsControlPointDataParser import no.nordicsemi.android.kotlin.ble.profile.gls.CGMSpecificOpsControlPointDataParser
import no.nordicsemi.android.kotlin.ble.profile.gls.RecordAccessControlPointInputParser import no.nordicsemi.android.kotlin.ble.profile.gls.RecordAccessControlPointInputParser
import no.nordicsemi.android.kotlin.ble.profile.gls.RecordAccessControlPointParser import no.nordicsemi.android.kotlin.ble.profile.gls.RecordAccessControlPointParser
@@ -133,7 +132,7 @@ internal class CGMService : NotificationService() {
} }
private fun startGattClient(device: ServerDevice) = lifecycleScope.launch { private fun startGattClient(device: ServerDevice) = lifecycleScope.launch {
val client = ClientBleGatt.connect(this@CGMService, device, logger = { p, s -> repository.log(p, s) }) val client = ClientBleGatt.connect(this@CGMService, device, lifecycleScope, logger = { p, s -> repository.log(p, s) })
this@CGMService.client = client this@CGMService.client = client
client.connectionStateWithStatus client.connectionStateWithStatus

View File

@@ -45,22 +45,20 @@ dependencies {
implementation(project(":lib_ui")) implementation(project(":lib_ui"))
implementation(project(":lib_utils")) implementation(project(":lib_utils"))
implementation(libs.nordic.core)
implementation(libs.nordic.theme)
implementation(libs.nordic.uilogger)
implementation(libs.nordic.navigation)
implementation(libs.nordic.blek.client) implementation(libs.nordic.blek.client)
implementation(libs.nordic.blek.profile) implementation(libs.nordic.blek.profile)
implementation(libs.nordic.ble.common)
implementation(libs.nordic.ble.ktx)
implementation(libs.nordic.uilogger)
implementation(libs.nordic.theme)
implementation(libs.nordic.navigation)
implementation(libs.nordic.blek.uiscanner) implementation(libs.nordic.blek.uiscanner)
implementation(libs.nordic.core)
implementation(libs.androidx.hilt.navigation.compose) implementation(libs.androidx.compose.material3)
implementation(libs.androidx.compose.material.iconsExtended) implementation(libs.androidx.compose.material.iconsExtended)
implementation(libs.androidx.core.ktx) implementation(libs.androidx.core.ktx)
implementation(libs.androidx.compose.material3)
implementation(libs.androidx.activity.compose) implementation(libs.androidx.activity.compose)
implementation(libs.androidx.lifecycle.service) implementation(libs.androidx.lifecycle.service)
implementation(libs.androidx.hilt.navigation.compose)
} }

View File

@@ -86,7 +86,7 @@ internal class CSCService : NotificationService() {
} }
private fun startGattClient(device: ServerDevice) = lifecycleScope.launch { private fun startGattClient(device: ServerDevice) = lifecycleScope.launch {
val client = ClientBleGatt.connect(this@CSCService, device, logger = { p, s -> repository.log(p, s) }) val client = ClientBleGatt.connect(this@CSCService, device, lifecycleScope, logger = { p, s -> repository.log(p, s) })
this@CSCService.client = client this@CSCService.client = client
client.connectionStateWithStatus client.connectionStateWithStatus

View File

@@ -45,27 +45,26 @@ dependencies {
implementation(project(":lib_ui")) implementation(project(":lib_ui"))
implementation(project(":lib_utils")) implementation(project(":lib_utils"))
implementation(libs.nordic.theme)
implementation(libs.nordic.navigation)
implementation(libs.nordic.uilogger)
implementation(libs.nordic.blek.client) implementation(libs.nordic.blek.client)
implementation(libs.nordic.blek.profile) implementation(libs.nordic.blek.profile)
implementation(libs.nordic.blek.server) implementation(libs.nordic.blek.server)
implementation(libs.nordic.blek.advertiser) implementation(libs.nordic.blek.advertiser)
implementation(libs.nordic.blek.uiscanner)
implementation(libs.chart) implementation(libs.chart)
implementation(libs.nordic.ble.common)
implementation(libs.nordic.ble.ktx)
implementation(libs.nordic.theme)
implementation(libs.nordic.blek.uiscanner)
implementation(libs.nordic.navigation)
implementation(libs.nordic.uilogger)
implementation(libs.androidx.hilt.navigation.compose)
implementation(libs.androidx.compose.material.iconsExtended) implementation(libs.androidx.compose.material.iconsExtended)
implementation(libs.androidx.core.ktx) implementation(libs.androidx.core.ktx)
implementation(libs.androidx.compose.material3) implementation(libs.androidx.compose.material3)
implementation(libs.androidx.activity.compose) implementation(libs.androidx.activity.compose)
implementation(libs.androidx.lifecycle.service) implementation(libs.androidx.lifecycle.service)
implementation(libs.androidx.hilt.navigation.compose)
testImplementation(libs.hilt.android.testing) testImplementation(libs.hilt.android.testing)
kaptTest(libs.hilt.compiler) kaptTest(libs.hilt.compiler)
testImplementation(libs.androidx.test.rules) testImplementation(libs.androidx.test.rules)

View File

@@ -44,12 +44,12 @@ class GlsServer @Inject constructor(
private val logger: BleLogger = DefaultConsoleLogger(context) private val logger: BleLogger = DefaultConsoleLogger(context)
) { ) {
lateinit var server: ServerBleGatt private lateinit var server: ServerBleGatt
lateinit var glsCharacteristic: ServerBleGattCharacteristic private lateinit var glsCharacteristic: ServerBleGattCharacteristic
lateinit var glsContextCharacteristic: ServerBleGattCharacteristic private lateinit var glsContextCharacteristic: ServerBleGattCharacteristic
lateinit var racpCharacteristic: ServerBleGattCharacteristic private lateinit var racpCharacteristic: ServerBleGattCharacteristic
lateinit var batteryLevelCharacteristic: ServerBleGattCharacteristic private lateinit var batteryLevelCharacteristic: ServerBleGattCharacteristic
private var lastRequest = DataByteArray() private var lastRequest = DataByteArray()
@@ -144,7 +144,7 @@ class GlsServer @Inject constructor(
OLDEST_RECORD OLDEST_RECORD
) )
val racp = DataByteArray.from(0x06, 0x00, 0x01, 0x01) private val SUCCESS = DataByteArray.from(0x06, 0x00, 0x01, 0x01)
fun start( fun start(
context: Context, context: Context,
@@ -193,7 +193,8 @@ class GlsServer @Inject constructor(
context = context, context = context,
config = arrayOf(serviceConfig, batteryService), config = arrayOf(serviceConfig, batteryService),
mock = device, mock = device,
logger = { priority, log -> println(log) } scope = scope,
logger = { _, log -> println(log) }
) )
val advertiser = BleAdvertiser.create(context) val advertiser = BleAdvertiser.create(context)
@@ -223,12 +224,11 @@ class GlsServer @Inject constructor(
BATTERY_LEVEL_CHARACTERISTIC_UUID BATTERY_LEVEL_CHARACTERISTIC_UUID
)!! )!!
startGlsService()
startGlsService(connection) // startBatteryService()
// startBatteryService(connection)
} }
private fun startGlsService(connection: ServerBluetoothGattConnection) { private fun startGlsService() {
racpCharacteristic.value racpCharacteristic.value
.onEach { lastRequest = it } .onEach { lastRequest = it }
.launchIn(scope) .launchIn(scope)
@@ -238,42 +238,38 @@ class GlsServer @Inject constructor(
sendResponse(lastRequest) sendResponse(lastRequest)
} }
private fun sendResponse(request: DataByteArray) { private fun sendResponse(request: DataByteArray) = scope.launch {
if (request == RecordAccessControlPointInputParser.reportNumberOfAllStoredRecords()) { when (request) {
sendAll(glsCharacteristic) RecordAccessControlPointInputParser.reportNumberOfAllStoredRecords() -> {
racpCharacteristic.setValue(racp) records.forEach {
} else if (request == RecordAccessControlPointInputParser.reportLastStoredRecord()) { send(glsCharacteristic, it)
sendLast(glsCharacteristic) delay(100)
racpCharacteristic.setValue(racp) }
} else if (request == RecordAccessControlPointInputParser.reportFirstStoredRecord()) { racpCharacteristic.setValueAndNotifyClient(SUCCESS)
sendFirst(glsCharacteristic) }
racpCharacteristic.setValue(racp) RecordAccessControlPointInputParser.reportLastStoredRecord() -> {
send(glsCharacteristic, records.last())
send(racpCharacteristic, SUCCESS)
}
RecordAccessControlPointInputParser.reportFirstStoredRecord() -> {
send(glsCharacteristic, records.first())
send(racpCharacteristic, SUCCESS)
}
} }
} }
private fun sendFirst(characteristics: ServerBleGattCharacteristic) { private suspend fun send(characteristics: ServerBleGattCharacteristic, data: DataByteArray) {
characteristics.setValue(records.first()) characteristics.setValueAndNotifyClient(data)
} }
private fun sendLast(characteristics: ServerBleGattCharacteristic) { private fun startBatteryService() {
characteristics.setValue(records.last())
}
private fun sendAll(characteristics: ServerBleGattCharacteristic) = scope.launch {
records.forEach {
characteristics.setValue(it)
delay(100)
}
}
private fun startBatteryService(connection: ServerBluetoothGattConnection) {
scope.launch { scope.launch {
repeat(100) { repeat(100) {
batteryLevelCharacteristic.setValue(DataByteArray.from(0x61)) send(batteryLevelCharacteristic, DataByteArray.from(0x61))
delay(STANDARD_DELAY) delay(STANDARD_DELAY)
batteryLevelCharacteristic.setValue(DataByteArray.from(0x60)) send(batteryLevelCharacteristic, DataByteArray.from(0x60))
delay(STANDARD_DELAY) delay(STANDARD_DELAY)
batteryLevelCharacteristic.setValue(DataByteArray.from(0x5F)) send(batteryLevelCharacteristic, DataByteArray.from(0x5F))
delay(STANDARD_DELAY) delay(STANDARD_DELAY)
} }
} }

View File

@@ -40,7 +40,7 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Divider import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
@@ -71,7 +71,7 @@ internal fun GLSDetailsContentView(record: GLSRecord, context: GLSMeasurementCon
) )
} }
Divider( HorizontalDivider(
color = MaterialTheme.colorScheme.secondary, color = MaterialTheme.colorScheme.secondary,
thickness = 1.dp, thickness = 1.dp,
modifier = Modifier.padding(vertical = 16.dp) modifier = Modifier.padding(vertical = 16.dp)
@@ -112,7 +112,7 @@ internal fun GLSDetailsContentView(record: GLSRecord, context: GLSMeasurementCon
} }
record.status?.let { record.status?.let {
Divider( HorizontalDivider(
color = MaterialTheme.colorScheme.secondary, color = MaterialTheme.colorScheme.secondary,
thickness = 1.dp, thickness = 1.dp,
modifier = Modifier.padding(vertical = 16.dp) modifier = Modifier.padding(vertical = 16.dp)
@@ -178,7 +178,7 @@ internal fun GLSDetailsContentView(record: GLSRecord, context: GLSMeasurementCon
} }
context?.let { context?.let {
Divider( HorizontalDivider(
color = MaterialTheme.colorScheme.secondary, color = MaterialTheme.colorScheme.secondary,
thickness = 1.dp, thickness = 1.dp,
modifier = Modifier.padding(vertical = 16.dp) modifier = Modifier.padding(vertical = 16.dp)

View File

@@ -32,9 +32,10 @@
package no.nordicsemi.android.gls.main.viewmodel package no.nordicsemi.android.gls.main.viewmodel
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.Application
import android.content.Context import android.content.Context
import android.os.ParcelUuid import android.os.ParcelUuid
import androidx.lifecycle.ViewModel import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.qualifiers.ApplicationContext
@@ -61,12 +62,12 @@ import no.nordicsemi.android.gls.main.view.OnGLSRecordClick
import no.nordicsemi.android.gls.main.view.OnWorkingModeSelected import no.nordicsemi.android.gls.main.view.OnWorkingModeSelected
import no.nordicsemi.android.gls.main.view.OpenLoggerEvent import no.nordicsemi.android.gls.main.view.OpenLoggerEvent
import no.nordicsemi.android.kotlin.ble.client.main.callback.ClientBleGatt import no.nordicsemi.android.kotlin.ble.client.main.callback.ClientBleGatt
import no.nordicsemi.android.kotlin.ble.client.main.errors.GattOperationException
import no.nordicsemi.android.kotlin.ble.client.main.service.ClientBleGattCharacteristic import no.nordicsemi.android.kotlin.ble.client.main.service.ClientBleGattCharacteristic
import no.nordicsemi.android.kotlin.ble.client.main.service.ClientBleGattServices import no.nordicsemi.android.kotlin.ble.client.main.service.ClientBleGattServices
import no.nordicsemi.android.kotlin.ble.core.ServerDevice import no.nordicsemi.android.kotlin.ble.core.ServerDevice
import no.nordicsemi.android.kotlin.ble.core.data.GattConnectionState import no.nordicsemi.android.kotlin.ble.core.data.GattConnectionState
import no.nordicsemi.android.kotlin.ble.core.data.GattConnectionStateWithStatus import no.nordicsemi.android.kotlin.ble.core.data.GattConnectionStateWithStatus
import no.nordicsemi.android.kotlin.ble.core.errors.GattOperationException
import no.nordicsemi.android.kotlin.ble.profile.battery.BatteryLevelParser import no.nordicsemi.android.kotlin.ble.profile.battery.BatteryLevelParser
import no.nordicsemi.android.kotlin.ble.profile.gls.GlucoseMeasurementContextParser import no.nordicsemi.android.kotlin.ble.profile.gls.GlucoseMeasurementContextParser
import no.nordicsemi.android.kotlin.ble.profile.gls.GlucoseMeasurementParser import no.nordicsemi.android.kotlin.ble.profile.gls.GlucoseMeasurementParser
@@ -99,13 +100,12 @@ val BATTERY_LEVEL_CHARACTERISTIC_UUID = UUID.fromString("00002A19-0000-1000-8000
@SuppressLint("MissingPermission") @SuppressLint("MissingPermission")
@HiltViewModel @HiltViewModel
internal class GLSViewModel @Inject constructor( internal class GLSViewModel @Inject constructor(
@ApplicationContext @ApplicationContext context: Context,
private val context: Context,
private val navigationManager: Navigator, private val navigationManager: Navigator,
private val analytics: AppAnalytics, private val analytics: AppAnalytics,
private val stringConst: StringConst, private val stringConst: StringConst,
private val loggerFactory: NordicLoggerFactory private val loggerFactory: NordicLoggerFactory
) : ViewModel() { ) : AndroidViewModel(context as Application) {
private var client: ClientBleGatt? = null private var client: ClientBleGatt? = null
private lateinit var logger: BleLoggerAndLauncher private lateinit var logger: BleLoggerAndLauncher
@@ -168,9 +168,9 @@ internal class GLSViewModel @Inject constructor(
private fun startGattClient(device: ServerDevice) = viewModelScope.launch { private fun startGattClient(device: ServerDevice) = viewModelScope.launch {
_state.value = _state.value.copy(deviceName = device.name) _state.value = _state.value.copy(deviceName = device.name)
logger = loggerFactory.createNordicLogger(context, stringConst.APP_NAME, "GLS", device.address) logger = loggerFactory.createNordicLogger(getApplication(), stringConst.APP_NAME, "GLS", device.address)
val client = ClientBleGatt.connect(context, device, logger = logger) val client = ClientBleGatt.connect(getApplication(), device, viewModelScope, logger = logger)
this@GLSViewModel.client = client this@GLSViewModel.client = client
client.waitForBonding() client.waitForBonding()

View File

@@ -45,23 +45,22 @@ dependencies {
implementation(project(":lib_ui")) implementation(project(":lib_ui"))
implementation(project(":lib_utils")) implementation(project(":lib_utils"))
implementation(libs.nordic.core)
implementation(libs.nordic.theme)
implementation(libs.nordic.navigation)
implementation(libs.nordic.uilogger)
implementation(libs.nordic.blek.client) implementation(libs.nordic.blek.client)
implementation(libs.nordic.blek.profile) implementation(libs.nordic.blek.profile)
implementation(libs.nordic.blek.uiscanner)
implementation(libs.chart) implementation(libs.chart)
implementation(libs.nordic.theme) implementation(libs.androidx.compose.material3)
implementation(libs.nordic.ble.common)
implementation(libs.nordic.ble.ktx)
implementation(libs.nordic.navigation)
implementation(libs.nordic.blek.uiscanner)
implementation(libs.nordic.uilogger)
implementation(libs.nordic.core)
implementation(libs.androidx.hilt.navigation.compose)
implementation(libs.androidx.compose.material.iconsExtended) implementation(libs.androidx.compose.material.iconsExtended)
implementation(libs.androidx.core.ktx) implementation(libs.androidx.core.ktx)
implementation(libs.androidx.compose.material3)
implementation(libs.androidx.activity.compose) implementation(libs.androidx.activity.compose)
implementation(libs.androidx.lifecycle.service) implementation(libs.androidx.lifecycle.service)
implementation(libs.androidx.hilt.navigation.compose)
} }

View File

@@ -88,7 +88,7 @@ internal class HRSService : NotificationService() {
} }
private fun startGattClient(device: ServerDevice) = lifecycleScope.launch { private fun startGattClient(device: ServerDevice) = lifecycleScope.launch {
val client = ClientBleGatt.connect(this@HRSService, device, logger = { p, s -> repository.log(p, s) }) val client = ClientBleGatt.connect(this@HRSService, device, lifecycleScope, logger = { p, s -> repository.log(p, s) })
this@HRSService.client = client this@HRSService.client = client
client.waitForBonding() client.waitForBonding()

View File

@@ -47,20 +47,18 @@ dependencies {
implementation(libs.nordic.blek.client) implementation(libs.nordic.blek.client)
implementation(libs.nordic.blek.profile) implementation(libs.nordic.blek.profile)
implementation(libs.nordic.ble.common)
implementation(libs.nordic.ble.ktx)
implementation(libs.nordic.theme)
implementation(libs.nordic.blek.uiscanner) implementation(libs.nordic.blek.uiscanner)
implementation(libs.nordic.core)
implementation(libs.nordic.theme)
implementation(libs.nordic.navigation) implementation(libs.nordic.navigation)
implementation(libs.nordic.uilogger) implementation(libs.nordic.uilogger)
implementation(libs.nordic.core)
implementation(libs.androidx.hilt.navigation.compose) implementation(libs.androidx.compose.material3)
implementation(libs.androidx.compose.material.iconsExtended) implementation(libs.androidx.compose.material.iconsExtended)
implementation(libs.androidx.core.ktx) implementation(libs.androidx.core.ktx)
implementation(libs.androidx.compose.material3)
implementation(libs.androidx.activity.compose) implementation(libs.androidx.activity.compose)
implementation(libs.androidx.lifecycle.service) implementation(libs.androidx.lifecycle.service)
implementation(libs.androidx.hilt.navigation.compose)
} }

View File

@@ -86,7 +86,7 @@ internal class HTSService : NotificationService() {
} }
private fun startGattClient(device: ServerDevice) = lifecycleScope.launch { private fun startGattClient(device: ServerDevice) = lifecycleScope.launch {
val client = ClientBleGatt.connect(this@HTSService, device, logger = { p, s -> repository.log(p, s) }) val client = ClientBleGatt.connect(this@HTSService, device, lifecycleScope, logger = { p, s -> repository.log(p, s) })
this@HTSService.client = client this@HTSService.client = client
client.connectionStateWithStatus client.connectionStateWithStatus

View File

@@ -48,20 +48,18 @@ dependencies {
implementation(libs.nordic.blek.client) implementation(libs.nordic.blek.client)
implementation(libs.nordic.blek.profile) implementation(libs.nordic.blek.profile)
implementation(libs.nordic.blek.server) implementation(libs.nordic.blek.server)
implementation(libs.nordic.ble.common)
implementation(libs.nordic.ble.ktx)
implementation(libs.nordic.theme)
implementation(libs.nordic.blek.uiscanner) implementation(libs.nordic.blek.uiscanner)
implementation(libs.nordic.core)
implementation(libs.nordic.theme)
implementation(libs.nordic.navigation) implementation(libs.nordic.navigation)
implementation(libs.nordic.uilogger) implementation(libs.nordic.uilogger)
implementation(libs.nordic.core)
implementation(libs.androidx.hilt.navigation.compose) implementation(libs.androidx.compose.material3)
implementation(libs.androidx.compose.material.iconsExtended) implementation(libs.androidx.compose.material.iconsExtended)
implementation(libs.androidx.core.ktx) implementation(libs.androidx.core.ktx)
implementation(libs.androidx.compose.material3)
implementation(libs.androidx.activity.compose) implementation(libs.androidx.activity.compose)
implementation(libs.androidx.lifecycle.service) implementation(libs.androidx.lifecycle.service)
implementation(libs.androidx.hilt.navigation.compose)
} }

View File

@@ -129,7 +129,7 @@ internal class PRXService : NotificationService() {
characteristicConfigs = listOf(linkLossCharacteristic) characteristicConfigs = listOf(linkLossCharacteristic)
) )
val server = ServerBleGatt.create(this@PRXService, prxServiceConfig, linkLossServiceConfig) val server = ServerBleGatt.create(this@PRXService, lifecycleScope, prxServiceConfig, linkLossServiceConfig)
this@PRXService.server = server this@PRXService.server = server
//Order is important. We don't want to connect before services have been added to the server. //Order is important. We don't want to connect before services have been added to the server.
@@ -163,6 +163,7 @@ internal class PRXService : NotificationService() {
val client = ClientBleGatt.connect( val client = ClientBleGatt.connect(
this@PRXService, this@PRXService,
device, device,
lifecycleScope,
logger = { p, s -> repository.log(p, s) }, logger = { p, s -> repository.log(p, s) },
options = BleGattConnectOptions(autoConnect = true) options = BleGattConnectOptions(autoConnect = true)
) )

View File

@@ -45,22 +45,20 @@ dependencies {
implementation(project(":lib_ui")) implementation(project(":lib_ui"))
implementation(project(":lib_utils")) implementation(project(":lib_utils"))
implementation(libs.nordic.blek.client) implementation(libs.nordic.core)
implementation(libs.nordic.blek.profile)
implementation(libs.nordic.ble.common)
implementation(libs.nordic.ble.ktx)
implementation(libs.nordic.theme) implementation(libs.nordic.theme)
implementation(libs.nordic.blek.uiscanner)
implementation(libs.nordic.navigation) implementation(libs.nordic.navigation)
implementation(libs.nordic.uilogger) implementation(libs.nordic.uilogger)
implementation(libs.nordic.core)
implementation(libs.androidx.hilt.navigation.compose) implementation(libs.nordic.blek.client)
implementation(libs.nordic.blek.profile)
implementation(libs.nordic.blek.uiscanner)
implementation(libs.androidx.compose.material3)
implementation(libs.androidx.compose.material.iconsExtended) implementation(libs.androidx.compose.material.iconsExtended)
implementation(libs.androidx.core.ktx) implementation(libs.androidx.core.ktx)
implementation(libs.androidx.compose.material3)
implementation(libs.androidx.activity.compose) implementation(libs.androidx.activity.compose)
implementation(libs.androidx.lifecycle.service) implementation(libs.androidx.lifecycle.service)
implementation(libs.androidx.hilt.navigation.compose)
} }

View File

@@ -86,7 +86,7 @@ internal class RSCSService : NotificationService() {
} }
private fun startGattClient(device: ServerDevice) = lifecycleScope.launch { private fun startGattClient(device: ServerDevice) = lifecycleScope.launch {
val client = ClientBleGatt.connect(this@RSCSService, device, logger = { p, s -> repository.log(p, s) }) val client = ClientBleGatt.connect(this@RSCSService, device, lifecycleScope, logger = { p, s -> repository.log(p, s) })
this@RSCSService.client = client this@RSCSService.client = client
client.connectionStateWithStatus client.connectionStateWithStatus

View File

@@ -50,11 +50,17 @@ dependencies {
implementation(project(":lib_ui")) implementation(project(":lib_ui"))
implementation(project(":lib_utils")) implementation(project(":lib_utils"))
implementation(libs.nordic.core)
implementation(libs.nordic.theme)
implementation(libs.nordic.navigation)
implementation(libs.nordic.uilogger)
implementation(libs.nordic.blek.client) implementation(libs.nordic.blek.client)
implementation(libs.nordic.blek.profile) implementation(libs.nordic.blek.profile)
implementation(libs.nordic.blek.core) implementation(libs.nordic.blek.core)
implementation(libs.nordic.blek.server) implementation(libs.nordic.blek.server)
implementation(libs.nordic.blek.advertiser) implementation(libs.nordic.blek.advertiser)
implementation(libs.nordic.blek.uiscanner)
implementation(libs.room.runtime) implementation(libs.room.runtime)
implementation(libs.room.ktx) implementation(libs.room.ktx)
@@ -63,25 +69,16 @@ dependencies {
implementation(libs.accompanist.pager) implementation(libs.accompanist.pager)
implementation(libs.accompanist.pagerindicators) implementation(libs.accompanist.pagerindicators)
implementation(libs.nordic.ble.common)
implementation(libs.nordic.ble.ktx)
implementation(libs.nordic.theme)
implementation(libs.nordic.navigation)
implementation(libs.nordic.uilogger)
implementation(libs.nordic.core)
implementation(libs.nordic.blek.uiscanner)
implementation(libs.androidx.dataStore.core) implementation(libs.androidx.dataStore.core)
implementation(libs.androidx.dataStore.preferences) implementation(libs.androidx.dataStore.preferences)
implementation(libs.androidx.compose.material3)
implementation(libs.androidx.hilt.navigation.compose)
implementation(libs.androidx.compose.material.iconsExtended) implementation(libs.androidx.compose.material.iconsExtended)
implementation(libs.androidx.core.ktx) implementation(libs.androidx.core.ktx)
implementation(libs.androidx.compose.material3)
implementation(libs.androidx.activity.compose) implementation(libs.androidx.activity.compose)
implementation(libs.androidx.lifecycle.service) implementation(libs.androidx.lifecycle.service)
implementation(libs.androidx.hilt.navigation.compose)
testImplementation(libs.hilt.android.testing) testImplementation(libs.hilt.android.testing)
kaptTest(libs.hilt.compiler) kaptTest(libs.hilt.compiler)
testImplementation(libs.androidx.test.rules) testImplementation(libs.androidx.test.rules)

View File

@@ -36,11 +36,11 @@ class UartServer @Inject constructor(
private val scope: CoroutineScope private val scope: CoroutineScope
) { ) {
lateinit var server: ServerBleGatt private lateinit var server: ServerBleGatt
lateinit var rxCharacteristic: ServerBleGattCharacteristic private lateinit var rxCharacteristic: ServerBleGattCharacteristic
lateinit var txCharacteristic: ServerBleGattCharacteristic private lateinit var txCharacteristic: ServerBleGattCharacteristic
lateinit var batteryLevelCharacteristic: ServerBleGattCharacteristic private lateinit var batteryLevelCharacteristic: ServerBleGattCharacteristic
fun start( fun start(
context: Context, context: Context,
@@ -81,6 +81,7 @@ class UartServer @Inject constructor(
server = ServerBleGatt.create( server = ServerBleGatt.create(
context = context, context = context,
scope = scope,
config = arrayOf(uartService, batteryService), config = arrayOf(uartService, batteryService),
mock = device mock = device
) )
@@ -105,27 +106,30 @@ class UartServer @Inject constructor(
txCharacteristic = glsService.findCharacteristic(UART_TX_CHARACTERISTIC_UUID)!! txCharacteristic = glsService.findCharacteristic(UART_TX_CHARACTERISTIC_UUID)!!
rxCharacteristic.value.onEach { rxCharacteristic.value.onEach {
txCharacteristic.setValue(it) send(txCharacteristic, it)
}.launchIn(scope) }.launchIn(scope)
val batteryService = connection.services.findService(BATTERY_SERVICE_UUID)!! val batteryService = connection.services.findService(BATTERY_SERVICE_UUID)!!
batteryLevelCharacteristic = batteryService.findCharacteristic( batteryLevelCharacteristic = batteryService
BATTERY_LEVEL_CHARACTERISTIC_UUID .findCharacteristic(BATTERY_LEVEL_CHARACTERISTIC_UUID)!!
)!!
startBatteryService(connection) startBatteryService()
} }
private fun startBatteryService(connection: ServerBluetoothGattConnection) { private fun startBatteryService() {
scope.launch { scope.launch {
repeat(100) { repeat(100) {
batteryLevelCharacteristic.setValue(DataByteArray.from(0x61)) send(batteryLevelCharacteristic, DataByteArray.from(0x61))
delay(STANDARD_DELAY) delay(STANDARD_DELAY)
batteryLevelCharacteristic.setValue(DataByteArray.from(0x60)) send(batteryLevelCharacteristic, DataByteArray.from(0x60))
delay(STANDARD_DELAY) delay(STANDARD_DELAY)
batteryLevelCharacteristic.setValue(DataByteArray.from(0x5F)) send(batteryLevelCharacteristic, DataByteArray.from(0x5F))
delay(STANDARD_DELAY) delay(STANDARD_DELAY)
} }
} }
} }
private suspend fun send(characteristics: ServerBleGattCharacteristic, data: DataByteArray) {
characteristics.setValueAndNotifyClient(data)
}
} }

View File

@@ -39,6 +39,7 @@ import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.mapNotNull import kotlinx.coroutines.flow.mapNotNull
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@@ -91,7 +92,7 @@ internal class UARTService : NotificationService() {
} }
private fun startGattClient(device: ServerDevice) = lifecycleScope.launch { private fun startGattClient(device: ServerDevice) = lifecycleScope.launch {
val client = ClientBleGatt.connect(this@UARTService, device, logger = { p, s -> repository.log(p, s) }) val client = ClientBleGatt.connect(this@UARTService, device, lifecycleScope, logger = { p, s -> repository.log(p, s) })
this@UARTService.client = client this@UARTService.client = client
if (!client.isConnected) { if (!client.isConnected) {
@@ -133,8 +134,9 @@ internal class UARTService : NotificationService() {
?.launchIn(lifecycleScope) ?.launchIn(lifecycleScope)
txCharacteristic.getNotifications() txCharacteristic.getNotifications()
.onEach { repository.onNewMessageReceived(String(it.value)) } .map { String(it.value) }
.onEach { repository.log(10, "Received: ${String(it.value)}") } .onEach { repository.onNewMessageReceived(it) }
.onEach { repository.log(10, "Received: $it") }
.catch { it.printStackTrace() } .catch { it.printStackTrace() }
.launchIn(lifecycleScope) .launchIn(lifecycleScope)

View File

@@ -50,7 +50,7 @@ dependencyResolutionManagement {
} }
versionCatalogs { versionCatalogs {
create("libs") { create("libs") {
from("no.nordicsemi.android.gradle:version-catalog:1.9.13") from("no.nordicsemi.android.gradle:version-catalog:1.10.6")
} }
} }
} }