From 16da51d095ef0fa9cb8670551ebe1f2d2631ec51 Mon Sep 17 00:00:00 2001 From: darken Date: Mon, 19 Dec 2022 16:40:19 +0100 Subject: [PATCH] Refactor fake airpods code and improve tests --- .../eu/darken/capod/pods/core/PodDevice.kt | 8 +- .../pods/core/apple/AppleFactoryModule.kt | 4 +- .../misc/{Twsi99999.kt => FakeAirPodsGen1.kt} | 11 +- .../pods/core/apple/misc/FakeAirPodsGen3.kt | 108 +++++++++++++++--- .../pods/core/apple/misc/FakeAirPodsPro.kt | 1 + .../core/apple/airpods/AirPodsGen1Test.kt | 3 + .../core/apple/airpods/AirPodsGen2Test.kt | 3 + .../core/apple/airpods/AirPodsGen3Test.kt | 3 + .../pods/core/apple/airpods/AirPodsMaxTest.kt | 3 + .../core/apple/airpods/AirPodsPro2Test.kt | 3 + .../pods/core/apple/airpods/AirPodsProTest.kt | 3 + .../pods/core/apple/beats/BeatsFlexText.kt | 3 + .../pods/core/apple/beats/BeatsSolo3Test.kt | 3 + .../pods/core/apple/beats/BeatsStudio3Test.kt | 3 + .../capod/pods/core/apple/beats/BeatsXTest.kt | 3 + .../pods/core/apple/beats/PowerBeats3Test.kt | 3 + .../core/apple/beats/PowerBeatsProTest.kt | 3 + ...wsi99999Test.kt => FakeAirPodsGen1Test.kt} | 7 +- .../core/apple/misc/FakeAirPodsGen3Test.kt | 22 ++-- .../core/apple/misc/FakeAirPodsProTest.kt | 3 + 20 files changed, 163 insertions(+), 37 deletions(-) rename app-common/src/main/java/eu/darken/capod/pods/core/apple/misc/{Twsi99999.kt => FakeAirPodsGen1.kt} (92%) rename app-common/src/test/java/eu/darken/capod/pods/core/apple/misc/{Twsi99999Test.kt => FakeAirPodsGen1Test.kt} (78%) 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 28aefcd6..5272ede2 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 @@ -104,14 +104,14 @@ interface PodDevice { @Json(name = "beats.powerbeats.pro") POWERBEATS_PRO( "Power Beats Pro" ), - @Json(name = "fakes.tws.i99999") TWS_I99999( - "TWS i99999" + @Json(name = "fakes.tws.i99999") FAKE_AIRPODS_GEN1( + "AirPods (Gen 1)? \uD83C\uDFAD" ), @Json(name = "fakes.varunr.airpodspro") FAKE_AIRPODS_PRO( - "AirPods Pro?" + "AirPods Pro? \uD83C\uDFAD" ), @Json(name = "fakes.generic.airpods.gen3") FAKE_AIRPODS_GEN3( - "AirPods (Gen 3)?" + "AirPods (Gen 3)? \uD83C\uDFAD" ), @Json(name = "unknown") UNKNOWN( "Unknown" diff --git a/app-common/src/main/java/eu/darken/capod/pods/core/apple/AppleFactoryModule.kt b/app-common/src/main/java/eu/darken/capod/pods/core/apple/AppleFactoryModule.kt index e4b49314..6e591111 100644 --- a/app-common/src/main/java/eu/darken/capod/pods/core/apple/AppleFactoryModule.kt +++ b/app-common/src/main/java/eu/darken/capod/pods/core/apple/AppleFactoryModule.kt @@ -7,9 +7,9 @@ import dagger.hilt.components.SingletonComponent import dagger.multibindings.IntoSet import eu.darken.capod.pods.core.apple.airpods.* import eu.darken.capod.pods.core.apple.beats.* +import eu.darken.capod.pods.core.apple.misc.FakeAirPodsGen1 import eu.darken.capod.pods.core.apple.misc.FakeAirPodsGen3 import eu.darken.capod.pods.core.apple.misc.FakeAirPodsPro -import eu.darken.capod.pods.core.apple.misc.Twsi99999 @InstallIn(SingletonComponent::class) @Module @@ -30,7 +30,7 @@ abstract class AppleFactoryModule { @Binds @IntoSet abstract fun powerBeats3(factory: PowerBeats3.Factory): ApplePodsFactory @Binds @IntoSet abstract fun powerBeatsPro(factory: PowerBeatsPro.Factory): ApplePodsFactory - @Binds @IntoSet abstract fun fakesTwsi999999(factory: Twsi99999.Factory): ApplePodsFactory + @Binds @IntoSet abstract fun fakeAirPodsGen1(factory: FakeAirPodsGen1.Factory): ApplePodsFactory @Binds @IntoSet abstract fun fakeAirPodsPro(factory: FakeAirPodsPro.Factory): ApplePodsFactory @Binds @IntoSet abstract fun fakeAirPodsGen3(factory: FakeAirPodsGen3.Factory): ApplePodsFactory } \ No newline at end of file diff --git a/app-common/src/main/java/eu/darken/capod/pods/core/apple/misc/Twsi99999.kt b/app-common/src/main/java/eu/darken/capod/pods/core/apple/misc/FakeAirPodsGen1.kt similarity index 92% rename from app-common/src/main/java/eu/darken/capod/pods/core/apple/misc/Twsi99999.kt rename to app-common/src/main/java/eu/darken/capod/pods/core/apple/misc/FakeAirPodsGen1.kt index c8a319b3..449bca60 100644 --- a/app-common/src/main/java/eu/darken/capod/pods/core/apple/misc/Twsi99999.kt +++ b/app-common/src/main/java/eu/darken/capod/pods/core/apple/misc/FakeAirPodsGen1.kt @@ -19,8 +19,9 @@ import javax.inject.Inject /** * Basically an AirPods GEN1 clone * Similar data structure but a lot of placeholder values or hardcoded values + * Marketed as TWS i99999 */ -data class Twsi99999 constructor( +data class FakeAirPodsGen1 constructor( override val identifier: PodDevice.Id = PodDevice.Id(), override val seenLastAt: Instant = Instant.now(), override val seenFirstAt: Instant = Instant.now(), @@ -32,7 +33,7 @@ data class Twsi99999 constructor( private val cachedBatteryPercentage: Float? = null, ) : ApplePods, DualPodDevice, HasDualMicrophone, HasCase { - override val model: PodDevice.Model = PodDevice.Model.TWS_I99999 + override val model: PodDevice.Model = PodDevice.Model.FAKE_AIRPODS_GEN1 override val rssi: Int get() = rssiAverage ?: super.rssi @@ -109,7 +110,7 @@ data class Twsi99999 constructor( override val isCaseCharging: Boolean get() = rawFlags.isBitSet(2) - class Factory @Inject constructor() : ApplePodsFactory(TAG) { + class Factory @Inject constructor() : ApplePodsFactory(TAG) { override fun isResponsible(message: ProximityPairing.Message): Boolean = message.run { // Official message length is 19HEX, i.e. binary 25, did they copy this wrong? @@ -117,7 +118,7 @@ data class Twsi99999 constructor( } override fun create(scanResult: BleScanResult, message: ProximityPairing.Message): ApplePods { - var basic = Twsi99999(scanResult = scanResult, proximityMessage = message) + var basic = FakeAirPodsGen1(scanResult = scanResult, proximityMessage = message) val result = searchHistory(basic) if (result != null) basic = basic.copy(identifier = result.id) @@ -139,6 +140,6 @@ data class Twsi99999 constructor( companion object { private val DEVICE_CODE = 0x0220.toUShort() - private val TAG = logTag("PodDevice", "Apple", "TWS", "i99999") + private val TAG = logTag("PodDevice", "Apple", "Fake", "AirPods", "Gen1") } } \ No newline at end of file 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 2ee3b7b6..62ec3b5b 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 @@ -1,11 +1,14 @@ package eu.darken.capod.pods.core.apple.misc import eu.darken.capod.common.bluetooth.BleScanResult +import eu.darken.capod.common.debug.logging.log import eu.darken.capod.common.debug.logging.logTag -import eu.darken.capod.pods.core.PodDevice +import eu.darken.capod.common.isBitSet +import eu.darken.capod.common.lowerNibble +import eu.darken.capod.common.upperNibble +import eu.darken.capod.pods.core.* import eu.darken.capod.pods.core.apple.ApplePods -import eu.darken.capod.pods.core.apple.DualAirPods -import eu.darken.capod.pods.core.apple.DualApplePodsFactory +import eu.darken.capod.pods.core.apple.ApplePodsFactory import eu.darken.capod.pods.core.apple.protocol.ProximityPairing import java.time.Instant import javax.inject.Inject @@ -25,20 +28,98 @@ data class FakeAirPodsGen3 constructor( override val confidence: Float = PodDevice.BASE_CONFIDENCE, private val rssiAverage: Int? = null, private val cachedBatteryPercentage: Float? = null, - private val cachedCaseState: DualAirPods.LidState? = null -) : DualAirPods { +) : ApplePods, DualPodDevice, HasDualMicrophone, HasCase, HasChargeDetectionDual { + override val model: PodDevice.Model = PodDevice.Model.FAKE_AIRPODS_GEN3 - override val batteryCasePercent: Float? - get() = super.batteryCasePercent ?: cachedBatteryPercentage - - override val caseLidState: DualAirPods.LidState - get() = cachedCaseState ?: super.caseLidState - override val rssi: Int - get() = rssiAverage ?: super.rssi + get() = rssiAverage ?: super.rssi - class Factory @Inject constructor() : DualApplePodsFactory(TAG) { + /** + * Normally values for the left pod are in the lower nibbles, if the left pod is primary (microphone) + * If the right pod is the primary, the values are flipped. + */ + val areValuesFlipped: Boolean + get() = !rawStatus.isBitSet(5) + + override val batteryLeftPodPercent: Float? + get() { + val value = when (areValuesFlipped) { + true -> rawPodsBattery.upperNibble.toInt() + false -> rawPodsBattery.lowerNibble.toInt() + } + return when (value) { + 15 -> null + else -> if (value > 10) { + log { "Left pod: Above 100% battery: $value" } + 1.0f + } else { + (value / 10f) + } + } + } + + override val batteryRightPodPercent: Float? + get() { + val value = when (areValuesFlipped) { + true -> rawPodsBattery.lowerNibble.toInt() + false -> rawPodsBattery.upperNibble.toInt() + } + return when (value) { + 15 -> null + else -> if (value > 10) { + log { "Right pod: Above 100% battery: $value" } + 1.0f + } else { + value / 10f + } + } + } + + override val isLeftPodCharging: Boolean + get() = when (areValuesFlipped) { + false -> rawFlags.isBitSet(0) + true -> rawFlags.isBitSet(1) + } + + override val isRightPodCharging: Boolean + get() = when (areValuesFlipped) { + false -> rawFlags.isBitSet(1) + true -> rawFlags.isBitSet(0) + } + + val isThisPodInThecase: Boolean + get() = rawStatus.isBitSet(6) + + /** + * The data flip bit is set if the left pod is primary. + * For the pod that is in the case, this is flipped again though. + */ + override val isLeftPodMicrophone: Boolean + get() = rawStatus.isBitSet(5) xor isThisPodInThecase + + /** + * The data flip bit is UNset if the right pod is primary. + * For the pod that is in the case, this is flipped again though. + */ + override val isRightPodMicrophone: Boolean + get() = !rawStatus.isBitSet(5) xor isThisPodInThecase + + override val batteryCasePercent: Float? + get() = when (val value = rawCaseBattery.toInt()) { + 15 -> cachedBatteryPercentage + else -> if (value > 10) { + log { "Case: Above 100% battery: $value" } + 1.0f + } else { + value / 10f + } + } + + override val isCaseCharging: Boolean + get() = rawFlags.isBitSet(2) + + class Factory @Inject constructor() : ApplePodsFactory(TAG) { override fun isResponsible(message: ProximityPairing.Message): Boolean = message.run { // Official message length is 19HEX, i.e. binary 25, did they copy this wrong? @@ -62,7 +143,6 @@ data class FakeAirPodsGen3 constructor( confidence = result.confidence, cachedBatteryPercentage = result.getLatestCaseBattery(), rssiAverage = result.averageRssi(basic.rssi), - cachedCaseState = result.getLatestCaseLidState(basic) ) } 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 f28cece1..ef622ff5 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 @@ -19,6 +19,7 @@ import javax.inject.Inject /** * AirPods Pro clone similar to Twsi999999. * Shorter data structure. + * https://discord.com/channels/548521543039189022/927235844127993866/962068944196358234 */ data class FakeAirPodsPro constructor( override val identifier: PodDevice.Id = PodDevice.Id(), diff --git a/app-common/src/test/java/eu/darken/capod/pods/core/apple/airpods/AirPodsGen1Test.kt b/app-common/src/test/java/eu/darken/capod/pods/core/apple/airpods/AirPodsGen1Test.kt index 316989a4..8bcb23e9 100644 --- a/app-common/src/test/java/eu/darken/capod/pods/core/apple/airpods/AirPodsGen1Test.kt +++ b/app-common/src/test/java/eu/darken/capod/pods/core/apple/airpods/AirPodsGen1Test.kt @@ -1,5 +1,6 @@ package eu.darken.capod.pods.core.apple.airpods +import eu.darken.capod.pods.core.PodDevice import eu.darken.capod.pods.core.apple.BaseAirPodsTest import eu.darken.capod.pods.core.apple.DualAirPods import eu.darken.capod.pods.core.apple.HasAppleColor @@ -39,6 +40,8 @@ class AirPodsGen1Test : BaseAirPodsTest() { state shouldBe DualAirPods.ConnectionState.DISCONNECTED podStyle.identifier shouldBe HasAppleColor.DeviceColor.WHITE.name + + model shouldBe PodDevice.Model.AIRPODS_GEN1 } } } \ No newline at end of file diff --git a/app-common/src/test/java/eu/darken/capod/pods/core/apple/airpods/AirPodsGen2Test.kt b/app-common/src/test/java/eu/darken/capod/pods/core/apple/airpods/AirPodsGen2Test.kt index c8a9e5bd..b4ce5960 100644 --- a/app-common/src/test/java/eu/darken/capod/pods/core/apple/airpods/AirPodsGen2Test.kt +++ b/app-common/src/test/java/eu/darken/capod/pods/core/apple/airpods/AirPodsGen2Test.kt @@ -1,5 +1,6 @@ package eu.darken.capod.pods.core.apple.airpods +import eu.darken.capod.pods.core.PodDevice import eu.darken.capod.pods.core.apple.BaseAirPodsTest import eu.darken.capod.pods.core.apple.DualAirPods import eu.darken.capod.pods.core.apple.HasAppleColor @@ -38,6 +39,8 @@ class AirPodsGen2Test : BaseAirPodsTest() { state shouldBe DualAirPods.ConnectionState.MUSIC podStyle.identifier shouldBe HasAppleColor.DeviceColor.WHITE.name + + model shouldBe PodDevice.Model.AIRPODS_GEN2 } } } \ No newline at end of file diff --git a/app-common/src/test/java/eu/darken/capod/pods/core/apple/airpods/AirPodsGen3Test.kt b/app-common/src/test/java/eu/darken/capod/pods/core/apple/airpods/AirPodsGen3Test.kt index 92a69489..fd42ac2c 100644 --- a/app-common/src/test/java/eu/darken/capod/pods/core/apple/airpods/AirPodsGen3Test.kt +++ b/app-common/src/test/java/eu/darken/capod/pods/core/apple/airpods/AirPodsGen3Test.kt @@ -1,5 +1,6 @@ package eu.darken.capod.pods.core.apple.airpods +import eu.darken.capod.pods.core.PodDevice import eu.darken.capod.pods.core.apple.BaseAirPodsTest import eu.darken.capod.pods.core.apple.DualAirPods import eu.darken.capod.pods.core.apple.HasAppleColor @@ -38,6 +39,8 @@ class AirPodsGen3Test : BaseAirPodsTest() { state shouldBe DualAirPods.ConnectionState.IDLE podStyle.identifier shouldBe HasAppleColor.DeviceColor.WHITE.name + + model shouldBe PodDevice.Model.AIRPODS_GEN3 } } diff --git a/app-common/src/test/java/eu/darken/capod/pods/core/apple/airpods/AirPodsMaxTest.kt b/app-common/src/test/java/eu/darken/capod/pods/core/apple/airpods/AirPodsMaxTest.kt index 842dd256..9ca5d6b1 100644 --- a/app-common/src/test/java/eu/darken/capod/pods/core/apple/airpods/AirPodsMaxTest.kt +++ b/app-common/src/test/java/eu/darken/capod/pods/core/apple/airpods/AirPodsMaxTest.kt @@ -1,5 +1,6 @@ package eu.darken.capod.pods.core.apple.airpods +import eu.darken.capod.pods.core.PodDevice import eu.darken.capod.pods.core.apple.BaseAirPodsTest import io.kotest.matchers.shouldBe import kotlinx.coroutines.test.runTest @@ -26,6 +27,8 @@ class AirPodsMaxTest : BaseAirPodsTest() { isHeadsetBeingCharged shouldBe false isHeadphonesBeingWorn shouldBe true + + model shouldBe PodDevice.Model.AIRPODS_MAX } } diff --git a/app-common/src/test/java/eu/darken/capod/pods/core/apple/airpods/AirPodsPro2Test.kt b/app-common/src/test/java/eu/darken/capod/pods/core/apple/airpods/AirPodsPro2Test.kt index e297b296..03600f07 100644 --- a/app-common/src/test/java/eu/darken/capod/pods/core/apple/airpods/AirPodsPro2Test.kt +++ b/app-common/src/test/java/eu/darken/capod/pods/core/apple/airpods/AirPodsPro2Test.kt @@ -1,5 +1,6 @@ package eu.darken.capod.pods.core.apple.airpods +import eu.darken.capod.pods.core.PodDevice import eu.darken.capod.pods.core.apple.BaseAirPodsTest import eu.darken.capod.pods.core.apple.HasAppleColor import io.kotest.matchers.shouldBe @@ -40,6 +41,8 @@ class AirPodsPro2Test : BaseAirPodsTest() { batteryCasePercent shouldBe 0.9f podStyle.identifier shouldBe HasAppleColor.DeviceColor.WHITE.name + + model shouldBe PodDevice.Model.AIRPODS_PRO2 } } diff --git a/app-common/src/test/java/eu/darken/capod/pods/core/apple/airpods/AirPodsProTest.kt b/app-common/src/test/java/eu/darken/capod/pods/core/apple/airpods/AirPodsProTest.kt index 9a94e283..c131a090 100644 --- a/app-common/src/test/java/eu/darken/capod/pods/core/apple/airpods/AirPodsProTest.kt +++ b/app-common/src/test/java/eu/darken/capod/pods/core/apple/airpods/AirPodsProTest.kt @@ -1,5 +1,6 @@ package eu.darken.capod.pods.core.apple.airpods +import eu.darken.capod.pods.core.PodDevice import eu.darken.capod.pods.core.apple.BaseAirPodsTest import eu.darken.capod.pods.core.apple.HasAppleColor import io.kotest.matchers.shouldBe @@ -34,6 +35,8 @@ class AirPodsProTest : BaseAirPodsTest() { batteryCasePercent shouldBe 0.5f podStyle.identifier shouldBe HasAppleColor.DeviceColor.WHITE.name + + model shouldBe PodDevice.Model.AIRPODS_PRO } } diff --git a/app-common/src/test/java/eu/darken/capod/pods/core/apple/beats/BeatsFlexText.kt b/app-common/src/test/java/eu/darken/capod/pods/core/apple/beats/BeatsFlexText.kt index 4cb64433..0f591c34 100644 --- a/app-common/src/test/java/eu/darken/capod/pods/core/apple/beats/BeatsFlexText.kt +++ b/app-common/src/test/java/eu/darken/capod/pods/core/apple/beats/BeatsFlexText.kt @@ -1,5 +1,6 @@ package eu.darken.capod.pods.core.apple.beats +import eu.darken.capod.pods.core.PodDevice import eu.darken.capod.pods.core.apple.BaseAirPodsTest import io.kotest.matchers.shouldBe import kotlinx.coroutines.test.runTest @@ -22,6 +23,8 @@ class BeatsFlexText : BaseAirPodsTest() { rawSuffix shouldBe 0x00.toUByte() batteryHeadsetPercent shouldBe 0.4f + + model shouldBe PodDevice.Model.BEATS_FLEX } } diff --git a/app-common/src/test/java/eu/darken/capod/pods/core/apple/beats/BeatsSolo3Test.kt b/app-common/src/test/java/eu/darken/capod/pods/core/apple/beats/BeatsSolo3Test.kt index bee7c5cc..1287e0ec 100644 --- a/app-common/src/test/java/eu/darken/capod/pods/core/apple/beats/BeatsSolo3Test.kt +++ b/app-common/src/test/java/eu/darken/capod/pods/core/apple/beats/BeatsSolo3Test.kt @@ -1,5 +1,6 @@ package eu.darken.capod.pods.core.apple.beats +import eu.darken.capod.pods.core.PodDevice import eu.darken.capod.pods.core.apple.BaseAirPodsTest import io.kotest.matchers.shouldBe import kotlinx.coroutines.test.runTest @@ -22,6 +23,8 @@ class BeatsSolo3Test : BaseAirPodsTest() { rawSuffix shouldBe 0x40.toUByte() batteryHeadsetPercent shouldBe 0.4f + + model shouldBe PodDevice.Model.BEATS_SOLO_3 } } } \ No newline at end of file diff --git a/app-common/src/test/java/eu/darken/capod/pods/core/apple/beats/BeatsStudio3Test.kt b/app-common/src/test/java/eu/darken/capod/pods/core/apple/beats/BeatsStudio3Test.kt index 8bbcec61..1e0c2b11 100644 --- a/app-common/src/test/java/eu/darken/capod/pods/core/apple/beats/BeatsStudio3Test.kt +++ b/app-common/src/test/java/eu/darken/capod/pods/core/apple/beats/BeatsStudio3Test.kt @@ -1,5 +1,6 @@ package eu.darken.capod.pods.core.apple.beats +import eu.darken.capod.pods.core.PodDevice import eu.darken.capod.pods.core.apple.BaseAirPodsTest import io.kotest.matchers.shouldBe import kotlinx.coroutines.test.runTest @@ -22,6 +23,8 @@ class BeatsStudio3Test : BaseAirPodsTest() { rawSuffix shouldBe 0x40.toUByte() batteryHeadsetPercent shouldBe 0.4f + + model shouldBe PodDevice.Model.BEATS_STUDIO_3 } } } \ No newline at end of file diff --git a/app-common/src/test/java/eu/darken/capod/pods/core/apple/beats/BeatsXTest.kt b/app-common/src/test/java/eu/darken/capod/pods/core/apple/beats/BeatsXTest.kt index b917bb98..a645d751 100644 --- a/app-common/src/test/java/eu/darken/capod/pods/core/apple/beats/BeatsXTest.kt +++ b/app-common/src/test/java/eu/darken/capod/pods/core/apple/beats/BeatsXTest.kt @@ -1,5 +1,6 @@ package eu.darken.capod.pods.core.apple.beats +import eu.darken.capod.pods.core.PodDevice import eu.darken.capod.pods.core.apple.BaseAirPodsTest import io.kotest.matchers.shouldBe import kotlinx.coroutines.test.runTest @@ -22,6 +23,8 @@ class BeatsXTest : BaseAirPodsTest() { rawSuffix shouldBe 0x00.toUByte() batteryHeadsetPercent shouldBe 0.5f + + model shouldBe PodDevice.Model.BEATS_X } } } \ No newline at end of file diff --git a/app-common/src/test/java/eu/darken/capod/pods/core/apple/beats/PowerBeats3Test.kt b/app-common/src/test/java/eu/darken/capod/pods/core/apple/beats/PowerBeats3Test.kt index 8a14f17a..ea4c7928 100644 --- a/app-common/src/test/java/eu/darken/capod/pods/core/apple/beats/PowerBeats3Test.kt +++ b/app-common/src/test/java/eu/darken/capod/pods/core/apple/beats/PowerBeats3Test.kt @@ -1,5 +1,6 @@ package eu.darken.capod.pods.core.apple.beats +import eu.darken.capod.pods.core.PodDevice import eu.darken.capod.pods.core.apple.BaseAirPodsTest import io.kotest.matchers.shouldBe import kotlinx.coroutines.test.runTest @@ -22,6 +23,8 @@ class PowerBeats3Test : BaseAirPodsTest() { rawSuffix shouldBe 0x40.toUByte() batteryHeadsetPercent shouldBe 0.4f + + model shouldBe PodDevice.Model.POWERBEATS_3 } } } \ No newline at end of file diff --git a/app-common/src/test/java/eu/darken/capod/pods/core/apple/beats/PowerBeatsProTest.kt b/app-common/src/test/java/eu/darken/capod/pods/core/apple/beats/PowerBeatsProTest.kt index b3e5a10a..bad843f0 100644 --- a/app-common/src/test/java/eu/darken/capod/pods/core/apple/beats/PowerBeatsProTest.kt +++ b/app-common/src/test/java/eu/darken/capod/pods/core/apple/beats/PowerBeatsProTest.kt @@ -1,5 +1,6 @@ package eu.darken.capod.pods.core.apple.beats +import eu.darken.capod.pods.core.PodDevice import eu.darken.capod.pods.core.apple.BaseAirPodsTest import eu.darken.capod.pods.core.apple.HasAppleColor import io.kotest.matchers.shouldBe @@ -34,6 +35,8 @@ class PowerBeatsProTest : BaseAirPodsTest() { batteryCasePercent shouldBe 0.5f podStyle.identifier shouldBe HasAppleColor.DeviceColor.WHITE.name + + model shouldBe PodDevice.Model.POWERBEATS_PRO } } } \ No newline at end of file diff --git a/app-common/src/test/java/eu/darken/capod/pods/core/apple/misc/Twsi99999Test.kt b/app-common/src/test/java/eu/darken/capod/pods/core/apple/misc/FakeAirPodsGen1Test.kt similarity index 78% rename from app-common/src/test/java/eu/darken/capod/pods/core/apple/misc/Twsi99999Test.kt rename to app-common/src/test/java/eu/darken/capod/pods/core/apple/misc/FakeAirPodsGen1Test.kt index cdfce42f..25e62a3a 100644 --- a/app-common/src/test/java/eu/darken/capod/pods/core/apple/misc/Twsi99999Test.kt +++ b/app-common/src/test/java/eu/darken/capod/pods/core/apple/misc/FakeAirPodsGen1Test.kt @@ -1,15 +1,16 @@ package eu.darken.capod.pods.core.apple.misc +import eu.darken.capod.pods.core.PodDevice import eu.darken.capod.pods.core.apple.BaseAirPodsTest import io.kotest.matchers.shouldBe import kotlinx.coroutines.test.runTest import org.junit.jupiter.api.Test -class Twsi99999Test : BaseAirPodsTest() { +class FakeAirPodsGen1Test : BaseAirPodsTest() { @Test fun `charging in box`() = runTest { - create("07 13 01 02 20 71 AA 37 32 00 10 00 64 64 FF 00 00 00 00 00 00") { + create("07 13 01 02 20 71 AA 37 32 00 10 00 64 64 FF 00 00 00 00 00 00") { rawPrefix shouldBe 0x01.toUByte() rawDeviceModel shouldBe 0x0220.toUShort() rawStatus shouldBe 0x71.toUByte() @@ -26,6 +27,8 @@ class Twsi99999Test : BaseAirPodsTest() { isCaseCharging shouldBe false batteryCasePercent shouldBe 0.7f + + model shouldBe PodDevice.Model.FAKE_AIRPODS_GEN1 } } } \ No newline at end of file diff --git a/app-common/src/test/java/eu/darken/capod/pods/core/apple/misc/FakeAirPodsGen3Test.kt b/app-common/src/test/java/eu/darken/capod/pods/core/apple/misc/FakeAirPodsGen3Test.kt index 7994b48b..49ec6245 100644 --- a/app-common/src/test/java/eu/darken/capod/pods/core/apple/misc/FakeAirPodsGen3Test.kt +++ b/app-common/src/test/java/eu/darken/capod/pods/core/apple/misc/FakeAirPodsGen3Test.kt @@ -1,8 +1,7 @@ package eu.darken.capod.pods.core.apple.misc +import eu.darken.capod.pods.core.PodDevice import eu.darken.capod.pods.core.apple.BaseAirPodsTest -import eu.darken.capod.pods.core.apple.DualAirPods -import eu.darken.capod.pods.core.apple.HasAppleColor import io.kotest.matchers.shouldBe import kotlinx.coroutines.test.runTest import org.junit.jupiter.api.Test @@ -12,6 +11,16 @@ class FakeAirPodsGen3Test : BaseAirPodsTest() { @Test fun `charging in case`() = runTest { create("07 13 01 13 20 75 AA 37 34 00 10 00 E4 E4 64 00 00 00 00 00 00") { + rawPrefix shouldBe 0x01.toUByte() + rawDeviceModel shouldBe 0x1320.toUShort() + rawStatus shouldBe 0x75.toUByte() + rawPodsBattery shouldBe 0xAA.toUByte() + rawFlags shouldBe 0x3.toUShort() + rawCaseBattery shouldBe 0x7.toUShort() + rawCaseLidState shouldBe 0x34.toUByte() + rawDeviceColor shouldBe 0x00.toUByte() + rawSuffix shouldBe 0x10.toUByte() + batteryLeftPodPercent shouldBe 1f batteryRightPodPercent shouldBe 1f @@ -19,16 +28,9 @@ class FakeAirPodsGen3Test : BaseAirPodsTest() { isLeftPodCharging shouldBe true isRightPodCharging shouldBe true - isLeftPodInEar shouldBe false - isRightPodInEar shouldBe false batteryCasePercent shouldBe 0.7f - caseLidState shouldBe DualAirPods.LidState.OPEN - - state shouldBe DualAirPods.ConnectionState.UNKNOWN - - podStyle.identifier shouldBe HasAppleColor.DeviceColor.WHITE.name - + model shouldBe PodDevice.Model.FAKE_AIRPODS_GEN3 } } } \ No newline at end of file diff --git a/app-common/src/test/java/eu/darken/capod/pods/core/apple/misc/FakeAirPodsProTest.kt b/app-common/src/test/java/eu/darken/capod/pods/core/apple/misc/FakeAirPodsProTest.kt index 4bc8837b..a9935522 100644 --- a/app-common/src/test/java/eu/darken/capod/pods/core/apple/misc/FakeAirPodsProTest.kt +++ b/app-common/src/test/java/eu/darken/capod/pods/core/apple/misc/FakeAirPodsProTest.kt @@ -1,5 +1,6 @@ package eu.darken.capod.pods.core.apple.misc +import eu.darken.capod.pods.core.PodDevice import eu.darken.capod.pods.core.apple.BaseAirPodsTest import io.kotest.matchers.shouldBe import kotlinx.coroutines.test.runTest @@ -26,6 +27,8 @@ class FakeAirPodsProTest : BaseAirPodsTest() { isCaseCharging shouldBe false batteryCasePercent shouldBe 0.7f + + model shouldBe PodDevice.Model.FAKE_AIRPODS_PRO } } } \ No newline at end of file