fix: properly handle connecting to bonded devices

This commit is contained in:
Stefan Zollinger
2024-04-11 15:13:16 +02:00
parent 7311ba335f
commit 62ce221860
5 changed files with 72 additions and 16 deletions

View File

@@ -59,6 +59,7 @@ dependencies {
implementation 'androidx.recyclerview:recyclerview:1.2.0'
implementation 'com.google.code.gson:gson:2.8.8'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.0'
implementation group: 'commons-codec', name: 'commons-codec', version: '1.16.0'

View File

@@ -394,9 +394,11 @@ class ConnectionManager(val context: Context, bleAdapter: BluetoothAdapter) {
@Synchronized
private fun enqueueOperation(operation: BleOperationType) {
/*
if (isScanning) {
stopScan()
}
*/
operationQueue.add(operation)
notifyListenersOfQueueChange(operation.device.address)
if (pendingOperation == null) {

View File

@@ -84,6 +84,7 @@ object DecoderIaq {
}
data class Measurement (
var deviceId: String? = null,
var msgType: Number? = null,
var co2: Number? = null,
var voc: Number? = null,
@@ -110,8 +111,5 @@ object DecoderIaq {
'}'
}
fun toCsv() : String {
return "${msgType},${co2},${voc},${humidity},${temperature},${pressure}${pm25},${pm10},${occupancy}"
}
}
}

View File

@@ -45,16 +45,18 @@ class KirbyDevice(
private val queue: RequestQueue = Volley.newRequestQueue(context)
fun subscribe() {
if(statuses.contains(DeviceStatus.CONNECTED)) {
connectionManager.enableNotification(
bleDevice, SERVICE_UUID, CHAR_UUID
)
}
}
fun readIaq() {
connectionManager.readChar(bleDevice, SERVICE_UUID, CHAR_UUID)
}
override fun onSuccessfulCharRead(
gatt: BluetoothGatt,
characteristic: BluetoothGattCharacteristic
@@ -66,13 +68,20 @@ class KirbyDevice(
override fun onScanResult(callbackType: Int, result: ScanResult) {
rssi = result.rssi
onStateChange(this)
if(result.isConnectable) {
connectionManager.connect(bleDevice)
connectionManager.discoverServices(bleDevice)
}
}
override fun onConnect(gatt: BluetoothGatt) {
statuses.add(DeviceStatus.CONNECTED)
statuses.remove(DeviceStatus.MISSING)
subscribe()
onStateChange(this)
}
override fun onConnectToBondedFailed(gatt: BluetoothGatt) {
@@ -136,6 +145,7 @@ class KirbyDevice(
if (measurement == null) {
payload = Payload(hexPayload)
} else {
measurement.deviceId = bleDevice.address
payload = Payload(measurement.toString())
Log.i("BleListener", "Char received: $payload")
val base64Payload = Base64.getEncoder().encodeToString(characteristic.value)
@@ -155,6 +165,11 @@ class KirbyDevice(
private fun publishMeasurement(payload: String) {
val accessKey = BuildConfig.API_KEY
val url = BuildConfig.API_BASE_URL
if(url.isEmpty()) {
return
}
val eui = "0000${bleDevice.address.replace(":", "")}"
val postData = JSONObject()

View File

@@ -15,20 +15,29 @@ import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.util.Log
import android.view.Menu
import android.view.MenuItem
import android.view.View.INVISIBLE
import android.view.View.VISIBLE
import android.widget.Toast
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.result.contract.ActivityResultContracts.CreateDocument
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.core.view.WindowCompat
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.SimpleItemAnimator
import com.logitech.vc.kirbytest.databinding.ActivityMainBinding
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
@@ -108,10 +117,31 @@ class MainActivity : AppCompatActivity() {
setupDevicesList()
createFileLauncher =
registerForActivityResult(ActivityResultContracts.CreateDocument()) { uri: Uri? ->
registerForActivityResult(CreateDocument("text/csv")) { uri: Uri? ->
uri?.let {
// Use the URI to write your CSV content
CoroutineScope(Dispatchers.IO).launch {
loggerDb.exportToUri(uri)
withContext(Dispatchers.Main) {
Toast.makeText(
this@MainActivity,
"Log export completed.",
Toast.LENGTH_SHORT
).show()
}
}
}
}
connectionManager.startScan()
lifecycleScope.launch {
withContext(Dispatchers.Main) {
delay(5000L)
connectionManager.stopScan()
}
}
}
@@ -156,11 +186,11 @@ class MainActivity : AppCompatActivity() {
private fun addBondedDevices(): Unit {
bluetoothAdapter.bondedDevices.filter { isKirbyDevice(it) }.forEach {
val kirbyDevice = newKirbyDevice(it)
kirbyDevice.subscribe()
newKirbyDevice(it)
}
}
@SuppressLint("NotifyDataSetChanged")
private fun addDummyDevices() {
for (i in 0..14) {
@@ -183,7 +213,7 @@ class MainActivity : AppCompatActivity() {
}
override fun onScanResult(callbackType: Int, result: ScanResult) {
if (isKirbyDevice(result.device)) {
if (isKirbyDevice(result.device) && result.isConnectable) {
Log.i(
"ScanCallback",
@@ -200,7 +230,10 @@ class MainActivity : AppCompatActivity() {
return mngr
}
private fun newKirbyDevice(bleDevice: BluetoothDevice): KirbyDevice {
private fun newKirbyDevice(
bleDevice: BluetoothDevice,
autoConnect: Boolean = false
): KirbyDevice {
val device = KirbyDevice(this.applicationContext, connectionManager, bleDevice, loggerDb) {
val i = kirbyDevices.indexOfFirst { d -> d === it }
@@ -208,9 +241,16 @@ class MainActivity : AppCompatActivity() {
deviceListAdapter.notifyItemChanged(i)
}
}
Log.i("MainActivity", bleDevice.address)
connectionManager.register(device)
if (autoConnect) {
connectionManager.connect(bleDevice)
connectionManager.discoverServices(bleDevice)
}
kirbyDevices.add(device)
deviceListAdapter.notifyItemInserted(kirbyDevices.size - 1)
return device