mirror of
https://github.com/d4rken-org/capod.git
synced 2026-09-15 02:36:12 -04:00
Use some bits of the proximity message to recognize the same device again
This commit is contained in:
@@ -27,7 +27,8 @@ class AppleFactory @Inject constructor(
|
||||
|
||||
data class KnownDevice(
|
||||
val identifier: UUID,
|
||||
val scanResult: ScanResult
|
||||
val scanResult: ScanResult,
|
||||
val message: ProximityPairing.Message,
|
||||
) {
|
||||
val address: String
|
||||
get() = scanResult.device.address
|
||||
@@ -72,25 +73,47 @@ class AppleFactory @Inject constructor(
|
||||
return proximityMessage
|
||||
}
|
||||
|
||||
private suspend fun recognizeDevice(scanResult: ScanResult): UUID {
|
||||
private suspend fun recognizeDevice(scanResult: ScanResult, message: ProximityPairing.Message): UUID {
|
||||
val address = scanResult.device.address
|
||||
|
||||
var identifier: UUID? = null
|
||||
|
||||
knownDevs.values.firstOrNull { it.address == address }?.let {
|
||||
log(TAG, VERBOSE) { "recognizeDevice: Recovered previous ID via address: $it" }
|
||||
knownDevs[it.identifier] = it.copy(scanResult = scanResult)
|
||||
knownDevs[it.identifier] = it.copy(
|
||||
scanResult = scanResult,
|
||||
message = message,
|
||||
)
|
||||
identifier = it.identifier
|
||||
}
|
||||
|
||||
if (identifier == null) {
|
||||
val currentMarkers = message.getRecogMarkers()
|
||||
knownDevs.values
|
||||
.firstOrNull { it.message.getRecogMarkers() == currentMarkers }
|
||||
?.let {
|
||||
log(TAG, DEBUG) { "recognizeDevice: Close match based similarity markers." }
|
||||
log(TAG, DEBUG) { "recognizeDevice: Old marker: ${it.message.getRecogMarkers()}" }
|
||||
log(TAG, DEBUG) { "recognizeDevice: New marker: $currentMarkers" }
|
||||
knownDevs[it.identifier] = it.copy(
|
||||
scanResult = scanResult,
|
||||
message = message,
|
||||
)
|
||||
identifier = it.identifier
|
||||
}
|
||||
}
|
||||
|
||||
if (identifier == null) {
|
||||
knownDevs.values
|
||||
.firstOrNull {
|
||||
it.rssi > -60 && !it.isOlderThan(Duration.ofSeconds(10))
|
||||
}
|
||||
?.let {
|
||||
log(TAG, VERBOSE) { "recognizeDevice: Close match based on RSSI and timestamp." }
|
||||
knownDevs[it.identifier] = it.copy(scanResult = scanResult)
|
||||
log(TAG, DEBUG) { "recognizeDevice: Close match based on RSSI and timestamp." }
|
||||
knownDevs[it.identifier] = it.copy(
|
||||
scanResult = scanResult,
|
||||
message = message,
|
||||
)
|
||||
identifier = it.identifier
|
||||
}
|
||||
}
|
||||
@@ -103,7 +126,8 @@ class AppleFactory @Inject constructor(
|
||||
|
||||
knownDevs[identifier!!] = KnownDevice(
|
||||
identifier = identifier!!,
|
||||
scanResult = scanResult
|
||||
scanResult = scanResult,
|
||||
message = message
|
||||
)
|
||||
|
||||
knownDevs.values.toList().forEach { knownDevice ->
|
||||
@@ -119,7 +143,7 @@ class AppleFactory @Inject constructor(
|
||||
suspend fun create(scanResult: ScanResult): PodDevice? = mutex.withLock {
|
||||
val pm = getMessage(scanResult) ?: return@withLock null
|
||||
|
||||
val identifier = recognizeDevice(scanResult)
|
||||
val identifier = recognizeDevice(scanResult, pm)
|
||||
|
||||
log(TAG, INFO) {
|
||||
val data = scanResult.scanRecord!!.getManufacturerSpecificData(
|
||||
@@ -131,6 +155,14 @@ class AppleFactory @Inject constructor(
|
||||
"Decoding (MAC=${scanResult.device.address}, nanos=${scanResult.timestampNanos}, rssi=${scanResult.rssi}): $dataHex"
|
||||
}
|
||||
|
||||
return createPodDevice(scanResult, pm, identifier)
|
||||
}
|
||||
|
||||
private fun createPodDevice(
|
||||
scanResult: ScanResult,
|
||||
pm: ProximityPairing.Message,
|
||||
identifier: UUID
|
||||
): ApplePods {
|
||||
val dm = (
|
||||
((pm.data[1].toInt() and 255) shl 8) or (pm.data[2].toInt() and 255)
|
||||
).toUShort()
|
||||
|
||||
@@ -3,6 +3,8 @@ package eu.darken.capod.pods.core.apple.protocol
|
||||
import android.bluetooth.le.ScanFilter
|
||||
import dagger.Reusable
|
||||
import eu.darken.capod.common.debug.logging.log
|
||||
import eu.darken.capod.common.lowerNibble
|
||||
import eu.darken.capod.common.upperNibble
|
||||
import eu.darken.capod.pods.core.apple.ApplePods
|
||||
import javax.inject.Inject
|
||||
|
||||
@@ -13,7 +15,24 @@ object ProximityPairing {
|
||||
val type: UByte,
|
||||
val length: Int,
|
||||
val data: UByteArray
|
||||
)
|
||||
) {
|
||||
data class Markers(
|
||||
val vendor: UByte,
|
||||
val length: UByte,
|
||||
val device: UShort,
|
||||
val batteryData: Set<UByte>,
|
||||
val deviceColor: UByte,
|
||||
)
|
||||
|
||||
fun getRecogMarkers(): Markers = Markers(
|
||||
vendor = CONTINUITY_PROTOCOL_MESSAGE_TYPE_PROXIMITY_PAIRING,
|
||||
length = PROXIMITY_PAIRING_MESSAGE_LENGTH.toUByte(),
|
||||
device = (((data[1].toInt() and 255) shl 8) or (data[2].toInt() and 255)).toUShort(),
|
||||
// Make comparison order independent
|
||||
batteryData = setOf(data[4].upperNibble, data[4].lowerNibble),
|
||||
deviceColor = data[7]
|
||||
)
|
||||
}
|
||||
|
||||
@Reusable
|
||||
class Decoder @Inject constructor() {
|
||||
|
||||
Reference in New Issue
Block a user