kotlin ble migration
This commit is contained in:
parent
a059cacda9
commit
f65023b4c7
|
|
@ -11,8 +11,6 @@ import kotlinx.coroutines.launch
|
|||
import llc.arma.ble.app.ui.common.BaseViewModel
|
||||
import llc.arma.ble.domain.usecase.ExportToXlsx
|
||||
import llc.arma.ble.domain.usecase.GetBleAroundFlow
|
||||
import llc.arma.ble.domain.usecase.GetConnectedBleDevices
|
||||
import llc.arma.ble.domain.usecase.MeasureData
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
|
|
|
|||
|
|
@ -1,26 +1,17 @@
|
|||
package llc.arma.ble.data
|
||||
|
||||
import android.Manifest
|
||||
import android.app.Application
|
||||
import android.bluetooth.*
|
||||
import android.bluetooth.le.ScanCallback
|
||||
import android.bluetooth.le.ScanResult
|
||||
import android.bluetooth.le.ScanSettings
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Build
|
||||
import android.os.SystemClock
|
||||
import android.util.Log
|
||||
import androidx.core.app.ActivityCompat
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.channels.awaitClose
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.callbackFlow
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import llc.arma.ble.domain.Result
|
||||
import llc.arma.ble.domain.common.BleException
|
||||
import llc.arma.ble.domain.common.ProgressState
|
||||
|
|
@ -37,22 +28,13 @@ import llc.arma.ble.domain.usecase.FftFrequency
|
|||
import llc.arma.ble.domain.usecase.FftViewMode
|
||||
import no.nordicsemi.android.common.core.DataByteArray
|
||||
import no.nordicsemi.android.kotlin.ble.client.main.callback.ClientBleGatt
|
||||
import no.nordicsemi.android.kotlin.ble.core.scanner.BleNumOfMatches
|
||||
import no.nordicsemi.android.kotlin.ble.core.scanner.BleScanMode
|
||||
import no.nordicsemi.android.kotlin.ble.core.scanner.BleScanResult
|
||||
import no.nordicsemi.android.kotlin.ble.core.scanner.BleScannerCallbackType
|
||||
import no.nordicsemi.android.kotlin.ble.core.scanner.BleScannerMatchMode
|
||||
import no.nordicsemi.android.kotlin.ble.core.scanner.BleScannerSettings
|
||||
import no.nordicsemi.android.kotlin.ble.scanner.BleScanner
|
||||
import no.nordicsemi.android.kotlin.ble.scanner.aggregator.BleScanResultAggregator
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
import kotlin.coroutines.resume
|
||||
import kotlin.math.PI
|
||||
import kotlin.math.atan
|
||||
import kotlin.math.pow
|
||||
import kotlin.math.sqrt
|
||||
|
||||
|
||||
val FftFrequency.sendData: Byte
|
||||
|
|
@ -728,6 +710,8 @@ class BleRepositoryImpl @Inject constructor(
|
|||
frequency: FftFrequency
|
||||
): Flow<Result<ProgressState<List<Ble.Accelerometer.MeasurePoint>>, BleException>> {
|
||||
|
||||
//return readAccelerometerSpectre(serial, app, accelScale, accelMode, fftAxis, fftMode, frequency)
|
||||
|
||||
var gatt: BluetoothGatt? = null
|
||||
|
||||
return callbackFlow {
|
||||
|
|
@ -769,7 +753,9 @@ class BleRepositoryImpl @Inject constructor(
|
|||
serial: String
|
||||
): Flow<Result<ProgressState<List<Ble.Thermometer.MeasurePoint>>, BleException>> {
|
||||
|
||||
var gatt: BluetoothGatt? = null
|
||||
return readThermometerHistory(serial, app)
|
||||
|
||||
/*var gatt: BluetoothGatt? = null
|
||||
|
||||
return callbackFlow {
|
||||
|
||||
|
|
@ -799,7 +785,7 @@ class BleRepositoryImpl @Inject constructor(
|
|||
gatt?.close()
|
||||
}
|
||||
|
||||
}
|
||||
}*/
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -1199,15 +1185,15 @@ class BleRepositoryImpl @Inject constructor(
|
|||
|
||||
when(accelMode){
|
||||
ANGLE -> {
|
||||
x = calculateZAngle(
|
||||
x = calculateAngle(
|
||||
data[2].toFloat(),
|
||||
data[1].toFloat()
|
||||
) * 180f / Math.PI.toFloat()
|
||||
y = calculateZAngle(
|
||||
y = calculateAngle(
|
||||
data[2].toFloat(),
|
||||
data[0].toFloat()
|
||||
) * 180f / Math.PI.toFloat()
|
||||
z = calculateZAngle(
|
||||
z = calculateAngle(
|
||||
data[0].toFloat(),
|
||||
data[1].toFloat()
|
||||
) * 180f / Math.PI.toFloat()
|
||||
|
|
@ -1287,16 +1273,6 @@ class BleRepositoryImpl @Inject constructor(
|
|||
}
|
||||
|
||||
fun calculateAngle(
|
||||
targetAxis: Float,
|
||||
firstAxis: Float,
|
||||
secondAxis: Float
|
||||
): Float {
|
||||
|
||||
return atan(targetAxis.div(sqrt(firstAxis.pow(2) + secondAxis.pow(2))))
|
||||
|
||||
}
|
||||
|
||||
public fun calculateZAngle(
|
||||
x: Float,
|
||||
y: Float
|
||||
): Float {
|
||||
|
|
|
|||
|
|
@ -170,15 +170,15 @@ fun readAccelerometerHistory(
|
|||
resultTemperaturePackage.chunked(3).withIndex().map {
|
||||
Ble.Accelerometer.HistoryPoint.Angle(
|
||||
date = lastMeasureSystemTime!! - (((resultTemperaturePackage.size - 1) - it.index) * bleMeasureInterval!!),
|
||||
x = calculateZAngle(
|
||||
x = calculateAngle(
|
||||
it.value[2],
|
||||
it.value[1]
|
||||
) * 180f / Math.PI.toFloat(),
|
||||
y = calculateZAngle(
|
||||
y = calculateAngle(
|
||||
it.value[2],
|
||||
it.value[0]
|
||||
) * 180f / Math.PI.toFloat(),
|
||||
z = calculateZAngle(
|
||||
z = calculateAngle(
|
||||
it.value[0],
|
||||
it.value[1]
|
||||
) * 180f / Math.PI.toFloat()
|
||||
|
|
|
|||
|
|
@ -214,6 +214,8 @@ class ReadAccelerometerSpectreCallback(
|
|||
status: Int
|
||||
){
|
||||
|
||||
Log.d("value", value.joinToString(separator = ""))
|
||||
|
||||
if(status == BluetoothGatt.GATT_SUCCESS){
|
||||
when(readProperty){
|
||||
Property.DATA_SIZE -> {
|
||||
|
|
@ -454,25 +456,24 @@ class ReadAccelerometerSpectreCallback(
|
|||
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@OptIn(ExperimentalUnsignedTypes::class)
|
||||
fun readAccelerometerSpectre(
|
||||
address: String,
|
||||
mode: AccelViewMode,
|
||||
scale: AccelScale,
|
||||
app: Application,
|
||||
accelScale: AccelScale,
|
||||
accelMode: AccelViewMode,
|
||||
fftAxis: FftAxis,
|
||||
fftMode: FftViewMode,
|
||||
frequency: FftFrequency,
|
||||
): Flow<Result<ProgressState<List<Ble.Accelerometer.MeasurePoint>>, BleException>> {
|
||||
|
||||
return flow {
|
||||
var lastMeasureSystemTime: Long? = null
|
||||
|
||||
var bleMeasureInterval: Long? = null
|
||||
var bleRealTime: Long? = null
|
||||
var bleLastMeasureTime: Long? = null
|
||||
var initialValue: Long? = null
|
||||
var frequencyInterval: Long? = null
|
||||
|
||||
val resultTemperaturePackage: MutableList<Float> = mutableListOf()
|
||||
|
||||
val result = mutableListOf<List<UByte>>()
|
||||
val resultAccelerometerPackage: MutableList<Float> = mutableListOf()
|
||||
|
||||
var expectedDataSize: Int? = null
|
||||
|
||||
|
|
@ -484,15 +485,45 @@ fun readAccelerometerSpectre(
|
|||
ClientBleGatt.connect(app, address, CoroutineScope(Dispatchers.Default))
|
||||
|
||||
val characteristic = connection.discoverServices()
|
||||
.findService(serviceUUID)
|
||||
?.findCharacteristic(accelerometerReadUUID)
|
||||
?: throw IllegalStateException()
|
||||
|
||||
val historyCharacteristic = connection.discoverServices()
|
||||
.findService(serviceUUID)
|
||||
?.findCharacteristic(accelerometerHistoryReadUUID)
|
||||
?: throw IllegalStateException()
|
||||
|
||||
if(characteristic != null) {
|
||||
Log.d("notification", "-1")
|
||||
|
||||
Log.d("notification", "0")
|
||||
|
||||
characteristic.write(DataByteArray(byteArrayOf(
|
||||
4,
|
||||
accelMode.sendData,
|
||||
accelScale.sendData,
|
||||
fftMode.sendData,
|
||||
fftAxis.sendData,
|
||||
frequency.sendData,
|
||||
2
|
||||
)))
|
||||
|
||||
Log.d("notification", "1")
|
||||
|
||||
val notifications = characteristic.getNotifications()
|
||||
|
||||
notifications.collect {
|
||||
|
||||
|
||||
characteristic.write(DataByteArray.from(2))
|
||||
|
||||
var value = characteristic.read().value
|
||||
Log.d("notification", "0")
|
||||
|
||||
historyCharacteristic.write(DataByteArray.from(2))
|
||||
|
||||
var value = historyCharacteristic.read().value
|
||||
|
||||
Log.d("value", value.joinToString(separator = ""))
|
||||
Log.d("value", value.get2byteUIntAt(0).toString())
|
||||
|
||||
if (value.contentEquals(byteArrayOf(0, 0))) {
|
||||
|
||||
|
|
@ -510,118 +541,74 @@ fun readAccelerometerSpectre(
|
|||
addAll(value.toList())
|
||||
}.toByteArray()
|
||||
|
||||
characteristic.write(DataByteArray(writeData))
|
||||
value = characteristic.read().value
|
||||
historyCharacteristic.write(DataByteArray(writeData))
|
||||
value = historyCharacteristic.read().value
|
||||
var nextPackageDataCount = value.get2byteUIntAt(2)
|
||||
|
||||
while (nextPackageDataCount.toInt() != 0) {
|
||||
|
||||
val temperatureDataArray = if (value[0] == 250.toByte()) {
|
||||
val accelerometerDataArray = if (value[0] == 250.toByte()) {
|
||||
|
||||
bleMeasureInterval = value.get4byteUIntAt(4).toLong()
|
||||
bleLastMeasureTime = value.get4byteUIntAt(8).toLong()
|
||||
bleRealTime = value.get4byteUIntAt(12).toLong()
|
||||
initialValue = value.get4byteUIntAt(8).toLong()
|
||||
frequencyInterval = value.get4byteUIntAt(4).toLong()
|
||||
|
||||
lastMeasureSystemTime =
|
||||
System.currentTimeMillis() - ((bleRealTime!! - bleLastMeasureTime!!) * 1_000)
|
||||
|
||||
value.toUByteArray().asList().subList(16, value.size)
|
||||
value.asList().subList(16, value.size)
|
||||
|
||||
} else {
|
||||
|
||||
value.toUByteArray().asList().subList(4, value.size)
|
||||
value.asList().subList(4, value.size)
|
||||
|
||||
}
|
||||
|
||||
result.add(value.toUByteArray().toList())
|
||||
nextPackageDataCount = value.get2byteUIntAt(2)
|
||||
|
||||
resultTemperaturePackage.addAll(
|
||||
temperatureDataArray.chunked(2).map {
|
||||
it.toUByteArray().toByteArray().get2byteShortAt().toFloat()
|
||||
resultAccelerometerPackage.addAll(
|
||||
accelerometerDataArray.chunked(2).map {
|
||||
it.toByteArray().get2byteShortAt().toFloat()
|
||||
}.toMutableList()
|
||||
)
|
||||
|
||||
Log.d(
|
||||
"received data size",
|
||||
(temperatureDataArray.chunked(2).size).toString()
|
||||
)
|
||||
Log.d("next data size", nextPackageDataCount.toString())
|
||||
expectedDataSize = nextPackageDataCount.toInt() + resultAccelerometerPackage.size
|
||||
|
||||
expectedDataSize =
|
||||
nextPackageDataCount.toInt() + resultTemperaturePackage.size
|
||||
emit(Result.success(ProgressState.Progress(0f / expectedDataSize!!.toFloat())))
|
||||
emit(Result.success(ProgressState.Progress(resultAccelerometerPackage.size.toFloat() / expectedDataSize!!.toFloat())))
|
||||
|
||||
emit(Result.success(ProgressState.Progress(0f / expectedDataSize.toFloat())))
|
||||
emit(Result.success(ProgressState.Progress(resultTemperaturePackage.size.toFloat() / expectedDataSize.toFloat())))
|
||||
|
||||
characteristic.write(DataByteArray.from(5))
|
||||
value = characteristic.read().value
|
||||
historyCharacteristic.write(DataByteArray.from(5))
|
||||
value = historyCharacteristic.read().value
|
||||
|
||||
}
|
||||
|
||||
emit(
|
||||
Result.success(
|
||||
ProgressState.Finished(
|
||||
when (mode) {
|
||||
AccelViewMode.ROTATIONS,
|
||||
AccelViewMode.ACCELERATION,
|
||||
AccelViewMode.PEAK_ACCELERATION,
|
||||
AccelViewMode.RMS -> {
|
||||
resultTemperaturePackage.chunked(3).withIndex().map {
|
||||
Ble.Accelerometer.HistoryPoint.Angle(
|
||||
date = lastMeasureSystemTime!! - (((resultTemperaturePackage.size - 1) - it.index) * bleMeasureInterval!!),
|
||||
x = (it.value[0] * scale.k) / Short.MAX_VALUE,
|
||||
y = (it.value[1] * scale.k) / Short.MAX_VALUE,
|
||||
z = (it.value[2] * scale.k) / Short.MAX_VALUE
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
AccelViewMode.ANGLE -> {
|
||||
resultTemperaturePackage.chunked(3).withIndex().map {
|
||||
Ble.Accelerometer.HistoryPoint.Angle(
|
||||
date = lastMeasureSystemTime!! - (((resultTemperaturePackage.size - 1) - it.index) * bleMeasureInterval!!),
|
||||
x = calculateZAngle(
|
||||
it.value[2],
|
||||
it.value[1]
|
||||
) * 180f / Math.PI.toFloat(),
|
||||
y = calculateZAngle(
|
||||
it.value[2],
|
||||
it.value[0]
|
||||
) * 180f / Math.PI.toFloat(),
|
||||
z = calculateZAngle(
|
||||
it.value[0],
|
||||
it.value[1]
|
||||
) * 180f / Math.PI.toFloat()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
AccelViewMode.VIBRATION -> {
|
||||
resultTemperaturePackage.withIndex().map {
|
||||
Ble.Accelerometer.HistoryPoint.Vibration(
|
||||
date = lastMeasureSystemTime!! - (((resultTemperaturePackage.size - 1) - it.index) * bleMeasureInterval!!),
|
||||
value = (it.value * scale.k) / Short.MAX_VALUE
|
||||
)
|
||||
}
|
||||
}
|
||||
resultAccelerometerPackage.withIndex().map {
|
||||
Ble.Accelerometer.MeasurePoint(
|
||||
frequency = frequencyInterval!! * it.index + initialValue!!,
|
||||
value = (it.value * accelScale.k) / Short.MAX_VALUE
|
||||
)
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
)
|
||||
|
||||
characteristic.write(DataByteArray(byteArrayOf(
|
||||
4,
|
||||
accelMode.sendData,
|
||||
accelScale.sendData,
|
||||
fftMode.sendData,
|
||||
fftAxis.sendData,
|
||||
frequency.sendData,
|
||||
2
|
||||
)))
|
||||
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
|
||||
emit(Result.failure(BleException.UnexpectedResponse))
|
||||
|
||||
}
|
||||
|
||||
|
||||
} catch (err: Throwable) {
|
||||
|
||||
err.printStackTrace()
|
||||
emit(Result.failure(BleException.UnexpectedResponse))
|
||||
|
||||
}
|
||||
|
|
@ -636,4 +623,4 @@ fun readAccelerometerSpectre(
|
|||
|
||||
|
||||
|
||||
}*/
|
||||
}
|
||||
|
|
@ -9,10 +9,18 @@ import android.content.pm.PackageManager
|
|||
import android.os.Build
|
||||
import android.util.Log
|
||||
import androidx.core.app.ActivityCompat
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import llc.arma.ble.domain.Result
|
||||
import llc.arma.ble.domain.common.BleException
|
||||
import llc.arma.ble.domain.common.ProgressState
|
||||
import llc.arma.ble.domain.model.Ble
|
||||
import llc.arma.ble.domain.usecase.AccelScale
|
||||
import llc.arma.ble.domain.usecase.AccelViewMode
|
||||
import no.nordicsemi.android.common.core.DataByteArray
|
||||
import no.nordicsemi.android.kotlin.ble.client.main.callback.ClientBleGatt
|
||||
|
||||
class ReadTemperatureHistoryCallback(
|
||||
private val app: Application,
|
||||
|
|
@ -319,4 +327,135 @@ class ReadTemperatureHistoryCallback(
|
|||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalUnsignedTypes::class)
|
||||
fun readThermometerHistory(
|
||||
address: String,
|
||||
app: Application,
|
||||
): Flow<Result<ProgressState<List<Ble.Thermometer.MeasurePoint>>, BleException>> {
|
||||
|
||||
return flow {
|
||||
|
||||
var lastMeasureSystemTime: Long? = null
|
||||
|
||||
var bleMeasureInterval: Long? = null
|
||||
var bleRealTime: Long? = null
|
||||
var bleLastMeasureTime: Long? = null
|
||||
|
||||
val resultTemperaturePackage: MutableList<Float> = mutableListOf()
|
||||
|
||||
var expectedDataSize: Int? = null
|
||||
|
||||
if (app.checkPermission()) {
|
||||
|
||||
try {
|
||||
|
||||
val connection =
|
||||
ClientBleGatt.connect(app, address, CoroutineScope(Dispatchers.Default))
|
||||
|
||||
val characteristic = connection.discoverServices()
|
||||
.findService(serviceUUID)
|
||||
?.findCharacteristic(temperatureHistoryReadUUID)
|
||||
?: throw IllegalStateException()
|
||||
|
||||
characteristic.write(DataByteArray.from(2))
|
||||
|
||||
var value = characteristic.read().value
|
||||
|
||||
if (value.contentEquals(byteArrayOf(0, 0))) {
|
||||
|
||||
emit(Result.success(ProgressState.Finished(emptyList())))
|
||||
|
||||
} else {
|
||||
|
||||
Log.d("expected data size", value.get2byteUIntAt(0).toString())
|
||||
|
||||
val writeData = mutableListOf(
|
||||
1.toByte(),
|
||||
0.toByte(),
|
||||
0.toByte()
|
||||
).apply {
|
||||
addAll(value.toList())
|
||||
}.toByteArray()
|
||||
|
||||
characteristic.write(DataByteArray(writeData))
|
||||
value = characteristic.read().value
|
||||
var nextPackageDataCount = value.get2byteUIntAt(2)
|
||||
|
||||
while (nextPackageDataCount.toInt() != 0) {
|
||||
|
||||
val temperatureDataArray = if (value[0] == 250.toByte()) {
|
||||
|
||||
bleMeasureInterval = value.get4byteUIntAt(4).toLong()
|
||||
bleLastMeasureTime = value.get4byteUIntAt(8).toLong()
|
||||
bleRealTime = value.get4byteUIntAt(12).toLong()
|
||||
|
||||
lastMeasureSystemTime =
|
||||
System.currentTimeMillis() - ((bleRealTime - bleLastMeasureTime) * 1_000)
|
||||
|
||||
value.toUByteArray().asList().subList(16, value.size)
|
||||
|
||||
} else {
|
||||
|
||||
value.toUByteArray().asList().subList(4, value.size)
|
||||
|
||||
}
|
||||
|
||||
nextPackageDataCount = value.get2byteUIntAt(2)
|
||||
|
||||
resultTemperaturePackage.addAll(
|
||||
temperatureDataArray.chunked(2).map {
|
||||
it.toUByteArray().toTemperature()
|
||||
}.toMutableList()
|
||||
)
|
||||
|
||||
Log.d(
|
||||
"received data size",
|
||||
(temperatureDataArray.chunked(2).size).toString()
|
||||
)
|
||||
Log.d("next data size", nextPackageDataCount.toString())
|
||||
|
||||
expectedDataSize =
|
||||
nextPackageDataCount.toInt() + resultTemperaturePackage.size
|
||||
|
||||
emit(Result.success(ProgressState.Progress(0f / expectedDataSize.toFloat())))
|
||||
emit(Result.success(ProgressState.Progress(resultTemperaturePackage.size.toFloat() / expectedDataSize.toFloat())))
|
||||
|
||||
characteristic.write(DataByteArray.from(5))
|
||||
value = characteristic.read().value
|
||||
|
||||
}
|
||||
|
||||
emit(
|
||||
Result.success(
|
||||
ProgressState.Finished(
|
||||
resultTemperaturePackage.withIndex().map {
|
||||
Ble.Thermometer.MeasurePoint(
|
||||
date = lastMeasureSystemTime!! - (((resultTemperaturePackage.size - 1) - it.index) * bleMeasureInterval!!),
|
||||
value = it.value
|
||||
)
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
|
||||
} catch (err: Throwable) {
|
||||
|
||||
emit(Result.failure(BleException.UnexpectedResponse))
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
emit(Result.failure(BleException.PermissionDenied))
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,230 +0,0 @@
|
|||
package llc.arma.ble.data
|
||||
|
||||
import android.Manifest
|
||||
import android.app.Application
|
||||
import android.bluetooth.BluetoothGatt
|
||||
import android.bluetooth.BluetoothGattCallback
|
||||
import android.bluetooth.BluetoothGattCharacteristic
|
||||
import android.bluetooth.BluetoothProfile
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Build
|
||||
import android.util.Log
|
||||
import androidx.core.app.ActivityCompat
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import llc.arma.ble.domain.Result
|
||||
import llc.arma.ble.domain.common.BleException
|
||||
import llc.arma.ble.domain.model.Ble
|
||||
import java.util.UUID
|
||||
|
||||
class WriteThermometerCallback(
|
||||
private val app: Application,
|
||||
private var request: Ble.Thermometer.WriteRequest,
|
||||
private val onResult: (Result<Unit, BleException>) -> Unit
|
||||
) : BluetoothGattCallback() {
|
||||
|
||||
private var flashed = false
|
||||
|
||||
override fun onConnectionStateChange(
|
||||
gatt: BluetoothGatt,
|
||||
status: Int,
|
||||
newState: Int
|
||||
) {
|
||||
super.onConnectionStateChange(gatt, status, newState)
|
||||
|
||||
if(app.checkPermission()) {
|
||||
|
||||
if(status == BluetoothGatt.GATT_SUCCESS && newState == BluetoothProfile.STATE_CONNECTED) {
|
||||
|
||||
gatt.discoverServices()
|
||||
|
||||
} else {
|
||||
|
||||
onResult(Result.failure(BleException.UnexpectedResponse))
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
onResult(Result.failure(BleException.PermissionDenied))
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun onServicesDiscovered(
|
||||
gatt: BluetoothGatt,
|
||||
status: Int
|
||||
) {
|
||||
super.onServicesDiscovered(gatt, status)
|
||||
onCycle(gatt, status)
|
||||
|
||||
}
|
||||
|
||||
private fun onCycle(
|
||||
gatt: BluetoothGatt,
|
||||
status: Int
|
||||
){
|
||||
|
||||
if(request.tx != null || request.saveHistory != null || request.historyInterval != null) {
|
||||
|
||||
fun UInt.to4ByteArrayInLittleEndian(): ByteArray =
|
||||
(3 downTo 0).map {
|
||||
(this shr (it * Byte.SIZE_BITS)).toByte()
|
||||
}.toByteArray()
|
||||
|
||||
var uuid: Triple<UUID, ByteArray, Ble.Thermometer.WriteRequest>? = null
|
||||
|
||||
uuid = request.historyInterval?.let {
|
||||
|
||||
Triple(
|
||||
intervalWriteUUID,
|
||||
mutableListOf<Byte>(3).apply {
|
||||
addAll((it).toUInt().to4ByteArrayInLittleEndian().reversed().toList())
|
||||
}.toByteArray(),
|
||||
request.copy(
|
||||
historyInterval = null
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
uuid = request.saveHistory?.let {
|
||||
|
||||
Triple(
|
||||
saveEnabledWriteUUID,
|
||||
mutableListOf<Byte>(4).apply {
|
||||
add(if (it) 1 else 0)
|
||||
}.toByteArray(),
|
||||
request.copy(
|
||||
saveHistory = null
|
||||
)
|
||||
)
|
||||
} ?: uuid
|
||||
|
||||
uuid = request.tx?.let {
|
||||
|
||||
Triple(
|
||||
txWriteUUID,
|
||||
byteArrayOf(
|
||||
when (it) {
|
||||
Ble.BleState.TX.MINUS_40 -> -40
|
||||
Ble.BleState.TX.MINUS_20 -> -20
|
||||
Ble.BleState.TX.MINUS_16 -> -16
|
||||
Ble.BleState.TX.MINUS_12 -> -12
|
||||
Ble.BleState.TX.MINUS_8 -> -8
|
||||
Ble.BleState.TX.MINUS_4 -> -4
|
||||
Ble.BleState.TX.ZERO -> 0
|
||||
Ble.BleState.TX.PLUS_3 -> 3
|
||||
Ble.BleState.TX.PLUS_4 -> 4
|
||||
}
|
||||
),
|
||||
request.copy(
|
||||
tx = null
|
||||
)
|
||||
)
|
||||
|
||||
} ?: uuid
|
||||
|
||||
uuid?.let { uuid ->
|
||||
|
||||
gatt.services.firstOrNull { it.uuid == serviceUUID }?.characteristics?.firstOrNull {
|
||||
it.uuid == uuid.first
|
||||
}?.let {
|
||||
|
||||
gatt.writeCharacteristic(it, uuid.second)
|
||||
request = uuid.third
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
onResult(Result.failure(BleException.UnexpectedResponse))
|
||||
|
||||
} else {
|
||||
|
||||
if(flashed.not()){
|
||||
|
||||
flashed = true
|
||||
|
||||
gatt.services.firstOrNull { it.uuid == serviceUUID }?.characteristics?.firstOrNull {
|
||||
it.uuid == flashWriteUUID
|
||||
}?.let {
|
||||
|
||||
gatt.writeCharacteristic(it, byteArrayOf(9))
|
||||
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
onResult(Result.failure(BleException.UnexpectedResponse))
|
||||
|
||||
} else {
|
||||
|
||||
onResult(Result.success(Unit))
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun onCharacteristicWrite(
|
||||
gatt: BluetoothGatt,
|
||||
characteristic: BluetoothGattCharacteristic,
|
||||
status: Int
|
||||
) {
|
||||
|
||||
super.onCharacteristicWrite(gatt, characteristic, status)
|
||||
|
||||
if(app.checkPermission()) {
|
||||
|
||||
if(status == BluetoothGatt.GATT_SUCCESS || flashed) {
|
||||
|
||||
onCycle(gatt, status)
|
||||
|
||||
} else {
|
||||
|
||||
onResult(Result.failure(BleException.UnexpectedResponse))
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
onResult(Result.failure(BleException.PermissionDenied))
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun BluetoothGatt.writeCharacteristic(
|
||||
characteristic: BluetoothGattCharacteristic,
|
||||
data: ByteArray
|
||||
): Result<Unit, BleException> {
|
||||
|
||||
return if(app.checkPermission()){
|
||||
|
||||
Log.d("write", data.asUByteArray().joinToString(" ") { it.toString(16).padStart(2, '0') })
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
writeCharacteristic(characteristic, data, BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT)
|
||||
}else{
|
||||
|
||||
characteristic.writeType = BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT
|
||||
characteristic.value = data
|
||||
writeCharacteristic(characteristic)
|
||||
}
|
||||
|
||||
Result.success(Unit)
|
||||
|
||||
} else {
|
||||
Result.failure(BleException.PermissionDenied)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue