Skip to content

Commit b4b9e32

Browse files
committed
just goto version to
1 parent c48e3af commit b4b9e32

File tree

9 files changed

+438
-17
lines changed

9 files changed

+438
-17
lines changed

features/bluetooth/src/main/java/com/jerry/blescanner/features/bluetooth/data/mapper/BleDeviceServiceMapper.kt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,20 @@ import com.jerry.blescanner.features.bluetooth.domain.BleDeviceCharacteristic
1010
import com.jerry.blescanner.features.bluetooth.domain.BleDeviceDescriptor
1111
import com.jerry.blescanner.features.bluetooth.domain.BleDeviceService
1212

13+
/*
14+
BluetoothGattService(藍牙 GATT 服務):它代表著藍牙裝置中的一個服務。服務是藍牙設備上的一個功能單元,通常包含一個或多個特徵(BluetoothGattCharacteristic)。服務可以提供設備的不同功能,例如心率監測、電池狀態等等。每個服務都有一個唯一的識別符號(UUID)來區分不同的服務。
15+
16+
BluetoothGattCharacteristic(藍牙 GATT 特徵):它代表著藍牙裝置服務中的一個特徵。特徵是服務的一個特定功能,例如傳感器數據、設備配置等。特徵可以包含數據值,並且可以進行讀取和寫入操作。每個特徵也有一個唯一的 UUID 來識別它。
17+
18+
BluetoothGattDescriptor(藍牙 GATT 描述符):它代表著藍牙特徵中的一個描述符。描述符提供了特徵的額外信息,例如特徵的配置設置、單位、格式等。描述符通常用於特徵的讀取和寫入操作之外的其他操作。
19+
*/
20+
/*
21+
BluetoothGattService 代表一個 BLE 服務,它可以提供一個或多個特性。服務通常用於表示一個功能或設備的組件。例如,一個心率監測器可能會有一個名為 "Heart Rate" 的服務,它可以提供一個名為 "Heart Rate Measurement" 的特性。
22+
23+
BluetoothGattCharacteristic 代表一個 BLE 特性,它可以用來存儲數據或提供一個功能。特性通常用於表示一個設備的狀態或配置。例如,一個心率監測器可能會有一個名為 "Heart Rate Measurement" 的特性,它可以用來存儲心率數據。
24+
25+
BluetoothGattDescriptor 代表一個 BLE 描述符,它可以用來提供有關特性的附加信息。描述符通常用於配置特性的行為或提供有關特性的額外信息。例如,一個心率監測器可能會有一個名為 "Client Characteristic Configuration" 的描述符,它可以用來配置客戶端是否可以讀取或寫入特性。
26+
*/
1327
fun BluetoothGattService.toBleDeviceService(): BleDeviceService {
1428
return BleDeviceService(
1529
uuid = uuid,
@@ -20,6 +34,7 @@ fun BluetoothGattService.toBleDeviceService(): BleDeviceService {
2034
}
2135

2236
fun BluetoothGattCharacteristic.toBleDeviceCharacteristic(): BleDeviceCharacteristic {
37+
val aaa = this.value
2338
return BleDeviceCharacteristic(
2439
uuid = uuid,
2540
name = AllGattCharacteristics.lookup(uuid),

features/bluetooth/src/main/java/com/jerry/blescanner/features/bluetooth/domain/BleConnectManager.kt

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,41 @@ import android.bluetooth.BluetoothAdapter
55
import android.bluetooth.BluetoothDevice.TRANSPORT_LE
66
import android.bluetooth.BluetoothGatt
77
import android.bluetooth.BluetoothGattCallback
8+
import android.bluetooth.BluetoothGattCharacteristic
89
import android.bluetooth.BluetoothProfile
910
import android.content.Context
10-
import androidx.compose.runtime.MutableIntState
11-
import com.jerry.blescanner.basemodule.presentation.UiDataState
11+
import android.util.Log
1212
import com.jerry.blescanner.features.bluetooth.data.mapper.toBleDeviceService
1313
import kotlinx.coroutines.flow.MutableStateFlow
1414
import kotlinx.coroutines.flow.StateFlow
1515
import kotlinx.coroutines.flow.asStateFlow
1616
import timber.log.Timber
1717
import javax.inject.Inject
1818

19+
1920
//https://medium.com/@martijn.van.welie/making-android-ble-work-part-2-47a3cdaade07
21+
22+
// for getValue was @Deprecated in BluetoothGattCharacteristic
2023
//https://stackoverflow.com/questions/25330938/android-bluetoothgatt-status-133-register-callback
24+
25+
26+
//example got the value from BLE
27+
/*
28+
1
29+
如果要接受 Bluetooth device 的 byebalue,您應該從 BluetoothGattCharacteristic 來取得。BluetoothGattCharacteristic 是用來存儲數據的,而 BluetoothGattService 和 BluetoothGattDescriptor 都是 GATT 模型的組成部分,不直接存儲數據。
30+
31+
具體來說,您可以使用 BluetoothGattCharacteristic 的 getValue() 方法來取得它的值。該方法返回一個 byte[] 數組,其中包含特徵的值。您可以使用該數組來解析數據。
32+
33+
例如,如果您要取得心率監測器的當前心率,您可以使用以下代碼:
34+
35+
BluetoothGattCharacteristic characteristic = service.getCharacteristic(UUID.fromString("00002a37-0000-1000-8000-00805f9b34fb"));
36+
37+
int heartRate = characteristic.getValue()[0];
38+
39+
這段代碼會取得心率監測器的 GATT 服務中的 00002a37-0000-1000-8000-00805f9b34fb 特徵。該特徵用來存儲當前心率。代碼會使用 getValue() 方法來取得特徵的值,並將其存儲在 heartRate 變量中。
40+
*/
41+
//https://github.com/marcolivierarsenault/PolarHeartRateApplication/blob/master/app/src/main/java/org/marco45/polarheartmonitor/H7ConnectThread.java
42+
2143
@SuppressLint("MissingPermission")
2244
class BleConnectManager @Inject constructor(
2345
private val bluetoothAdapter: BluetoothAdapter,
@@ -59,6 +81,19 @@ class BleConnectManager @Inject constructor(
5981

6082
}
6183

84+
override fun onCharacteristicRead(
85+
gatt: BluetoothGatt?,
86+
characteristic: BluetoothGattCharacteristic,
87+
status: Int
88+
) {
89+
if (status == BluetoothGatt.GATT_SUCCESS) {
90+
}
91+
92+
val value = characteristic.value
93+
Timber.d("onCharacteristicRead::status: $value")
94+
}
95+
96+
6297
override fun onServicesDiscovered(gatt: BluetoothGatt?, status: Int) {
6398
super.onServicesDiscovered(gatt, status)
6499

features/bluetooth/src/main/java/com/jerry/blescanner/features/bluetooth/domain/BleDeviceService.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,21 @@ import android.bluetooth.BluetoothGattService
66
import java.util.UUID
77

88
data class BleDeviceService(
9-
val service: BluetoothGattService,
9+
val service: BluetoothGattService? = null,
1010
val uuid: UUID,
1111
val name: String,
1212
val characteristics: List<BleDeviceCharacteristic>
1313
)
1414

1515
data class BleDeviceCharacteristic(
16-
val characteristic: BluetoothGattCharacteristic,
16+
val characteristic: BluetoothGattCharacteristic? = null,
1717
val uuid:UUID,
1818
val name: String,
1919
val bleDeviceDescriptors: List<BleDeviceDescriptor>
2020
)
2121

2222
data class BleDeviceDescriptor(
23-
val descriptor: BluetoothGattDescriptor,
23+
val descriptor: BluetoothGattDescriptor? = null,
2424
val uuid:UUID,
2525
val name: String
2626
)

features/bluetooth/src/main/java/com/jerry/blescanner/features/bluetooth/presentation/BluetoothActivity.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import androidx.navigation.compose.NavHost
2626
import androidx.navigation.compose.composable
2727
import androidx.navigation.compose.rememberNavController
2828
import androidx.navigation.navArgument
29-
import com.jerry.blescanner.features.bluetooth.presentation.components.BleConnectPage
29+
import com.jerry.blescanner.features.bluetooth.presentation.components.connect.BleConnectPage
3030
import com.jerry.blescanner.features.bluetooth.presentation.components.BleScanPage
3131
import com.jerry.blescanner.features.bluetooth.presentation.mvi.BluetoothPageIntent
3232
import com.jerry.blescanner.features.bluetooth.presentation.viewmodel.BluetoothConnectViewModel
@@ -36,7 +36,6 @@ import com.jerry.blescanner.features.bluetooth.utils.BluetoothStopSource
3636
import com.jerry.blescanner.jetpack_design_lib.theme.MyTheme
3737
import com.polidea.rxandroidble3.RxBleClient
3838
import dagger.hilt.android.AndroidEntryPoint
39-
import io.reactivex.rxjava3.disposables.Disposable
4039
import timber.log.Timber
4140
import javax.inject.Inject
4241

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,26 @@
1-
package com.jerry.blescanner.features.bluetooth.presentation.components
1+
package com.jerry.blescanner.features.bluetooth.presentation.components.connect
22

3+
4+
import androidx.compose.foundation.ExperimentalFoundationApi
35
import androidx.compose.foundation.layout.Column
46
import androidx.compose.foundation.layout.fillMaxSize
7+
58
import androidx.compose.foundation.lazy.LazyColumn
69
import androidx.compose.foundation.lazy.items
10+
711
import androidx.compose.material3.Text
812
import androidx.compose.runtime.Composable
913
import androidx.compose.runtime.DisposableEffect
1014
import androidx.compose.runtime.LaunchedEffect
15+
1116
import androidx.compose.ui.Modifier
17+
1218
import androidx.lifecycle.compose.collectAsStateWithLifecycle
13-
import androidx.lifecycle.viewmodel.compose.viewModel
14-
import com.jerry.blescanner.basemodule.presentation.UiDataState
1519
import com.jerry.blescanner.features.bluetooth.domain.BleDeviceService
1620
import com.jerry.blescanner.features.bluetooth.presentation.viewmodel.BluetoothConnectViewModel
1721
import com.jerry.blescanner.jetpack_design_lib.common.loading.CommonLoading
1822

23+
@OptIn(ExperimentalFoundationApi::class)
1924
@Composable
2025
fun BleConnectPage(
2126
address: String,
@@ -47,27 +52,25 @@ fun BleConnectPage(
4752

4853
//UI
4954
if (serviceListState.value?.isNotEmpty() == true){
50-
51-
LazyColumn(modifier = Modifier.fillMaxSize()) {
52-
items(serviceListState.value!!){
53-
ServiceItem(bleDeviceService = it)
54-
}
55-
}
56-
55+
BleConnectServiceViewPager(
56+
serviceListState = serviceListState
57+
)
5758
}
5859
else {
5960
CommonLoading()
6061
}
6162
}
6263
}
6364

65+
6466
@Composable
6567
fun ServiceItem(
6668
bleDeviceService: BleDeviceService
6769
) {
6870
Column {
6971
Text(text = "Service: ${bleDeviceService.name} (${bleDeviceService.uuid}" )
7072
}
73+
7174
bleDeviceService.characteristics.forEach { char->
7275
Column {
7376
Text(text = " Characteristic: ${char.name} (${char.uuid}" )
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package com.jerry.blescanner.features.bluetooth.presentation.components.connect
2+
3+
import android.annotation.SuppressLint
4+
import androidx.compose.foundation.ExperimentalFoundationApi
5+
import androidx.compose.foundation.layout.Column
6+
import androidx.compose.foundation.layout.Spacer
7+
import androidx.compose.foundation.layout.fillMaxWidth
8+
import androidx.compose.foundation.layout.height
9+
import androidx.compose.foundation.layout.padding
10+
import androidx.compose.foundation.pager.HorizontalPager
11+
import androidx.compose.foundation.pager.rememberPagerState
12+
import androidx.compose.material3.MaterialTheme
13+
import androidx.compose.runtime.Composable
14+
import androidx.compose.runtime.State
15+
import androidx.compose.runtime.mutableStateOf
16+
import androidx.compose.ui.Modifier
17+
import androidx.compose.ui.tooling.preview.Preview
18+
import androidx.compose.ui.unit.dp
19+
import com.jerry.blescanner.features.bluetooth.domain.BleDeviceCharacteristic
20+
import com.jerry.blescanner.features.bluetooth.domain.BleDeviceDescriptor
21+
import com.jerry.blescanner.features.bluetooth.domain.BleDeviceService
22+
import com.jerry.blescanner.jetpack_design_lib.common.indicator.DotsIndicator
23+
import com.jerry.blescanner.jetpack_design_lib.theme.MyTheme
24+
import java.util.UUID
25+
26+
@OptIn(ExperimentalFoundationApi::class)
27+
@Composable
28+
fun BleConnectServiceViewPager(
29+
serviceListState: State<List<BleDeviceService>?>
30+
) {
31+
serviceListState.value?.let {
32+
val pageCount = it.size
33+
val pagerState = rememberPagerState { pageCount }
34+
35+
Column(
36+
modifier = Modifier.fillMaxWidth()
37+
) {
38+
HorizontalPager(state = pagerState) {
39+
BleConnectTable(
40+
bleDeviceService = serviceListState.value!![it]
41+
)
42+
}
43+
44+
Spacer(modifier = Modifier.height(10.dp))
45+
46+
DotsIndicator(
47+
totalDots = pageCount,
48+
selectedIndex = pagerState.currentPage,
49+
selectedColor = MaterialTheme.colorScheme.onSurfaceVariant,
50+
unSelectedColor = MaterialTheme.colorScheme.surfaceVariant
51+
)
52+
53+
}
54+
55+
56+
}
57+
}
58+
59+
@SuppressLint("UnrememberedMutableState")
60+
@Preview(showBackground = true)
61+
@Composable
62+
private fun BleConnectServiceViewPagerPreview() {
63+
val listState = mutableStateOf<List<BleDeviceService>?>(null)
64+
65+
listState.value = listOf(
66+
BleDeviceService(
67+
name = "this is name",
68+
uuid = UUID.fromString("this is UUID"),
69+
characteristics = listOf(
70+
BleDeviceCharacteristic(
71+
name = "this is char 1",
72+
uuid = UUID.fromString("this is char UUID 1"),
73+
bleDeviceDescriptors = listOf(
74+
BleDeviceDescriptor(
75+
name = "this is desc 1",
76+
uuid = UUID.fromString("this is desc UUID 1"),
77+
)
78+
)
79+
)
80+
)
81+
)
82+
)
83+
MyTheme {
84+
BleConnectServiceViewPager(
85+
serviceListState = listState
86+
)
87+
}
88+
89+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package com.jerry.blescanner.features.bluetooth.presentation.components.connect
2+
3+
import androidx.compose.foundation.background
4+
import androidx.compose.foundation.border
5+
import androidx.compose.foundation.layout.Arrangement
6+
import androidx.compose.foundation.layout.Box
7+
import androidx.compose.foundation.layout.Column
8+
import androidx.compose.foundation.layout.Row
9+
import androidx.compose.foundation.layout.Spacer
10+
import androidx.compose.foundation.layout.fillMaxSize
11+
import androidx.compose.foundation.layout.fillMaxWidth
12+
import androidx.compose.foundation.layout.height
13+
import androidx.compose.foundation.layout.padding
14+
import androidx.compose.material3.MaterialTheme
15+
import androidx.compose.material3.OutlinedButton
16+
import androidx.compose.material3.OutlinedCard
17+
import androidx.compose.material3.Text
18+
import androidx.compose.runtime.Composable
19+
import androidx.compose.ui.Alignment
20+
import androidx.compose.ui.Modifier
21+
import androidx.compose.ui.unit.dp
22+
import com.jerry.blescanner.features.bluetooth.domain.BleDeviceService
23+
24+
@Composable
25+
fun BleConnectTable(
26+
bleDeviceService : BleDeviceService
27+
) {
28+
Column(
29+
modifier = Modifier
30+
.fillMaxSize()
31+
.border(1.dp, MaterialTheme.colorScheme.onBackground)
32+
) {
33+
//title
34+
Column(
35+
modifier = Modifier
36+
.fillMaxWidth()
37+
.background(color = MaterialTheme.colorScheme.primary)
38+
.padding(5.dp),
39+
verticalArrangement = Arrangement.Center,
40+
horizontalAlignment = Alignment.CenterHorizontally
41+
) {
42+
Text(
43+
text = bleDeviceService.name,
44+
color = MaterialTheme.colorScheme.onPrimary
45+
)
46+
Text(
47+
text = bleDeviceService.uuid.toString(),
48+
color = MaterialTheme.colorScheme.onPrimary
49+
)
50+
}
51+
52+
Column(
53+
modifier = Modifier.padding(10.dp)
54+
) {
55+
bleDeviceService.characteristics.forEachIndexed { index, char->
56+
57+
ExpandableCharacteristicCard(
58+
bleDeviceCharacteristic = char
59+
)
60+
Spacer(modifier = Modifier.height(10.dp))
61+
62+
}
63+
}
64+
65+
}
66+
67+
68+
}

0 commit comments

Comments
 (0)