From a5e72cc5e0764ce567f2a8b60931f67be64c95b5 Mon Sep 17 00:00:00 2001 From: eldcn Date: Sun, 8 Dec 2024 23:24:27 +0100 Subject: [PATCH] Bluetooth device connections (#147) # *Bluetooth device connections* ## :recycle: Current situation & Problem - Fixes last connected (seen) timestamp to be formatted to current time zone - Fixes double paring request. I was able to reproduce the issue and from different stack overflow posts it seems to be an android bug. This [suggestion](https://github.com/PhilipsHue/flutter_reactive_ble/issues/507#issuecomment-1108254857) to create the bond request manually before connecting seems to work. ## :gear: Release Notes *Add a bullet point list summary of the feature and possible migration guides if this is a breaking change so this section can be added to the release notes.* *Include code snippets that provide examples of the feature implemented or links to the documentation if it appends or changes the public interface.* ## :books: Documentation *Please ensure that you properly document any additions in conformance to [Spezi Documentation Guide](https://github.com/StanfordSpezi/.github/blob/main/DOCUMENTATIONGUIDE.md).* *You can use this section to describe your solution, but we encourage contributors to document your reasoning and changes using in-line documentation.* ## :white_check_mark: Testing *Please ensure that the PR meets the testing requirements set by CodeCov and that new functionality is appropriately tested.* *This section describes important information about the tests and why some elements might not be testable.* ## :pencil: Code of Conduct & Contributing Guidelines By submitting creating this pull request, you agree to follow our [Code of Conduct](https://github.com/StanfordSpezi/.github/blob/main/CODE_OF_CONDUCT.md) and [Contributing Guidelines](https://github.com/StanfordSpezi/.github/blob/main/CONTRIBUTING.md): - [ ] I agree to follow the [Code of Conduct](https://github.com/StanfordSpezi/.github/blob/main/CODE_OF_CONDUCT.md) and [Contributing Guidelines](https://github.com/StanfordSpezi/.github/blob/main/CONTRIBUTING.md). --------- Co-authored-by: Paul Schmiedmayer --- .../bluetooth/data/mapper/BluetoothUiStateMapper.kt | 6 +++++- .../spezi/core/bluetooth/domain/BLEDeviceConnector.kt | 1 + .../spezi/core/bluetooth/domain/BLEDeviceConnectorTest.kt | 2 ++ .../kotlin/edu/stanford/spezi/core/utils/TimeProvider.kt | 3 ++- .../edu/stanford/spezi/core/utils/TimeProviderTest.kt | 5 +++-- 5 files changed, 13 insertions(+), 4 deletions(-) diff --git a/app/src/main/kotlin/edu/stanford/bdh/engagehf/bluetooth/data/mapper/BluetoothUiStateMapper.kt b/app/src/main/kotlin/edu/stanford/bdh/engagehf/bluetooth/data/mapper/BluetoothUiStateMapper.kt index 62697a3ce..e4ba233c1 100644 --- a/app/src/main/kotlin/edu/stanford/bdh/engagehf/bluetooth/data/mapper/BluetoothUiStateMapper.kt +++ b/app/src/main/kotlin/edu/stanford/bdh/engagehf/bluetooth/data/mapper/BluetoothUiStateMapper.kt @@ -33,6 +33,10 @@ class BluetoothUiStateMapper @Inject constructor( ) } + private val systemDefaultDateFormatter by lazy { + dateFormatter.withZone(ZoneId.systemDefault()) + } + fun mapBleServiceState(state: EngageBLEServiceState): BluetoothUiState { return when (state) { EngageBLEServiceState.Idle -> { @@ -81,7 +85,7 @@ class BluetoothUiStateMapper @Inject constructor( name = it.device.name, summary = summary, connected = it.device.connected, - lastSeen = StringResource(R.string.last_seen_on, dateFormatter.format(time)) + lastSeen = StringResource(R.string.last_seen_on, systemDefaultDateFormatter.format(time)) ) } val header = if (devices.isEmpty()) { diff --git a/core/bluetooth/src/main/kotlin/edu/stanford/spezi/core/bluetooth/domain/BLEDeviceConnector.kt b/core/bluetooth/src/main/kotlin/edu/stanford/spezi/core/bluetooth/domain/BLEDeviceConnector.kt index 8239845ad..d5a84138c 100644 --- a/core/bluetooth/src/main/kotlin/edu/stanford/spezi/core/bluetooth/domain/BLEDeviceConnector.kt +++ b/core/bluetooth/src/main/kotlin/edu/stanford/spezi/core/bluetooth/domain/BLEDeviceConnector.kt @@ -95,6 +95,7 @@ internal class BLEDeviceConnector @AssistedInject constructor( fun connect() { val currentGatt = bluetoothGatt if (currentGatt != null || isDestroyed.get()) return + device.createBond() bluetoothGatt = device.connectGatt(context, false, gattCallback) } diff --git a/core/bluetooth/src/test/kotlin/edu/stanford/spezi/core/bluetooth/domain/BLEDeviceConnectorTest.kt b/core/bluetooth/src/test/kotlin/edu/stanford/spezi/core/bluetooth/domain/BLEDeviceConnectorTest.kt index de4fd0d55..0a2d43042 100644 --- a/core/bluetooth/src/test/kotlin/edu/stanford/spezi/core/bluetooth/domain/BLEDeviceConnectorTest.kt +++ b/core/bluetooth/src/test/kotlin/edu/stanford/spezi/core/bluetooth/domain/BLEDeviceConnectorTest.kt @@ -46,6 +46,7 @@ class BLEDeviceConnectorTest { @Before fun setup() { + every { device.createBond() } returns true every { device.connectGatt(context, false, any()) } returns bluetoothGatt every { bluetoothGatt.disconnect() } just Runs } @@ -59,6 +60,7 @@ class BLEDeviceConnectorTest { repeat(10) { sut.connect() } // then + verify(exactly = 1) { device.createBond() } verify(exactly = 1) { device.connectGatt(context, false, any()) } } diff --git a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/TimeProvider.kt b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/TimeProvider.kt index 04d3e405d..200977991 100644 --- a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/TimeProvider.kt +++ b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/TimeProvider.kt @@ -1,7 +1,8 @@ package edu.stanford.spezi.core.utils +import java.time.Instant import javax.inject.Inject class TimeProvider @Inject constructor() { - fun currentTimeMillis(): Long = System.currentTimeMillis() + fun currentTimeMillis(): Long = Instant.now().toEpochMilli() } diff --git a/core/utils/src/test/kotlin/edu/stanford/spezi/core/utils/TimeProviderTest.kt b/core/utils/src/test/kotlin/edu/stanford/spezi/core/utils/TimeProviderTest.kt index 9edd46ddd..a7a8eedb1 100644 --- a/core/utils/src/test/kotlin/edu/stanford/spezi/core/utils/TimeProviderTest.kt +++ b/core/utils/src/test/kotlin/edu/stanford/spezi/core/utils/TimeProviderTest.kt @@ -2,14 +2,15 @@ package edu.stanford.spezi.core.utils import com.google.common.truth.Truth.assertThat import org.junit.Test +import java.time.Instant class TimeProviderTest { private val provider = TimeProvider() @Test - fun `it should indicate system currentTimeMillis`() { + fun `it should indicate now instant epoch millis`() { // given - val current = System.currentTimeMillis() + val current = Instant.now().toEpochMilli() val threshold = 1000L // when