Migration to AGP and Commons Library (#142)

* Update dependencies

* Migrated logger feature

* Updated to be compatible with common library version 2.0.0

* Migration to Kotlin BLE 1.1.0

* Changed to Enum entries

* Removed unnecessary ExperimentalMaterial3Api annotation

* Migrated from SmallTopAppBar to TopAppBar

* Changed to data object

* Made nullable logger

* Changed to nullable

* Changed import
This commit is contained in:
Himali Aryal
2025-07-25 16:13:50 +02:00
committed by GitHub
parent a253906cf9
commit 9a71e66c10
56 changed files with 316 additions and 242 deletions

View File

@@ -66,7 +66,7 @@ dependencies {
implementation(libs.nordic.theme) implementation(libs.nordic.theme)
implementation(libs.nordic.navigation) implementation(libs.nordic.navigation)
implementation(libs.nordic.blek.uiscanner) implementation(libs.nordic.blek.uiscanner)
implementation(libs.nordic.uilogger) implementation(libs.nordic.logger)
implementation(libs.nordic.permissions.ble) implementation(libs.nordic.permissions.ble)
implementation(libs.nordic.analytics) implementation(libs.nordic.analytics)
@@ -79,4 +79,8 @@ dependencies {
implementation(libs.androidx.lifecycle.runtime.compose) implementation(libs.androidx.lifecycle.runtime.compose)
implementation(libs.androidx.hilt.navigation.compose) implementation(libs.androidx.hilt.navigation.compose)
// Timber & SLF4J
implementation (libs.slf4j.timber)
implementation(libs.nordic.log.timber)
} }

View File

@@ -37,6 +37,7 @@ import no.nordicsemi.android.analytics.AppAnalytics
import no.nordicsemi.android.analytics.AppOpenEvent import no.nordicsemi.android.analytics.AppOpenEvent
import no.nordicsemi.android.gls.GLSServer import no.nordicsemi.android.gls.GLSServer
import no.nordicsemi.android.uart.UartServer import no.nordicsemi.android.uart.UartServer
import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
@HiltAndroidApp @HiltAndroidApp
@@ -58,5 +59,7 @@ class NrfToolboxApplication : Application() {
uartServer.start(this) uartServer.start(this)
glsServer.start(this) glsServer.start(this)
Timber.plant(Timber.DebugTree())
} }
} }

View File

@@ -1,21 +0,0 @@
package no.nordicsemi.android.nrftoolbox
import android.content.Context
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import no.nordicsemi.android.common.logger.BleLogger
import no.nordicsemi.android.common.logger.DefaultConsoleLogger
@Suppress("unused")
@Module
@InstallIn(SingletonComponent::class)
internal class AppModule {
@Provides
fun provideNordicLogger(
@ApplicationContext context: Context
): BleLogger = DefaultConsoleLogger(context)
}

View File

