From c5cc127df4a1235f56f52024070918f70c748140 Mon Sep 17 00:00:00 2001 From: darken Date: Thu, 2 Feb 2023 11:50:33 +0100 Subject: [PATCH] Smooth rssi values and use reliability (missed signals) as boost, not as factor. --- .../collections/CollectionExtensions.kt | 10 ++++ .../eu/darken/capod/pods/core/PodDevice.kt | 19 +++++--- .../capod/pods/core/apple/ApplePodsFactory.kt | 46 ++++++++++++++----- .../pods/core/apple/airpods/AirPodsGen1.kt | 6 +-- .../pods/core/apple/airpods/AirPodsGen2.kt | 6 +-- .../pods/core/apple/airpods/AirPodsGen3.kt | 6 +-- .../pods/core/apple/airpods/AirPodsMax.kt | 6 +-- .../pods/core/apple/airpods/AirPodsPro.kt | 6 +-- .../pods/core/apple/airpods/AirPodsPro2.kt | 6 +-- .../pods/core/apple/beats/BeatsFitPro.kt | 6 +-- .../capod/pods/core/apple/beats/BeatsFlex.kt | 6 +-- .../capod/pods/core/apple/beats/BeatsSolo3.kt | 6 +-- .../pods/core/apple/beats/BeatsStudio3.kt | 6 +-- .../capod/pods/core/apple/beats/BeatsX.kt | 6 +-- .../pods/core/apple/beats/PowerBeats3.kt | 6 +-- .../pods/core/apple/beats/PowerBeatsPro.kt | 6 +-- .../pods/core/apple/misc/FakeAirPodsGen1.kt | 6 +-- .../pods/core/apple/misc/FakeAirPodsGen2.kt | 6 +-- .../pods/core/apple/misc/FakeAirPodsGen3.kt | 6 +-- .../pods/core/apple/misc/FakeAirPodsPro.kt | 6 +-- .../pods/core/apple/misc/FakeAirPodsPro2.kt | 6 +-- .../core/apple/misc/UnknownAppleDevice.kt | 6 +-- .../capod/pods/core/unknown/UnknownDevice.kt | 2 +- .../pods/core/unknown/UnknownDeviceFactory.kt | 8 ++-- 24 files changed, 118 insertions(+), 81 deletions(-) create mode 100644 app-common/src/main/java/eu/darken/capod/common/collections/CollectionExtensions.kt diff --git a/app-common/src/main/java/eu/darken/capod/common/collections/CollectionExtensions.kt b/app-common/src/main/java/eu/darken/capod/common/collections/CollectionExtensions.kt new file mode 100644 index 00000000..2b917926 --- /dev/null +++ b/app-common/src/main/java/eu/darken/capod/common/collections/CollectionExtensions.kt @@ -0,0 +1,10 @@ +package eu.darken.capod.common.collections + + +fun Collection.median(): Int = this.sorted().let { + if (it.size % 2 == 0) { + (it[it.size / 2] + it[(it.size - 1) / 2]) / 2 + } else { + it[it.size / 2] + } +} \ No newline at end of file diff --git a/app-common/src/main/java/eu/darken/capod/pods/core/PodDevice.kt b/app-common/src/main/java/eu/darken/capod/pods/core/PodDevice.kt index 69a51d42..83719cb1 100644 --- a/app-common/src/main/java/eu/darken/capod/pods/core/PodDevice.kt +++ b/app-common/src/main/java/eu/darken/capod/pods/core/PodDevice.kt @@ -31,14 +31,19 @@ interface PodDevice { val rssi: Int get() = scanResult.rssi - val confidence: Float + val reliability: Float - /** - * This is not correct but it works ¯\_(ツ)_/¯ - * The range of the RSSI is device specific (ROMs). - */ val signalQuality: Float - get() = ((100 - abs(rssi)) / 100f) * (max(BASE_CONFIDENCE, confidence)) + get() { + /** + * This is not correct but it works ¯\_(ツ)_/¯ + * The range of the RSSI is device specific (ROMs). + */ + val sqRssi = ((100 - abs(rssi)) / 100f) + //log("#####", Logging.Priority.VERBOSE) { "Signal Quality ($address): rssi=$sqRssi, reliability=$reliability" } + val sqConfidence = max(BASE_CONFIDENCE, reliability) + return (sqRssi + sqConfidence) / 2f + } val rawData: Map get() = scanResult.manufacturerSpecificData @@ -133,6 +138,6 @@ interface PodDevice { } companion object { - const val BASE_CONFIDENCE = 0.5f + const val BASE_CONFIDENCE = 0.0f } } \ No newline at end of file diff --git a/app-common/src/main/java/eu/darken/capod/pods/core/apple/ApplePodsFactory.kt b/app-common/src/main/java/eu/darken/capod/pods/core/apple/ApplePodsFactory.kt index 5eedcb60..bb1224b5 100644 --- a/app-common/src/main/java/eu/darken/capod/pods/core/apple/ApplePodsFactory.kt +++ b/app-common/src/main/java/eu/darken/capod/pods/core/apple/ApplePodsFactory.kt @@ -1,6 +1,7 @@ package eu.darken.capod.pods.core.apple import eu.darken.capod.common.bluetooth.BleScanResult +import eu.darken.capod.common.collections.median import eu.darken.capod.common.debug.logging.Logging.Priority.VERBOSE import eu.darken.capod.common.debug.logging.Logging.Priority.WARN import eu.darken.capod.common.debug.logging.log @@ -12,6 +13,7 @@ import eu.darken.capod.pods.core.apple.airpods.AirPodsPro import eu.darken.capod.pods.core.apple.protocol.ProximityPairing import java.time.Duration import java.time.Instant +import kotlin.math.max abstract class ApplePodsFactory(private val tag: String) { @@ -46,28 +48,48 @@ abstract class ApplePodsFactory(private val tag: String) { val lastAddress: String get() = history.last().address - val confidence: Float - get() = 0.75f + (history.size / (MAX_HISTORY * 4f)) + val reliability: Float + get() { + if (history.size < 2) return 0f - fun averageRssi(latest: Int): Int = - history.map { it.rssi }.plus(latest).takeLast(10).median() + val now = Instant.now() + + val pingInterval = List(history.dropLast(1).size) { index -> + Duration.between(history[index].seenLastAt, history[index + 1].seenLastAt).toMillis() + }.map { it.toInt() }.median() + + val expectedPings: Float = LOOKBACK.toMillis() / pingInterval.toFloat() + + val recentPings = history.filter { + Duration.between(it.seenLastAt, now).toMillis() < LOOKBACK.toMillis() + pingInterval + }.size + + val reliability: Float = (recentPings / expectedPings) + // log("#####") { "interval=$pingInterval, expectedPerMinute=$expectedPings, count=$recentPings" } + + return max(0.0f, reliability) + } + + fun rssiSmoothed(latest: Int): Int { + val now = Instant.now() + return history + .filter { Duration.between(it.seenLastAt, now) < LOOKBACK } + .map { it.rssi } + .plus(latest) + .median() + } fun isOlderThan(age: Duration): Boolean { val now = Instant.now() return Duration.between(history.last().seenLastAt, now) > age } - private fun List.median(): Int = this.sorted().let { - if (it.size % 2 == 0) - (it[it.size / 2] + it[(it.size - 1) / 2]) / 2 - else - it[it.size / 2] - } - override fun toString(): String = "KnownDevice(history=${history.size}, last=${history.last()})" companion object { - const val MAX_HISTORY = 20 + // 30 seconds at fastest interval + const val MAX_HISTORY = 60 + val LOOKBACK = Duration.ofSeconds(30) } } diff --git a/app-common/src/main/java/eu/darken/capod/pods/core/apple/airpods/AirPodsGen1.kt b/app-common/src/main/java/eu/darken/capod/pods/core/apple/airpods/AirPodsGen1.kt index 68e9d362..24deeb8b 100644 --- a/app-common/src/main/java/eu/darken/capod/pods/core/apple/airpods/AirPodsGen1.kt +++ b/app-common/src/main/java/eu/darken/capod/pods/core/apple/airpods/AirPodsGen1.kt @@ -17,7 +17,7 @@ data class AirPodsGen1 constructor( override val seenCounter: Int = 1, override val scanResult: BleScanResult, override val proximityMessage: ProximityPairing.Message, - override val confidence: Float = PodDevice.BASE_CONFIDENCE, + override val reliability: Float = PodDevice.BASE_CONFIDENCE, private val rssiAverage: Int? = null, private val cachedBatteryPercentage: Float? = null, private val cachedCaseState: DualApplePods.LidState? = null @@ -55,9 +55,9 @@ data class AirPodsGen1 constructor( seenFirstAt = result.seenFirstAt, seenLastAt = scanResult.receivedAt, seenCounter = result.seenCounter, - confidence = result.confidence, + reliability = result.reliability, cachedBatteryPercentage = result.getLatestCaseBattery(), - rssiAverage = result.averageRssi(basic.rssi), + rssiAverage = result.rssiSmoothed(basic.rssi), cachedCaseState = result.getLatestCaseLidState(basic) ) } diff --git a/app-common/src/main/java/eu/darken/capod/pods/core/apple/airpods/AirPodsGen2.kt b/app-common/src/main/java/eu/darken/capod/pods/core/apple/airpods/AirPodsGen2.kt index 10b69825..7fa0c320 100644 --- a/app-common/src/main/java/eu/darken/capod/pods/core/apple/airpods/AirPodsGen2.kt +++ b/app-common/src/main/java/eu/darken/capod/pods/core/apple/airpods/AirPodsGen2.kt @@ -17,7 +17,7 @@ data class AirPodsGen2 constructor( override val seenCounter: Int = 1, override val scanResult: BleScanResult, override val proximityMessage: ProximityPairing.Message, - override val confidence: Float = PodDevice.BASE_CONFIDENCE, + override val reliability: Float = PodDevice.BASE_CONFIDENCE, private val rssiAverage: Int? = null, private val cachedBatteryPercentage: Float? = null, private val cachedCaseState: DualApplePods.LidState? = null @@ -54,9 +54,9 @@ data class AirPodsGen2 constructor( seenFirstAt = result.seenFirstAt, seenLastAt = scanResult.receivedAt, seenCounter = result.seenCounter, - confidence = result.confidence, + reliability = result.reliability, cachedBatteryPercentage = result.getLatestCaseBattery(), - rssiAverage = result.averageRssi(basic.rssi), + rssiAverage = result.rssiSmoothed(basic.rssi), cachedCaseState = result.getLatestCaseLidState(basic) ) } diff --git a/app-common/src/main/java/eu/darken/capod/pods/core/apple/airpods/AirPodsGen3.kt b/app-common/src/main/java/eu/darken/capod/pods/core/apple/airpods/AirPodsGen3.kt index bbe7b9fa..f5701726 100644 --- a/app-common/src/main/java/eu/darken/capod/pods/core/apple/airpods/AirPodsGen3.kt +++ b/app-common/src/main/java/eu/darken/capod/pods/core/apple/airpods/AirPodsGen3.kt @@ -17,7 +17,7 @@ data class AirPodsGen3 constructor( override val seenCounter: Int = 1, override val scanResult: BleScanResult, override val proximityMessage: ProximityPairing.Message, - override val confidence: Float = PodDevice.BASE_CONFIDENCE, + override val reliability: Float = PodDevice.BASE_CONFIDENCE, private val rssiAverage: Int? = null, private val cachedBatteryPercentage: Float? = null, private val cachedCaseState: DualApplePods.LidState? = null @@ -54,9 +54,9 @@ data class AirPodsGen3 constructor( seenFirstAt = result.seenFirstAt, seenLastAt = scanResult.receivedAt, seenCounter = result.seenCounter, - confidence = result.confidence, + reliability = result.reliability, cachedBatteryPercentage = result.getLatestCaseBattery(), - rssiAverage = result.averageRssi(basic.rssi), + rssiAverage = result.rssiSmoothed(basic.rssi), cachedCaseState = result.getLatestCaseLidState(basic) ) } diff --git a/app-common/src/main/java/eu/darken/capod/pods/core/apple/airpods/AirPodsMax.kt b/app-common/src/main/java/eu/darken/capod/pods/core/apple/airpods/AirPodsMax.kt index ca8909aa..76fcfc83 100644 --- a/app-common/src/main/java/eu/darken/capod/pods/core/apple/airpods/AirPodsMax.kt +++ b/app-common/src/main/java/eu/darken/capod/pods/core/apple/airpods/AirPodsMax.kt @@ -20,7 +20,7 @@ data class AirPodsMax( override val seenCounter: Int = 1, override val scanResult: BleScanResult, override val proximityMessage: ProximityPairing.Message, - override val confidence: Float = PodDevice.BASE_CONFIDENCE, + override val reliability: Float = PodDevice.BASE_CONFIDENCE, private val rssiAverage: Int? = null, ) : SingleApplePods, HasEarDetection, HasAppleColor { @@ -58,8 +58,8 @@ data class AirPodsMax( seenFirstAt = result.seenFirstAt, seenLastAt = scanResult.receivedAt, seenCounter = result.seenCounter, - confidence = result.confidence, - rssiAverage = result.averageRssi(basic.rssi), + reliability = result.reliability, + rssiAverage = result.rssiSmoothed(basic.rssi), ) } } diff --git a/app-common/src/main/java/eu/darken/capod/pods/core/apple/airpods/AirPodsPro.kt b/app-common/src/main/java/eu/darken/capod/pods/core/apple/airpods/AirPodsPro.kt index 35c82a2e..2f2d98c3 100644 --- a/app-common/src/main/java/eu/darken/capod/pods/core/apple/airpods/AirPodsPro.kt +++ b/app-common/src/main/java/eu/darken/capod/pods/core/apple/airpods/AirPodsPro.kt @@ -20,7 +20,7 @@ data class AirPodsPro( override val seenCounter: Int = 1, override val scanResult: BleScanResult, override val proximityMessage: ProximityPairing.Message, - override val confidence: Float = PodDevice.BASE_CONFIDENCE, + override val reliability: Float = PodDevice.BASE_CONFIDENCE, private val rssiAverage: Int? = null, private val cachedBatteryPercentage: Float? = null, private val cachedCaseState: LidState? = null @@ -73,9 +73,9 @@ data class AirPodsPro( seenFirstAt = result.seenFirstAt, seenLastAt = scanResult.receivedAt, seenCounter = result.seenCounter, - confidence = result.confidence, + reliability = result.reliability, cachedBatteryPercentage = result.getLatestCaseBattery(), - rssiAverage = result.averageRssi(basic.rssi), + rssiAverage = result.rssiSmoothed(basic.rssi), cachedCaseState = result.getLatestCaseLidState(basic) ) } diff --git a/app-common/src/main/java/eu/darken/capod/pods/core/apple/airpods/AirPodsPro2.kt b/app-common/src/main/java/eu/darken/capod/pods/core/apple/airpods/AirPodsPro2.kt index c6de800e..2353b09e 100644 --- a/app-common/src/main/java/eu/darken/capod/pods/core/apple/airpods/AirPodsPro2.kt +++ b/app-common/src/main/java/eu/darken/capod/pods/core/apple/airpods/AirPodsPro2.kt @@ -20,7 +20,7 @@ data class AirPodsPro2( override val seenCounter: Int = 1, override val scanResult: BleScanResult, override val proximityMessage: ProximityPairing.Message, - override val confidence: Float = PodDevice.BASE_CONFIDENCE, + override val reliability: Float = PodDevice.BASE_CONFIDENCE, private val rssiAverage: Int? = null, private val cachedBatteryPercentage: Float? = null, private val cachedCaseState: LidState? = null @@ -73,9 +73,9 @@ data class AirPodsPro2( seenFirstAt = result.seenFirstAt, seenLastAt = scanResult.receivedAt, seenCounter = result.seenCounter, - confidence = result.confidence, + reliability = result.reliability, cachedBatteryPercentage = result.getLatestCaseBattery(), - rssiAverage = result.averageRssi(basic.rssi), + rssiAverage = result.rssiSmoothed(basic.rssi), cachedCaseState = result.getLatestCaseLidState(basic) ) } diff --git a/app-common/src/main/java/eu/darken/capod/pods/core/apple/beats/BeatsFitPro.kt b/app-common/src/main/java/eu/darken/capod/pods/core/apple/beats/BeatsFitPro.kt index c38597ba..ba821e35 100644 --- a/app-common/src/main/java/eu/darken/capod/pods/core/apple/beats/BeatsFitPro.kt +++ b/app-common/src/main/java/eu/darken/capod/pods/core/apple/beats/BeatsFitPro.kt @@ -17,7 +17,7 @@ data class BeatsFitPro( override val seenCounter: Int = 1, override val scanResult: BleScanResult, override val proximityMessage: ProximityPairing.Message, - override val confidence: Float = PodDevice.BASE_CONFIDENCE, + override val reliability: Float = PodDevice.BASE_CONFIDENCE, private val rssiAverage: Int? = null, private val cachedBatteryPercentage: Float? = null, private val cachedCaseState: DualApplePods.LidState? = null @@ -54,9 +54,9 @@ data class BeatsFitPro( seenFirstAt = result.seenFirstAt, seenLastAt = scanResult.receivedAt, seenCounter = result.seenCounter, - confidence = result.confidence, + reliability = result.reliability, cachedBatteryPercentage = result.getLatestCaseBattery(), - rssiAverage = result.averageRssi(basic.rssi), + rssiAverage = result.rssiSmoothed(basic.rssi), cachedCaseState = result.getLatestCaseLidState(basic) ) } diff --git a/app-common/src/main/java/eu/darken/capod/pods/core/apple/beats/BeatsFlex.kt b/app-common/src/main/java/eu/darken/capod/pods/core/apple/beats/BeatsFlex.kt index 93f69439..02dcc5e2 100644 --- a/app-common/src/main/java/eu/darken/capod/pods/core/apple/beats/BeatsFlex.kt +++ b/app-common/src/main/java/eu/darken/capod/pods/core/apple/beats/BeatsFlex.kt @@ -17,7 +17,7 @@ data class BeatsFlex( override val seenCounter: Int = 1, override val scanResult: BleScanResult, override val proximityMessage: ProximityPairing.Message, - override val confidence: Float = PodDevice.BASE_CONFIDENCE, + override val reliability: Float = PodDevice.BASE_CONFIDENCE, private val rssiAverage: Int? = null, ) : SingleApplePods { @@ -46,8 +46,8 @@ data class BeatsFlex( seenFirstAt = result.seenFirstAt, seenLastAt = scanResult.receivedAt, seenCounter = result.seenCounter, - confidence = result.confidence, - rssiAverage = result.averageRssi(basic.rssi), + reliability = result.reliability, + rssiAverage = result.rssiSmoothed(basic.rssi), ) } diff --git a/app-common/src/main/java/eu/darken/capod/pods/core/apple/beats/BeatsSolo3.kt b/app-common/src/main/java/eu/darken/capod/pods/core/apple/beats/BeatsSolo3.kt index 11f4d0ab..ab965acd 100644 --- a/app-common/src/main/java/eu/darken/capod/pods/core/apple/beats/BeatsSolo3.kt +++ b/app-common/src/main/java/eu/darken/capod/pods/core/apple/beats/BeatsSolo3.kt @@ -17,7 +17,7 @@ data class BeatsSolo3( override val seenCounter: Int = 1, override val scanResult: BleScanResult, override val proximityMessage: ProximityPairing.Message, - override val confidence: Float = PodDevice.BASE_CONFIDENCE, + override val reliability: Float = PodDevice.BASE_CONFIDENCE, private val rssiAverage: Int? = null, ) : SingleApplePods { @@ -45,8 +45,8 @@ data class BeatsSolo3( seenFirstAt = result.seenFirstAt, seenLastAt = scanResult.receivedAt, seenCounter = result.seenCounter, - confidence = result.confidence, - rssiAverage = result.averageRssi(basic.rssi), + reliability = result.reliability, + rssiAverage = result.rssiSmoothed(basic.rssi), ) } diff --git a/app-common/src/main/java/eu/darken/capod/pods/core/apple/beats/BeatsStudio3.kt b/app-common/src/main/java/eu/darken/capod/pods/core/apple/beats/BeatsStudio3.kt index 72cf5a3a..43d9199a 100644 --- a/app-common/src/main/java/eu/darken/capod/pods/core/apple/beats/BeatsStudio3.kt +++ b/app-common/src/main/java/eu/darken/capod/pods/core/apple/beats/BeatsStudio3.kt @@ -17,7 +17,7 @@ data class BeatsStudio3( override val seenCounter: Int = 1, override val scanResult: BleScanResult, override val proximityMessage: ProximityPairing.Message, - override val confidence: Float = PodDevice.BASE_CONFIDENCE, + override val reliability: Float = PodDevice.BASE_CONFIDENCE, private val rssiAverage: Int? = null, ) : SingleApplePods { @@ -43,8 +43,8 @@ data class BeatsStudio3( seenFirstAt = result.seenFirstAt, seenLastAt = scanResult.receivedAt, seenCounter = result.seenCounter, - confidence = result.confidence, - rssiAverage = result.averageRssi(basic.rssi), + reliability = result.reliability, + rssiAverage = result.rssiSmoothed(basic.rssi), ) } } diff --git a/app-common/src/main/java/eu/darken/capod/pods/core/apple/beats/BeatsX.kt b/app-common/src/main/java/eu/darken/capod/pods/core/apple/beats/BeatsX.kt index f6b93fbb..879f1ebb 100644 --- a/app-common/src/main/java/eu/darken/capod/pods/core/apple/beats/BeatsX.kt +++ b/app-common/src/main/java/eu/darken/capod/pods/core/apple/beats/BeatsX.kt @@ -17,7 +17,7 @@ data class BeatsX( override val seenCounter: Int = 1, override val scanResult: BleScanResult, override val proximityMessage: ProximityPairing.Message, - override val confidence: Float = PodDevice.BASE_CONFIDENCE, + override val reliability: Float = PodDevice.BASE_CONFIDENCE, private val rssiAverage: Int? = null, ) : SingleApplePods { @@ -46,8 +46,8 @@ data class BeatsX( seenFirstAt = result.seenFirstAt, seenLastAt = scanResult.receivedAt, seenCounter = result.seenCounter, - confidence = result.confidence, - rssiAverage = result.averageRssi(basic.rssi), + reliability = result.reliability, + rssiAverage = result.rssiSmoothed(basic.rssi), ) } diff --git a/app-common/src/main/java/eu/darken/capod/pods/core/apple/beats/PowerBeats3.kt b/app-common/src/main/java/eu/darken/capod/pods/core/apple/beats/PowerBeats3.kt index 83130e9d..2ab40e8e 100644 --- a/app-common/src/main/java/eu/darken/capod/pods/core/apple/beats/PowerBeats3.kt +++ b/app-common/src/main/java/eu/darken/capod/pods/core/apple/beats/PowerBeats3.kt @@ -17,7 +17,7 @@ data class PowerBeats3( override val seenCounter: Int = 1, override val scanResult: BleScanResult, override val proximityMessage: ProximityPairing.Message, - override val confidence: Float = PodDevice.BASE_CONFIDENCE, + override val reliability: Float = PodDevice.BASE_CONFIDENCE, private val rssiAverage: Int? = null, ) : SingleApplePods { @@ -46,8 +46,8 @@ data class PowerBeats3( seenFirstAt = result.seenFirstAt, seenLastAt = scanResult.receivedAt, seenCounter = result.seenCounter, - confidence = result.confidence, - rssiAverage = result.averageRssi(basic.rssi), + reliability = result.reliability, + rssiAverage = result.rssiSmoothed(basic.rssi), ) } } diff --git a/app-common/src/main/java/eu/darken/capod/pods/core/apple/beats/PowerBeatsPro.kt b/app-common/src/main/java/eu/darken/capod/pods/core/apple/beats/PowerBeatsPro.kt index ce3e3045..aaabfe56 100644 --- a/app-common/src/main/java/eu/darken/capod/pods/core/apple/beats/PowerBeatsPro.kt +++ b/app-common/src/main/java/eu/darken/capod/pods/core/apple/beats/PowerBeatsPro.kt @@ -17,7 +17,7 @@ data class PowerBeatsPro( override val seenCounter: Int = 1, override val scanResult: BleScanResult, override val proximityMessage: ProximityPairing.Message, - override val confidence: Float = PodDevice.BASE_CONFIDENCE, + override val reliability: Float = PodDevice.BASE_CONFIDENCE, private val rssiAverage: Int? = null, private val cachedBatteryPercentage: Float? = null, private val cachedCaseState: DualApplePods.LidState? = null @@ -54,9 +54,9 @@ data class PowerBeatsPro( seenFirstAt = result.seenFirstAt, seenLastAt = scanResult.receivedAt, seenCounter = result.seenCounter, - confidence = result.confidence, + reliability = result.reliability, cachedBatteryPercentage = result.getLatestCaseBattery(), - rssiAverage = result.averageRssi(basic.rssi), + rssiAverage = result.rssiSmoothed(basic.rssi), cachedCaseState = result.getLatestCaseLidState(basic) ) } diff --git a/app-common/src/main/java/eu/darken/capod/pods/core/apple/misc/FakeAirPodsGen1.kt b/app-common/src/main/java/eu/darken/capod/pods/core/apple/misc/FakeAirPodsGen1.kt index 52672f44..a4edb0c0 100644 --- a/app-common/src/main/java/eu/darken/capod/pods/core/apple/misc/FakeAirPodsGen1.kt +++ b/app-common/src/main/java/eu/darken/capod/pods/core/apple/misc/FakeAirPodsGen1.kt @@ -25,7 +25,7 @@ data class FakeAirPodsGen1 constructor( override val seenCounter: Int = 1, override val scanResult: BleScanResult, override val proximityMessage: ProximityPairing.Message, - override val confidence: Float = PodDevice.BASE_CONFIDENCE, + override val reliability: Float = PodDevice.BASE_CONFIDENCE, private val rssiAverage: Int? = null, private val cachedBatteryPercentage: Float? = null, ) : ApplePods, DualPodDevice, HasEarDetectionDual, HasChargeDetectionDual, HasCase { @@ -138,9 +138,9 @@ data class FakeAirPodsGen1 constructor( seenFirstAt = result.seenFirstAt, seenLastAt = scanResult.receivedAt, seenCounter = result.seenCounter, - confidence = result.confidence, + reliability = result.reliability, cachedBatteryPercentage = result.getLatestCaseBattery(), - rssiAverage = result.averageRssi(basic.rssi), + rssiAverage = result.rssiSmoothed(basic.rssi), ) } } diff --git a/app-common/src/main/java/eu/darken/capod/pods/core/apple/misc/FakeAirPodsGen2.kt b/app-common/src/main/java/eu/darken/capod/pods/core/apple/misc/FakeAirPodsGen2.kt index 6de84fe9..53d06708 100644 --- a/app-common/src/main/java/eu/darken/capod/pods/core/apple/misc/FakeAirPodsGen2.kt +++ b/app-common/src/main/java/eu/darken/capod/pods/core/apple/misc/FakeAirPodsGen2.kt @@ -23,7 +23,7 @@ data class FakeAirPodsGen2 constructor( override val seenCounter: Int = 1, override val scanResult: BleScanResult, override val proximityMessage: ProximityPairing.Message, - override val confidence: Float = PodDevice.BASE_CONFIDENCE, + override val reliability: Float = PodDevice.BASE_CONFIDENCE, private val rssiAverage: Int? = null, private val cachedBatteryPercentage: Float? = null, ) : ApplePods, DualPodDevice, HasEarDetectionDual, HasChargeDetectionDual, HasCase { @@ -136,9 +136,9 @@ data class FakeAirPodsGen2 constructor( seenFirstAt = result.seenFirstAt, seenLastAt = scanResult.receivedAt, seenCounter = result.seenCounter, - confidence = result.confidence, + reliability = result.reliability, cachedBatteryPercentage = result.getLatestCaseBattery(), - rssiAverage = result.averageRssi(basic.rssi), + rssiAverage = result.rssiSmoothed(basic.rssi), ) } } diff --git a/app-common/src/main/java/eu/darken/capod/pods/core/apple/misc/FakeAirPodsGen3.kt b/app-common/src/main/java/eu/darken/capod/pods/core/apple/misc/FakeAirPodsGen3.kt index d9b6d418..c6765186 100644 --- a/app-common/src/main/java/eu/darken/capod/pods/core/apple/misc/FakeAirPodsGen3.kt +++ b/app-common/src/main/java/eu/darken/capod/pods/core/apple/misc/FakeAirPodsGen3.kt @@ -25,7 +25,7 @@ data class FakeAirPodsGen3 constructor( override val seenCounter: Int = 1, override val scanResult: BleScanResult, override val proximityMessage: ProximityPairing.Message, - override val confidence: Float = PodDevice.BASE_CONFIDENCE, + override val reliability: Float = PodDevice.BASE_CONFIDENCE, private val rssiAverage: Int? = null, private val cachedBatteryPercentage: Float? = null, ) : ApplePods, DualPodDevice, HasEarDetectionDual, HasChargeDetectionDual, HasCase { @@ -138,9 +138,9 @@ data class FakeAirPodsGen3 constructor( seenFirstAt = result.seenFirstAt, seenLastAt = scanResult.receivedAt, seenCounter = result.seenCounter, - confidence = result.confidence, + reliability = result.reliability, cachedBatteryPercentage = result.getLatestCaseBattery(), - rssiAverage = result.averageRssi(basic.rssi), + rssiAverage = result.rssiSmoothed(basic.rssi), ) } diff --git a/app-common/src/main/java/eu/darken/capod/pods/core/apple/misc/FakeAirPodsPro.kt b/app-common/src/main/java/eu/darken/capod/pods/core/apple/misc/FakeAirPodsPro.kt index def93362..03dee942 100644 --- a/app-common/src/main/java/eu/darken/capod/pods/core/apple/misc/FakeAirPodsPro.kt +++ b/app-common/src/main/java/eu/darken/capod/pods/core/apple/misc/FakeAirPodsPro.kt @@ -27,7 +27,7 @@ data class FakeAirPodsPro constructor( override val seenCounter: Int = 1, override val scanResult: BleScanResult, override val proximityMessage: ProximityPairing.Message, - override val confidence: Float = PodDevice.BASE_CONFIDENCE, + override val reliability: Float = PodDevice.BASE_CONFIDENCE, private val rssiAverage: Int? = null, private val cachedBatteryPercentage: Float? = null, ) : ApplePods, DualPodDevice, HasChargeDetectionDual, HasEarDetectionDual, HasCase { @@ -156,9 +156,9 @@ data class FakeAirPodsPro constructor( seenFirstAt = result.seenFirstAt, seenLastAt = scanResult.receivedAt, seenCounter = result.seenCounter, - confidence = result.confidence, + reliability = result.reliability, cachedBatteryPercentage = result.getLatestCaseBattery(), - rssiAverage = result.averageRssi(basic.rssi), + rssiAverage = result.rssiSmoothed(basic.rssi), ) } } diff --git a/app-common/src/main/java/eu/darken/capod/pods/core/apple/misc/FakeAirPodsPro2.kt b/app-common/src/main/java/eu/darken/capod/pods/core/apple/misc/FakeAirPodsPro2.kt index 8179e208..dc3a5a00 100644 --- a/app-common/src/main/java/eu/darken/capod/pods/core/apple/misc/FakeAirPodsPro2.kt +++ b/app-common/src/main/java/eu/darken/capod/pods/core/apple/misc/FakeAirPodsPro2.kt @@ -27,7 +27,7 @@ data class FakeAirPodsPro2 constructor( override val seenCounter: Int = 1, override val scanResult: BleScanResult, override val proximityMessage: ProximityPairing.Message, - override val confidence: Float = PodDevice.BASE_CONFIDENCE, + override val reliability: Float = PodDevice.BASE_CONFIDENCE, private val rssiAverage: Int? = null, private val cachedBatteryPercentage: Float? = null, private val cachedCaseState: DualApplePods.LidState? = null, @@ -153,9 +153,9 @@ data class FakeAirPodsPro2 constructor( seenFirstAt = result.seenFirstAt, seenLastAt = scanResult.receivedAt, seenCounter = result.seenCounter, - confidence = result.confidence, + reliability = result.reliability, cachedBatteryPercentage = result.getLatestCaseBattery(), - rssiAverage = result.averageRssi(basic.rssi), + rssiAverage = result.rssiSmoothed(basic.rssi), ) } diff --git a/app-common/src/main/java/eu/darken/capod/pods/core/apple/misc/UnknownAppleDevice.kt b/app-common/src/main/java/eu/darken/capod/pods/core/apple/misc/UnknownAppleDevice.kt index d82048b2..2a6fd530 100644 --- a/app-common/src/main/java/eu/darken/capod/pods/core/apple/misc/UnknownAppleDevice.kt +++ b/app-common/src/main/java/eu/darken/capod/pods/core/apple/misc/UnknownAppleDevice.kt @@ -18,7 +18,7 @@ data class UnknownAppleDevice( override val seenCounter: Int = 1, override val scanResult: BleScanResult, override val proximityMessage: ProximityPairing.Message, - override val confidence: Float = 0f, + override val reliability: Float = 0f, private val rssiAverage: Int? = null, ) : ApplePods { @@ -49,8 +49,8 @@ data class UnknownAppleDevice( seenFirstAt = result.seenFirstAt, seenLastAt = scanResult.receivedAt, seenCounter = result.seenCounter, - confidence = result.confidence, - rssiAverage = result.averageRssi(basic.rssi), + reliability = result.reliability, + rssiAverage = result.rssiSmoothed(basic.rssi), ) } } diff --git a/app-common/src/main/java/eu/darken/capod/pods/core/unknown/UnknownDevice.kt b/app-common/src/main/java/eu/darken/capod/pods/core/unknown/UnknownDevice.kt index b3d5bc64..685862ed 100644 --- a/app-common/src/main/java/eu/darken/capod/pods/core/unknown/UnknownDevice.kt +++ b/app-common/src/main/java/eu/darken/capod/pods/core/unknown/UnknownDevice.kt @@ -13,7 +13,7 @@ data class UnknownDevice( override val seenFirstAt: Instant = Instant.now(), override val seenCounter: Int = 1, override val scanResult: BleScanResult, - override val confidence: Float = 0f, + override val reliability: Float = 0f, private val rssiAverage: Int? = null, ) : PodDevice { diff --git a/app-common/src/main/java/eu/darken/capod/pods/core/unknown/UnknownDeviceFactory.kt b/app-common/src/main/java/eu/darken/capod/pods/core/unknown/UnknownDeviceFactory.kt index 97c08564..7fae3918 100644 --- a/app-common/src/main/java/eu/darken/capod/pods/core/unknown/UnknownDeviceFactory.kt +++ b/app-common/src/main/java/eu/darken/capod/pods/core/unknown/UnknownDeviceFactory.kt @@ -34,8 +34,8 @@ class UnknownDeviceFactory @Inject constructor() { seenFirstAt = result.seenFirstAt, seenLastAt = scanResult.receivedAt, seenCounter = result.seenCounter, - confidence = result.confidence, - rssiAverage = result.averageRssi(basic.rssi), + reliability = result.confidence, + rssiAverage = result.rssiSmoothed(basic.rssi), ) } @@ -52,7 +52,7 @@ class UnknownDeviceFactory @Inject constructor() { val confidence: Float get() = 0.75f + (history.size / (MAX_HISTORY * 4f)) - fun averageRssi(latest: Int): Int = + fun rssiSmoothed(latest: Int): Int = history.map { it.rssi }.plus(latest).takeLast(10).median() fun isOlderThan(age: Duration): Boolean { @@ -70,7 +70,7 @@ class UnknownDeviceFactory @Inject constructor() { override fun toString(): String = "KnownDevice(history=${history.size}, last=${history.last()})" companion object { - const val MAX_HISTORY = 10 + const val MAX_HISTORY = 20 } }