[go: nahoru, domu]

blob: 6d06ac8e48e65179c78487ba2db60f2fb3d2c380 [file] [log] [blame]
/*
* Copyright 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.bluetooth.integration.testapp.ui.gatt_server
import android.util.Log
import androidx.bluetooth.BluetoothLe
import androidx.bluetooth.GattCharacteristic
import androidx.bluetooth.GattServerRequest
import androidx.bluetooth.GattService
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
@HiltViewModel
class GattServerViewModel @Inject constructor(
private val bluetoothLe: BluetoothLe
) : ViewModel() {
private companion object {
private const val TAG = "GattServerViewModel"
}
var gattServerJob: Job? = null
private val _gattServerServices = mutableListOf<GattService>()
val gattServerServices: List<GattService> = _gattServerServices
private val gattServerServicesCharacteristicValueMap =
mutableMapOf<GattCharacteristic, ByteArray>()
private val _uiState = MutableStateFlow(GattServerUiState())
val uiState: StateFlow<GattServerUiState> = _uiState.asStateFlow()
fun addGattService(gattService: GattService) {
_gattServerServices.add(gattService)
}
fun addGattCharacteristic(service: GattService, characteristic: GattCharacteristic) {
val index = _gattServerServices.indexOf(service)
if (index < 0) return
_gattServerServices[index] = GattService(service.uuid,
service.characteristics.toMutableList().apply {
add(characteristic)
}
)
}
fun openGattServer() {
Log.d(TAG, "openGattServer() called")
gattServerJob = viewModelScope.launch {
Log.d(
TAG, "bluetoothLe.openGattServer() called with " +
"gattServerServices = $gattServerServices"
)
_uiState.update {
it.copy(isGattServerOpen = true)
}
bluetoothLe.openGattServer(gattServerServices) {
Log.d(
TAG, "bluetoothLe.openGattServer() called with: " +
"gattServerServices = $gattServerServices"
)
connectRequests.collect {
Log.d(TAG, "connectRequests.collected: GattServerConnectRequest = $it")
launch {
it.accept {
Log.d(
TAG,
"GattServerConnectRequest accepted: GattServerSessionScope = $it"
)
requests.collect { gattServerRequest ->
Log.d(
TAG,
"requests collected: gattServerRequest = $gattServerRequest"
)
// TODO(b/269390098): Handle requests correctly
when (gattServerRequest) {
is GattServerRequest.ReadCharacteristic -> {
val characteristic = gattServerRequest.characteristic
val value = readGattCharacteristicValue(characteristic)
_uiState.update { state ->
state.copy(
resultMessage = "Read value: " +
"${value.decodeToString()} for characteristic" +
" = ${characteristic.uuid}"
)
}
gattServerRequest.sendResponse(value)
}
is GattServerRequest.WriteCharacteristics -> {
val characteristic =
gattServerRequest.parts[0].characteristic
val value = gattServerRequest.parts[0].value
_uiState.update { state ->
state.copy(
resultMessage = "Writing value: " +
"${value.decodeToString()} to characteristic" +
" = ${characteristic.uuid}"
)
}
updateGattCharacteristicValue(characteristic, value)
gattServerRequest.sendResponse()
}
else -> {
throw NotImplementedError("Unknown request")
}
}
}
}
}
}
}
}
gattServerJob?.invokeOnCompletion {
Log.d(TAG, "bluetoothLe.openGattServer completed")
_uiState.update {
it.copy(isGattServerOpen = false)
}
}
}
fun resultMessageShown() {
_uiState.update {
it.copy(resultMessage = null)
}
}
private fun readGattCharacteristicValue(characteristic: GattCharacteristic): ByteArray {
return gattServerServicesCharacteristicValueMap[characteristic] ?: ByteArray(0)
}
private fun updateGattCharacteristicValue(
characteristic: GattCharacteristic,
value: ByteArray
) {
gattServerServicesCharacteristicValueMap[characteristic] = value
}
}