@@ -61,7 +61,6 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import no.nordicsemi.android.nrftoolbox.R import no.nordicsemi.android.nrftoolbox.R
@OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun FeatureButton( fun FeatureButton(
@DrawableRes iconId: Int, @DrawableRes iconId: Int,

View File

@@ -34,7 +34,6 @@ package no.nordicsemi.android.nrftoolbox.view
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text import androidx.compose.material3.Text
@@ -69,7 +68,6 @@ private const val DFU_LINK = "https://play.google.com/store/apps/details?id=no.n
private const val LOGGER_PACKAGE_NAME = "no.nordicsemi.android.log" private const val LOGGER_PACKAGE_NAME = "no.nordicsemi.android.log"
@OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun HomeScreen() { fun HomeScreen() {
val viewModel: HomeViewModel = hiltViewModel() val viewModel: HomeViewModel = hiltViewModel()

View File

@@ -33,8 +33,8 @@ package no.nordicsemi.android.nrftoolbox.view
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.SmallTopAppBar
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.colorResource
@@ -44,9 +44,9 @@ import no.nordicsemi.android.nrftoolbox.R
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun TitleAppBar(text: String) { fun TitleAppBar(text: String) {
SmallTopAppBar( TopAppBar(
title = { Text(text, maxLines = 2) }, title = { Text(text, maxLines = 2) },
colors = TopAppBarDefaults.smallTopAppBarColors( colors = TopAppBarDefaults.topAppBarColors(
scrolledContainerColor = MaterialTheme.colorScheme.primary, scrolledContainerColor = MaterialTheme.colorScheme.primary,
containerColor = colorResource(id = R.color.appBarColor), containerColor = colorResource(id = R.color.appBarColor),
titleContentColor = MaterialTheme.colorScheme.onPrimary, titleContentColor = MaterialTheme.colorScheme.onPrimary,

View File

@@ -114,7 +114,7 @@ class HomeViewModel @Inject constructor(
} }
fun openLogger() { fun openLogger() {
LoggerLauncher.launch(context) LoggerLauncher.launch(context, null)
} }
fun logEvent(event: ProfileOpenEvent) { fun logEvent(event: ProfileOpenEvent) {

View File

@@ -47,5 +47,7 @@ class NrfToolboxApplication : Application() {
super.onCreate() super.onCreate()
analytics.logEvent(AppOpenEvent) analytics.logEvent(AppOpenEvent)
Timber.plant(Timber.DebugTree())
} }
} }

View File

@@ -32,20 +32,25 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules. // Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins { plugins {
alias(libs.plugins.android.application) apply false alias(libs.plugins.android.application) apply false
alias(libs.plugins.android.library) apply false
alias(libs.plugins.compose.compiler) apply false
alias(libs.plugins.kotlin.android) apply false
alias(libs.plugins.kotlin.parcelize) apply false
alias(libs.plugins.kotlin.serialization) apply false
alias(libs.plugins.kotlin.jvm) apply false alias(libs.plugins.kotlin.jvm) apply false
alias(libs.plugins.kotlin.kapt) apply false alias(libs.plugins.kotlin.kapt) apply false
alias(libs.plugins.ksp) apply false
alias(libs.plugins.kotlin.serialization) apply false
alias(libs.plugins.kotlin.parcelize) apply false
alias(libs.plugins.hilt) apply false alias(libs.plugins.hilt) apply false
alias(libs.plugins.secrets) apply false alias(libs.plugins.secrets) apply false
alias(libs.plugins.protobuf) apply false alias(libs.plugins.protobuf) apply false
alias(libs.plugins.ksp) apply false
alias(libs.plugins.google.services) apply false
alias(libs.plugins.firebase.crashlytics) apply false
// Nordic plugins are defined in https://github.com/NordicSemiconductor/Android-Gradle-Plugins
alias(libs.plugins.nordic.application) apply false alias(libs.plugins.nordic.application) apply false
alias(libs.plugins.nordic.application.compose) apply false alias(libs.plugins.nordic.application.compose) apply false
alias(libs.plugins.nordic.library) apply false alias(libs.plugins.nordic.library) apply false
alias(libs.plugins.nordic.library.compose) apply false alias(libs.plugins.nordic.library.compose) apply false
alias(libs.plugins.nordic.hilt) apply false alias(libs.plugins.nordic.hilt) apply false
alias(libs.plugins.nordic.feature) apply false alias(libs.plugins.nordic.feature) apply false
alias(libs.plugins.google.services) apply false
alias(libs.plugins.firebase.crashlytics) apply false
} }

View File

@@ -50,3 +50,5 @@ android.useAndroidX=true
kotlin.code.style=official kotlin.code.style=official
android.nonTransitiveRClass=false android.nonTransitiveRClass=false
# https://github.com/google/ksp/issues/1942#issuecomment-2157733096
ksp.useKSP2=true

View File

@@ -31,7 +31,7 @@
#Mon Feb 14 14:46:55 CET 2022 #Mon Feb 14 14:46:55 CET 2022
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME

View File

@@ -35,7 +35,7 @@ import android.os.Bundle
sealed class FirebaseEvent(val eventName: String, val params: Bundle?) sealed class FirebaseEvent(val eventName: String, val params: Bundle?)
object AppOpenEvent : FirebaseEvent("APP_OPEN", null) data object AppOpenEvent : FirebaseEvent("APP_OPEN", null)
class ProfileOpenEvent : FirebaseEvent { class ProfileOpenEvent : FirebaseEvent {

View File

@@ -42,7 +42,6 @@ android {
} }
dependencies { dependencies {
implementation(libs.nordic.uilogger)
implementation(libs.nordic.theme) implementation(libs.nordic.theme)
implementation(libs.nordic.logger) implementation(libs.nordic.logger)
@@ -52,4 +51,8 @@ dependencies {
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.activity.compose) implementation(libs.androidx.activity.compose)
// Timber & SLF4J
implementation (libs.slf4j.timber)
implementation(libs.nordic.log.timber)
} }

View File

@@ -1,9 +0,0 @@
package no.nordicsemi.android.ui.view
import android.content.Context
import no.nordicsemi.android.common.logger.BleLoggerAndLauncher
interface NordicLoggerFactory {
fun createNordicLogger(context: Context, profile: String?, key: String, name: String?): BleLoggerAndLauncher
}

View File

@@ -1,28 +0,0 @@
package no.nordicsemi.android.ui.view
import android.content.Context
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import no.nordicsemi.android.common.logger.BleLoggerAndLauncher
import no.nordicsemi.android.common.logger.DefaultBleLogger
@Module
@InstallIn(SingletonComponent::class)
class NordicLoggerFactoryHiltModule {
@Provides
fun createLogger(): NordicLoggerFactory {
return object : NordicLoggerFactory {
override fun createNordicLogger(
context: Context,
profile: String?,
key: String,
name: String?,
): BleLoggerAndLauncher {
return DefaultBleLogger.create(context, profile, key, name)
}
}
}
}

View File

@@ -36,11 +36,18 @@ import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.filled.Close import androidx.compose.material.icons.filled.Close
import androidx.compose.material3.* import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
@@ -51,11 +58,11 @@ import no.nordicsemi.android.ui.R
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun CloseIconAppBar(text: String, onClick: () -> Unit) { fun CloseIconAppBar(text: String, onClick: () -> Unit) {
SmallTopAppBar( TopAppBar(
title = { Text(text, maxLines = 2) }, title = { Text(text, maxLines = 2) },
colors = TopAppBarDefaults.smallTopAppBarColors( colors = TopAppBarDefaults.topAppBarColors(
scrolledContainerColor = MaterialTheme.colorScheme.primary, scrolledContainerColor = MaterialTheme.colorScheme.primary,
containerColor = colorResource(id = R.color.appBarColor), containerColor = MaterialTheme.colorScheme.primaryContainer,
titleContentColor = MaterialTheme.colorScheme.onPrimary, titleContentColor = MaterialTheme.colorScheme.onPrimary,
actionIconContentColor = MaterialTheme.colorScheme.onPrimary, actionIconContentColor = MaterialTheme.colorScheme.onPrimary,
navigationIconContentColor = MaterialTheme.colorScheme.onPrimary, navigationIconContentColor = MaterialTheme.colorScheme.onPrimary,
@@ -74,11 +81,11 @@ fun CloseIconAppBar(text: String, onClick: () -> Unit) {
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun LoggerBackIconAppBar(text: String, onClick: () -> Unit) { fun LoggerBackIconAppBar(text: String, onClick: () -> Unit) {
SmallTopAppBar( TopAppBar(
title = { Text(text, maxLines = 2) }, title = { Text(text, maxLines = 2) },
colors = TopAppBarDefaults.smallTopAppBarColors( colors = TopAppBarDefaults.topAppBarColors(
scrolledContainerColor = MaterialTheme.colorScheme.primary, scrolledContainerColor = MaterialTheme.colorScheme.primary,
containerColor = colorResource(id = R.color.appBarColor), containerColor = MaterialTheme.colorScheme.primaryContainer,
titleContentColor = MaterialTheme.colorScheme.onPrimary, titleContentColor = MaterialTheme.colorScheme.onPrimary,
actionIconContentColor = MaterialTheme.colorScheme.onPrimary, actionIconContentColor = MaterialTheme.colorScheme.onPrimary,
navigationIconContentColor = MaterialTheme.colorScheme.onPrimary, navigationIconContentColor = MaterialTheme.colorScheme.onPrimary,
@@ -108,11 +115,11 @@ fun LoggerBackIconAppBar(text: String, onClick: () -> Unit) {
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun BackIconAppBar(text: String, onClick: () -> Unit) { fun BackIconAppBar(text: String, onClick: () -> Unit) {
SmallTopAppBar( TopAppBar(
title = { Text(text, maxLines = 2) }, title = { Text(text, maxLines = 2) },
colors = TopAppBarDefaults.smallTopAppBarColors( colors = TopAppBarDefaults.topAppBarColors(
scrolledContainerColor = MaterialTheme.colorScheme.primary, scrolledContainerColor = MaterialTheme.colorScheme.primary,
containerColor = colorResource(id = R.color.appBarColor), containerColor = MaterialTheme.colorScheme.primaryContainer,
titleContentColor = MaterialTheme.colorScheme.onPrimary, titleContentColor = MaterialTheme.colorScheme.onPrimary,
actionIconContentColor = MaterialTheme.colorScheme.onPrimary, actionIconContentColor = MaterialTheme.colorScheme.onPrimary,
navigationIconContentColor = MaterialTheme.colorScheme.onPrimary, navigationIconContentColor = MaterialTheme.colorScheme.onPrimary,
@@ -131,12 +138,17 @@ fun BackIconAppBar(text: String, onClick: () -> Unit) {
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun LoggerIconAppBar(text: String, onClick: () -> Unit, onDisconnectClick: () -> Unit, onLoggerClick: () -> Unit) { fun LoggerIconAppBar(
SmallTopAppBar( text: String,
onClick: () -> Unit,
onDisconnectClick: () -> Unit,
onLoggerClick: () -> Unit
) {
TopAppBar(
title = { Text(text, maxLines = 2) }, title = { Text(text, maxLines = 2) },
colors = TopAppBarDefaults.smallTopAppBarColors( colors = TopAppBarDefaults.topAppBarColors(
scrolledContainerColor = MaterialTheme.colorScheme.primary, scrolledContainerColor = MaterialTheme.colorScheme.primary,
containerColor = colorResource(id = R.color.appBarColor), containerColor = MaterialTheme.colorScheme.primaryContainer,
titleContentColor = MaterialTheme.colorScheme.onPrimary, titleContentColor = MaterialTheme.colorScheme.onPrimary,
actionIconContentColor = MaterialTheme.colorScheme.onPrimary, actionIconContentColor = MaterialTheme.colorScheme.onPrimary,
navigationIconContentColor = MaterialTheme.colorScheme.onPrimary, navigationIconContentColor = MaterialTheme.colorScheme.onPrimary,

View File

@@ -51,7 +51,7 @@ dependencies {
implementation(libs.nordic.navigation) implementation(libs.nordic.navigation)
implementation(libs.nordic.theme) implementation(libs.nordic.theme)
implementation(libs.nordic.uilogger) implementation(libs.nordic.logger)
implementation(libs.androidx.compose.material3) implementation(libs.androidx.compose.material3)
implementation(libs.androidx.compose.material.iconsExtended) implementation(libs.androidx.compose.material.iconsExtended)
@@ -60,4 +60,8 @@ dependencies {
implementation(libs.androidx.lifecycle.service) implementation(libs.androidx.lifecycle.service)
implementation(libs.androidx.hilt.navigation.compose) implementation(libs.androidx.hilt.navigation.compose)
// Timber & SLF4J
implementation (libs.slf4j.timber)
implementation(libs.nordic.log.timber)
} }

View File

@@ -53,8 +53,7 @@ import no.nordicsemi.android.bps.view.BPSViewEvent
import no.nordicsemi.android.bps.view.BPSViewState import no.nordicsemi.android.bps.view.BPSViewState
import no.nordicsemi.android.bps.view.DisconnectEvent import no.nordicsemi.android.bps.view.DisconnectEvent
import no.nordicsemi.android.bps.view.OpenLoggerEvent import no.nordicsemi.android.bps.view.OpenLoggerEvent
import no.nordicsemi.android.common.logger.BleLoggerAndLauncher import no.nordicsemi.android.common.logger.LoggerLauncher
import no.nordicsemi.android.common.logger.DefaultBleLogger
import no.nordicsemi.android.common.navigation.NavigationResult import no.nordicsemi.android.common.navigation.NavigationResult
import no.nordicsemi.android.common.navigation.Navigator import no.nordicsemi.android.common.navigation.Navigator
import no.nordicsemi.android.kotlin.ble.client.main.callback.ClientBleGatt import no.nordicsemi.android.kotlin.ble.client.main.callback.ClientBleGatt
@@ -67,8 +66,11 @@ import no.nordicsemi.android.kotlin.ble.profile.bps.BloodPressureMeasurementPars
import no.nordicsemi.android.kotlin.ble.profile.bps.IntermediateCuffPressureParser import no.nordicsemi.android.kotlin.ble.profile.bps.IntermediateCuffPressureParser
import no.nordicsemi.android.kotlin.ble.profile.bps.data.BloodPressureMeasurementData import no.nordicsemi.android.kotlin.ble.profile.bps.data.BloodPressureMeasurementData
import no.nordicsemi.android.kotlin.ble.profile.bps.data.IntermediateCuffPressureData import no.nordicsemi.android.kotlin.ble.profile.bps.data.IntermediateCuffPressureData
import no.nordicsemi.android.log.LogSession
import no.nordicsemi.android.log.timber.nRFLoggerTree
import no.nordicsemi.android.toolbox.scanner.ScannerDestinationId import no.nordicsemi.android.toolbox.scanner.ScannerDestinationId
import no.nordicsemi.android.ui.view.StringConst import no.nordicsemi.android.ui.view.StringConst
import timber.log.Timber
import java.util.UUID import java.util.UUID
import javax.inject.Inject import javax.inject.Inject
@@ -93,7 +95,7 @@ internal class BPSViewModel @Inject constructor(
val state = _state.asStateFlow() val state = _state.asStateFlow()
private var client: ClientBleGatt? = null private var client: ClientBleGatt? = null
private lateinit var logger: BleLoggerAndLauncher private var logger: nRFLoggerTree? = null
init { init {
navigationManager.navigateTo(ScannerDestinationId, ParcelUuid(BPS_SERVICE_UUID)) navigationManager.navigateTo(ScannerDestinationId, ParcelUuid(BPS_SERVICE_UUID))
@@ -113,7 +115,7 @@ internal class BPSViewModel @Inject constructor(
fun onEvent(event: BPSViewEvent) { fun onEvent(event: BPSViewEvent) {
when (event) { when (event) {
DisconnectEvent -> onDisconnectEvent() DisconnectEvent -> onDisconnectEvent()
OpenLoggerEvent -> logger.launch() OpenLoggerEvent -> LoggerLauncher.launch(context, logger?.session as? LogSession)
} }
} }
@@ -122,12 +124,18 @@ internal class BPSViewModel @Inject constructor(
navigationManager.navigateUp() navigationManager.navigateUp()
} }
private fun initLogger(device: ServerDevice) {
logger?.let { Timber.uproot(it) }
logger = nRFLoggerTree(context, stringConst.APP_NAME, "BPS", device.address)
.also { Timber.plant(it) }
}
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 = DefaultBleLogger.create(context, stringConst.APP_NAME, "BPS", device.address) initLogger(device)
val client = ClientBleGatt.connect(context, device, viewModelScope, logger = logger) val client = ClientBleGatt.connect(context, device, viewModelScope)
this@BPSViewModel.client = client this@BPSViewModel.client = client
client.connectionStateWithStatus client.connectionStateWithStatus

View File

@@ -47,7 +47,7 @@ dependencies {
implementation(libs.nordic.core) implementation(libs.nordic.core)
implementation(libs.nordic.theme) implementation(libs.nordic.theme)
implementation(libs.nordic.uilogger) implementation(libs.nordic.logger)
implementation(libs.nordic.navigation) implementation(libs.nordic.navigation)
implementation(libs.nordic.blek.uiscanner) implementation(libs.nordic.blek.uiscanner)
@@ -61,4 +61,8 @@ dependencies {
implementation(libs.androidx.lifecycle.service) implementation(libs.androidx.lifecycle.service)
implementation(libs.androidx.hilt.navigation.compose) implementation(libs.androidx.hilt.navigation.compose)
// Timber & SLF4J
implementation(libs.slf4j.timber)
implementation(libs.nordic.log.timber)
} }

View File

@@ -41,15 +41,17 @@ 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.cgms.data.CGMServiceData import no.nordicsemi.android.cgms.data.CGMServiceData
import no.nordicsemi.android.common.core.simpleSharedFlow import no.nordicsemi.android.common.core.simpleSharedFlow
import no.nordicsemi.android.common.logger.BleLoggerAndLauncher import no.nordicsemi.android.common.logger.LoggerLauncher
import no.nordicsemi.android.common.logger.DefaultBleLogger
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.profile.gls.data.RequestStatus import no.nordicsemi.android.kotlin.ble.profile.gls.data.RequestStatus
import no.nordicsemi.android.log.LogSession
import no.nordicsemi.android.log.timber.nRFLoggerTree
import no.nordicsemi.android.service.DisconnectAndStopEvent import no.nordicsemi.android.service.DisconnectAndStopEvent
import no.nordicsemi.android.service.ServiceManager import no.nordicsemi.android.service.ServiceManager
import no.nordicsemi.android.ui.view.StringConst import no.nordicsemi.android.ui.view.StringConst
import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@@ -60,7 +62,7 @@ class CGMRepository @Inject constructor(
private val serviceManager: ServiceManager, private val serviceManager: ServiceManager,
private val stringConst: StringConst private val stringConst: StringConst
) { ) {
private var logger: BleLoggerAndLauncher? = null private var logger: nRFLoggerTree? = null
private val _data = MutableStateFlow(CGMServiceData()) private val _data = MutableStateFlow(CGMServiceData())
internal val data = _data.asStateFlow() internal val data = _data.asStateFlow()
@@ -92,8 +94,14 @@ class CGMRepository @Inject constructor(
private fun shouldClean() = !isOnScreen && !isServiceRunning private fun shouldClean() = !isOnScreen && !isServiceRunning
private fun initLogger(device: ServerDevice) {
logger?.let { Timber.uproot(it) }
logger = nRFLoggerTree(context, stringConst.APP_NAME, "CGM", device.address)
.also { Timber.plant(it) }
}
fun launch(device: ServerDevice) { fun launch(device: ServerDevice) {
logger = DefaultBleLogger.create(context, stringConst.APP_NAME, "CGM", device.address) initLogger(device)
_data.value = _data.value.copy(deviceName = device.name) _data.value = _data.value.copy(deviceName = device.name)
serviceManager.startService(CGMService::class.java, device) serviceManager.startService(CGMService::class.java, device)
} }
@@ -124,7 +132,7 @@ class CGMRepository @Inject constructor(
} }
fun openLogger() { fun openLogger() {
logger?.launch() LoggerLauncher.launch(context, logger?.session as? LogSession)
} }
fun log(priority: Int, message: String) { fun log(priority: Int, message: String) {

View File

@@ -132,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, lifecycleScope, logger = { p, s -> repository.log(p, s) }) val client = ClientBleGatt.connect(this@CGMService, device, lifecycleScope)
this@CGMService.client = client this@CGMService.client = client
client.connectionStateWithStatus client.connectionStateWithStatus

View File

@@ -46,8 +46,9 @@ dependencies {
implementation(project(":lib_utils")) implementation(project(":lib_utils"))
implementation(libs.nordic.core) implementation(libs.nordic.core)
implementation(libs.nordic.ui)
implementation(libs.nordic.theme) implementation(libs.nordic.theme)
implementation(libs.nordic.uilogger) implementation(libs.nordic.logger)
implementation(libs.nordic.navigation) implementation(libs.nordic.navigation)
implementation(libs.nordic.blek.client) implementation(libs.nordic.blek.client)
@@ -61,4 +62,8 @@ dependencies {
implementation(libs.androidx.lifecycle.service) implementation(libs.androidx.lifecycle.service)
implementation(libs.androidx.hilt.navigation.compose) implementation(libs.androidx.hilt.navigation.compose)
// Timber & SLF4J
implementation (libs.slf4j.timber)
implementation(libs.nordic.log.timber)
} }

View File

@@ -38,8 +38,7 @@ import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import no.nordicsemi.android.common.core.simpleSharedFlow import no.nordicsemi.android.common.core.simpleSharedFlow
import no.nordicsemi.android.common.logger.BleLoggerAndLauncher import no.nordicsemi.android.common.logger.LoggerLauncher
import no.nordicsemi.android.common.logger.DefaultBleLogger
import no.nordicsemi.android.csc.data.CSCServiceData import no.nordicsemi.android.csc.data.CSCServiceData
import no.nordicsemi.android.csc.data.SpeedUnit import no.nordicsemi.android.csc.data.SpeedUnit
import no.nordicsemi.android.kotlin.ble.core.ServerDevice import no.nordicsemi.android.kotlin.ble.core.ServerDevice
@@ -48,9 +47,12 @@ import no.nordicsemi.android.kotlin.ble.core.data.GattConnectionStateWithStatus
import no.nordicsemi.android.kotlin.ble.profile.csc.data.CSCData import no.nordicsemi.android.kotlin.ble.profile.csc.data.CSCData
import no.nordicsemi.android.kotlin.ble.profile.csc.data.WheelSize import no.nordicsemi.android.kotlin.ble.profile.csc.data.WheelSize
import no.nordicsemi.android.kotlin.ble.profile.csc.data.WheelSizes import no.nordicsemi.android.kotlin.ble.profile.csc.data.WheelSizes
import no.nordicsemi.android.log.LogSession
import no.nordicsemi.android.log.timber.nRFLoggerTree
import no.nordicsemi.android.service.DisconnectAndStopEvent import no.nordicsemi.android.service.DisconnectAndStopEvent
import no.nordicsemi.android.service.ServiceManager import no.nordicsemi.android.service.ServiceManager
import no.nordicsemi.android.ui.view.StringConst import no.nordicsemi.android.ui.view.StringConst
import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@@ -61,7 +63,7 @@ class CSCRepository @Inject constructor(
private val serviceManager: ServiceManager, private val serviceManager: ServiceManager,
private val stringConst: StringConst private val stringConst: StringConst
) { ) {
private var logger: BleLoggerAndLauncher? = null private var logger: nRFLoggerTree? = null
private val _wheelSize = MutableStateFlow(WheelSizes.default) private val _wheelSize = MutableStateFlow(WheelSizes.default)
internal val wheelSize = _wheelSize.asStateFlow() internal val wheelSize = _wheelSize.asStateFlow()
@@ -91,8 +93,14 @@ class CSCRepository @Inject constructor(
private fun shouldClean() = !isOnScreen && !isServiceRunning private fun shouldClean() = !isOnScreen && !isServiceRunning
private fun initLogger(device: ServerDevice) {
logger?.let { Timber.uproot(it) }
logger = nRFLoggerTree(context, stringConst.APP_NAME, "CSC", device.address)
.also { Timber.plant(it) }
}
fun launch(device: ServerDevice) { fun launch(device: ServerDevice) {
logger = DefaultBleLogger.create(context, stringConst.APP_NAME, "CSC", device.address) initLogger(device)
_data.value = _data.value.copy(deviceName = device.name) _data.value = _data.value.copy(deviceName = device.name)
serviceManager.startService(CSCService::class.java, device) serviceManager.startService(CSCService::class.java, device)
} }
@@ -123,7 +131,7 @@ class CSCRepository @Inject constructor(
} }
fun openLogger() { fun openLogger() {
logger?.launch() LoggerLauncher.launch(context, logger?.session as? LogSession)
} }
fun log(priority: Int, message: String) { fun log(priority: Int, message: String) {

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, lifecycleScope, logger = { p, s -> repository.log(p, s) }) val client = ClientBleGatt.connect(this@CSCService, device, lifecycleScope)
this@CSCService.client = client this@CSCService.client = client
client.connectionStateWithStatus client.connectionStateWithStatus

View File

@@ -47,7 +47,7 @@ import androidx.compose.ui.res.stringArrayResource
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import no.nordicsemi.android.common.theme.view.RadioButtonGroup import no.nordicsemi.android.common.ui.view.RadioButtonGroup
import no.nordicsemi.android.csc.R import no.nordicsemi.android.csc.R
import no.nordicsemi.android.csc.data.CSCServiceData import no.nordicsemi.android.csc.data.CSCServiceData
import no.nordicsemi.android.csc.data.SpeedUnit import no.nordicsemi.android.csc.data.SpeedUnit
@@ -107,8 +107,10 @@ private fun SettingsSection(
Column( Column(
horizontalAlignment = Alignment.CenterHorizontally horizontalAlignment = Alignment.CenterHorizontally
) { ) {
SectionTitle(icon = Icons.Default.Settings, SectionTitle(
title = stringResource(R.string.csc_settings)) icon = Icons.Default.Settings,
title = stringResource(R.string.csc_settings)
)
Spacer(modifier = Modifier.height(16.dp)) Spacer(modifier = Modifier.height(16.dp))

View File

@@ -31,8 +31,8 @@
package no.nordicsemi.android.csc.view package no.nordicsemi.android.csc.view
import no.nordicsemi.android.common.theme.view.RadioButtonItem import no.nordicsemi.android.common.ui.view.RadioButtonItem
import no.nordicsemi.android.common.theme.view.RadioGroupViewEntity import no.nordicsemi.android.common.ui.view.RadioGroupViewEntity
import no.nordicsemi.android.csc.data.SpeedUnit import no.nordicsemi.android.csc.data.SpeedUnit
import no.nordicsemi.android.kotlin.ble.profile.csc.data.CSCData import no.nordicsemi.android.kotlin.ble.profile.csc.data.CSCData
import java.util.Locale import java.util.Locale
@@ -52,29 +52,29 @@ internal fun CSCData.speedWithSpeedUnit(speedUnit: SpeedUnit): Float {
internal fun CSCData.displaySpeed(speedUnit: SpeedUnit): String { internal fun CSCData.displaySpeed(speedUnit: SpeedUnit): String {
val speedWithUnit = speedWithSpeedUnit(speedUnit) val speedWithUnit = speedWithSpeedUnit(speedUnit)
return when (speedUnit) { return when (speedUnit) {
SpeedUnit.M_S -> String.format("%.1f m/s", speedWithUnit) SpeedUnit.M_S -> String.format(Locale.US, "%.1f m/s", speedWithUnit)
SpeedUnit.KM_H -> String.format("%.1f km/h", speedWithUnit) SpeedUnit.KM_H -> String.format(Locale.US, "%.1f km/h", speedWithUnit)
SpeedUnit.MPH -> String.format("%.1f mph", speedWithUnit) SpeedUnit.MPH -> String.format(Locale.US, "%.1f mph", speedWithUnit)
} }
} }
internal fun CSCData.displayCadence(): String { internal fun CSCData.displayCadence(): String {
return String.format("%.0f RPM", cadence) return String.format(Locale.US, "%.0f RPM", cadence)
} }
internal fun CSCData.displayDistance(speedUnit: SpeedUnit): String { internal fun CSCData.displayDistance(speedUnit: SpeedUnit): String {
return when (speedUnit) { return when (speedUnit) {
SpeedUnit.M_S -> String.format("%.0f m", distance) SpeedUnit.M_S -> String.format(Locale.US, "%.0f m", distance)
SpeedUnit.KM_H -> String.format("%.0f m", distance) SpeedUnit.KM_H -> String.format(Locale.US, "%.0f m", distance)
SpeedUnit.MPH -> String.format("%.0f yd", distance.toYards()) SpeedUnit.MPH -> String.format(Locale.US, "%.0f yd", distance.toYards())
} }
} }
internal fun CSCData.displayTotalDistance(speedUnit: SpeedUnit): String { internal fun CSCData.displayTotalDistance(speedUnit: SpeedUnit): String {
return when (speedUnit) { return when (speedUnit) {
SpeedUnit.M_S -> String.format("%.2f m", totalDistance) SpeedUnit.M_S -> String.format(Locale.US, "%.2f m", totalDistance)
SpeedUnit.KM_H -> String.format("%.2f km", totalDistance.toKilometers()) SpeedUnit.KM_H -> String.format(Locale.US, "%.2f km", totalDistance.toKilometers())
SpeedUnit.MPH -> String.format("%.2f mile", totalDistance.toMiles()) SpeedUnit.MPH -> String.format(Locale.US, "%.2f mile", totalDistance.toMiles())
} }
} }
@@ -93,7 +93,7 @@ internal fun String.toSpeedUnit(): SpeedUnit {
internal fun SpeedUnit.temperatureSettingsItems(): RadioGroupViewEntity { internal fun SpeedUnit.temperatureSettingsItems(): RadioGroupViewEntity {
return RadioGroupViewEntity( return RadioGroupViewEntity(
SpeedUnit.values().map { createRadioButtonItem(it, this) } SpeedUnit.entries.toTypedArray().map { createRadioButtonItem(it, this) }
) )
} }

View File

@@ -45,9 +45,10 @@ 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.theme)
implementation(libs.nordic.navigation) implementation(libs.nordic.navigation)
implementation(libs.nordic.uilogger) implementation(libs.nordic.logger)
implementation(libs.nordic.blek.client) implementation(libs.nordic.blek.client)
implementation(libs.nordic.blek.profile) implementation(libs.nordic.blek.profile)
@@ -65,6 +66,10 @@ dependencies {
implementation(libs.androidx.hilt.navigation.compose) implementation(libs.androidx.hilt.navigation.compose)
// Timber & SLF4J
implementation (libs.slf4j.timber)
implementation(libs.nordic.log.timber)
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)
@@ -73,7 +78,7 @@ dependencies {
testImplementation(libs.test.mockk) testImplementation(libs.test.mockk)
testImplementation(libs.androidx.test.ext) testImplementation(libs.androidx.test.ext)
testImplementation(libs.kotlinx.coroutines.test) testImplementation(libs.kotlinx.coroutines.test)
testImplementation(libs.test.slf4j.simple) testImplementation(libs.slf4j.simple)
testImplementation(libs.test.robolectric) testImplementation(libs.test.robolectric)
testImplementation(libs.kotlin.junit) testImplementation(libs.kotlin.junit)
} }

View File

@@ -3,16 +3,12 @@ package no.nordicsemi.android.gls
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.os.ParcelUuid import android.os.ParcelUuid
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
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
import no.nordicsemi.android.common.core.DataByteArray
import no.nordicsemi.android.common.logger.BleLogger
import no.nordicsemi.android.common.logger.DefaultConsoleLogger
import no.nordicsemi.android.gls.main.viewmodel.BATTERY_LEVEL_CHARACTERISTIC_UUID import no.nordicsemi.android.gls.main.viewmodel.BATTERY_LEVEL_CHARACTERISTIC_UUID
import no.nordicsemi.android.gls.main.viewmodel.BATTERY_SERVICE_UUID import no.nordicsemi.android.gls.main.viewmodel.BATTERY_SERVICE_UUID
import no.nordicsemi.android.gls.main.viewmodel.GLS_SERVICE_UUID import no.nordicsemi.android.gls.main.viewmodel.GLS_SERVICE_UUID
@@ -26,6 +22,7 @@ import no.nordicsemi.android.kotlin.ble.core.advertiser.BleAdvertisingData
import no.nordicsemi.android.kotlin.ble.core.advertiser.BleAdvertisingSettings import no.nordicsemi.android.kotlin.ble.core.advertiser.BleAdvertisingSettings
import no.nordicsemi.android.kotlin.ble.core.data.BleGattPermission import no.nordicsemi.android.kotlin.ble.core.data.BleGattPermission
import no.nordicsemi.android.kotlin.ble.core.data.BleGattProperty import no.nordicsemi.android.kotlin.ble.core.data.BleGattProperty
import no.nordicsemi.android.kotlin.ble.core.data.util.DataByteArray
import no.nordicsemi.android.kotlin.ble.profile.gls.RecordAccessControlPointInputParser import no.nordicsemi.android.kotlin.ble.profile.gls.RecordAccessControlPointInputParser
import no.nordicsemi.android.kotlin.ble.server.main.ServerBleGatt import no.nordicsemi.android.kotlin.ble.server.main.ServerBleGatt
import no.nordicsemi.android.kotlin.ble.server.main.service.ServerBleGattCharacteristic import no.nordicsemi.android.kotlin.ble.server.main.service.ServerBleGattCharacteristic
@@ -42,9 +39,6 @@ private const val STANDARD_DELAY = 1000L
@Singleton @Singleton
class GLSServer @Inject constructor( class GLSServer @Inject constructor(
private val scope: CoroutineScope, private val scope: CoroutineScope,
@ApplicationContext
private val context: Context,
private val logger: BleLogger = DefaultConsoleLogger(context),
) { ) {
private lateinit var server: ServerBleGatt private lateinit var server: ServerBleGatt
@@ -197,7 +191,6 @@ class GLSServer @Inject constructor(
config = arrayOf(serviceConfig, batteryService), config = arrayOf(serviceConfig, batteryService),
mock = device, mock = device,
scope = scope, scope = scope,
logger = { _, log -> println(log) }
) )
BleAdvertiser.create(context) BleAdvertiser.create(context)

View File

@@ -32,10 +32,9 @@
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.AndroidViewModel import androidx.lifecycle.ViewModel
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
@@ -50,7 +49,7 @@ import kotlinx.coroutines.launch
import no.nordicsemi.android.analytics.AppAnalytics import no.nordicsemi.android.analytics.AppAnalytics
import no.nordicsemi.android.analytics.Profile import no.nordicsemi.android.analytics.Profile
import no.nordicsemi.android.analytics.ProfileConnectedEvent import no.nordicsemi.android.analytics.ProfileConnectedEvent
import no.nordicsemi.android.common.logger.BleLoggerAndLauncher import no.nordicsemi.android.common.logger.LoggerLauncher
import no.nordicsemi.android.common.navigation.NavigationResult import no.nordicsemi.android.common.navigation.NavigationResult
import no.nordicsemi.android.common.navigation.Navigator import no.nordicsemi.android.common.navigation.Navigator
import no.nordicsemi.android.gls.GlsDetailsDestinationId import no.nordicsemi.android.gls.GlsDetailsDestinationId
@@ -80,11 +79,13 @@ import no.nordicsemi.android.kotlin.ble.profile.gls.data.RequestStatus
import no.nordicsemi.android.kotlin.ble.profile.gls.data.ResponseData import no.nordicsemi.android.kotlin.ble.profile.gls.data.ResponseData
import no.nordicsemi.android.kotlin.ble.profile.racp.RACPOpCode import no.nordicsemi.android.kotlin.ble.profile.racp.RACPOpCode
import no.nordicsemi.android.kotlin.ble.profile.racp.RACPResponseCode import no.nordicsemi.android.kotlin.ble.profile.racp.RACPResponseCode
import no.nordicsemi.android.log.LogSession
import no.nordicsemi.android.log.timber.nRFLoggerTree
import no.nordicsemi.android.toolbox.scanner.ScannerDestinationId import no.nordicsemi.android.toolbox.scanner.ScannerDestinationId
import no.nordicsemi.android.ui.view.NordicLoggerFactory
import no.nordicsemi.android.ui.view.StringConst import no.nordicsemi.android.ui.view.StringConst
import no.nordicsemi.android.utils.tryOrLog import no.nordicsemi.android.utils.tryOrLog
import java.util.* import timber.log.Timber
import java.util.UUID
import javax.inject.Inject import javax.inject.Inject
val GLS_SERVICE_UUID: UUID = UUID.fromString("00001808-0000-1000-8000-00805f9b34fb") val GLS_SERVICE_UUID: UUID = UUID.fromString("00001808-0000-1000-8000-00805f9b34fb")
@@ -100,15 +101,14 @@ 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 context: Context, @ApplicationContext 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 ) : ViewModel() {
) : AndroidViewModel(context as Application) {
private var client: ClientBleGatt? = null private var client: ClientBleGatt? = null
private lateinit var logger: BleLoggerAndLauncher private var logger: nRFLoggerTree? = null
private lateinit var glucoseMeasurementCharacteristic: ClientBleGattCharacteristic private lateinit var glucoseMeasurementCharacteristic: ClientBleGattCharacteristic
private lateinit var recordAccessControlPointCharacteristic: ClientBleGattCharacteristic private lateinit var recordAccessControlPointCharacteristic: ClientBleGattCharacteristic
@@ -136,7 +136,7 @@ internal class GLSViewModel @Inject constructor(
fun onEvent(event: GLSScreenViewEvent) { fun onEvent(event: GLSScreenViewEvent) {
when (event) { when (event) {
OpenLoggerEvent -> logger.launch() OpenLoggerEvent -> LoggerLauncher.launch(context, logger?.session as? LogSession)
is OnWorkingModeSelected -> onEvent(event) is OnWorkingModeSelected -> onEvent(event)
is OnGLSRecordClick -> navigateToDetails(event.record) is OnGLSRecordClick -> navigateToDetails(event.record)
DisconnectEvent -> onDisconnectEvent() DisconnectEvent -> onDisconnectEvent()
@@ -167,10 +167,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)
initLogger(device)
logger = loggerFactory.createNordicLogger(getApplication(), stringConst.APP_NAME, "GLS", device.address) val client = ClientBleGatt.connect(context, device, viewModelScope)
val client = ClientBleGatt.connect(getApplication(), device, viewModelScope, logger = logger)
this@GLSViewModel.client = client this@GLSViewModel.client = client
client.waitForBonding() client.waitForBonding()
@@ -333,4 +332,10 @@ internal class GLSViewModel @Inject constructor(
_state.value = _state.value.copyWithNewRequestStatus(RequestStatus.FAILED) _state.value = _state.value.copyWithNewRequestStatus(RequestStatus.FAILED)
} }
} }
private fun initLogger(device: ServerDevice) {
logger?.let { Timber.uproot(it) }
logger = nRFLoggerTree(context, stringConst.APP_NAME, "GLS", device.address)
.also { Timber.plant(it) }
}
} }

View File

@@ -48,7 +48,7 @@ dependencies {
implementation(libs.nordic.core) implementation(libs.nordic.core)
implementation(libs.nordic.theme) implementation(libs.nordic.theme)
implementation(libs.nordic.navigation) implementation(libs.nordic.navigation)
implementation(libs.nordic.uilogger) implementation(libs.nordic.logger)
implementation(libs.nordic.blek.client) implementation(libs.nordic.blek.client)
implementation(libs.nordic.blek.profile) implementation(libs.nordic.blek.profile)
@@ -63,4 +63,8 @@ dependencies {
implementation(libs.androidx.lifecycle.service) implementation(libs.androidx.lifecycle.service)
implementation(libs.androidx.hilt.navigation.compose) implementation(libs.androidx.hilt.navigation.compose)
// Timber & SLF4J
implementation (libs.slf4j.timber)
implementation(libs.nordic.log.timber)
} }

View File

@@ -38,16 +38,18 @@ import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import no.nordicsemi.android.common.core.simpleSharedFlow import no.nordicsemi.android.common.core.simpleSharedFlow
import no.nordicsemi.android.common.logger.BleLoggerAndLauncher import no.nordicsemi.android.common.logger.LoggerLauncher
import no.nordicsemi.android.common.logger.DefaultBleLogger
import no.nordicsemi.android.hrs.data.HRSServiceData import no.nordicsemi.android.hrs.data.HRSServiceData
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.profile.hrs.data.HRSData import no.nordicsemi.android.kotlin.ble.profile.hrs.data.HRSData
import no.nordicsemi.android.log.LogSession
import no.nordicsemi.android.log.timber.nRFLoggerTree
import no.nordicsemi.android.service.DisconnectAndStopEvent import no.nordicsemi.android.service.DisconnectAndStopEvent
import no.nordicsemi.android.service.ServiceManager import no.nordicsemi.android.service.ServiceManager
import no.nordicsemi.android.ui.view.StringConst import no.nordicsemi.android.ui.view.StringConst
import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@@ -58,7 +60,7 @@ class HRSRepository @Inject constructor(
private val serviceManager: ServiceManager, private val serviceManager: ServiceManager,
private val stringConst: StringConst private val stringConst: StringConst
) { ) {
private var logger: BleLoggerAndLauncher? = null private var logger: nRFLoggerTree? = null
private val _data = MutableStateFlow(HRSServiceData()) private val _data = MutableStateFlow(HRSServiceData())
internal val data = _data.asStateFlow() internal val data = _data.asStateFlow()
@@ -85,8 +87,14 @@ class HRSRepository @Inject constructor(
private fun shouldClean() = !isOnScreen && !isServiceRunning private fun shouldClean() = !isOnScreen && !isServiceRunning
private fun initLogger(device: ServerDevice) {
logger?.let { Timber.uproot(it) }
logger = nRFLoggerTree(context, stringConst.APP_NAME, "HRS", device.address)
.also { Timber.plant(it) }
}
fun launch(device: ServerDevice) { fun launch(device: ServerDevice) {
logger = DefaultBleLogger.create(context, stringConst.APP_NAME, "HRS", device.address) initLogger(device)
_data.value = _data.value.copy(deviceName = device.name) _data.value = _data.value.copy(deviceName = device.name)
serviceManager.startService(HRSService::class.java, device) serviceManager.startService(HRSService::class.java, device)
} }
@@ -117,7 +125,7 @@ class HRSRepository @Inject constructor(
} }
fun openLogger() { fun openLogger() {
logger?.launch() LoggerLauncher.launch(context, logger?.session as? LogSession)
} }
fun log(priority: Int, message: String) { fun log(priority: Int, message: String) {

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, lifecycleScope, logger = { p, s -> repository.log(p, s) }) val client = ClientBleGatt.connect(this@HRSService, device, lifecycleScope)
this@HRSService.client = client this@HRSService.client = client
client.waitForBonding() client.waitForBonding()

View File

@@ -50,9 +50,10 @@ dependencies {
implementation(libs.nordic.blek.uiscanner) implementation(libs.nordic.blek.uiscanner)
implementation(libs.nordic.core) implementation(libs.nordic.core)
implementation(libs.nordic.ui)
implementation(libs.nordic.theme) implementation(libs.nordic.theme)
implementation(libs.nordic.navigation) implementation(libs.nordic.navigation)
implementation(libs.nordic.uilogger) implementation(libs.nordic.logger)
implementation(libs.androidx.compose.material3) implementation(libs.androidx.compose.material3)
implementation(libs.androidx.compose.material.iconsExtended) implementation(libs.androidx.compose.material.iconsExtended)
@@ -61,4 +62,8 @@ dependencies {
implementation(libs.androidx.lifecycle.service) implementation(libs.androidx.lifecycle.service)
implementation(libs.androidx.hilt.navigation.compose) implementation(libs.androidx.hilt.navigation.compose)
// Timber & SLF4J
implementation (libs.slf4j.timber)
implementation(libs.nordic.log.timber)
} }

View File

@@ -38,17 +38,19 @@ import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import no.nordicsemi.android.common.core.simpleSharedFlow import no.nordicsemi.android.common.core.simpleSharedFlow
import no.nordicsemi.android.common.logger.BleLoggerAndLauncher import no.nordicsemi.android.common.logger.LoggerLauncher
import no.nordicsemi.android.common.logger.DefaultBleLogger
import no.nordicsemi.android.hts.data.HTSServiceData import no.nordicsemi.android.hts.data.HTSServiceData
import no.nordicsemi.android.hts.view.TemperatureUnit import no.nordicsemi.android.hts.view.TemperatureUnit
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.profile.hts.data.HTSData import no.nordicsemi.android.kotlin.ble.profile.hts.data.HTSData
import no.nordicsemi.android.log.LogSession
import no.nordicsemi.android.log.timber.nRFLoggerTree
import no.nordicsemi.android.service.DisconnectAndStopEvent import no.nordicsemi.android.service.DisconnectAndStopEvent
import no.nordicsemi.android.service.ServiceManager import no.nordicsemi.android.service.ServiceManager
import no.nordicsemi.android.ui.view.StringConst import no.nordicsemi.android.ui.view.StringConst
import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@@ -59,7 +61,7 @@ class HTSRepository @Inject constructor(
private val serviceManager: ServiceManager, private val serviceManager: ServiceManager,
private val stringConst: StringConst private val stringConst: StringConst
) { ) {
private var logger: BleLoggerAndLauncher? = null private var logger: nRFLoggerTree? = null
private val _data = MutableStateFlow(HTSServiceData()) private val _data = MutableStateFlow(HTSServiceData())
internal val data = _data.asStateFlow() internal val data = _data.asStateFlow()
@@ -86,9 +88,15 @@ class HTSRepository @Inject constructor(
private fun shouldClean() = !isOnScreen && !isServiceRunning private fun shouldClean() = !isOnScreen && !isServiceRunning
private fun initLogger(device: ServerDevice) {
logger?.let { Timber.uproot(it) }
logger = nRFLoggerTree(context, stringConst.APP_NAME, "HTS", device.address)
.also { Timber.plant(it) }
}
fun launch(device: ServerDevice) { fun launch(device: ServerDevice) {
_data.value = _data.value.copy(deviceName = device.name) _data.value = _data.value.copy(deviceName = device.name)
logger = DefaultBleLogger.create(context, stringConst.APP_NAME, "HTS", device.address) initLogger(device)
serviceManager.startService(HTSService::class.java, device) serviceManager.startService(HTSService::class.java, device)
} }
@@ -109,7 +117,7 @@ class HTSRepository @Inject constructor(
} }
fun openLogger() { fun openLogger() {
logger?.launch() LoggerLauncher.launch(context, logger?.session as? LogSession)
} }
fun log(priority: Int, message: String) { fun log(priority: Int, message: String) {

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, lifecycleScope, logger = { p, s -> repository.log(p, s) }) val client = ClientBleGatt.connect(this@HTSService, device, lifecycleScope)
this@HTSService.client = client this@HTSService.client = client
client.connectionStateWithStatus client.connectionStateWithStatus

View File

@@ -43,7 +43,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import no.nordicsemi.android.common.theme.view.RadioButtonGroup import no.nordicsemi.android.common.ui.view.RadioButtonGroup
import no.nordicsemi.android.hts.R import no.nordicsemi.android.hts.R
import no.nordicsemi.android.hts.data.HTSServiceData import no.nordicsemi.android.hts.data.HTSServiceData
import no.nordicsemi.android.ui.view.BatteryLevelView import no.nordicsemi.android.ui.view.BatteryLevelView

View File

@@ -31,8 +31,9 @@
package no.nordicsemi.android.hts.view package no.nordicsemi.android.hts.view
import no.nordicsemi.android.common.theme.view.RadioButtonItem import no.nordicsemi.android.common.ui.view.RadioButtonItem
import no.nordicsemi.android.common.theme.view.RadioGroupViewEntity import no.nordicsemi.android.common.ui.view.RadioGroupViewEntity
import java.util.Locale
private const val DISPLAY_FAHRENHEIT = "°F" private const val DISPLAY_FAHRENHEIT = "°F"
private const val DISPLAY_CELSIUS = "°C" private const val DISPLAY_CELSIUS = "°C"
@@ -40,9 +41,9 @@ private const val DISPLAY_KELVIN = "°K"
internal fun displayTemperature(value: Float, temperatureUnit: TemperatureUnit): String { internal fun displayTemperature(value: Float, temperatureUnit: TemperatureUnit): String {
return when (temperatureUnit) { return when (temperatureUnit) {
TemperatureUnit.CELSIUS -> String.format("%.1f °C", value) TemperatureUnit.CELSIUS -> String.format(Locale.US, "%.1f °C", value)
TemperatureUnit.FAHRENHEIT -> String.format("%.1f °F", value * 1.8f + 32f) TemperatureUnit.FAHRENHEIT -> String.format(Locale.US, "%.1f °F", value * 1.8f + 32f)
TemperatureUnit.KELVIN -> String.format("%.1f °K", value + 273.15f) TemperatureUnit.KELVIN -> String.format(Locale.US, "%.1f °K", value + 273.15f)
} }
} }
@@ -57,11 +58,14 @@ internal fun String.toTemperatureUnit(): TemperatureUnit {
internal fun TemperatureUnit.temperatureSettingsItems(): RadioGroupViewEntity { internal fun TemperatureUnit.temperatureSettingsItems(): RadioGroupViewEntity {
return RadioGroupViewEntity( return RadioGroupViewEntity(
TemperatureUnit.values().map { createRadioButtonItem(it, this) } TemperatureUnit.entries.map { createRadioButtonItem(it, this) }
) )
} }
private fun createRadioButtonItem(unit: TemperatureUnit, selectedTemperatureUnit: TemperatureUnit): RadioButtonItem { private fun createRadioButtonItem(
unit: TemperatureUnit,
selectedTemperatureUnit: TemperatureUnit
): RadioButtonItem {
return RadioButtonItem(displayTemperature(unit), unit == selectedTemperatureUnit) return RadioButtonItem(displayTemperature(unit), unit == selectedTemperatureUnit)
} }

View File

@@ -53,7 +53,7 @@ dependencies {
implementation(libs.nordic.core) implementation(libs.nordic.core)
implementation(libs.nordic.theme) implementation(libs.nordic.theme)
implementation(libs.nordic.navigation) implementation(libs.nordic.navigation)
implementation(libs.nordic.uilogger) implementation(libs.nordic.logger)
implementation(libs.androidx.compose.material3) implementation(libs.androidx.compose.material3)
implementation(libs.androidx.compose.material.iconsExtended) implementation(libs.androidx.compose.material.iconsExtended)
@@ -62,4 +62,8 @@ dependencies {
implementation(libs.androidx.lifecycle.service) implementation(libs.androidx.lifecycle.service)
implementation(libs.androidx.hilt.navigation.compose) implementation(libs.androidx.hilt.navigation.compose)
// Timber & SLF4J
implementation (libs.slf4j.timber)
implementation(libs.nordic.log.timber)
} }

View File

@@ -38,16 +38,18 @@ import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import no.nordicsemi.android.common.core.simpleSharedFlow import no.nordicsemi.android.common.core.simpleSharedFlow
import no.nordicsemi.android.common.logger.BleLoggerAndLauncher import no.nordicsemi.android.common.logger.LoggerLauncher
import no.nordicsemi.android.common.logger.DefaultBleLogger
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.profile.prx.AlarmLevel import no.nordicsemi.android.kotlin.ble.profile.prx.AlarmLevel
import no.nordicsemi.android.log.LogSession
import no.nordicsemi.android.log.timber.nRFLoggerTree
import no.nordicsemi.android.prx.data.PRXServiceData import no.nordicsemi.android.prx.data.PRXServiceData
import no.nordicsemi.android.service.DisconnectAndStopEvent import no.nordicsemi.android.service.DisconnectAndStopEvent
import no.nordicsemi.android.service.ServiceManager import no.nordicsemi.android.service.ServiceManager
import no.nordicsemi.android.ui.view.StringConst import no.nordicsemi.android.ui.view.StringConst
import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@@ -58,7 +60,7 @@ class PRXRepository @Inject internal constructor(
private val serviceManager: ServiceManager, private val serviceManager: ServiceManager,
private val stringConst: StringConst private val stringConst: StringConst
) { ) {
private var logger: BleLoggerAndLauncher? = null private var logger: nRFLoggerTree? = null
private val _data = MutableStateFlow(PRXServiceData()) private val _data = MutableStateFlow(PRXServiceData())
internal val data = _data.asStateFlow() internal val data = _data.asStateFlow()
@@ -88,8 +90,14 @@ class PRXRepository @Inject internal constructor(
private fun shouldClean() = !isOnScreen && !isServiceRunning private fun shouldClean() = !isOnScreen && !isServiceRunning
private fun initLogger(device: ServerDevice) {
logger?.let { Timber.uproot(it) }
logger = nRFLoggerTree(context, stringConst.APP_NAME, "PRX", device.address)
.also { Timber.plant(it) }
}
fun launch(device: ServerDevice) { fun launch(device: ServerDevice) {
logger = DefaultBleLogger.create(context, stringConst.APP_NAME, "PRX", device.address) initLogger(device)
_data.value = _data.value.copy(deviceName = device.name) _data.value = _data.value.copy(deviceName = device.name)
serviceManager.startService(PRXService::class.java, device) serviceManager.startService(PRXService::class.java, device)
} }
@@ -119,7 +127,7 @@ class PRXRepository @Inject internal constructor(
} }
fun openLogger() { fun openLogger() {
logger?.launch() LoggerLauncher.launch(context, logger?.session as? LogSession)
} }
fun log(priority: Int, message: String) { fun log(priority: Int, message: String) {

View File

@@ -164,7 +164,6 @@ internal class PRXService : NotificationService() {
this@PRXService, this@PRXService,
device, device,
lifecycleScope, lifecycleScope,
logger = { p, s -> repository.log(p, s) },
options = BleGattConnectOptions(autoConnect = true) options = BleGattConnectOptions(autoConnect = true)
) )
this@PRXService.client = client this@PRXService.client = client

View File

@@ -48,7 +48,7 @@ dependencies {
implementation(libs.nordic.core) implementation(libs.nordic.core)
implementation(libs.nordic.theme) implementation(libs.nordic.theme)
implementation(libs.nordic.navigation) implementation(libs.nordic.navigation)
implementation(libs.nordic.uilogger) implementation(libs.nordic.logger)
implementation(libs.nordic.blek.client) implementation(libs.nordic.blek.client)
implementation(libs.nordic.blek.profile) implementation(libs.nordic.blek.profile)
@@ -61,4 +61,8 @@ dependencies {
implementation(libs.androidx.lifecycle.service) implementation(libs.androidx.lifecycle.service)
implementation(libs.androidx.hilt.navigation.compose) implementation(libs.androidx.hilt.navigation.compose)
// Timber & SLF4J
implementation (libs.slf4j.timber)
implementation(libs.nordic.log.timber)
} }

View File

@@ -38,16 +38,18 @@ import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import no.nordicsemi.android.common.core.simpleSharedFlow import no.nordicsemi.android.common.core.simpleSharedFlow
import no.nordicsemi.android.common.logger.BleLoggerAndLauncher import no.nordicsemi.android.common.logger.LoggerLauncher
import no.nordicsemi.android.common.logger.DefaultBleLogger
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.profile.rscs.data.RSCSData import no.nordicsemi.android.kotlin.ble.profile.rscs.data.RSCSData
import no.nordicsemi.android.log.LogSession
import no.nordicsemi.android.log.timber.nRFLoggerTree
import no.nordicsemi.android.rscs.data.RSCSServiceData import no.nordicsemi.android.rscs.data.RSCSServiceData
import no.nordicsemi.android.service.DisconnectAndStopEvent import no.nordicsemi.android.service.DisconnectAndStopEvent
import no.nordicsemi.android.service.ServiceManager import no.nordicsemi.android.service.ServiceManager
import no.nordicsemi.android.ui.view.StringConst import no.nordicsemi.android.ui.view.StringConst
import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@@ -58,7 +60,7 @@ class RSCSRepository @Inject constructor(
private val serviceManager: ServiceManager, private val serviceManager: ServiceManager,
private val stringConst: StringConst private val stringConst: StringConst
) { ) {
private var logger: BleLoggerAndLauncher? = null private var logger: nRFLoggerTree? = null
private val _data = MutableStateFlow(RSCSServiceData()) private val _data = MutableStateFlow(RSCSServiceData())
internal val data = _data.asStateFlow() internal val data = _data.asStateFlow()
@@ -85,8 +87,14 @@ class RSCSRepository @Inject constructor(
private fun shouldClean() = !isOnScreen && !isServiceRunning private fun shouldClean() = !isOnScreen && !isServiceRunning
private fun initLogger(device: ServerDevice) {
logger?.let { Timber.uproot(it) }
logger = nRFLoggerTree(context, stringConst.APP_NAME, "RSCS", device.address)
.also { Timber.plant(it) }
}
fun launch(device: ServerDevice) { fun launch(device: ServerDevice) {
logger = DefaultBleLogger.create(context, stringConst.APP_NAME, "RSCS", device.address) initLogger(device)
_data.value = _data.value.copy(deviceName = device.name) _data.value = _data.value.copy(deviceName = device.name)
serviceManager.startService(RSCSService::class.java, device) serviceManager.startService(RSCSService::class.java, device)
} }
@@ -109,7 +117,7 @@ class RSCSRepository @Inject constructor(
} }
fun openLogger() { fun openLogger() {
logger?.launch() LoggerLauncher.launch(context, logger?.session as? LogSession)
} }
fun log(priority: Int, message: String) { fun log(priority: Int, message: String) {

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, lifecycleScope, logger = { p, s -> repository.log(p, s) }) val client = ClientBleGatt.connect(this@RSCSService, device, lifecycleScope)
this@RSCSService.client = client this@RSCSService.client = client
client.connectionStateWithStatus client.connectionStateWithStatus

View File

@@ -52,8 +52,9 @@ dependencies {
implementation(libs.nordic.core) implementation(libs.nordic.core)
implementation(libs.nordic.theme) implementation(libs.nordic.theme)
implementation(libs.nordic.ui)
implementation(libs.nordic.navigation) implementation(libs.nordic.navigation)
implementation(libs.nordic.uilogger) implementation(libs.nordic.logger)
implementation(libs.nordic.blek.client) implementation(libs.nordic.blek.client)
implementation(libs.nordic.blek.profile) implementation(libs.nordic.blek.profile)
@@ -66,12 +67,8 @@ dependencies {
implementation(libs.room.ktx) implementation(libs.room.ktx)
ksp(libs.room.compiler) ksp(libs.room.compiler)
implementation(libs.accompanist.pager)
implementation(libs.accompanist.pagerindicators)
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.compose.material.iconsExtended) implementation(libs.androidx.compose.material.iconsExtended)
implementation(libs.androidx.core.ktx) implementation(libs.androidx.core.ktx)
implementation(libs.androidx.activity.compose) implementation(libs.androidx.activity.compose)
@@ -79,6 +76,11 @@ dependencies {
implementation(libs.androidx.hilt.navigation.compose) implementation(libs.androidx.hilt.navigation.compose)
// Timber & SLF4J
implementation (libs.slf4j.timber)
implementation(libs.nordic.log.timber)
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)
@@ -87,7 +89,7 @@ dependencies {
testImplementation(libs.test.mockk) testImplementation(libs.test.mockk)
testImplementation(libs.androidx.test.ext) testImplementation(libs.androidx.test.ext)
testImplementation(libs.kotlinx.coroutines.test) testImplementation(libs.kotlinx.coroutines.test)
testImplementation(libs.test.slf4j.simple) testImplementation(libs.slf4j.simple)
testImplementation(libs.test.robolectric) testImplementation(libs.test.robolectric)
testImplementation(libs.kotlin.junit) testImplementation(libs.kotlin.junit)

View File

@@ -9,13 +9,13 @@ import kotlinx.coroutines.flow.launchIn
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
import no.nordicsemi.android.common.core.DataByteArray
import no.nordicsemi.android.kotlin.ble.advertiser.BleAdvertiser import no.nordicsemi.android.kotlin.ble.advertiser.BleAdvertiser
import no.nordicsemi.android.kotlin.ble.core.MockServerDevice import no.nordicsemi.android.kotlin.ble.core.MockServerDevice
import no.nordicsemi.android.kotlin.ble.core.advertiser.BleAdvertisingConfig import no.nordicsemi.android.kotlin.ble.core.advertiser.BleAdvertisingConfig
import no.nordicsemi.android.kotlin.ble.core.advertiser.BleAdvertisingData import no.nordicsemi.android.kotlin.ble.core.advertiser.BleAdvertisingData
import no.nordicsemi.android.kotlin.ble.core.data.BleGattPermission import no.nordicsemi.android.kotlin.ble.core.data.BleGattPermission
import no.nordicsemi.android.kotlin.ble.core.data.BleGattProperty import no.nordicsemi.android.kotlin.ble.core.data.BleGattProperty
import no.nordicsemi.android.kotlin.ble.core.data.util.DataByteArray
import no.nordicsemi.android.kotlin.ble.server.main.ServerBleGatt import no.nordicsemi.android.kotlin.ble.server.main.ServerBleGatt
import no.nordicsemi.android.kotlin.ble.server.main.service.ServerBleGattCharacteristic import no.nordicsemi.android.kotlin.ble.server.main.service.ServerBleGattCharacteristic
import no.nordicsemi.android.kotlin.ble.server.main.service.ServerBleGattCharacteristicConfig import no.nordicsemi.android.kotlin.ble.server.main.service.ServerBleGattCharacteristicConfig

View File

@@ -55,7 +55,7 @@ enum class MacroIcon(public val index: Int) {
companion object { companion object {
fun create(index: Int): MacroIcon { fun create(index: Int): MacroIcon {
return values().firstOrNull { it.index == index } return entries.firstOrNull { it.index == index }
?: throw IllegalArgumentException("Cannot create MacroIcon for index: $index") ?: throw IllegalArgumentException("Cannot create MacroIcon for index: $index")
} }
} }

View File

@@ -51,7 +51,7 @@ internal class CommentVisitor : Visitor {
val element = node.node val element = node.node
val builder = val builder =
StringBuilder("A configuration must have 9 commands, one for each button.\n Possible icons are:") StringBuilder("A configuration must have 9 commands, one for each button.\n Possible icons are:")
for (icon in MacroIcon.values()) builder.append("\n - ") for (icon in MacroIcon.entries) builder.append("\n - ")
.append(icon.toString()) .append(icon.toString())
element.comment = builder.toString() element.comment = builder.toString()
} }

View File

@@ -38,10 +38,12 @@ import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import no.nordicsemi.android.common.core.simpleSharedFlow import no.nordicsemi.android.common.core.simpleSharedFlow
import no.nordicsemi.android.common.logger.BleLoggerAndLauncher import no.nordicsemi.android.common.logger.LoggerLauncher
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.log.LogSession
import no.nordicsemi.android.log.timber.nRFLoggerTree
import no.nordicsemi.android.service.DisconnectAndStopEvent import no.nordicsemi.android.service.DisconnectAndStopEvent
import no.nordicsemi.android.service.ServiceManager import no.nordicsemi.android.service.ServiceManager
import no.nordicsemi.android.uart.data.ConfigurationDataSource import no.nordicsemi.android.uart.data.ConfigurationDataSource
@@ -51,8 +53,8 @@ import no.nordicsemi.android.uart.data.UARTRecord
import no.nordicsemi.android.uart.data.UARTRecordType import no.nordicsemi.android.uart.data.UARTRecordType
import no.nordicsemi.android.uart.data.UARTServiceData import no.nordicsemi.android.uart.data.UARTServiceData
import no.nordicsemi.android.uart.data.parseWithNewLineChar import no.nordicsemi.android.uart.data.parseWithNewLineChar
import no.nordicsemi.android.ui.view.NordicLoggerFactory
import no.nordicsemi.android.ui.view.StringConst import no.nordicsemi.android.ui.view.StringConst
import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@@ -63,9 +65,8 @@ class UARTRepository @Inject internal constructor(
private val serviceManager: ServiceManager, private val serviceManager: ServiceManager,
private val configurationDataSource: ConfigurationDataSource, private val configurationDataSource: ConfigurationDataSource,
private val stringConst: StringConst, private val stringConst: StringConst,
private val loggerFactory: NordicLoggerFactory
) { ) {
private var logger: BleLoggerAndLauncher? = null private var logger: nRFLoggerTree? = null
private val _data = MutableStateFlow(UARTServiceData()) private val _data = MutableStateFlow(UARTServiceData())
internal val data = _data.asStateFlow() internal val data = _data.asStateFlow()
@@ -98,11 +99,17 @@ class UARTRepository @Inject internal constructor(
private fun shouldClean() = !isOnScreen && !isServiceRunning private fun shouldClean() = !isOnScreen && !isServiceRunning
fun launch(device: ServerDevice) { fun launch(device: ServerDevice) {
logger = loggerFactory.createNordicLogger(context, stringConst.APP_NAME, "UART", device.address) initLogger(device)
_data.value = _data.value.copy(deviceName = device.name) _data.value = _data.value.copy(deviceName = device.name)
serviceManager.startService(UARTService::class.java, device) serviceManager.startService(UARTService::class.java, device)
} }
private fun initLogger(device : ServerDevice) {
logger?.let { Timber.uproot(it) }
logger = nRFLoggerTree(context, stringConst.APP_NAME, "UART", device.name ?: "Unknown")
.also { Timber.plant(it) }
}
fun onConnectionStateChanged(connectionState: GattConnectionStateWithStatus?) { fun onConnectionStateChanged(connectionState: GattConnectionStateWithStatus?) {
_data.value = _data.value.copy(connectionState = connectionState) _data.value = _data.value.copy(connectionState = connectionState)
} }
@@ -135,7 +142,7 @@ class UARTRepository @Inject internal constructor(
} }
fun openLogger() { fun openLogger() {
logger?.launch() LoggerLauncher.launch(context, logger?.session as? LogSession)
} }
fun log(priority: Int, message: String) { fun log(priority: Int, message: String) {

View File

@@ -43,7 +43,6 @@ 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
import no.nordicsemi.android.common.core.DataByteArray
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.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
@@ -53,10 +52,11 @@ import no.nordicsemi.android.kotlin.ble.core.data.BleGattProperty
import no.nordicsemi.android.kotlin.ble.core.data.BleWriteType import no.nordicsemi.android.kotlin.ble.core.data.BleWriteType
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.Mtu import no.nordicsemi.android.kotlin.ble.core.data.Mtu
import no.nordicsemi.android.kotlin.ble.core.data.util.DataByteArray
import no.nordicsemi.android.kotlin.ble.profile.battery.BatteryLevelParser import no.nordicsemi.android.kotlin.ble.profile.battery.BatteryLevelParser
import no.nordicsemi.android.service.DEVICE_DATA import no.nordicsemi.android.service.DEVICE_DATA
import no.nordicsemi.android.service.NotificationService import no.nordicsemi.android.service.NotificationService
import java.util.* import java.util.UUID
import javax.inject.Inject import javax.inject.Inject
val UART_SERVICE_UUID: UUID = UUID.fromString("6E400001-B5A3-F393-E0A9-E50E24DCCA9E") val UART_SERVICE_UUID: UUID = UUID.fromString("6E400001-B5A3-F393-E0A9-E50E24DCCA9E")
@@ -92,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, lifecycleScope, logger = { p, s -> repository.log(p, s) }) val client = ClientBleGatt.connect(this@UARTService, device, lifecycleScope)
this@UARTService.client = client this@UARTService.client = client
if (!client.isConnected) { if (!client.isConnected) {

View File

@@ -45,21 +45,20 @@ import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import no.nordicsemi.android.common.theme.view.RadioButtonGroup import no.nordicsemi.android.common.ui.view.RadioButtonGroup
import no.nordicsemi.android.common.theme.view.RadioButtonItem import no.nordicsemi.android.common.ui.view.RadioButtonItem
import no.nordicsemi.android.common.theme.view.RadioGroupViewEntity import no.nordicsemi.android.common.ui.view.RadioGroupViewEntity
import no.nordicsemi.android.uart.R import no.nordicsemi.android.uart.R
import no.nordicsemi.android.uart.data.MacroEol import no.nordicsemi.android.uart.data.MacroEol
import no.nordicsemi.android.ui.view.ScreenSection import no.nordicsemi.android.ui.view.ScreenSection
import no.nordicsemi.android.ui.view.SectionTitle import no.nordicsemi.android.ui.view.SectionTitle
import no.nordicsemi.android.utils.EMPTY import no.nordicsemi.android.utils.EMPTY
@OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
internal fun InputSection(onEvent: (UARTViewEvent) -> Unit) { internal fun InputSection(onEvent: (UARTViewEvent) -> Unit) {
val text = rememberSaveable { mutableStateOf(String.EMPTY) } val text = rememberSaveable { mutableStateOf(String.EMPTY) }
val hint = stringResource(id = R.string.uart_input_hint) val hint = stringResource(id = R.string.uart_input_hint)
val checkedItem = rememberSaveable { mutableStateOf(MacroEol.values()[0]) } val checkedItem = rememberSaveable { mutableStateOf(MacroEol.entries[0]) }
Row(verticalAlignment = Alignment.CenterVertically) { Row(verticalAlignment = Alignment.CenterVertically) {
Box(modifier = Modifier.weight(1f)) { Box(modifier = Modifier.weight(1f)) {
@@ -99,9 +98,9 @@ internal fun InputSection(onEvent: (UARTViewEvent) -> Unit) {
@Composable @Composable
internal fun EditInputSection(onEvent: (UARTViewEvent) -> Unit) { internal fun EditInputSection(onEvent: (UARTViewEvent) -> Unit) {
val checkedItem = rememberSaveable { mutableStateOf(MacroEol.values()[0]) } val checkedItem = rememberSaveable { mutableStateOf(MacroEol.entries[0]) }
val items = MacroEol.values().map { val items = MacroEol.entries.map {
RadioButtonItem(it.toDisplayString(), it == checkedItem.value) RadioButtonItem(it.toDisplayString(), it == checkedItem.value)
} }
val viewEntity = RadioGroupViewEntity(items) val viewEntity = RadioGroupViewEntity(items)

View File

@@ -70,7 +70,6 @@ internal fun UARTAddConfigurationDialog(onEvent: (UARTViewEvent) -> Unit, onDism
) )
} }
@OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
private fun NameInput( private fun NameInput(
name: MutableState<String>, name: MutableState<String>,

View File

@@ -34,12 +34,21 @@ package no.nordicsemi.android.uart.view
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.lazy.grid.GridCells import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.GridItemSpan import androidx.compose.foundation.lazy.grid.GridItemSpan
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.* import androidx.compose.material3.AlertDialog
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
@@ -52,9 +61,9 @@ import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import no.nordicsemi.android.common.theme.view.RadioButtonGroup import no.nordicsemi.android.common.ui.view.RadioButtonGroup
import no.nordicsemi.android.common.theme.view.RadioButtonItem import no.nordicsemi.android.common.ui.view.RadioButtonItem
import no.nordicsemi.android.common.theme.view.RadioGroupViewEntity import no.nordicsemi.android.common.ui.view.RadioGroupViewEntity
import no.nordicsemi.android.uart.R import no.nordicsemi.android.uart.R
import no.nordicsemi.android.uart.data.MacroEol import no.nordicsemi.android.uart.data.MacroEol
import no.nordicsemi.android.uart.data.MacroIcon import no.nordicsemi.android.uart.data.MacroIcon
@@ -67,7 +76,7 @@ private const val GRID_SIZE = 5
internal fun UARTAddMacroDialog(macro: UARTMacro?, onEvent: (UARTViewEvent) -> Unit) { internal fun UARTAddMacroDialog(macro: UARTMacro?, onEvent: (UARTViewEvent) -> Unit) {
val newLineChar = rememberSaveable { mutableStateOf(macro?.newLineChar ?: MacroEol.LF) } val newLineChar = rememberSaveable { mutableStateOf(macro?.newLineChar ?: MacroEol.LF) }
val command = rememberSaveable { mutableStateOf(macro?.command ?: String.EMPTY) } val command = rememberSaveable { mutableStateOf(macro?.command ?: String.EMPTY) }
val selectedIcon = rememberSaveable { mutableStateOf(macro?.icon ?: MacroIcon.values()[0]) } val selectedIcon = rememberSaveable { mutableStateOf(macro?.icon ?: MacroIcon.entries.toTypedArray()[0]) }
AlertDialog( AlertDialog(
onDismissRequest = { onEvent(OnEditFinish) }, onDismissRequest = { onEvent(OnEditFinish) },
@@ -130,7 +139,6 @@ internal fun UARTAddMacroDialog(macro: UARTMacro?, onEvent: (UARTViewEvent) -> U
) )
} }
@OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
private fun CommandInput(command: MutableState<String>) { private fun CommandInput(command: MutableState<String>) {
Column { Column {
@@ -150,7 +158,7 @@ private fun CommandInput(command: MutableState<String>) {
@Composable @Composable
private fun NewLineCharSection(checkedItem: MacroEol, onItemClick: (MacroEol) -> Unit) { private fun NewLineCharSection(checkedItem: MacroEol, onItemClick: (MacroEol) -> Unit) {
val items = MacroEol.values().map { val items = MacroEol.entries.map {
RadioButtonItem(it.toDisplayString(), it == checkedItem) RadioButtonItem(it.toDisplayString(), it == checkedItem)
} }
val viewEntity = RadioGroupViewEntity(items) val viewEntity = RadioGroupViewEntity(items)

View File

@@ -31,12 +31,10 @@
package no.nordicsemi.android.uart.view package no.nordicsemi.android.uart.view
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
@@ -46,16 +44,16 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel import androidx.hilt.navigation.compose.hiltViewModel
import no.nordicsemi.android.common.theme.view.PagerView import no.nordicsemi.android.common.ui.view.PagerView
import no.nordicsemi.android.common.theme.view.PagerViewEntity import no.nordicsemi.android.common.ui.view.PagerViewEntity
import no.nordicsemi.android.common.theme.view.PagerViewItem import no.nordicsemi.android.common.ui.view.PagerViewItem
import no.nordicsemi.android.kotlin.ble.core.data.GattConnectionState import no.nordicsemi.android.kotlin.ble.core.data.GattConnectionState
import no.nordicsemi.android.kotlin.ble.ui.scanner.view.DeviceConnectingView
import no.nordicsemi.android.kotlin.ble.ui.scanner.view.DeviceDisconnectedView
import no.nordicsemi.android.uart.R import no.nordicsemi.android.uart.R
import no.nordicsemi.android.uart.viewmodel.UARTViewModel import no.nordicsemi.android.uart.viewmodel.UARTViewModel
import no.nordicsemi.android.ui.view.NavigateUpButton import no.nordicsemi.android.ui.view.NavigateUpButton
import no.nordicsemi.android.ui.view.ProfileAppBar import no.nordicsemi.android.ui.view.ProfileAppBar
import no.nordicsemi.android.kotlin.ble.ui.scanner.view.DeviceConnectingView
import no.nordicsemi.android.kotlin.ble.ui.scanner.view.DeviceDisconnectedView
@Composable @Composable
fun UARTScreen() { fun UARTScreen() {
@@ -99,7 +97,6 @@ private fun PaddingBox(content: @Composable () -> Unit) {
} }
} }
@OptIn(ExperimentalFoundationApi::class)
@Composable @Composable
private fun SuccessScreen() { private fun SuccessScreen() {
val input = stringResource(id = R.string.uart_input) val input = stringResource(id = R.string.uart_input)

View File

@@ -39,20 +39,20 @@ internal sealed class UARTViewEvent
internal data class OnEditMacro(val position: Int) : UARTViewEvent() internal data class OnEditMacro(val position: Int) : UARTViewEvent()
internal data class OnCreateMacro(val macro: UARTMacro) : UARTViewEvent() internal data class OnCreateMacro(val macro: UARTMacro) : UARTViewEvent()
internal object OnDeleteMacro : UARTViewEvent() internal data object OnDeleteMacro : UARTViewEvent()
internal object OnEditFinish : UARTViewEvent() internal data object OnEditFinish : UARTViewEvent()
internal data class OnConfigurationSelected(val configuration: UARTConfiguration) : UARTViewEvent() internal data class OnConfigurationSelected(val configuration: UARTConfiguration) : UARTViewEvent()
internal data class OnAddConfiguration(val name: String) : UARTViewEvent() internal data class OnAddConfiguration(val name: String) : UARTViewEvent()
internal object OnEditConfiguration : UARTViewEvent() internal data object OnEditConfiguration : UARTViewEvent()
internal object OnDeleteConfiguration : UARTViewEvent() internal data object OnDeleteConfiguration : UARTViewEvent()
internal data class OnRunMacro(val macro: UARTMacro) : UARTViewEvent() internal data class OnRunMacro(val macro: UARTMacro) : UARTViewEvent()
internal data class OnRunInput(val text: String, val newLineChar: MacroEol) : UARTViewEvent() internal data class OnRunInput(val text: String, val newLineChar: MacroEol) : UARTViewEvent()
internal object ClearOutputItems : UARTViewEvent() internal data object ClearOutputItems : UARTViewEvent()
internal object DisconnectEvent : UARTViewEvent() internal data object DisconnectEvent : UARTViewEvent()
internal object NavigateUp : UARTViewEvent() internal data object NavigateUp : UARTViewEvent()
internal object OpenLogger : UARTViewEvent() internal data object OpenLogger : UARTViewEvent()
internal object MacroInputSwitchClick : UARTViewEvent() internal data object MacroInputSwitchClick : UARTViewEvent()

View File

@@ -77,7 +77,6 @@ import no.nordicsemi.android.uart.view.OnRunMacro
import no.nordicsemi.android.uart.view.OpenLogger import no.nordicsemi.android.uart.view.OpenLogger
import no.nordicsemi.android.uart.view.UARTViewEvent import no.nordicsemi.android.uart.view.UARTViewEvent
import no.nordicsemi.android.uart.view.UARTViewState import no.nordicsemi.android.uart.view.UARTViewState
import no.nordicsemi.android.ui.view.NordicLoggerFactory
import javax.inject.Inject import javax.inject.Inject
@HiltViewModel @HiltViewModel
@@ -86,7 +85,6 @@ internal class UARTViewModel @Inject constructor(
private val navigationManager: Navigator, private val navigationManager: Navigator,
private val dataSource: UARTPersistentDataSource, private val dataSource: UARTPersistentDataSource,
private val analytics: AppAnalytics, private val analytics: AppAnalytics,
private val loggerFactory: NordicLoggerFactory
) : ViewModel() { ) : ViewModel() {
private val _state = MutableStateFlow(UARTViewState()) private val _state = MutableStateFlow(UARTViewState())

View File

@@ -50,7 +50,7 @@ dependencyResolutionManagement {
} }
versionCatalogs { versionCatalogs {
create("libs") { create("libs") {
from("no.nordicsemi.android.gradle:version-catalog:1.11.1") from("no.nordicsemi.android.gradle:version-catalog:2.4")
} }
} }
} }
@@ -79,6 +79,6 @@ include(":lib_utils")
// includeBuild("../Android-Common-Libraries") // includeBuild("../Android-Common-Libraries")
//} //}
// //
if (file("../Kotlin-BLE-Library").exists()) { //if (file("../Kotlin-BLE-Library").exists()) {
includeBuild("../Kotlin-BLE-Library") // includeBuild("../Kotlin-BLE-Library")
} //}