From bb3ea6a7839618f2964567a3b86729e73fc82423 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sylwester=20Zieli=C5=84ski?= Date: Wed, 16 Feb 2022 09:59:42 +0100 Subject: [PATCH] Fix proximity profile --- .../nrftoolbox/viewmodel/HomeViewModel.kt | 14 +-- .../android/service/BatteryManager.kt | 97 ------------------- .../android/service/BleManagerStatus.kt | 2 +- .../service/ConnectionObserverAdapter.kt | 6 +- .../java/no/nordicsemi/android/utils/Ext.kt | 20 ---- .../no/nordicsemi/android/bps/data/BPSData.kt | 2 +- .../bps/{repository => data}/BPSManager.kt | 9 +- .../bps/{data => repository}/BPSRepository.kt | 5 +- .../android/bps/view/BPSSensorsReadingView.kt | 4 +- .../android/bps/viewmodel/BPSViewModel.kt | 4 +- .../android/bps/BPSViewModelTest.kt | 81 ---------------- .../nordicsemi/android/cgms/data/CGMData.kt | 9 +- .../cgms/{repository => data}/CGMManager.kt | 34 ++++--- .../android/cgms/{repository => data}/Ext.kt | 0 .../{data => repository}/CGMRepository.kt | 6 +- .../android/cgms/repository/CGMService.kt | 1 - .../android/cgms/view/CGMContentView.kt | 6 +- .../cgms/viewmodel/CGMScreenViewModel.kt | 4 +- profile_cgms/src/main/res/values/strings.xml | 2 +- .../android/cgms/CGMSViewModelTest.kt | 77 --------------- .../no/nordicsemi/android/csc/data/CSCData.kt | 2 +- .../csc/{repository => data}/CSCManager.kt | 4 +- .../csc/{data => repository}/CSCRepository.kt | 7 +- .../android/csc/repository/CSCService.kt | 1 - .../android/csc/view/SensorsReadingView.kt | 4 +- .../android/csc/viewmodel/CSCViewModel.kt | 4 +- .../android/csc/CSCViewModelTest.kt | 77 --------------- .../no/nordicsemi/android/gls/data/GLSData.kt | 2 +- .../nordicsemi/android/gls/data/GLSManager.kt | 11 +-- .../android/gls/main/view/GLSContentView.kt | 6 +- .../gls/main/viewmodel/GLSViewModel.kt | 2 +- .../gls/{data => repository}/GLSRepository.kt | 5 +- .../android/gls/GLSViewModelTest.kt | 82 ---------------- .../no/nordicsemi/android/hrs/data/HRSData.kt | 2 +- .../hrs/{service => data}/HRSManager.kt | 14 +-- .../hrs/{data => service}/HRSRepository.kt | 6 +- .../android/hrs/service/HRSService.kt | 1 - .../android/hrs/view/HRSContentView.kt | 6 +- .../android/hrs/viewmodel/HRSViewModel.kt | 4 +- .../android/hrs/HRSViewModelTest.kt | 77 --------------- .../no/nordicsemi/android/hts/data/HTSData.kt | 2 +- .../hts/{repository => data}/HTSManager.kt | 4 +- .../android/hts/data/HTSServiceCommand.kt | 3 - .../hts/{data => repository}/HTSRepository.kt | 6 +- .../android/hts/repository/HTSService.kt | 1 - .../android/hts/view/HTSContentView.kt | 6 +- .../android/hts/viewmodel/HTSViewModel.kt | 4 +- .../android/hts/HTSViewModelTest.kt | 77 --------------- .../nordicsemi/android/prx/data/PRXCommand.kt | 9 -- .../no/nordicsemi/android/prx/data/PRXData.kt | 2 +- .../prx/{repository => data}/PRXManager.kt | 9 +- .../ProximityServerManager.kt | 2 +- .../android/prx/repository/AlarmHandler.kt | 13 ++- .../prx/{data => repository}/PRXRepository.kt | 26 ++--- .../android/prx/repository/PRXService.kt | 1 - .../android/prx/view/PRXContentView.kt | 10 +- .../nordicsemi/android/prx/view/PRXMapper.kt | 8 ++ .../android/prx/viewmodel/PRXViewModel.kt | 4 +- profile_prx/src/main/res/values/strings.xml | 7 +- .../android/prx/PRXViewModelTest.kt | 77 --------------- .../nordicsemi/android/rscs/data/RSCSData.kt | 2 +- .../rscs/{repository => data}/RSCSManager.kt | 4 +- .../android/rscs/data/RSCSServiceCommand.kt | 3 - .../{data => repository}/RSCSRepository.kt | 6 +- .../android/rscs/repository/RSCSService.kt | 1 - .../android/rscs/view/RSCSContentView.kt | 6 +- .../android/rscs/viewmodel/RSCSViewModel.kt | 4 +- .../android/rscs/RSCSViewModelTest.kt | 77 --------------- .../nordicsemi/android/uart/data/UARTData.kt | 2 +- .../uart/{repository => data}/UARTManager.kt | 2 +- .../android/uart/data/UARTServiceCommand.kt | 7 -- .../{data => repository}/UARTRepository.kt | 7 +- .../android/uart/repository/UARTService.kt | 1 - .../android/uart/viewmodel/UARTViewModel.kt | 4 +- .../android/gls/UARTViewModelTest.kt | 77 --------------- settings.gradle | 21 ++-- 76 files changed, 176 insertions(+), 1019 deletions(-) delete mode 100644 lib_service/src/main/java/no/nordicsemi/android/service/BatteryManager.kt rename profile_bps/src/main/java/no/nordicsemi/android/bps/{repository => data}/BPSManager.kt (94%) rename profile_bps/src/main/java/no/nordicsemi/android/bps/{data => repository}/BPSRepository.kt (88%) delete mode 100644 profile_bps/src/test/java/no/nordicsemi/android/bps/BPSViewModelTest.kt rename profile_cgms/src/main/java/no/nordicsemi/android/cgms/{repository => data}/CGMManager.kt (95%) rename profile_cgms/src/main/java/no/nordicsemi/android/cgms/{repository => data}/Ext.kt (100%) rename profile_cgms/src/main/java/no/nordicsemi/android/cgms/{data => repository}/CGMRepository.kt (93%) delete mode 100644 profile_cgms/src/test/java/no/nordicsemi/android/cgms/CGMSViewModelTest.kt rename profile_csc/src/main/java/no/nordicsemi/android/csc/{repository => data}/CSCManager.kt (97%) rename profile_csc/src/main/java/no/nordicsemi/android/csc/{data => repository}/CSCRepository.kt (90%) delete mode 100644 profile_csc/src/test/java/no/nordicsemi/android/csc/CSCViewModelTest.kt rename profile_gls/src/main/java/no/nordicsemi/android/gls/{data => repository}/GLSRepository.kt (90%) delete mode 100644 profile_gls/src/test/java/no/nordicsemi/android/gls/GLSViewModelTest.kt rename profile_hrs/src/main/java/no/nordicsemi/android/hrs/{service => data}/HRSManager.kt (92%) rename profile_hrs/src/main/java/no/nordicsemi/android/hrs/{data => service}/HRSRepository.kt (92%) delete mode 100644 profile_hrs/src/test/java/no/nordicsemi/android/hrs/HRSViewModelTest.kt rename profile_hts/src/main/java/no/nordicsemi/android/hts/{repository => data}/HTSManager.kt (97%) delete mode 100644 profile_hts/src/main/java/no/nordicsemi/android/hts/data/HTSServiceCommand.kt rename profile_hts/src/main/java/no/nordicsemi/android/hts/{data => repository}/HTSRepository.kt (92%) delete mode 100644 profile_hts/src/test/java/no/nordicsemi/android/hts/HTSViewModelTest.kt delete mode 100644 profile_prx/src/main/java/no/nordicsemi/android/prx/data/PRXCommand.kt rename profile_prx/src/main/java/no/nordicsemi/android/prx/{repository => data}/PRXManager.kt (96%) rename profile_prx/src/main/java/no/nordicsemi/android/prx/{repository => data}/ProximityServerManager.kt (98%) rename profile_prx/src/main/java/no/nordicsemi/android/prx/{data => repository}/PRXRepository.kt (75%) delete mode 100644 profile_prx/src/test/java/no/nordicsemi/android/prx/PRXViewModelTest.kt rename profile_rscs/src/main/java/no/nordicsemi/android/rscs/{repository => data}/RSCSManager.kt (97%) delete mode 100644 profile_rscs/src/main/java/no/nordicsemi/android/rscs/data/RSCSServiceCommand.kt rename profile_rscs/src/main/java/no/nordicsemi/android/rscs/{data => repository}/RSCSRepository.kt (92%) delete mode 100644 profile_rscs/src/test/java/no/nordicsemi/android/rscs/RSCSViewModelTest.kt rename profile_uart/src/main/java/no/nordicsemi/android/uart/{repository => data}/UARTManager.kt (99%) delete mode 100644 profile_uart/src/main/java/no/nordicsemi/android/uart/data/UARTServiceCommand.kt rename profile_uart/src/main/java/no/nordicsemi/android/uart/{data => repository}/UARTRepository.kt (90%) delete mode 100644 profile_uart/src/test/java/no/nordicsemi/android/gls/UARTViewModelTest.kt diff --git a/app/src/main/java/no/nordicsemi/android/nrftoolbox/viewmodel/HomeViewModel.kt b/app/src/main/java/no/nordicsemi/android/nrftoolbox/viewmodel/HomeViewModel.kt index aa556449..4b56b554 100644 --- a/app/src/main/java/no/nordicsemi/android/nrftoolbox/viewmodel/HomeViewModel.kt +++ b/app/src/main/java/no/nordicsemi/android/nrftoolbox/viewmodel/HomeViewModel.kt @@ -7,16 +7,16 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach -import no.nordicsemi.android.cgms.data.CGMRepository -import no.nordicsemi.android.csc.data.CSCRepository -import no.nordicsemi.android.hrs.data.HRSRepository -import no.nordicsemi.android.hts.data.HTSRepository +import no.nordicsemi.android.cgms.repository.CGMRepository +import no.nordicsemi.android.csc.repository.CSCRepository +import no.nordicsemi.android.hrs.service.HRSRepository +import no.nordicsemi.android.hts.repository.HTSRepository import no.nordicsemi.android.navigation.NavigationManager import no.nordicsemi.android.nrftoolbox.ProfileDestination import no.nordicsemi.android.nrftoolbox.view.HomeViewState -import no.nordicsemi.android.prx.data.PRXRepository -import no.nordicsemi.android.rscs.data.RSCSRepository -import no.nordicsemi.android.uart.data.UARTRepository +import no.nordicsemi.android.prx.repository.PRXRepository +import no.nordicsemi.android.rscs.repository.RSCSRepository +import no.nordicsemi.android.uart.repository.UARTRepository import javax.inject.Inject @HiltViewModel diff --git a/lib_service/src/main/java/no/nordicsemi/android/service/BatteryManager.kt b/lib_service/src/main/java/no/nordicsemi/android/service/BatteryManager.kt deleted file mode 100644 index ac204f16..00000000 --- a/lib_service/src/main/java/no/nordicsemi/android/service/BatteryManager.kt +++ /dev/null @@ -1,97 +0,0 @@ -package no.nordicsemi.android.service - -import android.bluetooth.BluetoothDevice -import android.bluetooth.BluetoothGatt -import android.bluetooth.BluetoothGattCharacteristic -import android.content.Context -import android.util.Log -import androidx.annotation.IntRange -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.cancel -import no.nordicsemi.android.ble.BleManager -import no.nordicsemi.android.ble.callback.DataReceivedCallback -import no.nordicsemi.android.ble.common.callback.battery.BatteryLevelDataCallback -import no.nordicsemi.android.ble.data.Data -import java.util.* - -private val BATTERY_SERVICE_UUID = UUID.fromString("0000180F-0000-1000-8000-00805f9b34fb") -private val BATTERY_LEVEL_CHARACTERISTIC_UUID = UUID.fromString("00002A19-0000-1000-8000-00805f9b34fb") - -abstract class BatteryManager(context: Context, protected val scope: CoroutineScope) : BleManager(context) { - - private val TAG = "BLE-MANAGER" - - private var batteryLevelCharacteristic: BluetoothGattCharacteristic? = null - - private val batteryLevelDataCallback: DataReceivedCallback = - object : BatteryLevelDataCallback() { - override fun onBatteryLevelChanged( - device: BluetoothDevice, - @IntRange(from = 0, to = 100) batteryLevel: Int - ) { - onBatteryLevelChanged(batteryLevel) - } - - override fun onInvalidDataReceived(device: BluetoothDevice, data: Data) { - log(Log.WARN, "Invalid Battery Level data received: $data") - } - } - - protected abstract fun onBatteryLevelChanged(batteryLevel: Int) - - fun readBatteryLevelCharacteristic() { - if (isConnected) { - readCharacteristic(batteryLevelCharacteristic) - .with(batteryLevelDataCallback) - .fail { device: BluetoothDevice?, status: Int -> - log(Log.WARN, "Battery Level characteristic not found") - } - .enqueue() - } - } - - fun enableBatteryLevelCharacteristicNotifications() { - if (isConnected) { - // If the Battery Level characteristic is null, the request will be ignored - setNotificationCallback(batteryLevelCharacteristic) - .with(batteryLevelDataCallback) - enableNotifications(batteryLevelCharacteristic) - .done { device: BluetoothDevice? -> - log(Log.INFO, "Battery Level notifications enabled") - } - .fail { device: BluetoothDevice?, status: Int -> - log(Log.WARN, "Battery Level characteristic not found") - } - .enqueue() - } - } - - override fun log(priority: Int, message: String) { - super.log(priority, message) - Log.println(priority, TAG, message) - } - - protected abstract inner class BatteryManagerGattCallback : BleManagerGattCallback() { - override fun initialize() { - readBatteryLevelCharacteristic() - enableBatteryLevelCharacteristicNotifications() - } - - override fun isOptionalServiceSupported(gatt: BluetoothGatt): Boolean { - val service = gatt.getService(BATTERY_SERVICE_UUID) - if (service != null) { - batteryLevelCharacteristic = service.getCharacteristic(BATTERY_LEVEL_CHARACTERISTIC_UUID) - } - return batteryLevelCharacteristic != null - } - - override fun onDeviceDisconnected() { - batteryLevelCharacteristic = null - onBatteryLevelChanged(0) - } - } - - fun release() { - scope.cancel() - } -} diff --git a/lib_service/src/main/java/no/nordicsemi/android/service/BleManagerStatus.kt b/lib_service/src/main/java/no/nordicsemi/android/service/BleManagerStatus.kt index cc4046a5..53fc7003 100644 --- a/lib_service/src/main/java/no/nordicsemi/android/service/BleManagerStatus.kt +++ b/lib_service/src/main/java/no/nordicsemi/android/service/BleManagerStatus.kt @@ -22,7 +22,7 @@ sealed class BleManagerResult { class ConnectingResult : BleManagerResult() data class SuccessResult(val data: T) : BleManagerResult() -class LinkLossResult : BleManagerResult() +class LinkLossResult(val data: T) : BleManagerResult() class DisconnectedResult : BleManagerResult() class UnknownErrorResult : BleManagerResult() class MissingServiceResult : BleManagerResult() diff --git a/lib_service/src/main/java/no/nordicsemi/android/service/ConnectionObserverAdapter.kt b/lib_service/src/main/java/no/nordicsemi/android/service/ConnectionObserverAdapter.kt index b1fe6490..97444adc 100644 --- a/lib_service/src/main/java/no/nordicsemi/android/service/ConnectionObserverAdapter.kt +++ b/lib_service/src/main/java/no/nordicsemi/android/service/ConnectionObserverAdapter.kt @@ -15,6 +15,10 @@ class ConnectionObserverAdapter : ConnectionObserver { private var lastValue: T? = null + private fun getData(): T? { + return (_status.value as? SuccessResult)?.data + } + override fun onDeviceConnecting(device: BluetoothDevice) { Log.d(TAG, "onDeviceConnecting()") } @@ -41,7 +45,7 @@ class ConnectionObserverAdapter : ConnectionObserver { Log.d(TAG, "onDeviceDisconnected(), reason: $reason") _status.value = when (reason) { ConnectionObserver.REASON_NOT_SUPPORTED -> MissingServiceResult() - ConnectionObserver.REASON_LINK_LOSS -> LinkLossResult() + ConnectionObserver.REASON_LINK_LOSS -> LinkLossResult(getData()!!) ConnectionObserver.REASON_SUCCESS -> DisconnectedResult() else -> UnknownErrorResult() } diff --git a/lib_utils/src/main/java/no/nordicsemi/android/utils/Ext.kt b/lib_utils/src/main/java/no/nordicsemi/android/utils/Ext.kt index faedf868..5ab906a2 100644 --- a/lib_utils/src/main/java/no/nordicsemi/android/utils/Ext.kt +++ b/lib_utils/src/main/java/no/nordicsemi/android/utils/Ext.kt @@ -3,15 +3,9 @@ package no.nordicsemi.android.utils import android.app.ActivityManager import android.content.Context import android.util.Log -import androidx.compose.runtime.Composable -import androidx.compose.runtime.livedata.observeAsState -import androidx.navigation.NavController import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch import no.nordicsemi.android.navigation.ParcelableArgument import no.nordicsemi.android.navigation.SuccessDestinationResult @@ -33,20 +27,6 @@ fun SuccessDestinationResult.getDevice(): DiscoveredBluetoothDevice { return (argument as ParcelableArgument).value as DiscoveredBluetoothDevice } -@Composable -fun NavController.consumeResult(value: String): T? { - - val secondScreenResult = currentBackStackEntry - ?.savedStateHandle - ?.getLiveData(value)?.observeAsState() - - return secondScreenResult?.value?.also { - currentBackStackEntry - ?.savedStateHandle - ?.set(value, null) - } -} - private val exceptionHandler = CoroutineExceptionHandler { _, t -> Log.e("COROUTINE-EXCEPTION", "Uncaught exception", t) } diff --git a/profile_bps/src/main/java/no/nordicsemi/android/bps/data/BPSData.kt b/profile_bps/src/main/java/no/nordicsemi/android/bps/data/BPSData.kt index 4b114214..ad07fa80 100644 --- a/profile_bps/src/main/java/no/nordicsemi/android/bps/data/BPSData.kt +++ b/profile_bps/src/main/java/no/nordicsemi/android/bps/data/BPSData.kt @@ -4,7 +4,7 @@ import no.nordicsemi.android.ble.common.profile.bp.BloodPressureTypes import java.util.* data class BPSData( - val batteryLevel: Int = 0, + val batteryLevel: Int? = null, val cuffPressure: Float = 0f, val unit: Int = 0, val pulseRate: Float? = null, diff --git a/profile_bps/src/main/java/no/nordicsemi/android/bps/repository/BPSManager.kt b/profile_bps/src/main/java/no/nordicsemi/android/bps/data/BPSManager.kt similarity index 94% rename from profile_bps/src/main/java/no/nordicsemi/android/bps/repository/BPSManager.kt rename to profile_bps/src/main/java/no/nordicsemi/android/bps/data/BPSManager.kt index 56856a7e..5ae31938 100644 --- a/profile_bps/src/main/java/no/nordicsemi/android/bps/repository/BPSManager.kt +++ b/profile_bps/src/main/java/no/nordicsemi/android/bps/data/BPSManager.kt @@ -19,7 +19,7 @@ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.bps.repository +package no.nordicsemi.android.bps.data import android.bluetooth.BluetoothGatt import android.bluetooth.BluetoothGattCharacteristic @@ -112,12 +112,7 @@ internal class BPSManager( gatt.getService(BATTERY_SERVICE_UUID)?.run { batteryLevelCharacteristic = getCharacteristic(BATTERY_LEVEL_CHARACTERISTIC_UUID) } - return bpmCharacteristic != null && batteryLevelCharacteristic != null - } - - override fun isOptionalServiceSupported(gatt: BluetoothGatt): Boolean { - super.isOptionalServiceSupported(gatt) // ignore the result of this - return icpCharacteristic != null + return bpmCharacteristic != null } override fun onServicesInvalidated() { diff --git a/profile_bps/src/main/java/no/nordicsemi/android/bps/data/BPSRepository.kt b/profile_bps/src/main/java/no/nordicsemi/android/bps/repository/BPSRepository.kt similarity index 88% rename from profile_bps/src/main/java/no/nordicsemi/android/bps/data/BPSRepository.kt rename to profile_bps/src/main/java/no/nordicsemi/android/bps/repository/BPSRepository.kt index 35cfaef5..1187201d 100644 --- a/profile_bps/src/main/java/no/nordicsemi/android/bps/data/BPSRepository.kt +++ b/profile_bps/src/main/java/no/nordicsemi/android/bps/repository/BPSRepository.kt @@ -1,4 +1,4 @@ -package no.nordicsemi.android.bps.data +package no.nordicsemi.android.bps.repository import android.bluetooth.BluetoothDevice import android.content.Context @@ -9,7 +9,8 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.callbackFlow import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach -import no.nordicsemi.android.bps.repository.BPSManager +import no.nordicsemi.android.bps.data.BPSData +import no.nordicsemi.android.bps.data.BPSManager import no.nordicsemi.android.service.BleManagerResult import javax.inject.Inject diff --git a/profile_bps/src/main/java/no/nordicsemi/android/bps/view/BPSSensorsReadingView.kt b/profile_bps/src/main/java/no/nordicsemi/android/bps/view/BPSSensorsReadingView.kt index c84f23d4..eb00ded7 100644 --- a/profile_bps/src/main/java/no/nordicsemi/android/bps/view/BPSSensorsReadingView.kt +++ b/profile_bps/src/main/java/no/nordicsemi/android/bps/view/BPSSensorsReadingView.kt @@ -36,7 +36,9 @@ internal fun BPSSensorsReadingView(state: BPSData) { Spacer(modifier = Modifier.height(16.dp)) - BatteryLevelView(state.batteryLevel) + state.batteryLevel?.let { + BatteryLevelView(it) + } } @Preview diff --git a/profile_bps/src/main/java/no/nordicsemi/android/bps/viewmodel/BPSViewModel.kt b/profile_bps/src/main/java/no/nordicsemi/android/bps/viewmodel/BPSViewModel.kt index 5c64d9e3..7199c064 100644 --- a/profile_bps/src/main/java/no/nordicsemi/android/bps/viewmodel/BPSViewModel.kt +++ b/profile_bps/src/main/java/no/nordicsemi/android/bps/viewmodel/BPSViewModel.kt @@ -7,8 +7,8 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach -import no.nordicsemi.android.bps.data.BPSRepository -import no.nordicsemi.android.bps.repository.BPS_SERVICE_UUID +import no.nordicsemi.android.bps.data.BPS_SERVICE_UUID +import no.nordicsemi.android.bps.repository.BPSRepository import no.nordicsemi.android.bps.view.* import no.nordicsemi.android.navigation.* import no.nordicsemi.android.utils.exhaustive diff --git a/profile_bps/src/test/java/no/nordicsemi/android/bps/BPSViewModelTest.kt b/profile_bps/src/test/java/no/nordicsemi/android/bps/BPSViewModelTest.kt deleted file mode 100644 index 70e222cb..00000000 --- a/profile_bps/src/test/java/no/nordicsemi/android/bps/BPSViewModelTest.kt +++ /dev/null @@ -1,81 +0,0 @@ -package no.nordicsemi.android.bps - -import io.mockk.every -import io.mockk.justRun -import io.mockk.mockk -import io.mockk.verify -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.channels.BufferOverflow -import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.test.UnconfinedTestDispatcher -import kotlinx.coroutines.test.resetMain -import kotlinx.coroutines.test.setMain -import no.nordicsemi.android.bps.repository.BPSManager -import no.nordicsemi.android.bps.view.DisconnectEvent -import no.nordicsemi.android.bps.viewmodel.BPSViewModel -import no.nordicsemi.android.navigation.NavigationManager -import no.nordicsemi.android.service.BleManagerStatus -import org.junit.After -import org.junit.Before -import org.junit.Test - -class BPSViewModelTest { - - val dispatcher = UnconfinedTestDispatcher() - - @Before - fun setup() { - Dispatchers.setMain(dispatcher) - } - - @After - fun tearDown() { - Dispatchers.resetMain() - } - - @Test - fun `check if navigation up called after disconnect event returns success`() { - val repository = BPSRepository() - val manager = mockk() - val navigationManager = mockk() - - every { navigationManager.recentResult } returns MutableSharedFlow( - extraBufferCapacity = 1, - onBufferOverflow = BufferOverflow.DROP_OLDEST - ) - justRun { navigationManager.navigateTo(any(), any()) } - every { manager.isConnected } returns true - justRun { manager.setConnectionObserver(any()) } - justRun { manager.disconnect().enqueue() } - - val viewModel = BPSViewModel(manager, repository, navigationManager) - - viewModel.onEvent(DisconnectEvent) - - //Invoke by manager - repository.setNewStatus(BleManagerStatus.DISCONNECTED) - - verify { navigationManager.navigateUp() } - } - - @Test - fun `check if navigation up called after disconnect if manager not connected event returns success`() { - val repository = BPSRepository() - val manager = mockk() - val navigationManager = mockk() - - every { navigationManager.recentResult } returns MutableSharedFlow( - extraBufferCapacity = 1, - onBufferOverflow = BufferOverflow.DROP_OLDEST - ) - justRun { navigationManager.navigateTo(any(), any()) } - every { manager.isConnected } returns false - justRun { manager.setConnectionObserver(any()) } - - val viewModel = BPSViewModel(manager, repository, navigationManager) - - viewModel.onEvent(DisconnectEvent) - - verify { navigationManager.navigateUp() } - } -} diff --git a/profile_cgms/src/main/java/no/nordicsemi/android/cgms/data/CGMData.kt b/profile_cgms/src/main/java/no/nordicsemi/android/cgms/data/CGMData.kt index 5d69b844..fcb766fb 100644 --- a/profile_cgms/src/main/java/no/nordicsemi/android/cgms/data/CGMData.kt +++ b/profile_cgms/src/main/java/no/nordicsemi/android/cgms/data/CGMData.kt @@ -2,11 +2,6 @@ package no.nordicsemi.android.cgms.data internal data class CGMData( val records: List = emptyList(), - val batteryLevel: Int = 0, + val batteryLevel: Int? = null, val requestStatus: RequestStatus = RequestStatus.IDLE -) { - - fun copyWithNewRecord(record: CGMRecord): CGMData { - return copy(records = records + record) - } -} +) diff --git a/profile_cgms/src/main/java/no/nordicsemi/android/cgms/repository/CGMManager.kt b/profile_cgms/src/main/java/no/nordicsemi/android/cgms/data/CGMManager.kt similarity index 95% rename from profile_cgms/src/main/java/no/nordicsemi/android/cgms/repository/CGMManager.kt rename to profile_cgms/src/main/java/no/nordicsemi/android/cgms/data/CGMManager.kt index fd8b1819..c1827dd1 100644 --- a/profile_cgms/src/main/java/no/nordicsemi/android/cgms/repository/CGMManager.kt +++ b/profile_cgms/src/main/java/no/nordicsemi/android/cgms/data/CGMManager.kt @@ -19,7 +19,7 @@ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.cgms.repository +package no.nordicsemi.android.cgms.data import android.bluetooth.BluetoothGatt import android.bluetooth.BluetoothGattCharacteristic @@ -44,9 +44,7 @@ import no.nordicsemi.android.ble.common.profile.cgm.CGMSpecificOpsControlPointCa import no.nordicsemi.android.ble.ktx.asValidResponseFlow import no.nordicsemi.android.ble.ktx.suspend import no.nordicsemi.android.ble.ktx.suspendForValidResponse -import no.nordicsemi.android.cgms.data.CGMData -import no.nordicsemi.android.cgms.data.CGMRecord -import no.nordicsemi.android.cgms.data.RequestStatus +import no.nordicsemi.android.cgms.repository.toList import no.nordicsemi.android.service.ConnectionObserverAdapter import no.nordicsemi.android.utils.launchWithCatch import java.util.* @@ -105,20 +103,18 @@ internal class CGMManager( override fun initialize() { super.initialize() - enableNotifications(cgmMeasurementCharacteristic).enqueue() - enableIndications(cgmSpecificOpsControlPointCharacteristic).enqueue() - enableIndications(recordAccessControlPointCharacteristic).enqueue() - enableNotifications(batteryLevelCharacteristic).enqueue() - setNotificationCallback(cgmMeasurementCharacteristic).asValidResponseFlow() .onEach { if (sessionStartTime == 0L && !recordAccessRequestInProgress) { - sessionStartTime = System.currentTimeMillis() - it.timeOffset * 60000L + val timeOffset = it.items.minOf { it.timeOffset } + sessionStartTime = System.currentTimeMillis() - timeOffset * 60000L } - val timestamp = sessionStartTime + it.timeOffset * 60000L - val record = CGMRecord(it.timeOffset, it.glucoseConcentration, timestamp) - records.put(record.sequenceNumber, record) + it.items.map { + val timestamp = sessionStartTime + it.timeOffset * 60000L + val item = CGMRecord(it.timeOffset, it.glucoseConcentration, timestamp) + records.put(item.sequenceNumber, item) + } data.value = data.value.copy(records = records.toList()) }.launchIn(scope) @@ -162,15 +158,24 @@ internal class CGMManager( data.value = data.value.copy(batteryLevel = it.batteryLevel) }.launchIn(scope) + enableNotifications(cgmMeasurementCharacteristic).enqueue() + enableIndications(cgmSpecificOpsControlPointCharacteristic).enqueue() + enableIndications(recordAccessControlPointCharacteristic).enqueue() + enableNotifications(batteryLevelCharacteristic).enqueue() + scope.launchWithCatch { val cgmResponse = readCharacteristic(cgmFeatureCharacteristic).suspendForValidResponse() this@CGMManager.secured = cgmResponse.features.e2eCrcSupported + } + scope.launchWithCatch { val response = readCharacteristic(cgmStatusCharacteristic).suspendForValidResponse() if (response.status?.sessionStopped == false) { sessionStartTime = System.currentTimeMillis() - response.timeOffset * 60000L } + } + scope.launchWithCatch { if (sessionStartTime == 0L) { writeCharacteristic( cgmSpecificOpsControlPointCharacteristic, @@ -240,8 +245,7 @@ internal class CGMManager( gatt.getService(BATTERY_SERVICE_UUID)?.run { batteryLevelCharacteristic = getCharacteristic(BATTERY_LEVEL_CHARACTERISTIC_UUID) } - return batteryLevelCharacteristic != null - && cgmMeasurementCharacteristic != null + return cgmMeasurementCharacteristic != null && cgmSpecificOpsControlPointCharacteristic != null && recordAccessControlPointCharacteristic != null && cgmStatusCharacteristic != null diff --git a/profile_cgms/src/main/java/no/nordicsemi/android/cgms/repository/Ext.kt b/profile_cgms/src/main/java/no/nordicsemi/android/cgms/data/Ext.kt similarity index 100% rename from profile_cgms/src/main/java/no/nordicsemi/android/cgms/repository/Ext.kt rename to profile_cgms/src/main/java/no/nordicsemi/android/cgms/data/Ext.kt diff --git a/profile_cgms/src/main/java/no/nordicsemi/android/cgms/data/CGMRepository.kt b/profile_cgms/src/main/java/no/nordicsemi/android/cgms/repository/CGMRepository.kt similarity index 93% rename from profile_cgms/src/main/java/no/nordicsemi/android/cgms/data/CGMRepository.kt rename to profile_cgms/src/main/java/no/nordicsemi/android/cgms/repository/CGMRepository.kt index 087dcda7..51b73068 100644 --- a/profile_cgms/src/main/java/no/nordicsemi/android/cgms/data/CGMRepository.kt +++ b/profile_cgms/src/main/java/no/nordicsemi/android/cgms/repository/CGMRepository.kt @@ -1,4 +1,4 @@ -package no.nordicsemi.android.cgms.data +package no.nordicsemi.android.cgms.repository import android.bluetooth.BluetoothDevice import android.content.Context @@ -7,8 +7,8 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch import no.nordicsemi.android.ble.ktx.suspend -import no.nordicsemi.android.cgms.repository.CGMManager -import no.nordicsemi.android.cgms.repository.CGMService +import no.nordicsemi.android.cgms.data.CGMData +import no.nordicsemi.android.cgms.data.CGMManager import no.nordicsemi.android.service.BleManagerResult import no.nordicsemi.android.service.ConnectingResult import no.nordicsemi.android.service.ServiceManager diff --git a/profile_cgms/src/main/java/no/nordicsemi/android/cgms/repository/CGMService.kt b/profile_cgms/src/main/java/no/nordicsemi/android/cgms/repository/CGMService.kt index f37daa33..d97d1a63 100644 --- a/profile_cgms/src/main/java/no/nordicsemi/android/cgms/repository/CGMService.kt +++ b/profile_cgms/src/main/java/no/nordicsemi/android/cgms/repository/CGMService.kt @@ -6,7 +6,6 @@ import androidx.lifecycle.lifecycleScope import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach -import no.nordicsemi.android.cgms.data.CGMRepository import no.nordicsemi.android.service.DEVICE_DATA import no.nordicsemi.android.service.NotificationService import javax.inject.Inject diff --git a/profile_cgms/src/main/java/no/nordicsemi/android/cgms/view/CGMContentView.kt b/profile_cgms/src/main/java/no/nordicsemi/android/cgms/view/CGMContentView.kt index 1ecd8543..8d8091fe 100644 --- a/profile_cgms/src/main/java/no/nordicsemi/android/cgms/view/CGMContentView.kt +++ b/profile_cgms/src/main/java/no/nordicsemi/android/cgms/view/CGMContentView.kt @@ -38,9 +38,11 @@ internal fun CGMContentView(state: CGMData, onEvent: (CGMViewEvent) -> Unit) { Spacer(modifier = Modifier.height(16.dp)) - BatteryLevelView(state.batteryLevel) + state.batteryLevel?.let { + BatteryLevelView(it) - Spacer(modifier = Modifier.height(16.dp)) + Spacer(modifier = Modifier.height(16.dp)) + } Button( onClick = { onEvent(DisconnectEvent) } diff --git a/profile_cgms/src/main/java/no/nordicsemi/android/cgms/viewmodel/CGMScreenViewModel.kt b/profile_cgms/src/main/java/no/nordicsemi/android/cgms/viewmodel/CGMScreenViewModel.kt index ac025360..2dbc7f2c 100644 --- a/profile_cgms/src/main/java/no/nordicsemi/android/cgms/viewmodel/CGMScreenViewModel.kt +++ b/profile_cgms/src/main/java/no/nordicsemi/android/cgms/viewmodel/CGMScreenViewModel.kt @@ -5,9 +5,9 @@ import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch -import no.nordicsemi.android.cgms.data.CGMRepository +import no.nordicsemi.android.cgms.data.CGMS_SERVICE_UUID +import no.nordicsemi.android.cgms.repository.CGMRepository import no.nordicsemi.android.cgms.data.CGMServiceCommand -import no.nordicsemi.android.cgms.repository.CGMS_SERVICE_UUID import no.nordicsemi.android.cgms.view.* import no.nordicsemi.android.navigation.* import no.nordicsemi.android.utils.exhaustive diff --git a/profile_cgms/src/main/res/values/strings.xml b/profile_cgms/src/main/res/values/strings.xml index d3b36593..c5622124 100644 --- a/profile_cgms/src/main/res/values/strings.xml +++ b/profile_cgms/src/main/res/values/strings.xml @@ -1,7 +1,7 @@ CGMS - There is no data available. Every record is created once a minute. Please wait. + There is no data available. Every record is created once a minute or longer. Please wait. All Last diff --git a/profile_cgms/src/test/java/no/nordicsemi/android/cgms/CGMSViewModelTest.kt b/profile_cgms/src/test/java/no/nordicsemi/android/cgms/CGMSViewModelTest.kt deleted file mode 100644 index 4afa6cf4..00000000 --- a/profile_cgms/src/test/java/no/nordicsemi/android/cgms/CGMSViewModelTest.kt +++ /dev/null @@ -1,77 +0,0 @@ -package no.nordicsemi.android.cgms - -import io.mockk.every -import io.mockk.justRun -import io.mockk.mockk -import io.mockk.verify -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.channels.BufferOverflow -import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.test.UnconfinedTestDispatcher -import kotlinx.coroutines.test.resetMain -import kotlinx.coroutines.test.setMain -import no.nordicsemi.android.cgms.data.CGMRepository -import no.nordicsemi.android.cgms.view.DisconnectEvent -import no.nordicsemi.android.cgms.viewmodel.CGMScreenViewModel -import no.nordicsemi.android.navigation.NavigationManager -import no.nordicsemi.android.service.BleManagerStatus -import no.nordicsemi.android.service.ServiceManager -import org.junit.After -import org.junit.Before -import org.junit.Test - -class CGMSViewModelTest { - - val dispatcher = UnconfinedTestDispatcher() - - @Before - fun setup() { - Dispatchers.setMain(dispatcher) - } - - @After - fun tearDown() { - Dispatchers.resetMain() - } - - @Test - fun `check if navigation up called after disconnect event returns success`() { - val repository = CGMRepository() - val serviceManager = mockk() - val navigationManager = mockk() - - every { navigationManager.recentResult } returns MutableSharedFlow( - extraBufferCapacity = 1, - onBufferOverflow = BufferOverflow.DROP_OLDEST - ) - justRun { navigationManager.navigateTo(any(), any()) } - - val viewModel = CGMScreenViewModel(repository, serviceManager, navigationManager) - - viewModel.onEvent(DisconnectEvent) - - //Invoke by remote service - repository.setNewStatus(BleManagerStatus.DISCONNECTED) - - verify { navigationManager.navigateUp() } - } - - @Test - fun `check if navigation up called after disconnect if no service started event returns success`() { - val repository = CGMRepository() - val serviceManager = mockk() - val navigationManager = mockk() - - every { navigationManager.recentResult } returns MutableSharedFlow( - extraBufferCapacity = 1, - onBufferOverflow = BufferOverflow.DROP_OLDEST - ) - justRun { navigationManager.navigateTo(any(), any()) } - - val viewModel = CGMScreenViewModel(repository, serviceManager, navigationManager) - - viewModel.onEvent(DisconnectEvent) - - verify { navigationManager.navigateUp() } - } -} diff --git a/profile_csc/src/main/java/no/nordicsemi/android/csc/data/CSCData.kt b/profile_csc/src/main/java/no/nordicsemi/android/csc/data/CSCData.kt index 21e4919f..9ed8ab81 100644 --- a/profile_csc/src/main/java/no/nordicsemi/android/csc/data/CSCData.kt +++ b/profile_csc/src/main/java/no/nordicsemi/android/csc/data/CSCData.kt @@ -7,6 +7,6 @@ internal data class CSCData( val distance: Float = 0f, val totalDistance: Float = 0f, val gearRatio: Float = 0f, - val batteryLevel: Int = 0, + val batteryLevel: Int? = null, val wheelSize: WheelSize = WheelSize() ) diff --git a/profile_csc/src/main/java/no/nordicsemi/android/csc/repository/CSCManager.kt b/profile_csc/src/main/java/no/nordicsemi/android/csc/data/CSCManager.kt similarity index 97% rename from profile_csc/src/main/java/no/nordicsemi/android/csc/repository/CSCManager.kt rename to profile_csc/src/main/java/no/nordicsemi/android/csc/data/CSCManager.kt index 3875f527..fd87e227 100644 --- a/profile_csc/src/main/java/no/nordicsemi/android/csc/repository/CSCManager.kt +++ b/profile_csc/src/main/java/no/nordicsemi/android/csc/data/CSCManager.kt @@ -19,7 +19,7 @@ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.csc.repository +package no.nordicsemi.android.csc.data import android.bluetooth.BluetoothGatt import android.bluetooth.BluetoothGattCharacteristic @@ -114,7 +114,7 @@ internal class CSCManager( gatt.getService(BATTERY_SERVICE_UUID)?.run { batteryLevelCharacteristic = getCharacteristic(BATTERY_LEVEL_CHARACTERISTIC_UUID) } - return cscMeasurementCharacteristic != null && batteryLevelCharacteristic != null + return cscMeasurementCharacteristic != null } override fun onServicesInvalidated() { diff --git a/profile_csc/src/main/java/no/nordicsemi/android/csc/data/CSCRepository.kt b/profile_csc/src/main/java/no/nordicsemi/android/csc/repository/CSCRepository.kt similarity index 90% rename from profile_csc/src/main/java/no/nordicsemi/android/csc/data/CSCRepository.kt rename to profile_csc/src/main/java/no/nordicsemi/android/csc/repository/CSCRepository.kt index 0dd26fcb..dde96028 100644 --- a/profile_csc/src/main/java/no/nordicsemi/android/csc/data/CSCRepository.kt +++ b/profile_csc/src/main/java/no/nordicsemi/android/csc/repository/CSCRepository.kt @@ -1,4 +1,4 @@ -package no.nordicsemi.android.csc.data +package no.nordicsemi.android.csc.repository import android.bluetooth.BluetoothDevice import android.content.Context @@ -7,8 +7,9 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch import no.nordicsemi.android.ble.ktx.suspend -import no.nordicsemi.android.csc.repository.CSCManager -import no.nordicsemi.android.csc.repository.CSCService +import no.nordicsemi.android.csc.data.CSCData +import no.nordicsemi.android.csc.data.CSCManager +import no.nordicsemi.android.csc.data.WheelSize import no.nordicsemi.android.service.BleManagerResult import no.nordicsemi.android.service.ConnectingResult import no.nordicsemi.android.service.ServiceManager diff --git a/profile_csc/src/main/java/no/nordicsemi/android/csc/repository/CSCService.kt b/profile_csc/src/main/java/no/nordicsemi/android/csc/repository/CSCService.kt index c26bd5e1..32fdf0f0 100644 --- a/profile_csc/src/main/java/no/nordicsemi/android/csc/repository/CSCService.kt +++ b/profile_csc/src/main/java/no/nordicsemi/android/csc/repository/CSCService.kt @@ -6,7 +6,6 @@ import androidx.lifecycle.lifecycleScope import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach -import no.nordicsemi.android.csc.data.CSCRepository import no.nordicsemi.android.service.DEVICE_DATA import no.nordicsemi.android.service.NotificationService import javax.inject.Inject diff --git a/profile_csc/src/main/java/no/nordicsemi/android/csc/view/SensorsReadingView.kt b/profile_csc/src/main/java/no/nordicsemi/android/csc/view/SensorsReadingView.kt index 2b45a407..9551eebf 100644 --- a/profile_csc/src/main/java/no/nordicsemi/android/csc/view/SensorsReadingView.kt +++ b/profile_csc/src/main/java/no/nordicsemi/android/csc/view/SensorsReadingView.kt @@ -40,7 +40,9 @@ internal fun SensorsReadingView(state: CSCData, speedUnit: SpeedUnit) { Spacer(modifier = Modifier.height(16.dp)) - BatteryLevelView(state.batteryLevel) + state.batteryLevel?.let { + BatteryLevelView(it) + } } @Preview diff --git a/profile_csc/src/main/java/no/nordicsemi/android/csc/viewmodel/CSCViewModel.kt b/profile_csc/src/main/java/no/nordicsemi/android/csc/viewmodel/CSCViewModel.kt index 9ba34051..555630cc 100644 --- a/profile_csc/src/main/java/no/nordicsemi/android/csc/viewmodel/CSCViewModel.kt +++ b/profile_csc/src/main/java/no/nordicsemi/android/csc/viewmodel/CSCViewModel.kt @@ -5,8 +5,8 @@ import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch -import no.nordicsemi.android.csc.data.CSCRepository -import no.nordicsemi.android.csc.repository.CSC_SERVICE_UUID +import no.nordicsemi.android.csc.data.CSC_SERVICE_UUID +import no.nordicsemi.android.csc.repository.CSCRepository import no.nordicsemi.android.csc.view.* import no.nordicsemi.android.navigation.* import no.nordicsemi.android.utils.exhaustive diff --git a/profile_csc/src/test/java/no/nordicsemi/android/csc/CSCViewModelTest.kt b/profile_csc/src/test/java/no/nordicsemi/android/csc/CSCViewModelTest.kt deleted file mode 100644 index 3b75f2ca..00000000 --- a/profile_csc/src/test/java/no/nordicsemi/android/csc/CSCViewModelTest.kt +++ /dev/null @@ -1,77 +0,0 @@ -package no.nordicsemi.android.csc - -import io.mockk.every -import io.mockk.justRun -import io.mockk.mockk -import io.mockk.verify -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.channels.BufferOverflow -import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.test.UnconfinedTestDispatcher -import kotlinx.coroutines.test.resetMain -import kotlinx.coroutines.test.setMain -import no.nordicsemi.android.csc.data.CSCRepository -import no.nordicsemi.android.csc.view.OnDisconnectButtonClick -import no.nordicsemi.android.csc.viewmodel.CSCViewModel -import no.nordicsemi.android.navigation.NavigationManager -import no.nordicsemi.android.service.BleManagerStatus -import no.nordicsemi.android.service.ServiceManager -import org.junit.After -import org.junit.Before -import org.junit.Test - -class CSCViewModelTest { - - val dispatcher = UnconfinedTestDispatcher() - - @Before - fun setup() { - Dispatchers.setMain(dispatcher) - } - - @After - fun tearDown() { - Dispatchers.resetMain() - } - - @Test - fun `check if navigation up called after disconnect event returns success`() { - val repository = CSCRepository() - val serviceManager = mockk() - val navigationManager = mockk() - - every { navigationManager.recentResult } returns MutableSharedFlow( - extraBufferCapacity = 1, - onBufferOverflow = BufferOverflow.DROP_OLDEST - ) - justRun { navigationManager.navigateTo(any(), any()) } - - val viewModel = CSCViewModel(repository, serviceManager, navigationManager) - - viewModel.onEvent(OnDisconnectButtonClick) - - //Invoke by remote service - repository.setNewStatus(BleManagerStatus.DISCONNECTED) - - verify { navigationManager.navigateUp() } - } - - @Test - fun `check if navigation up called after disconnect if no service started event returns success`() { - val repository = CSCRepository() - val serviceManager = mockk() - val navigationManager = mockk() - - every { navigationManager.recentResult } returns MutableSharedFlow( - extraBufferCapacity = 1, - onBufferOverflow = BufferOverflow.DROP_OLDEST - ) - justRun { navigationManager.navigateTo(any(), any()) } - - val viewModel = CSCViewModel(repository, serviceManager, navigationManager) - - viewModel.onEvent(OnDisconnectButtonClick) - - verify { navigationManager.navigateUp() } - } -} diff --git a/profile_gls/src/main/java/no/nordicsemi/android/gls/data/GLSData.kt b/profile_gls/src/main/java/no/nordicsemi/android/gls/data/GLSData.kt index be7e781d..41a54b20 100644 --- a/profile_gls/src/main/java/no/nordicsemi/android/gls/data/GLSData.kt +++ b/profile_gls/src/main/java/no/nordicsemi/android/gls/data/GLSData.kt @@ -2,6 +2,6 @@ package no.nordicsemi.android.gls.data internal data class GLSData( val records: List = emptyList(), - val batteryLevel: Int = 0, + val batteryLevel: Int? = null, val requestStatus: RequestStatus = RequestStatus.IDLE ) diff --git a/profile_gls/src/main/java/no/nordicsemi/android/gls/data/GLSManager.kt b/profile_gls/src/main/java/no/nordicsemi/android/gls/data/GLSManager.kt index 800b60da..55b50b8d 100644 --- a/profile_gls/src/main/java/no/nordicsemi/android/gls/data/GLSManager.kt +++ b/profile_gls/src/main/java/no/nordicsemi/android/gls/data/GLSManager.kt @@ -175,17 +175,10 @@ internal class GLSManager @Inject constructor( gatt.getService(BATTERY_SERVICE_UUID)?.run { batteryLevelCharacteristic = getCharacteristic(BATTERY_LEVEL_CHARACTERISTIC_UUID) } - return glucoseMeasurementCharacteristic != null && recordAccessControlPointCharacteristic != null && batteryLevelCharacteristic != null + return glucoseMeasurementCharacteristic != null && recordAccessControlPointCharacteristic != null } - override fun onServicesInvalidated() {} - - override fun isOptionalServiceSupported(gatt: BluetoothGatt): Boolean { - super.isOptionalServiceSupported(gatt) - return glucoseMeasurementContextCharacteristic != null - } - - override fun onDeviceDisconnected() { + override fun onServicesInvalidated() { glucoseMeasurementCharacteristic = null glucoseMeasurementContextCharacteristic = null recordAccessControlPointCharacteristic = null diff --git a/profile_gls/src/main/java/no/nordicsemi/android/gls/main/view/GLSContentView.kt b/profile_gls/src/main/java/no/nordicsemi/android/gls/main/view/GLSContentView.kt index e815e541..b0e6048b 100644 --- a/profile_gls/src/main/java/no/nordicsemi/android/gls/main/view/GLSContentView.kt +++ b/profile_gls/src/main/java/no/nordicsemi/android/gls/main/view/GLSContentView.kt @@ -45,9 +45,11 @@ internal fun GLSContentView(state: GLSData, onEvent: (GLSScreenViewEvent) -> Uni Spacer(modifier = Modifier.height(16.dp)) - BatteryLevelView(state.batteryLevel) + state.batteryLevel?.let { + BatteryLevelView(it) - Spacer(modifier = Modifier.height(16.dp)) + Spacer(modifier = Modifier.height(16.dp)) + } Button( onClick = { onEvent(DisconnectEvent) } diff --git a/profile_gls/src/main/java/no/nordicsemi/android/gls/main/viewmodel/GLSViewModel.kt b/profile_gls/src/main/java/no/nordicsemi/android/gls/main/viewmodel/GLSViewModel.kt index 1ccca985..58adf875 100644 --- a/profile_gls/src/main/java/no/nordicsemi/android/gls/main/viewmodel/GLSViewModel.kt +++ b/profile_gls/src/main/java/no/nordicsemi/android/gls/main/viewmodel/GLSViewModel.kt @@ -5,7 +5,7 @@ import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.* import no.nordicsemi.android.gls.GlsDetailsDestinationId -import no.nordicsemi.android.gls.data.GLSRepository +import no.nordicsemi.android.gls.repository.GLSRepository import no.nordicsemi.android.gls.data.GLS_SERVICE_UUID import no.nordicsemi.android.gls.main.view.* import no.nordicsemi.android.navigation.* diff --git a/profile_gls/src/main/java/no/nordicsemi/android/gls/data/GLSRepository.kt b/profile_gls/src/main/java/no/nordicsemi/android/gls/repository/GLSRepository.kt similarity index 90% rename from profile_gls/src/main/java/no/nordicsemi/android/gls/data/GLSRepository.kt rename to profile_gls/src/main/java/no/nordicsemi/android/gls/repository/GLSRepository.kt index 80fcb5f2..d8bb73fd 100644 --- a/profile_gls/src/main/java/no/nordicsemi/android/gls/data/GLSRepository.kt +++ b/profile_gls/src/main/java/no/nordicsemi/android/gls/repository/GLSRepository.kt @@ -1,4 +1,4 @@ -package no.nordicsemi.android.gls.data +package no.nordicsemi.android.gls.repository import android.bluetooth.BluetoothDevice import android.content.Context @@ -11,6 +11,9 @@ import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import no.nordicsemi.android.ble.ktx.suspend +import no.nordicsemi.android.gls.data.GLSData +import no.nordicsemi.android.gls.data.GLSManager +import no.nordicsemi.android.gls.data.WorkingMode import no.nordicsemi.android.service.BleManagerResult import no.nordicsemi.android.utils.exhaustive import javax.inject.Inject diff --git a/profile_gls/src/test/java/no/nordicsemi/android/gls/GLSViewModelTest.kt b/profile_gls/src/test/java/no/nordicsemi/android/gls/GLSViewModelTest.kt deleted file mode 100644 index 34be5f2e..00000000 --- a/profile_gls/src/test/java/no/nordicsemi/android/gls/GLSViewModelTest.kt +++ /dev/null @@ -1,82 +0,0 @@ -package no.nordicsemi.android.gls - -import io.mockk.every -import io.mockk.justRun -import io.mockk.mockk -import io.mockk.verify -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.channels.BufferOverflow -import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.test.UnconfinedTestDispatcher -import kotlinx.coroutines.test.resetMain -import kotlinx.coroutines.test.setMain -import no.nordicsemi.android.gls.data.GLSRepository -import no.nordicsemi.android.gls.main.view.DisconnectEvent -import no.nordicsemi.android.gls.main.viewmodel.GLSViewModel -import no.nordicsemi.android.gls.repository.GLSManager -import no.nordicsemi.android.navigation.NavigationManager -import no.nordicsemi.android.service.BleManagerStatus -import org.junit.After -import org.junit.Before -import org.junit.Test - -class GLSViewModelTest { - - val dispatcher = UnconfinedTestDispatcher() - - @Before - fun setup() { - Dispatchers.setMain(dispatcher) - } - - @After - fun tearDown() { - Dispatchers.resetMain() - } - - @Test - fun `check if navigation up called after disconnect event returns success`() { - val repository = GLSRepository() - val manager = mockk() - val navigationManager = mockk() - - every { navigationManager.recentResult } returns MutableSharedFlow( - extraBufferCapacity = 1, - onBufferOverflow = BufferOverflow.DROP_OLDEST - ) - justRun { navigationManager.navigateTo(any(), any()) } - every { manager.isConnected } returns true - justRun { manager.setConnectionObserver(any()) } - justRun { manager.disconnect().enqueue() } - - val viewModel = GLSViewModel(manager, repository, navigationManager) - - viewModel.onEvent(DisconnectEvent) - - //Invoke by manager - repository.setNewStatus(BleManagerStatus.DISCONNECTED) - - verify { navigationManager.navigateUp() } - } - - @Test - fun `check if navigation up called after disconnect if manager not connected event returns success`() { - val repository = GLSRepository() - val manager = mockk() - val navigationManager = mockk() - - every { navigationManager.recentResult } returns MutableSharedFlow( - extraBufferCapacity = 1, - onBufferOverflow = BufferOverflow.DROP_OLDEST - ) - justRun { navigationManager.navigateTo(any(), any()) } - every { manager.isConnected } returns false - justRun { manager.setConnectionObserver(any()) } - - val viewModel = GLSViewModel(manager, repository, navigationManager) - - viewModel.onEvent(DisconnectEvent) - - verify { navigationManager.navigateUp() } - } -} diff --git a/profile_hrs/src/main/java/no/nordicsemi/android/hrs/data/HRSData.kt b/profile_hrs/src/main/java/no/nordicsemi/android/hrs/data/HRSData.kt index 5ca9c7b2..807fd5e3 100644 --- a/profile_hrs/src/main/java/no/nordicsemi/android/hrs/data/HRSData.kt +++ b/profile_hrs/src/main/java/no/nordicsemi/android/hrs/data/HRSData.kt @@ -2,6 +2,6 @@ package no.nordicsemi.android.hrs.data internal data class HRSData( val heartRates: List = emptyList(), - val batteryLevel: Int = 0, + val batteryLevel: Int? = null, val sensorLocation: Int = 0, ) diff --git a/profile_hrs/src/main/java/no/nordicsemi/android/hrs/service/HRSManager.kt b/profile_hrs/src/main/java/no/nordicsemi/android/hrs/data/HRSManager.kt similarity index 92% rename from profile_hrs/src/main/java/no/nordicsemi/android/hrs/service/HRSManager.kt rename to profile_hrs/src/main/java/no/nordicsemi/android/hrs/data/HRSManager.kt index 2cb555f6..287156bb 100644 --- a/profile_hrs/src/main/java/no/nordicsemi/android/hrs/service/HRSManager.kt +++ b/profile_hrs/src/main/java/no/nordicsemi/android/hrs/data/HRSManager.kt @@ -19,7 +19,7 @@ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.hrs.service +package no.nordicsemi.android.hrs.data import android.bluetooth.BluetoothGatt import android.bluetooth.BluetoothGattCharacteristic @@ -34,7 +34,6 @@ import no.nordicsemi.android.ble.common.callback.hr.BodySensorLocationResponse import no.nordicsemi.android.ble.common.callback.hr.HeartRateMeasurementResponse import no.nordicsemi.android.ble.ktx.asValidResponseFlow import no.nordicsemi.android.ble.ktx.suspendForValidResponse -import no.nordicsemi.android.hrs.data.HRSData import no.nordicsemi.android.service.ConnectionObserverAdapter import no.nordicsemi.android.utils.launchWithCatch import java.util.* @@ -99,19 +98,12 @@ internal class HRSManager( override fun isRequiredServiceSupported(gatt: BluetoothGatt): Boolean { gatt.getService(HRS_SERVICE_UUID)?.run { heartRateCharacteristic = getCharacteristic(HEART_RATE_MEASUREMENT_CHARACTERISTIC_UUID) + bodySensorLocationCharacteristic = getCharacteristic(BODY_SENSOR_LOCATION_CHARACTERISTIC_UUID) } gatt.getService(BATTERY_SERVICE_UUID)?.run { batteryLevelCharacteristic = getCharacteristic(BATTERY_LEVEL_CHARACTERISTIC_UUID) } - return heartRateCharacteristic != null && batteryLevelCharacteristic != null - } - - override fun isOptionalServiceSupported(gatt: BluetoothGatt): Boolean { - super.isOptionalServiceSupported(gatt) - gatt.getService(HRS_SERVICE_UUID)?.run { - bodySensorLocationCharacteristic = getCharacteristic(BODY_SENSOR_LOCATION_CHARACTERISTIC_UUID) - } - return bodySensorLocationCharacteristic != null + return heartRateCharacteristic != null } override fun onServicesInvalidated() { diff --git a/profile_hrs/src/main/java/no/nordicsemi/android/hrs/data/HRSRepository.kt b/profile_hrs/src/main/java/no/nordicsemi/android/hrs/service/HRSRepository.kt similarity index 92% rename from profile_hrs/src/main/java/no/nordicsemi/android/hrs/data/HRSRepository.kt rename to profile_hrs/src/main/java/no/nordicsemi/android/hrs/service/HRSRepository.kt index f06184a7..ca18a130 100644 --- a/profile_hrs/src/main/java/no/nordicsemi/android/hrs/data/HRSRepository.kt +++ b/profile_hrs/src/main/java/no/nordicsemi/android/hrs/service/HRSRepository.kt @@ -1,4 +1,4 @@ -package no.nordicsemi.android.hrs.data +package no.nordicsemi.android.hrs.service import android.bluetooth.BluetoothDevice import android.content.Context @@ -7,8 +7,8 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch import no.nordicsemi.android.ble.ktx.suspend -import no.nordicsemi.android.hrs.service.HRSManager -import no.nordicsemi.android.hrs.service.HRSService +import no.nordicsemi.android.hrs.data.HRSData +import no.nordicsemi.android.hrs.data.HRSManager import no.nordicsemi.android.service.BleManagerResult import no.nordicsemi.android.service.ConnectingResult import no.nordicsemi.android.service.ServiceManager diff --git a/profile_hrs/src/main/java/no/nordicsemi/android/hrs/service/HRSService.kt b/profile_hrs/src/main/java/no/nordicsemi/android/hrs/service/HRSService.kt index 1502e017..565f4cd0 100644 --- a/profile_hrs/src/main/java/no/nordicsemi/android/hrs/service/HRSService.kt +++ b/profile_hrs/src/main/java/no/nordicsemi/android/hrs/service/HRSService.kt @@ -6,7 +6,6 @@ import androidx.lifecycle.lifecycleScope import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach -import no.nordicsemi.android.hrs.data.HRSRepository import no.nordicsemi.android.service.DEVICE_DATA import no.nordicsemi.android.service.NotificationService import javax.inject.Inject diff --git a/profile_hrs/src/main/java/no/nordicsemi/android/hrs/view/HRSContentView.kt b/profile_hrs/src/main/java/no/nordicsemi/android/hrs/view/HRSContentView.kt index 5a979710..ab5a0f51 100644 --- a/profile_hrs/src/main/java/no/nordicsemi/android/hrs/view/HRSContentView.kt +++ b/profile_hrs/src/main/java/no/nordicsemi/android/hrs/view/HRSContentView.kt @@ -34,9 +34,11 @@ internal fun HRSContentView(state: HRSData, onEvent: (HRSScreenViewEvent) -> Uni Spacer(modifier = Modifier.height(16.dp)) - BatteryLevelView(state.batteryLevel) + state.batteryLevel?.let { + BatteryLevelView(it) - Spacer(modifier = Modifier.height(16.dp)) + Spacer(modifier = Modifier.height(16.dp)) + } Button( onClick = { onEvent(DisconnectEvent) } diff --git a/profile_hrs/src/main/java/no/nordicsemi/android/hrs/viewmodel/HRSViewModel.kt b/profile_hrs/src/main/java/no/nordicsemi/android/hrs/viewmodel/HRSViewModel.kt index af64f2ec..6433889e 100644 --- a/profile_hrs/src/main/java/no/nordicsemi/android/hrs/viewmodel/HRSViewModel.kt +++ b/profile_hrs/src/main/java/no/nordicsemi/android/hrs/viewmodel/HRSViewModel.kt @@ -5,8 +5,8 @@ import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch -import no.nordicsemi.android.hrs.data.HRSRepository -import no.nordicsemi.android.hrs.service.HRS_SERVICE_UUID +import no.nordicsemi.android.hrs.data.HRS_SERVICE_UUID +import no.nordicsemi.android.hrs.service.HRSRepository import no.nordicsemi.android.hrs.view.* import no.nordicsemi.android.navigation.* import no.nordicsemi.android.utils.exhaustive diff --git a/profile_hrs/src/test/java/no/nordicsemi/android/hrs/HRSViewModelTest.kt b/profile_hrs/src/test/java/no/nordicsemi/android/hrs/HRSViewModelTest.kt deleted file mode 100644 index 6fb516c0..00000000 --- a/profile_hrs/src/test/java/no/nordicsemi/android/hrs/HRSViewModelTest.kt +++ /dev/null @@ -1,77 +0,0 @@ -package no.nordicsemi.android.hrs - -import io.mockk.every -import io.mockk.justRun -import io.mockk.mockk -import io.mockk.verify -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.channels.BufferOverflow -import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.test.UnconfinedTestDispatcher -import kotlinx.coroutines.test.resetMain -import kotlinx.coroutines.test.setMain -import no.nordicsemi.android.hrs.data.HRSRepository -import no.nordicsemi.android.hrs.view.DisconnectEvent -import no.nordicsemi.android.hrs.viewmodel.HRSViewModel -import no.nordicsemi.android.navigation.NavigationManager -import no.nordicsemi.android.service.BleManagerStatus -import no.nordicsemi.android.service.ServiceManager -import org.junit.After -import org.junit.Before -import org.junit.Test - -class HRSViewModelTest { - - val dispatcher = UnconfinedTestDispatcher() - - @Before - fun setup() { - Dispatchers.setMain(dispatcher) - } - - @After - fun tearDown() { - Dispatchers.resetMain() - } - - @Test - fun `check if navigation up called after disconnect event returns success`() { - val repository = HRSRepository() - val serviceManager = mockk() - val navigationManager = mockk() - - every { navigationManager.recentResult } returns MutableSharedFlow( - extraBufferCapacity = 1, - onBufferOverflow = BufferOverflow.DROP_OLDEST - ) - justRun { navigationManager.navigateTo(any(), any()) } - - val viewModel = HRSViewModel(repository, serviceManager, navigationManager) - - viewModel.onEvent(DisconnectEvent) - - //Invoke by remote service - repository.setNewStatus(BleManagerStatus.DISCONNECTED) - - verify { navigationManager.navigateUp() } - } - - @Test - fun `check if navigation up called after disconnect if no service started event returns success`() { - val repository = HRSRepository() - val serviceManager = mockk() - val navigationManager = mockk() - - every { navigationManager.recentResult } returns MutableSharedFlow( - extraBufferCapacity = 1, - onBufferOverflow = BufferOverflow.DROP_OLDEST - ) - justRun { navigationManager.navigateTo(any(), any()) } - - val viewModel = HRSViewModel(repository, serviceManager, navigationManager) - - viewModel.onEvent(DisconnectEvent) - - verify { navigationManager.navigateUp() } - } -} \ No newline at end of file diff --git a/profile_hts/src/main/java/no/nordicsemi/android/hts/data/HTSData.kt b/profile_hts/src/main/java/no/nordicsemi/android/hts/data/HTSData.kt index 6523de27..a83947cf 100644 --- a/profile_hts/src/main/java/no/nordicsemi/android/hts/data/HTSData.kt +++ b/profile_hts/src/main/java/no/nordicsemi/android/hts/data/HTSData.kt @@ -2,5 +2,5 @@ package no.nordicsemi.android.hts.data internal data class HTSData( val temperatureValue: Float = 0f, - val batteryLevel: Int = 0, + val batteryLevel: Int? = null, ) diff --git a/profile_hts/src/main/java/no/nordicsemi/android/hts/repository/HTSManager.kt b/profile_hts/src/main/java/no/nordicsemi/android/hts/data/HTSManager.kt similarity index 97% rename from profile_hts/src/main/java/no/nordicsemi/android/hts/repository/HTSManager.kt rename to profile_hts/src/main/java/no/nordicsemi/android/hts/data/HTSManager.kt index 0fc71fc2..e8770758 100644 --- a/profile_hts/src/main/java/no/nordicsemi/android/hts/repository/HTSManager.kt +++ b/profile_hts/src/main/java/no/nordicsemi/android/hts/data/HTSManager.kt @@ -19,7 +19,7 @@ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.hts.repository +package no.nordicsemi.android.hts.data import android.bluetooth.BluetoothGatt import android.bluetooth.BluetoothGattCharacteristic @@ -89,7 +89,7 @@ internal class HTSManager internal constructor( gatt.getService(BATTERY_SERVICE_UUID)?.run { batteryLevelCharacteristic = getCharacteristic(BATTERY_LEVEL_CHARACTERISTIC_UUID) } - return htCharacteristic != null && batteryLevelCharacteristic != null + return htCharacteristic != null } override fun onServicesInvalidated() { diff --git a/profile_hts/src/main/java/no/nordicsemi/android/hts/data/HTSServiceCommand.kt b/profile_hts/src/main/java/no/nordicsemi/android/hts/data/HTSServiceCommand.kt deleted file mode 100644 index bead4203..00000000 --- a/profile_hts/src/main/java/no/nordicsemi/android/hts/data/HTSServiceCommand.kt +++ /dev/null @@ -1,3 +0,0 @@ -package no.nordicsemi.android.hts.data - -internal object DisconnectCommand diff --git a/profile_hts/src/main/java/no/nordicsemi/android/hts/data/HTSRepository.kt b/profile_hts/src/main/java/no/nordicsemi/android/hts/repository/HTSRepository.kt similarity index 92% rename from profile_hts/src/main/java/no/nordicsemi/android/hts/data/HTSRepository.kt rename to profile_hts/src/main/java/no/nordicsemi/android/hts/repository/HTSRepository.kt index f837b7a4..d0870c49 100644 --- a/profile_hts/src/main/java/no/nordicsemi/android/hts/data/HTSRepository.kt +++ b/profile_hts/src/main/java/no/nordicsemi/android/hts/repository/HTSRepository.kt @@ -1,4 +1,4 @@ -package no.nordicsemi.android.hts.data +package no.nordicsemi.android.hts.repository import android.bluetooth.BluetoothDevice import android.content.Context @@ -7,8 +7,8 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch import no.nordicsemi.android.ble.ktx.suspend -import no.nordicsemi.android.hts.repository.HTSManager -import no.nordicsemi.android.hts.repository.HTSService +import no.nordicsemi.android.hts.data.HTSData +import no.nordicsemi.android.hts.data.HTSManager import no.nordicsemi.android.service.BleManagerResult import no.nordicsemi.android.service.ConnectingResult import no.nordicsemi.android.service.ServiceManager diff --git a/profile_hts/src/main/java/no/nordicsemi/android/hts/repository/HTSService.kt b/profile_hts/src/main/java/no/nordicsemi/android/hts/repository/HTSService.kt index 1b4399e5..fbb41b6e 100644 --- a/profile_hts/src/main/java/no/nordicsemi/android/hts/repository/HTSService.kt +++ b/profile_hts/src/main/java/no/nordicsemi/android/hts/repository/HTSService.kt @@ -6,7 +6,6 @@ import androidx.lifecycle.lifecycleScope import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach -import no.nordicsemi.android.hts.data.HTSRepository import no.nordicsemi.android.service.DEVICE_DATA import no.nordicsemi.android.service.NotificationService import javax.inject.Inject diff --git a/profile_hts/src/main/java/no/nordicsemi/android/hts/view/HTSContentView.kt b/profile_hts/src/main/java/no/nordicsemi/android/hts/view/HTSContentView.kt index 969ba126..5801b9e9 100644 --- a/profile_hts/src/main/java/no/nordicsemi/android/hts/view/HTSContentView.kt +++ b/profile_hts/src/main/java/no/nordicsemi/android/hts/view/HTSContentView.kt @@ -50,9 +50,11 @@ internal fun HTSContentView(state: HTSData, temperatureUnit: TemperatureUnit, on Spacer(modifier = Modifier.height(16.dp)) - BatteryLevelView(state.batteryLevel) + state.batteryLevel?.let { + BatteryLevelView(it) - Spacer(modifier = Modifier.height(16.dp)) + Spacer(modifier = Modifier.height(16.dp)) + } Button( onClick = { onEvent(DisconnectEvent) } diff --git a/profile_hts/src/main/java/no/nordicsemi/android/hts/viewmodel/HTSViewModel.kt b/profile_hts/src/main/java/no/nordicsemi/android/hts/viewmodel/HTSViewModel.kt index 03aee6bd..62f9d532 100644 --- a/profile_hts/src/main/java/no/nordicsemi/android/hts/viewmodel/HTSViewModel.kt +++ b/profile_hts/src/main/java/no/nordicsemi/android/hts/viewmodel/HTSViewModel.kt @@ -5,8 +5,8 @@ import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch -import no.nordicsemi.android.hts.data.HTSRepository -import no.nordicsemi.android.hts.repository.HTS_SERVICE_UUID +import no.nordicsemi.android.hts.data.HTS_SERVICE_UUID +import no.nordicsemi.android.hts.repository.HTSRepository import no.nordicsemi.android.hts.view.* import no.nordicsemi.android.navigation.* import no.nordicsemi.android.utils.exhaustive diff --git a/profile_hts/src/test/java/no/nordicsemi/android/hts/HTSViewModelTest.kt b/profile_hts/src/test/java/no/nordicsemi/android/hts/HTSViewModelTest.kt deleted file mode 100644 index 782137a1..00000000 --- a/profile_hts/src/test/java/no/nordicsemi/android/hts/HTSViewModelTest.kt +++ /dev/null @@ -1,77 +0,0 @@ -package no.nordicsemi.android.hts - -import io.mockk.every -import io.mockk.justRun -import io.mockk.mockk -import io.mockk.verify -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.channels.BufferOverflow -import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.test.UnconfinedTestDispatcher -import kotlinx.coroutines.test.resetMain -import kotlinx.coroutines.test.setMain -import no.nordicsemi.android.hts.data.HTSRepository -import no.nordicsemi.android.hts.view.DisconnectEvent -import no.nordicsemi.android.hts.viewmodel.HTSViewModel -import no.nordicsemi.android.navigation.NavigationManager -import no.nordicsemi.android.service.BleManagerStatus -import no.nordicsemi.android.service.ServiceManager -import org.junit.After -import org.junit.Before -import org.junit.Test - -class HTSViewModelTest { - - val dispatcher = UnconfinedTestDispatcher() - - @Before - fun setup() { - Dispatchers.setMain(dispatcher) - } - - @After - fun tearDown() { - Dispatchers.resetMain() - } - - @Test - fun `check if navigation up called after disconnect event returns success`() { - val repository = HTSRepository() - val serviceManager = mockk() - val navigationManager = mockk() - - every { navigationManager.recentResult } returns MutableSharedFlow( - extraBufferCapacity = 1, - onBufferOverflow = BufferOverflow.DROP_OLDEST - ) - justRun { navigationManager.navigateTo(any(), any()) } - - val viewModel = HTSViewModel(repository, serviceManager, navigationManager) - - viewModel.onEvent(DisconnectEvent) - - //Invoke by remote service - repository.setNewStatus(BleManagerStatus.DISCONNECTED) - - verify { navigationManager.navigateUp() } - } - - @Test - fun `check if navigation up called after disconnect if no service started event returns success`() { - val repository = HTSRepository() - val serviceManager = mockk() - val navigationManager = mockk() - - every { navigationManager.recentResult } returns MutableSharedFlow( - extraBufferCapacity = 1, - onBufferOverflow = BufferOverflow.DROP_OLDEST - ) - justRun { navigationManager.navigateTo(any(), any()) } - - val viewModel = HTSViewModel(repository, serviceManager, navigationManager) - - viewModel.onEvent(DisconnectEvent) - - verify { navigationManager.navigateUp() } - } -} \ No newline at end of file diff --git a/profile_prx/src/main/java/no/nordicsemi/android/prx/data/PRXCommand.kt b/profile_prx/src/main/java/no/nordicsemi/android/prx/data/PRXCommand.kt deleted file mode 100644 index 92000346..00000000 --- a/profile_prx/src/main/java/no/nordicsemi/android/prx/data/PRXCommand.kt +++ /dev/null @@ -1,9 +0,0 @@ -package no.nordicsemi.android.prx.data - -internal sealed class PRXCommand - -internal object EnableAlarm : PRXCommand() - -internal object DisableAlarm : PRXCommand() - -internal object Disconnect : PRXCommand() diff --git a/profile_prx/src/main/java/no/nordicsemi/android/prx/data/PRXData.kt b/profile_prx/src/main/java/no/nordicsemi/android/prx/data/PRXData.kt index 8e607e8c..f6691ad9 100644 --- a/profile_prx/src/main/java/no/nordicsemi/android/prx/data/PRXData.kt +++ b/profile_prx/src/main/java/no/nordicsemi/android/prx/data/PRXData.kt @@ -1,7 +1,7 @@ package no.nordicsemi.android.prx.data internal data class PRXData( - val batteryLevel: Int = 0, + val batteryLevel: Int? = null, val localAlarmLevel: AlarmLevel = AlarmLevel.NONE, val isRemoteAlarm: Boolean = false, val linkLossAlarmLevel: AlarmLevel = AlarmLevel.HIGH diff --git a/profile_prx/src/main/java/no/nordicsemi/android/prx/repository/PRXManager.kt b/profile_prx/src/main/java/no/nordicsemi/android/prx/data/PRXManager.kt similarity index 96% rename from profile_prx/src/main/java/no/nordicsemi/android/prx/repository/PRXManager.kt rename to profile_prx/src/main/java/no/nordicsemi/android/prx/data/PRXManager.kt index dbc34045..d85a8a55 100644 --- a/profile_prx/src/main/java/no/nordicsemi/android/prx/repository/PRXManager.kt +++ b/profile_prx/src/main/java/no/nordicsemi/android/prx/data/PRXManager.kt @@ -19,7 +19,7 @@ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.prx.repository +package no.nordicsemi.android.prx.data import android.bluetooth.BluetoothDevice import android.bluetooth.BluetoothGatt @@ -124,15 +124,10 @@ internal class PRXManager( gatt.getService(BATTERY_SERVICE_UUID)?.run { batteryLevelCharacteristic = getCharacteristic(BATTERY_LEVEL_CHARACTERISTIC_UUID) } - return linkLossCharacteristic != null - } - - override fun isOptionalServiceSupported(gatt: BluetoothGatt): Boolean { - super.isOptionalServiceSupported(gatt) gatt.getService(PRX_SERVICE_UUID)?.run { alertLevelCharacteristic = getCharacteristic(ALERT_LEVEL_CHARACTERISTIC_UUID) } - return alertLevelCharacteristic != null && batteryLevelCharacteristic != null + return linkLossCharacteristic != null } override fun onServicesInvalidated() { diff --git a/profile_prx/src/main/java/no/nordicsemi/android/prx/repository/ProximityServerManager.kt b/profile_prx/src/main/java/no/nordicsemi/android/prx/data/ProximityServerManager.kt similarity index 98% rename from profile_prx/src/main/java/no/nordicsemi/android/prx/repository/ProximityServerManager.kt rename to profile_prx/src/main/java/no/nordicsemi/android/prx/data/ProximityServerManager.kt index cb4dea63..858af39c 100644 --- a/profile_prx/src/main/java/no/nordicsemi/android/prx/repository/ProximityServerManager.kt +++ b/profile_prx/src/main/java/no/nordicsemi/android/prx/data/ProximityServerManager.kt @@ -19,7 +19,7 @@ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.prx.repository +package no.nordicsemi.android.prx.data import android.bluetooth.BluetoothGattCharacteristic import android.bluetooth.BluetoothGattService diff --git a/profile_prx/src/main/java/no/nordicsemi/android/prx/repository/AlarmHandler.kt b/profile_prx/src/main/java/no/nordicsemi/android/prx/repository/AlarmHandler.kt index 27cf81d6..0d9b03c0 100644 --- a/profile_prx/src/main/java/no/nordicsemi/android/prx/repository/AlarmHandler.kt +++ b/profile_prx/src/main/java/no/nordicsemi/android/prx/repository/AlarmHandler.kt @@ -20,7 +20,7 @@ internal class AlarmHandler @Inject constructor( private val TAG = "ALARM_MANAGER" private var mediaPlayer = MediaPlayer() - private var originalVolume = 0 + private var volume = 0 init { mediaPlayer.setAudioStreamType(AudioManager.STREAM_ALARM) @@ -38,17 +38,16 @@ internal class AlarmHandler @Inject constructor( fun playAlarm(alarmLevel: AlarmLevel) { val am = context.getSystemService(LifecycleService.AUDIO_SERVICE) as AudioManager - originalVolume = am.getStreamVolume(AudioManager.STREAM_ALARM) - val soundLevel = when (alarmLevel) { + volume = when (alarmLevel) { AlarmLevel.NONE -> 0 - AlarmLevel.MEDIUM -> originalVolume / 2 - AlarmLevel.HIGH -> originalVolume + AlarmLevel.MEDIUM -> am.getStreamVolume(AudioManager.STREAM_NOTIFICATION) + AlarmLevel.HIGH -> am.getStreamVolume(AudioManager.STREAM_ALARM) } am.setStreamVolume( AudioManager.STREAM_ALARM, - soundLevel, + volume, AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE ) try { @@ -65,7 +64,7 @@ internal class AlarmHandler @Inject constructor( mediaPlayer.stop() // Restore original volume val am = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager - am.setStreamVolume(AudioManager.STREAM_ALARM, originalVolume, 0) + am.setStreamVolume(AudioManager.STREAM_ALARM, volume, 0) } } catch (e: Exception) { Log.e(TAG, "Prepare Alarm failed: ", e) diff --git a/profile_prx/src/main/java/no/nordicsemi/android/prx/data/PRXRepository.kt b/profile_prx/src/main/java/no/nordicsemi/android/prx/repository/PRXRepository.kt similarity index 75% rename from profile_prx/src/main/java/no/nordicsemi/android/prx/data/PRXRepository.kt rename to profile_prx/src/main/java/no/nordicsemi/android/prx/repository/PRXRepository.kt index ce996361..a78f134b 100644 --- a/profile_prx/src/main/java/no/nordicsemi/android/prx/data/PRXRepository.kt +++ b/profile_prx/src/main/java/no/nordicsemi/android/prx/repository/PRXRepository.kt @@ -1,16 +1,14 @@ -package no.nordicsemi.android.prx.data +package no.nordicsemi.android.prx.repository import android.bluetooth.BluetoothDevice import android.content.Context import dagger.hilt.android.qualifiers.ApplicationContext import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.* -import kotlinx.coroutines.launch -import no.nordicsemi.android.ble.ktx.suspend -import no.nordicsemi.android.prx.repository.AlarmHandler -import no.nordicsemi.android.prx.repository.PRXManager -import no.nordicsemi.android.prx.repository.PRXService -import no.nordicsemi.android.prx.repository.ProximityServerManager +import no.nordicsemi.android.prx.data.AlarmLevel +import no.nordicsemi.android.prx.data.PRXData +import no.nordicsemi.android.prx.data.PRXManager +import no.nordicsemi.android.prx.data.ProximityServerManager import no.nordicsemi.android.service.* import javax.inject.Inject import javax.inject.Singleton @@ -47,11 +45,7 @@ class PRXRepository @Inject internal constructor( handleLocalAlarm(it) }.launchIn(scope) - manager.start(device) - } - - private fun PRXManager.start(device: BluetoothDevice) { - connect(device) + manager.connect(device) .useAutoConnect(true) .retry(3, 100) .enqueue() @@ -65,10 +59,9 @@ class PRXRepository @Inject internal constructor( alarmHandler.pauseAlarm() } } -// (result as? LinkLossResult)?.let { -// alarmHandler.playAlarm(it.data.localAlarmLevel) -// repository.setLocalAlarmLevel(repository.data.value.linkLossAlarmLevel) -// } + (result as? LinkLossResult)?.let { + alarmHandler.playAlarm(it.data.linkLossAlarmLevel) + } } fun enableAlarm() { @@ -80,6 +73,7 @@ class PRXRepository @Inject internal constructor( } fun release() { + alarmHandler.releaseAlarm() manager?.disconnect()?.enqueue() manager = null } diff --git a/profile_prx/src/main/java/no/nordicsemi/android/prx/repository/PRXService.kt b/profile_prx/src/main/java/no/nordicsemi/android/prx/repository/PRXService.kt index 82ae7e38..e2654c62 100644 --- a/profile_prx/src/main/java/no/nordicsemi/android/prx/repository/PRXService.kt +++ b/profile_prx/src/main/java/no/nordicsemi/android/prx/repository/PRXService.kt @@ -6,7 +6,6 @@ import androidx.lifecycle.lifecycleScope import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach -import no.nordicsemi.android.prx.data.PRXRepository import no.nordicsemi.android.service.DEVICE_DATA import no.nordicsemi.android.service.NotificationService import javax.inject.Inject diff --git a/profile_prx/src/main/java/no/nordicsemi/android/prx/view/PRXContentView.kt b/profile_prx/src/main/java/no/nordicsemi/android/prx/view/PRXContentView.kt index 732b08ce..17e5ce2e 100644 --- a/profile_prx/src/main/java/no/nordicsemi/android/prx/view/PRXContentView.kt +++ b/profile_prx/src/main/java/no/nordicsemi/android/prx/view/PRXContentView.kt @@ -34,9 +34,11 @@ internal fun ContentView(state: PRXData, onEvent: (PRXScreenViewEvent) -> Unit) Spacer(modifier = Modifier.height(16.dp)) - BatteryLevelView(state.batteryLevel) + state.batteryLevel?.let { + BatteryLevelView(it) - Spacer(modifier = Modifier.height(16.dp)) + Spacer(modifier = Modifier.height(16.dp)) + } Button( onClick = { onEvent(DisconnectEvent) } @@ -89,12 +91,12 @@ private fun RecordsSection(state: PRXData) { Column { KeyValueField( stringResource(id = R.string.prx_is_remote_alarm), - state.isRemoteAlarm.toString() + state.isRemoteAlarm.toDisplayString() ) Spacer(modifier = Modifier.height(4.dp)) KeyValueField( stringResource(id = R.string.prx_local_alarm_level), - state.localAlarmLevel.toDisplayString() + state.localAlarmLevel.toDisplayString().uppercase() ) } } diff --git a/profile_prx/src/main/java/no/nordicsemi/android/prx/view/PRXMapper.kt b/profile_prx/src/main/java/no/nordicsemi/android/prx/view/PRXMapper.kt index 2ff3681d..5073baec 100644 --- a/profile_prx/src/main/java/no/nordicsemi/android/prx/view/PRXMapper.kt +++ b/profile_prx/src/main/java/no/nordicsemi/android/prx/view/PRXMapper.kt @@ -5,6 +5,14 @@ import androidx.compose.ui.res.stringResource import no.nordicsemi.android.prx.R import no.nordicsemi.android.prx.data.AlarmLevel +@Composable +internal fun Boolean.toDisplayString(): String { + return when (this) { + true -> stringResource(id = R.string.prx_alarm_on) + false -> stringResource(id = R.string.prx_alarm_off) + }.uppercase() +} + @Composable internal fun AlarmLevel.toDisplayString(): String { return when (this) { diff --git a/profile_prx/src/main/java/no/nordicsemi/android/prx/viewmodel/PRXViewModel.kt b/profile_prx/src/main/java/no/nordicsemi/android/prx/viewmodel/PRXViewModel.kt index 7089d213..c788d9e7 100644 --- a/profile_prx/src/main/java/no/nordicsemi/android/prx/viewmodel/PRXViewModel.kt +++ b/profile_prx/src/main/java/no/nordicsemi/android/prx/viewmodel/PRXViewModel.kt @@ -6,8 +6,8 @@ import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch import no.nordicsemi.android.navigation.* -import no.nordicsemi.android.prx.data.PRXRepository -import no.nordicsemi.android.prx.repository.PRX_SERVICE_UUID +import no.nordicsemi.android.prx.data.PRX_SERVICE_UUID +import no.nordicsemi.android.prx.repository.PRXRepository import no.nordicsemi.android.prx.view.* import no.nordicsemi.android.utils.exhaustive import no.nordicsemi.android.utils.getDevice diff --git a/profile_prx/src/main/res/values/strings.xml b/profile_prx/src/main/res/values/strings.xml index fba896bf..decbbf9b 100644 --- a/profile_prx/src/main/res/values/strings.xml +++ b/profile_prx/src/main/res/values/strings.xml @@ -2,12 +2,15 @@ Proximity - SILENT ME - FIND ME + Silent me + Find me Data Settings + on + off + none medium height diff --git a/profile_prx/src/test/java/no/nordicsemi/android/prx/PRXViewModelTest.kt b/profile_prx/src/test/java/no/nordicsemi/android/prx/PRXViewModelTest.kt deleted file mode 100644 index 7c01ce59..00000000 --- a/profile_prx/src/test/java/no/nordicsemi/android/prx/PRXViewModelTest.kt +++ /dev/null @@ -1,77 +0,0 @@ -package no.nordicsemi.android.prx - -import io.mockk.every -import io.mockk.justRun -import io.mockk.mockk -import io.mockk.verify -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.channels.BufferOverflow -import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.test.UnconfinedTestDispatcher -import kotlinx.coroutines.test.resetMain -import kotlinx.coroutines.test.setMain -import no.nordicsemi.android.navigation.NavigationManager -import no.nordicsemi.android.prx.data.PRXRepository -import no.nordicsemi.android.prx.view.DisconnectEvent -import no.nordicsemi.android.prx.viewmodel.PRXViewModel -import no.nordicsemi.android.service.BleManagerStatus -import no.nordicsemi.android.service.ServiceManager -import org.junit.After -import org.junit.Before -import org.junit.Test - -class PRXViewModelTest { - - val dispatcher = UnconfinedTestDispatcher() - - @Before - fun setup() { - Dispatchers.setMain(dispatcher) - } - - @After - fun tearDown() { - Dispatchers.resetMain() - } - - @Test - fun `check if navigation up called after disconnect event returns success`() { - val repository = PRXRepository() - val serviceManager = mockk() - val navigationManager = mockk() - - every { navigationManager.recentResult } returns MutableSharedFlow( - extraBufferCapacity = 1, - onBufferOverflow = BufferOverflow.DROP_OLDEST - ) - justRun { navigationManager.navigateTo(any(), any()) } - - val viewModel = PRXViewModel(repository, serviceManager, navigationManager) - - viewModel.onEvent(DisconnectEvent) - - //Invoke by remote service - repository.setNewStatus(BleManagerStatus.DISCONNECTED) - - verify { navigationManager.navigateUp() } - } - - @Test - fun `check if navigation up called after disconnect if no service started event returns success`() { - val repository = PRXRepository() - val serviceManager = mockk() - val navigationManager = mockk() - - every { navigationManager.recentResult } returns MutableSharedFlow( - extraBufferCapacity = 1, - onBufferOverflow = BufferOverflow.DROP_OLDEST - ) - justRun { navigationManager.navigateTo(any(), any()) } - - val viewModel = PRXViewModel(repository, serviceManager, navigationManager) - - viewModel.onEvent(DisconnectEvent) - - verify { navigationManager.navigateUp() } - } -} \ No newline at end of file diff --git a/profile_rscs/src/main/java/no/nordicsemi/android/rscs/data/RSCSData.kt b/profile_rscs/src/main/java/no/nordicsemi/android/rscs/data/RSCSData.kt index e4809e30..2866245e 100644 --- a/profile_rscs/src/main/java/no/nordicsemi/android/rscs/data/RSCSData.kt +++ b/profile_rscs/src/main/java/no/nordicsemi/android/rscs/data/RSCSData.kt @@ -1,7 +1,7 @@ package no.nordicsemi.android.rscs.data internal data class RSCSData( - val batteryLevel: Int = 0, + val batteryLevel: Int? = null, val running: Boolean = false, val instantaneousSpeed: Float = 1.0f, val instantaneousCadence: Int = 0, diff --git a/profile_rscs/src/main/java/no/nordicsemi/android/rscs/repository/RSCSManager.kt b/profile_rscs/src/main/java/no/nordicsemi/android/rscs/data/RSCSManager.kt similarity index 97% rename from profile_rscs/src/main/java/no/nordicsemi/android/rscs/repository/RSCSManager.kt rename to profile_rscs/src/main/java/no/nordicsemi/android/rscs/data/RSCSManager.kt index 4c0aac5d..6301ab0f 100644 --- a/profile_rscs/src/main/java/no/nordicsemi/android/rscs/repository/RSCSManager.kt +++ b/profile_rscs/src/main/java/no/nordicsemi/android/rscs/data/RSCSManager.kt @@ -19,7 +19,7 @@ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.rscs.repository +package no.nordicsemi.android.rscs.data import android.bluetooth.BluetoothGatt import android.bluetooth.BluetoothGattCharacteristic @@ -94,7 +94,7 @@ internal class RSCSManager internal constructor( gatt.getService(BATTERY_SERVICE_UUID)?.run { batteryLevelCharacteristic = getCharacteristic(BATTERY_LEVEL_CHARACTERISTIC_UUID) } - return rscMeasurementCharacteristic != null && batteryLevelCharacteristic != null + return rscMeasurementCharacteristic != null } override fun onServicesInvalidated() { diff --git a/profile_rscs/src/main/java/no/nordicsemi/android/rscs/data/RSCSServiceCommand.kt b/profile_rscs/src/main/java/no/nordicsemi/android/rscs/data/RSCSServiceCommand.kt deleted file mode 100644 index 87a8636e..00000000 --- a/profile_rscs/src/main/java/no/nordicsemi/android/rscs/data/RSCSServiceCommand.kt +++ /dev/null @@ -1,3 +0,0 @@ -package no.nordicsemi.android.rscs.data - -internal object DisconnectCommand diff --git a/profile_rscs/src/main/java/no/nordicsemi/android/rscs/data/RSCSRepository.kt b/profile_rscs/src/main/java/no/nordicsemi/android/rscs/repository/RSCSRepository.kt similarity index 92% rename from profile_rscs/src/main/java/no/nordicsemi/android/rscs/data/RSCSRepository.kt rename to profile_rscs/src/main/java/no/nordicsemi/android/rscs/repository/RSCSRepository.kt index c668e1d2..21c4ddfd 100644 --- a/profile_rscs/src/main/java/no/nordicsemi/android/rscs/data/RSCSRepository.kt +++ b/profile_rscs/src/main/java/no/nordicsemi/android/rscs/repository/RSCSRepository.kt @@ -1,4 +1,4 @@ -package no.nordicsemi.android.rscs.data +package no.nordicsemi.android.rscs.repository import android.bluetooth.BluetoothDevice import android.content.Context @@ -7,8 +7,8 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch import no.nordicsemi.android.ble.ktx.suspend -import no.nordicsemi.android.rscs.repository.RSCSManager -import no.nordicsemi.android.rscs.repository.RSCSService +import no.nordicsemi.android.rscs.data.RSCSData +import no.nordicsemi.android.rscs.data.RSCSManager import no.nordicsemi.android.service.BleManagerResult import no.nordicsemi.android.service.ConnectingResult import no.nordicsemi.android.service.ServiceManager diff --git a/profile_rscs/src/main/java/no/nordicsemi/android/rscs/repository/RSCSService.kt b/profile_rscs/src/main/java/no/nordicsemi/android/rscs/repository/RSCSService.kt index f2fcb1c5..70007ded 100644 --- a/profile_rscs/src/main/java/no/nordicsemi/android/rscs/repository/RSCSService.kt +++ b/profile_rscs/src/main/java/no/nordicsemi/android/rscs/repository/RSCSService.kt @@ -6,7 +6,6 @@ import androidx.lifecycle.lifecycleScope import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach -import no.nordicsemi.android.rscs.data.RSCSRepository import no.nordicsemi.android.service.DEVICE_DATA import no.nordicsemi.android.service.NotificationService import javax.inject.Inject diff --git a/profile_rscs/src/main/java/no/nordicsemi/android/rscs/view/RSCSContentView.kt b/profile_rscs/src/main/java/no/nordicsemi/android/rscs/view/RSCSContentView.kt index ef1ad788..fc4ee249 100644 --- a/profile_rscs/src/main/java/no/nordicsemi/android/rscs/view/RSCSContentView.kt +++ b/profile_rscs/src/main/java/no/nordicsemi/android/rscs/view/RSCSContentView.kt @@ -26,7 +26,11 @@ internal fun RSCSContentView(state: RSCSData, onEvent: (RSCScreenViewEvent) -> U Spacer(modifier = Modifier.height(16.dp)) - BatteryLevelView(state.batteryLevel) + state.batteryLevel?.let { + BatteryLevelView(it) + + Spacer(modifier = Modifier.height(16.dp)) + } Spacer(modifier = Modifier.height(16.dp)) diff --git a/profile_rscs/src/main/java/no/nordicsemi/android/rscs/viewmodel/RSCSViewModel.kt b/profile_rscs/src/main/java/no/nordicsemi/android/rscs/viewmodel/RSCSViewModel.kt index c4126d80..c6b7a001 100644 --- a/profile_rscs/src/main/java/no/nordicsemi/android/rscs/viewmodel/RSCSViewModel.kt +++ b/profile_rscs/src/main/java/no/nordicsemi/android/rscs/viewmodel/RSCSViewModel.kt @@ -6,8 +6,8 @@ import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch import no.nordicsemi.android.navigation.* -import no.nordicsemi.android.rscs.data.RSCSRepository -import no.nordicsemi.android.rscs.repository.RSCS_SERVICE_UUID +import no.nordicsemi.android.rscs.data.RSCS_SERVICE_UUID +import no.nordicsemi.android.rscs.repository.RSCSRepository import no.nordicsemi.android.rscs.view.* import no.nordicsemi.android.utils.exhaustive import no.nordicsemi.android.utils.getDevice diff --git a/profile_rscs/src/test/java/no/nordicsemi/android/rscs/RSCSViewModelTest.kt b/profile_rscs/src/test/java/no/nordicsemi/android/rscs/RSCSViewModelTest.kt deleted file mode 100644 index 7ec24860..00000000 --- a/profile_rscs/src/test/java/no/nordicsemi/android/rscs/RSCSViewModelTest.kt +++ /dev/null @@ -1,77 +0,0 @@ -package no.nordicsemi.android.rscs - -import io.mockk.every -import io.mockk.justRun -import io.mockk.mockk -import io.mockk.verify -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.channels.BufferOverflow -import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.test.UnconfinedTestDispatcher -import kotlinx.coroutines.test.resetMain -import kotlinx.coroutines.test.setMain -import no.nordicsemi.android.navigation.NavigationManager -import no.nordicsemi.android.rscs.data.RSCSRepository -import no.nordicsemi.android.rscs.view.DisconnectEvent -import no.nordicsemi.android.rscs.viewmodel.RSCSViewModel -import no.nordicsemi.android.service.BleManagerStatus -import no.nordicsemi.android.service.ServiceManager -import org.junit.After -import org.junit.Before -import org.junit.Test - -class RSCSViewModelTest { - - val dispatcher = UnconfinedTestDispatcher() - - @Before - fun setup() { - Dispatchers.setMain(dispatcher) - } - - @After - fun tearDown() { - Dispatchers.resetMain() - } - - @Test - fun `check if navigation up called after disconnect event returns success`() { - val repository = RSCSRepository() - val serviceManager = mockk() - val navigationManager = mockk() - - every { navigationManager.recentResult } returns MutableSharedFlow( - extraBufferCapacity = 1, - onBufferOverflow = BufferOverflow.DROP_OLDEST - ) - justRun { navigationManager.navigateTo(any(), any()) } - - val viewModel = RSCSViewModel(repository, serviceManager, navigationManager) - - viewModel.onEvent(DisconnectEvent) - - //Invoke by remote service - repository.setNewStatus(BleManagerStatus.DISCONNECTED) - - verify { navigationManager.navigateUp() } - } - - @Test - fun `check if navigation up called after disconnect if no service started event returns success`() { - val repository = RSCSRepository() - val serviceManager = mockk() - val navigationManager = mockk() - - every { navigationManager.recentResult } returns MutableSharedFlow( - extraBufferCapacity = 1, - onBufferOverflow = BufferOverflow.DROP_OLDEST - ) - justRun { navigationManager.navigateTo(any(), any()) } - - val viewModel = RSCSViewModel(repository, serviceManager, navigationManager) - - viewModel.onEvent(DisconnectEvent) - - verify { navigationManager.navigateUp() } - } -} \ No newline at end of file diff --git a/profile_uart/src/main/java/no/nordicsemi/android/uart/data/UARTData.kt b/profile_uart/src/main/java/no/nordicsemi/android/uart/data/UARTData.kt index e7b0a0d9..a24fb561 100644 --- a/profile_uart/src/main/java/no/nordicsemi/android/uart/data/UARTData.kt +++ b/profile_uart/src/main/java/no/nordicsemi/android/uart/data/UARTData.kt @@ -4,5 +4,5 @@ import no.nordicsemi.android.utils.EMPTY internal data class UARTData( val text: String = String.EMPTY, - val batteryLevel: Int = 0 + val batteryLevel: Int? = null, ) diff --git a/profile_uart/src/main/java/no/nordicsemi/android/uart/repository/UARTManager.kt b/profile_uart/src/main/java/no/nordicsemi/android/uart/data/UARTManager.kt similarity index 99% rename from profile_uart/src/main/java/no/nordicsemi/android/uart/repository/UARTManager.kt rename to profile_uart/src/main/java/no/nordicsemi/android/uart/data/UARTManager.kt index 685612d7..4af26704 100644 --- a/profile_uart/src/main/java/no/nordicsemi/android/uart/repository/UARTManager.kt +++ b/profile_uart/src/main/java/no/nordicsemi/android/uart/data/UARTManager.kt @@ -19,7 +19,7 @@ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package no.nordicsemi.android.uart.repository +package no.nordicsemi.android.uart.data import android.bluetooth.BluetoothGatt import android.bluetooth.BluetoothGattCharacteristic diff --git a/profile_uart/src/main/java/no/nordicsemi/android/uart/data/UARTServiceCommand.kt b/profile_uart/src/main/java/no/nordicsemi/android/uart/data/UARTServiceCommand.kt deleted file mode 100644 index d7235ede..00000000 --- a/profile_uart/src/main/java/no/nordicsemi/android/uart/data/UARTServiceCommand.kt +++ /dev/null @@ -1,7 +0,0 @@ -package no.nordicsemi.android.uart.data - -internal sealed class UARTServiceCommand - -internal data class SendTextCommand(val command: String) : UARTServiceCommand() - -internal object DisconnectCommand : UARTServiceCommand() diff --git a/profile_uart/src/main/java/no/nordicsemi/android/uart/data/UARTRepository.kt b/profile_uart/src/main/java/no/nordicsemi/android/uart/repository/UARTRepository.kt similarity index 90% rename from profile_uart/src/main/java/no/nordicsemi/android/uart/data/UARTRepository.kt rename to profile_uart/src/main/java/no/nordicsemi/android/uart/repository/UARTRepository.kt index d6bc2aa8..2fb0e80b 100644 --- a/profile_uart/src/main/java/no/nordicsemi/android/uart/data/UARTRepository.kt +++ b/profile_uart/src/main/java/no/nordicsemi/android/uart/repository/UARTRepository.kt @@ -1,4 +1,4 @@ -package no.nordicsemi.android.uart.data +package no.nordicsemi.android.uart.repository import android.bluetooth.BluetoothDevice import android.content.Context @@ -10,8 +10,9 @@ import no.nordicsemi.android.ble.ktx.suspend import no.nordicsemi.android.service.BleManagerResult import no.nordicsemi.android.service.ConnectingResult import no.nordicsemi.android.service.ServiceManager -import no.nordicsemi.android.uart.repository.UARTManager -import no.nordicsemi.android.uart.repository.UARTService +import no.nordicsemi.android.uart.data.UARTData +import no.nordicsemi.android.uart.data.UARTMacro +import no.nordicsemi.android.uart.data.UARTManager import javax.inject.Inject import javax.inject.Singleton diff --git a/profile_uart/src/main/java/no/nordicsemi/android/uart/repository/UARTService.kt b/profile_uart/src/main/java/no/nordicsemi/android/uart/repository/UARTService.kt index 76bc617d..d01a5660 100644 --- a/profile_uart/src/main/java/no/nordicsemi/android/uart/repository/UARTService.kt +++ b/profile_uart/src/main/java/no/nordicsemi/android/uart/repository/UARTService.kt @@ -8,7 +8,6 @@ import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import no.nordicsemi.android.service.DEVICE_DATA import no.nordicsemi.android.service.NotificationService -import no.nordicsemi.android.uart.data.UARTRepository import javax.inject.Inject @AndroidEntryPoint diff --git a/profile_uart/src/main/java/no/nordicsemi/android/uart/viewmodel/UARTViewModel.kt b/profile_uart/src/main/java/no/nordicsemi/android/uart/viewmodel/UARTViewModel.kt index 101784c1..db994bcf 100644 --- a/profile_uart/src/main/java/no/nordicsemi/android/uart/viewmodel/UARTViewModel.kt +++ b/profile_uart/src/main/java/no/nordicsemi/android/uart/viewmodel/UARTViewModel.kt @@ -7,8 +7,8 @@ import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch import no.nordicsemi.android.navigation.* import no.nordicsemi.android.uart.data.UARTMacro -import no.nordicsemi.android.uart.data.UARTRepository -import no.nordicsemi.android.uart.repository.UART_SERVICE_UUID +import no.nordicsemi.android.uart.data.UART_SERVICE_UUID +import no.nordicsemi.android.uart.repository.UARTRepository import no.nordicsemi.android.uart.view.* import no.nordicsemi.android.utils.exhaustive import no.nordicsemi.android.utils.getDevice diff --git a/profile_uart/src/test/java/no/nordicsemi/android/gls/UARTViewModelTest.kt b/profile_uart/src/test/java/no/nordicsemi/android/gls/UARTViewModelTest.kt deleted file mode 100644 index 1d49f19a..00000000 --- a/profile_uart/src/test/java/no/nordicsemi/android/gls/UARTViewModelTest.kt +++ /dev/null @@ -1,77 +0,0 @@ -package no.nordicsemi.android.gls - -import io.mockk.every -import io.mockk.justRun -import io.mockk.mockk -import io.mockk.verify -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.channels.BufferOverflow -import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.test.UnconfinedTestDispatcher -import kotlinx.coroutines.test.resetMain -import kotlinx.coroutines.test.setMain -import no.nordicsemi.android.navigation.NavigationManager -import no.nordicsemi.android.service.BleManagerStatus -import no.nordicsemi.android.service.ServiceManager -import no.nordicsemi.android.uart.data.UARTRepository -import no.nordicsemi.android.uart.view.OnDisconnectButtonClick -import no.nordicsemi.android.uart.viewmodel.UARTViewModel -import org.junit.After -import org.junit.Before -import org.junit.Test - -class UARTViewModelTest { - - val dispatcher = UnconfinedTestDispatcher() - - @Before - fun setup() { - Dispatchers.setMain(dispatcher) - } - - @After - fun tearDown() { - Dispatchers.resetMain() - } - - @Test - fun `check if navigation up called after disconnect event returns success`() { - val repository = UARTRepository() - val serviceManager = mockk() - val navigationManager = mockk() - - every { navigationManager.recentResult } returns MutableSharedFlow( - extraBufferCapacity = 1, - onBufferOverflow = BufferOverflow.DROP_OLDEST - ) - justRun { navigationManager.navigateTo(any(), any()) } - - val viewModel = UARTViewModel(repository, serviceManager, navigationManager) - - viewModel.onEvent(OnDisconnectButtonClick) - - //Invoke by remote service - repository.setNewStatus(BleManagerStatus.DISCONNECTED) - - verify { navigationManager.navigateUp() } - } - - @Test - fun `check if navigation up called after disconnect if no service started event returns success`() { - val repository = UARTRepository() - val serviceManager = mockk() - val navigationManager = mockk() - - every { navigationManager.recentResult } returns MutableSharedFlow( - extraBufferCapacity = 1, - onBufferOverflow = BufferOverflow.DROP_OLDEST - ) - justRun { navigationManager.navigateTo(any(), any()) } - - val viewModel = UARTViewModel(repository, serviceManager, navigationManager) - - viewModel.onEvent(OnDisconnectButtonClick) - - verify { navigationManager.navigateUp() } - } -} diff --git a/settings.gradle b/settings.gradle index 6ca60227..cf0bcbc4 100644 --- a/settings.gradle +++ b/settings.gradle @@ -27,38 +27,37 @@ dependencyResolutionManagement { alias('nordic-theme').to('no.nordicsemi.android.common', 'theme').versionRef('commonlibraries') alias('localbroadcastmanager').to('androidx.localbroadcastmanager:localbroadcastmanager:1.1.0') - alias('material').to('com.google.android.material:material:1.6.0-alpha01') + alias('material').to('com.google.android.material:material:1.6.0-alpha02') - version('lifecycle', '2.4.0') + version('lifecycle', '2.4.1') alias('lifecycle-activity').to('androidx.lifecycle', 'lifecycle-runtime-ktx').versionRef('lifecycle') alias('lifecycle-service').to('androidx.lifecycle', 'lifecycle-service').versionRef('lifecycle') + alias('compose-lifecycle').to('androidx.lifecycle', 'lifecycle-viewmodel-compose').versionRef('lifecycle') alias('androidx-core').to('androidx.core:core-ktx:1.7.0') alias('compose-activity').to('androidx.activity:activity-compose:1.4.0') - alias('compose-lifecycle').to('androidx.lifecycle:lifecycle-viewmodel-compose:2.4.0') version('compose', '1.1.0') - alias('compose-livedata').to('androidx.compose.runtime', 'runtime-livedata').versionRef('compose') alias('compose-ui').to('androidx.compose.ui', 'ui').versionRef('compose') - alias('compose-material').to('androidx.compose.material3:material3:1.0.0-alpha04') + alias('compose-material').to('androidx.compose.material3:material3:1.0.0-alpha05') alias('compose-tooling-preview').to('androidx.compose.ui', 'ui-tooling-preview').versionRef('compose') - alias('compose-navigation').to('androidx.navigation:navigation-compose:2.4.0-alpha09') - bundle('compose', ['compose-livedata', 'compose-ui', 'compose-material', 'compose-tooling-preview', 'compose-navigation']) + alias('compose-navigation').to('androidx.navigation:navigation-compose:2.4.1') + bundle('compose', ['compose-ui', 'compose-material', 'compose-tooling-preview', 'compose-navigation']) alias('material-icons').to('androidx.compose.material', 'material-icons-core').versionRef('compose') alias('material-icons-extended').to('androidx.compose.material', 'material-icons-extended').versionRef('compose') bundle('icons', ['material-icons', 'material-icons-extended']) - alias('hilt-android').to('com.google.dagger:hilt-android:2.38.1') + alias('hilt-android').to('com.google.dagger:hilt-android:2.40.4') alias('hilt-compiler').to('com.google.dagger:hilt-compiler:2.40.4') - alias('hilt-compose').to('androidx.hilt:hilt-navigation-compose:1.0.0-rc01') + alias('hilt-compose').to('androidx.hilt:hilt-navigation-compose:1.0.0') alias('hilt-lifecycle').to('androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha03') alias('hilt-lifecyclecompiler').to('androidx.hilt:hilt-compiler:1.0.0') bundle('hilt', ['hilt-android', 'hilt-compose', 'hilt-lifecycle']) bundle('hiltkapt', ['hilt-compiler', 'hilt-lifecyclecompiler']) - alias('kotlin-coroutines').to('org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2') - alias('google-permissions').to('com.google.accompanist:accompanist-permissions:0.18.0') + alias('kotlin-coroutines').to('org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0') + alias('google-permissions').to('com.google.accompanist:accompanist-permissions:0.20.0') alias('chart').to('com.github.PhilJay:MPAndroidChart:v3.1.0') //-- Test ------------------------------------------------------------------------------