mirror of
https://github.com/permissionlesstech/bitchat-android.git
synced 2026-07-25 03:05:20 +00:00
track rssi correctly
This commit is contained in:
@@ -41,12 +41,23 @@ class BluetoothConnectionManager(
|
||||
// Delegate for component managers to call back to main manager
|
||||
private val componentDelegate = object : BluetoothConnectionManagerDelegate {
|
||||
override fun onPacketReceived(packet: BitchatPacket, peerID: String, device: BluetoothDevice?) {
|
||||
device?.let { bluetoothDevice ->
|
||||
// Get current RSSI for this device and update if available
|
||||
val currentRSSI = connectionTracker.getBestRSSI(bluetoothDevice.address)
|
||||
if (currentRSSI != null) {
|
||||
delegate?.onRSSIUpdated(bluetoothDevice.address, currentRSSI)
|
||||
}
|
||||
}
|
||||
delegate?.onPacketReceived(packet, peerID, device)
|
||||
}
|
||||
|
||||
override fun onDeviceConnected(device: BluetoothDevice) {
|
||||
delegate?.onDeviceConnected(device)
|
||||
}
|
||||
|
||||
override fun onRSSIUpdated(deviceAddress: String, rssi: Int) {
|
||||
delegate?.onRSSIUpdated(deviceAddress, rssi)
|
||||
}
|
||||
}
|
||||
|
||||
private val serverManager = BluetoothGattServerManager(
|
||||
@@ -231,4 +242,5 @@ class BluetoothConnectionManager(
|
||||
interface BluetoothConnectionManagerDelegate {
|
||||
fun onPacketReceived(packet: BitchatPacket, peerID: String, device: BluetoothDevice?)
|
||||
fun onDeviceConnected(device: BluetoothDevice)
|
||||
fun onRSSIUpdated(deviceAddress: String, rssi: Int)
|
||||
}
|
||||
|
||||
@@ -31,6 +31,9 @@ class BluetoothConnectionTracker(
|
||||
private val subscribedDevices = CopyOnWriteArrayList<BluetoothDevice>()
|
||||
val addressPeerMap = ConcurrentHashMap<String, String>()
|
||||
|
||||
// RSSI tracking from scan results (for devices we discover but may connect as servers)
|
||||
private val scanRSSI = ConcurrentHashMap<String, Int>()
|
||||
|
||||
// Connection attempt tracking with automatic cleanup
|
||||
private val pendingConnections = ConcurrentHashMap<String, ConnectionAttempt>()
|
||||
|
||||
@@ -117,6 +120,31 @@ class BluetoothConnectionTracker(
|
||||
return subscribedDevices.toList()
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current RSSI for a device address
|
||||
*/
|
||||
fun getDeviceRSSI(deviceAddress: String): Int? {
|
||||
return connectedDevices[deviceAddress]?.rssi?.takeIf { it != Int.MIN_VALUE }
|
||||
}
|
||||
|
||||
/**
|
||||
* Store RSSI from scan results
|
||||
*/
|
||||
fun updateScanRSSI(deviceAddress: String, rssi: Int) {
|
||||
scanRSSI[deviceAddress] = rssi
|
||||
}
|
||||
|
||||
/**
|
||||
* Get best available RSSI for a device (connection RSSI preferred, then scan RSSI)
|
||||
*/
|
||||
fun getBestRSSI(deviceAddress: String): Int? {
|
||||
// Prefer connection RSSI if available and valid
|
||||
connectedDevices[deviceAddress]?.rssi?.takeIf { it != Int.MIN_VALUE }?.let { return it }
|
||||
|
||||
// Fall back to scan RSSI
|
||||
return scanRSSI[deviceAddress]
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a subscribed device
|
||||
*/
|
||||
@@ -249,6 +277,7 @@ class BluetoothConnectionTracker(
|
||||
subscribedDevices.clear()
|
||||
addressPeerMap.clear()
|
||||
pendingConnections.clear()
|
||||
scanRSSI.clear()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -300,6 +329,11 @@ class BluetoothConnectionTracker(
|
||||
val elapsed = (now - attempt.lastAttempt) / 1000
|
||||
appendLine(" - $address: ${attempt.attempts} attempts, last ${elapsed}s ago")
|
||||
}
|
||||
appendLine()
|
||||
appendLine("Scan RSSI Cache: ${scanRSSI.size}")
|
||||
scanRSSI.forEach { (address, rssi) ->
|
||||
appendLine(" - $address: $rssi dBm")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.*
|
||||
import kotlinx.coroutines.Job
|
||||
|
||||
/**
|
||||
* Manages GATT client operations, scanning, and client-side connections
|
||||
@@ -31,6 +32,9 @@ class BluetoothGattClientManager(
|
||||
// Use exact same UUIDs as iOS version
|
||||
private val SERVICE_UUID = UUID.fromString("F47B5E2D-4A9E-4C5A-9B3F-8E1D2C3A4B5C")
|
||||
private val CHARACTERISTIC_UUID = UUID.fromString("A1B2C3D4-E5F6-4A5B-8C9D-0E1F2A3B4C5D")
|
||||
|
||||
// RSSI monitoring constants
|
||||
private const val RSSI_UPDATE_INTERVAL = 5000L // 5 seconds
|
||||
}
|
||||
|
||||
// Core Bluetooth components
|
||||
@@ -48,6 +52,9 @@ class BluetoothGattClientManager(
|
||||
private var isCurrentlyScanning = false
|
||||
private val scanRateLimit = 5000L // Minimum 5 seconds between scan start attempts
|
||||
|
||||
// RSSI monitoring state
|
||||
private var rssiMonitoringJob: Job? = null
|
||||
|
||||
// State management
|
||||
private var isActive = false
|
||||
|
||||
@@ -78,6 +85,9 @@ class BluetoothGattClientManager(
|
||||
} else {
|
||||
startScanning()
|
||||
}
|
||||
|
||||
// Start RSSI monitoring
|
||||
startRSSIMonitoring()
|
||||
}
|
||||
|
||||
return true
|
||||
@@ -91,6 +101,7 @@ class BluetoothGattClientManager(
|
||||
|
||||
connectionScope.launch {
|
||||
stopScanning()
|
||||
stopRSSIMonitoring()
|
||||
Log.i(TAG, "GATT client manager stopped")
|
||||
}
|
||||
}
|
||||
@@ -106,6 +117,41 @@ class BluetoothGattClientManager(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start periodic RSSI monitoring for all client connections
|
||||
*/
|
||||
private fun startRSSIMonitoring() {
|
||||
rssiMonitoringJob?.cancel()
|
||||
rssiMonitoringJob = connectionScope.launch {
|
||||
while (isActive) {
|
||||
try {
|
||||
// Request RSSI from all client connections
|
||||
val connectedDevices = connectionTracker.getConnectedDevices()
|
||||
connectedDevices.values.filter { it.isClient && it.gatt != null }.forEach { deviceConn ->
|
||||
try {
|
||||
Log.d(TAG, "Requesting RSSI from ${deviceConn.device.address}")
|
||||
deviceConn.gatt?.readRemoteRssi()
|
||||
} catch (e: Exception) {
|
||||
Log.w(TAG, "Failed to request RSSI from ${deviceConn.device.address}: ${e.message}")
|
||||
}
|
||||
}
|
||||
delay(RSSI_UPDATE_INTERVAL)
|
||||
} catch (e: Exception) {
|
||||
Log.w(TAG, "Error in RSSI monitoring: ${e.message}")
|
||||
delay(RSSI_UPDATE_INTERVAL)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop RSSI monitoring
|
||||
*/
|
||||
private fun stopRSSIMonitoring() {
|
||||
rssiMonitoringJob?.cancel()
|
||||
rssiMonitoringJob = null
|
||||
}
|
||||
|
||||
/**
|
||||
* Start scanning with rate limiting
|
||||
*/
|
||||
@@ -230,6 +276,9 @@ class BluetoothGattClientManager(
|
||||
return
|
||||
}
|
||||
|
||||
// Store RSSI from scan results for later use (especially for server connections)
|
||||
connectionTracker.updateScanRSSI(deviceAddress, rssi)
|
||||
|
||||
// Power-aware RSSI filtering
|
||||
if (rssi < powerManager.getRSSIThreshold()) {
|
||||
Log.d(TAG, "Skipping device $deviceAddress due to weak signal: $rssi < ${powerManager.getRSSIThreshold()}")
|
||||
@@ -381,6 +430,21 @@ class BluetoothGattClientManager(
|
||||
Log.w(TAG, "Client: Packet data: ${value.joinToString(" ") { "%02x".format(it) }}")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onReadRemoteRssi(gatt: BluetoothGatt, rssi: Int, status: Int) {
|
||||
val deviceAddress = gatt.device.address
|
||||
if (status == BluetoothGatt.GATT_SUCCESS) {
|
||||
Log.d(TAG, "Client: RSSI updated for $deviceAddress: $rssi dBm")
|
||||
|
||||
// Update the connection tracker with new RSSI value
|
||||
connectionTracker.getDeviceConnection(deviceAddress)?.let { deviceConn ->
|
||||
val updatedConn = deviceConn.copy(rssi = rssi)
|
||||
connectionTracker.updateDeviceConnection(deviceAddress, updatedConn)
|
||||
}
|
||||
} else {
|
||||
Log.w(TAG, "Client: Failed to read RSSI for $deviceAddress, status: $status")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
@@ -69,7 +69,7 @@ class BluetoothGattServerManager(
|
||||
isActive = true
|
||||
|
||||
connectionScope.launch {
|
||||
setupGattServer()
|
||||
// setupGattServer()
|
||||
delay(300) // Brief delay to ensure GATT server is ready
|
||||
startAdvertising()
|
||||
}
|
||||
@@ -122,8 +122,13 @@ class BluetoothGattServerManager(
|
||||
when (newState) {
|
||||
BluetoothProfile.STATE_CONNECTED -> {
|
||||
Log.i(TAG, "Server: Device connected ${device.address}")
|
||||
|
||||
// Get best available RSSI (scan RSSI for server connections)
|
||||
val rssi = connectionTracker.getBestRSSI(device.address) ?: Int.MIN_VALUE
|
||||
|
||||
val deviceConn = BluetoothConnectionTracker.DeviceConnection(
|
||||
device = device,
|
||||
rssi = rssi,
|
||||
isClient = false
|
||||
)
|
||||
connectionTracker.addDeviceConnection(device.address, deviceConn)
|
||||
|
||||
@@ -280,6 +280,13 @@ class BluetoothMeshService(private val context: Context) {
|
||||
sendKeyExchangeToDevice()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onRSSIUpdated(deviceAddress: String, rssi: Int) {
|
||||
// Find the peer ID for this device address and update RSSI in PeerManager
|
||||
connectionManager.addressPeerMap[deviceAddress]?.let { peerID ->
|
||||
peerManager.updatePeerRSSI(peerID, rssi)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user