Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import android.os.Handler
import android.os.Looper
import android.util.Log
import com.google.firebase.crashlytics.FirebaseCrashlytics
import java.util.UUID
import com.softwiredtech.dashpilot.ble.VehicleControl
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
Expand Down Expand Up @@ -67,6 +68,12 @@ class DashKitBleManager(private val context: Context) {
// Keepalive interval; the firmware drops the link after 60 s without a
// ping (KEEPALIVE_TIMEOUT_S), so this allows a few missed writes.
private const val PING_INTERVAL_MS = 15_000L

// Android's GATT client allows only one operation in flight, so a CCCD
// write racing another subscribe can be refused; retry a few times.
private val CCCD_UUID = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb")
private const val MAX_SUBSCRIBE_ATTEMPTS = 3
private const val SUBSCRIBE_RETRY_DELAY_MS = 250L
}

private val crashlytics = FirebaseCrashlytics.getInstance()
Expand Down Expand Up @@ -624,4 +631,38 @@ class DashKitBleManager(private val context: Context) {
} catch (_: Exception) {}
scanning = false
}

/** Subscribes to a characteristic's notifications, retrying if the CCCD
* write races another GATT operation. Shared by the CAN and Tesla status
* sources. */
fun subscribeWithRetry(
gatt: BluetoothGatt,
characteristic: BluetoothGattCharacteristic,
logTag: String,
label: String
) {
val descriptor = characteristic.getDescriptor(CCCD_UUID)
if (descriptor == null) {
Log.e(logTag, "$label CCCD (0x2902) not discovered")
return
}
var attempt = 0
fun writeCccd() {
val queued = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
gatt.writeDescriptor(descriptor, BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE) ==
BluetoothGatt.GATT_SUCCESS
} else {
@Suppress("DEPRECATION")
descriptor.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
@Suppress("DEPRECATION")
gatt.writeDescriptor(descriptor)
}
if (!queued && attempt < MAX_SUBSCRIBE_ATTEMPTS) {
attempt++
Log.d(logTag, "$label CCCD write not queued (attempt=$attempt); retrying")
handler.postDelayed({ writeCccd() }, SUBSCRIBE_RETRY_DELAY_MS)
}
}
writeCccd()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ package com.softwiredtech.dashpilot.datasource
import android.annotation.SuppressLint
import android.bluetooth.BluetoothGatt
import android.bluetooth.BluetoothGattCharacteristic
import android.bluetooth.BluetoothGattDescriptor
import android.os.Build
import android.util.Log
import com.softwiredtech.dashpilot.datamodel.dash.CarState
import kotlinx.coroutines.flow.Flow
Expand All @@ -26,7 +24,6 @@ class DashKitDataSource(
private const val TAG = "DashKitDataSource"
private val SERVICE_UUID = UUID.fromString("CADA0000-CA00-B1E0-B0D6-C000AA0100A1")
private val CHAR_UUID = UUID.fromString("CADA0001-CA00-B1E0-B0D6-C000AA0100A1")
private val CCCD_UUID = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb")
// The firmware now applies CAN acceptance filtering in hardware (per-bus
// MCP251xFD filters), so the app no longer pushes a BLE filter list.
}
Expand Down Expand Up @@ -58,18 +55,7 @@ class DashKitDataSource(
return
}
gatt.setCharacteristicNotification(characteristic, true)
val descriptor = characteristic.getDescriptor(CCCD_UUID)
if (descriptor != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
gatt.writeDescriptor(descriptor, BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE)
} else {
@Suppress("DEPRECATION")
descriptor.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
@Suppress("DEPRECATION")
gatt.writeDescriptor(descriptor)
}
}
Log.d(TAG, "Subscribed to CAN notifications")
manager.subscribeWithRetry(gatt, characteristic, TAG, "CAN")
}

override fun onCharacteristicChanged(
Expand Down
Loading