diff --git a/app/src/main/java/eu/darken/capod/pods/core/apple/ble/AppleFactoryModule.kt b/app/src/main/java/eu/darken/capod/pods/core/apple/ble/AppleFactoryModule.kt index ebda0ef9..9a8f31eb 100644 --- a/app/src/main/java/eu/darken/capod/pods/core/apple/ble/AppleFactoryModule.kt +++ b/app/src/main/java/eu/darken/capod/pods/core/apple/ble/AppleFactoryModule.kt @@ -20,7 +20,13 @@ import eu.darken.capod.pods.core.apple.ble.devices.airpods.AirPodsPro3 import eu.darken.capod.pods.core.apple.ble.devices.beats.BeatsFitPro import eu.darken.capod.pods.core.apple.ble.devices.beats.BeatsFlex import eu.darken.capod.pods.core.apple.ble.devices.beats.BeatsSolo3 +import eu.darken.capod.pods.core.apple.ble.devices.beats.BeatsSolo4 +import eu.darken.capod.pods.core.apple.ble.devices.beats.BeatsSoloBuds +import eu.darken.capod.pods.core.apple.ble.devices.beats.BeatsSoloPro import eu.darken.capod.pods.core.apple.ble.devices.beats.BeatsStudio3 +import eu.darken.capod.pods.core.apple.ble.devices.beats.BeatsStudioBuds +import eu.darken.capod.pods.core.apple.ble.devices.beats.BeatsStudioBudsPlus +import eu.darken.capod.pods.core.apple.ble.devices.beats.BeatsStudioPro import eu.darken.capod.pods.core.apple.ble.devices.beats.BeatsX import eu.darken.capod.pods.core.apple.ble.devices.beats.PowerBeats3 import eu.darken.capod.pods.core.apple.ble.devices.beats.PowerBeats4 @@ -58,6 +64,12 @@ abstract class AppleFactoryModule { @Binds @IntoSet abstract fun powerBeatsPro(factory: PowerBeatsPro.Factory): ApplePodsFactory @Binds @IntoSet abstract fun powerBeatsPro2(factory: PowerBeatsPro2.Factory): ApplePodsFactory @Binds @IntoSet abstract fun beatsFitPro(factory: BeatsFitPro.Factory): ApplePodsFactory + @Binds @IntoSet abstract fun beatsSoloPro(factory: BeatsSoloPro.Factory): ApplePodsFactory + @Binds @IntoSet abstract fun beatsSolo4(factory: BeatsSolo4.Factory): ApplePodsFactory + @Binds @IntoSet abstract fun beatsSoloBuds(factory: BeatsSoloBuds.Factory): ApplePodsFactory + @Binds @IntoSet abstract fun beatsStudioBuds(factory: BeatsStudioBuds.Factory): ApplePodsFactory + @Binds @IntoSet abstract fun beatsStudioBudsPlus(factory: BeatsStudioBudsPlus.Factory): ApplePodsFactory + @Binds @IntoSet abstract fun beatsStudioPro(factory: BeatsStudioPro.Factory): ApplePodsFactory @Binds @IntoSet abstract fun fakeAirPodsGen1(factory: FakeAirPodsGen1.Factory): ApplePodsFactory @Binds @IntoSet abstract fun fakeAirPodsGen2(factory: FakeAirPodsGen2.Factory): ApplePodsFactory diff --git a/app/src/main/java/eu/darken/capod/pods/core/apple/ble/devices/beats/BeatsSolo4.kt b/app/src/main/java/eu/darken/capod/pods/core/apple/ble/devices/beats/BeatsSolo4.kt new file mode 100644 index 00000000..9be53a1f --- /dev/null +++ b/app/src/main/java/eu/darken/capod/pods/core/apple/ble/devices/beats/BeatsSolo4.kt @@ -0,0 +1,68 @@ +package eu.darken.capod.pods.core.apple.ble.devices.beats + +import eu.darken.capod.common.bluetooth.BleScanResult +import eu.darken.capod.common.debug.logging.logTag +import eu.darken.capod.pods.core.apple.ble.BlePodSnapshot +import eu.darken.capod.pods.core.apple.PodModel +import eu.darken.capod.pods.core.apple.ble.devices.ApplePods +import eu.darken.capod.pods.core.apple.ble.devices.ApplePodsFactory +import eu.darken.capod.pods.core.apple.ble.devices.SingleApplePods +import eu.darken.capod.pods.core.apple.ble.history.PodHistoryRepo +import eu.darken.capod.pods.core.apple.ble.protocol.ProximityMessage +import eu.darken.capod.pods.core.apple.ble.protocol.ProximityPairing +import eu.darken.capod.pods.core.apple.ble.protocol.ProximityPayload +import java.time.Instant +import javax.inject.Inject + +data class BeatsSolo4( + override val identifier: BlePodSnapshot.Id = BlePodSnapshot.Id(), + override val seenLastAt: Instant = Instant.now(), + override val seenFirstAt: Instant = Instant.now(), + override val seenCounter: Int = 1, + override val scanResult: BleScanResult, + override val payload: ProximityPayload, + override val meta: ApplePods.AppleMeta, + override val reliability: Float = BlePodSnapshot.BASE_CONFIDENCE, + private val rssiAverage: Int? = null, +) : SingleApplePods { + + override val model: PodModel = PodModel.BEATS_SOLO_4 + override val rssi: Int + get() = rssiAverage ?: super.rssi + + class Factory @Inject constructor( + private val repo: PodHistoryRepo, + ) : ApplePodsFactory { + override fun isResponsible(message: ProximityMessage): Boolean = message.run { + getModelInfo().full == DEVICE_CODE && length == ProximityPairing.PAIRING_MESSAGE_LENGTH + } + + override suspend fun create( + scanResult: BleScanResult, + payload: ProximityPayload, + meta: ApplePods.AppleMeta + ): ApplePods { + var basic = BeatsSolo4(scanResult = scanResult, payload = payload, meta = meta) + val result = repo.search(basic) + + if (result != null) basic = basic.copy(identifier = result.id) + repo.updateHistory(basic) + + if (result == null) return basic + + return basic.copy( + identifier = result.id, + seenFirstAt = result.seenFirstAt, + seenLastAt = scanResult.receivedAt, + seenCounter = result.seenCounter, + reliability = result.reliability, + rssiAverage = result.rssiSmoothed(basic.rssi), + ) + } + } + + companion object { + private val DEVICE_CODE = 0x2520.toUShort() + private val TAG = logTag("PodDevice", "Beats", "Solo", "4") + } +} diff --git a/app/src/main/java/eu/darken/capod/pods/core/apple/ble/devices/beats/BeatsSoloBuds.kt b/app/src/main/java/eu/darken/capod/pods/core/apple/ble/devices/beats/BeatsSoloBuds.kt new file mode 100644 index 00000000..52bf80f0 --- /dev/null +++ b/app/src/main/java/eu/darken/capod/pods/core/apple/ble/devices/beats/BeatsSoloBuds.kt @@ -0,0 +1,93 @@ +package eu.darken.capod.pods.core.apple.ble.devices.beats + +import androidx.annotation.DrawableRes +import eu.darken.capod.R +import eu.darken.capod.common.bluetooth.BleScanResult +import eu.darken.capod.common.debug.logging.logTag +import eu.darken.capod.pods.core.apple.ble.BlePodSnapshot +import eu.darken.capod.pods.core.apple.PodModel +import eu.darken.capod.pods.core.apple.ble.devices.ApplePods +import eu.darken.capod.pods.core.apple.ble.devices.ApplePodsFactory +import eu.darken.capod.pods.core.apple.ble.devices.DualApplePods +import eu.darken.capod.pods.core.apple.ble.history.PodHistoryRepo +import eu.darken.capod.pods.core.apple.ble.protocol.ProximityMessage +import eu.darken.capod.pods.core.apple.ble.protocol.ProximityPairing +import eu.darken.capod.pods.core.apple.ble.protocol.ProximityPayload +import java.time.Instant +import javax.inject.Inject + +data class BeatsSoloBuds( + override val identifier: BlePodSnapshot.Id = BlePodSnapshot.Id(), + override val seenLastAt: Instant = Instant.now(), + override val seenFirstAt: Instant = Instant.now(), + override val seenCounter: Int = 1, + override val scanResult: BleScanResult, + override val payload: ProximityPayload, + override val meta: ApplePods.AppleMeta, + override val reliability: Float = BlePodSnapshot.BASE_CONFIDENCE, + private val rssiAverage: Int? = null, + private val cachedBatteryPercentage: Float? = null, + private val cachedCaseState: DualApplePods.LidState? = null +) : DualApplePods { + + override val model: PodModel = PodModel.BEATS_SOLO_BUDS + + @get:DrawableRes + override val leftPodIcon: Int + get() = R.drawable.device_beats_fitpro_left + + @get:DrawableRes + override val rightPodIcon: Int + get() = R.drawable.device_beats_fitpro_right + + @get:DrawableRes + override val caseIcon: Int + get() = R.drawable.device_beats_fitpro_case + + override val batteryCasePercent: Float? + get() = super.batteryCasePercent ?: cachedBatteryPercentage + + override val caseLidState: DualApplePods.LidState + get() = cachedCaseState ?: super.caseLidState + + override val rssi: Int + get() = rssiAverage ?: super.rssi + + class Factory @Inject constructor( + private val repo: PodHistoryRepo, + ) : ApplePodsFactory { + override fun isResponsible(message: ProximityMessage): Boolean = message.run { + getModelInfo().full == DEVICE_CODE && length == ProximityPairing.PAIRING_MESSAGE_LENGTH + } + + override suspend fun create( + scanResult: BleScanResult, + payload: ProximityPayload, + meta: ApplePods.AppleMeta + ): ApplePods { + var basic = BeatsSoloBuds(scanResult = scanResult, payload = payload, meta = meta) + val result = repo.search(basic) + + if (result != null) basic = basic.copy(identifier = result.id) + repo.updateHistory(basic) + + if (result == null) return basic + + return basic.copy( + identifier = result.id, + seenFirstAt = result.seenFirstAt, + seenLastAt = scanResult.receivedAt, + seenCounter = result.seenCounter, + reliability = result.reliability, + cachedBatteryPercentage = result.getLatestCaseBattery(), + rssiAverage = result.rssiSmoothed(basic.rssi), + cachedCaseState = result.getLatestCaseLidState(basic) + ) + } + } + + companion object { + private val DEVICE_CODE = 0x2620.toUShort() + private val TAG = logTag("PodDevice", "Beats", "Solo", "Buds") + } +} diff --git a/app/src/main/java/eu/darken/capod/pods/core/apple/ble/devices/beats/BeatsSoloPro.kt b/app/src/main/java/eu/darken/capod/pods/core/apple/ble/devices/beats/BeatsSoloPro.kt new file mode 100644 index 00000000..0b8e2310 --- /dev/null +++ b/app/src/main/java/eu/darken/capod/pods/core/apple/ble/devices/beats/BeatsSoloPro.kt @@ -0,0 +1,68 @@ +package eu.darken.capod.pods.core.apple.ble.devices.beats + +import eu.darken.capod.common.bluetooth.BleScanResult +import eu.darken.capod.common.debug.logging.logTag +import eu.darken.capod.pods.core.apple.ble.BlePodSnapshot +import eu.darken.capod.pods.core.apple.PodModel +import eu.darken.capod.pods.core.apple.ble.devices.ApplePods +import eu.darken.capod.pods.core.apple.ble.devices.ApplePodsFactory +import eu.darken.capod.pods.core.apple.ble.devices.SingleApplePods +import eu.darken.capod.pods.core.apple.ble.history.PodHistoryRepo +import eu.darken.capod.pods.core.apple.ble.protocol.ProximityMessage +import eu.darken.capod.pods.core.apple.ble.protocol.ProximityPairing +import eu.darken.capod.pods.core.apple.ble.protocol.ProximityPayload +import java.time.Instant +import javax.inject.Inject + +data class BeatsSoloPro( + override val identifier: BlePodSnapshot.Id = BlePodSnapshot.Id(), + override val seenLastAt: Instant = Instant.now(), + override val seenFirstAt: Instant = Instant.now(), + override val seenCounter: Int = 1, + override val scanResult: BleScanResult, + override val payload: ProximityPayload, + override val meta: ApplePods.AppleMeta, + override val reliability: Float = BlePodSnapshot.BASE_CONFIDENCE, + private val rssiAverage: Int? = null, +) : SingleApplePods { + + override val model: PodModel = PodModel.BEATS_SOLO_PRO + override val rssi: Int + get() = rssiAverage ?: super.rssi + + class Factory @Inject constructor( + private val repo: PodHistoryRepo, + ) : ApplePodsFactory { + override fun isResponsible(message: ProximityMessage): Boolean = message.run { + getModelInfo().full == DEVICE_CODE && length == ProximityPairing.PAIRING_MESSAGE_LENGTH + } + + override suspend fun create( + scanResult: BleScanResult, + payload: ProximityPayload, + meta: ApplePods.AppleMeta + ): ApplePods { + var basic = BeatsSoloPro(scanResult = scanResult, payload = payload, meta = meta) + val result = repo.search(basic) + + if (result != null) basic = basic.copy(identifier = result.id) + repo.updateHistory(basic) + + if (result == null) return basic + + return basic.copy( + identifier = result.id, + seenFirstAt = result.seenFirstAt, + seenLastAt = scanResult.receivedAt, + seenCounter = result.seenCounter, + reliability = result.reliability, + rssiAverage = result.rssiSmoothed(basic.rssi), + ) + } + } + + companion object { + private val DEVICE_CODE = 0x0C20.toUShort() + private val TAG = logTag("PodDevice", "Beats", "Solo", "Pro") + } +} diff --git a/app/src/main/java/eu/darken/capod/pods/core/apple/ble/devices/beats/BeatsStudioBuds.kt b/app/src/main/java/eu/darken/capod/pods/core/apple/ble/devices/beats/BeatsStudioBuds.kt new file mode 100644 index 00000000..61f2b507 --- /dev/null +++ b/app/src/main/java/eu/darken/capod/pods/core/apple/ble/devices/beats/BeatsStudioBuds.kt @@ -0,0 +1,93 @@ +package eu.darken.capod.pods.core.apple.ble.devices.beats + +import androidx.annotation.DrawableRes +import eu.darken.capod.R +import eu.darken.capod.common.bluetooth.BleScanResult +import eu.darken.capod.common.debug.logging.logTag +import eu.darken.capod.pods.core.apple.ble.BlePodSnapshot +import eu.darken.capod.pods.core.apple.PodModel +import eu.darken.capod.pods.core.apple.ble.devices.ApplePods +import eu.darken.capod.pods.core.apple.ble.devices.ApplePodsFactory +import eu.darken.capod.pods.core.apple.ble.devices.DualApplePods +import eu.darken.capod.pods.core.apple.ble.history.PodHistoryRepo +import eu.darken.capod.pods.core.apple.ble.protocol.ProximityMessage +import eu.darken.capod.pods.core.apple.ble.protocol.ProximityPairing +import eu.darken.capod.pods.core.apple.ble.protocol.ProximityPayload +import java.time.Instant +import javax.inject.Inject + +data class BeatsStudioBuds( + override val identifier: BlePodSnapshot.Id = BlePodSnapshot.Id(), + override val seenLastAt: Instant = Instant.now(), + override val seenFirstAt: Instant = Instant.now(), + override val seenCounter: Int = 1, + override val scanResult: BleScanResult, + override val payload: ProximityPayload, + override val meta: ApplePods.AppleMeta, + override val reliability: Float = BlePodSnapshot.BASE_CONFIDENCE, + private val rssiAverage: Int? = null, + private val cachedBatteryPercentage: Float? = null, + private val cachedCaseState: DualApplePods.LidState? = null +) : DualApplePods { + + override val model: PodModel = PodModel.BEATS_STUDIO_BUDS + + @get:DrawableRes + override val leftPodIcon: Int + get() = R.drawable.device_beats_fitpro_left + + @get:DrawableRes + override val rightPodIcon: Int + get() = R.drawable.device_beats_fitpro_right + + @get:DrawableRes + override val caseIcon: Int + get() = R.drawable.device_beats_fitpro_case + + override val batteryCasePercent: Float? + get() = super.batteryCasePercent ?: cachedBatteryPercentage + + override val caseLidState: DualApplePods.LidState + get() = cachedCaseState ?: super.caseLidState + + override val rssi: Int + get() = rssiAverage ?: super.rssi + + class Factory @Inject constructor( + private val repo: PodHistoryRepo, + ) : ApplePodsFactory { + override fun isResponsible(message: ProximityMessage): Boolean = message.run { + getModelInfo().full == DEVICE_CODE && length == ProximityPairing.PAIRING_MESSAGE_LENGTH + } + + override suspend fun create( + scanResult: BleScanResult, + payload: ProximityPayload, + meta: ApplePods.AppleMeta + ): ApplePods { + var basic = BeatsStudioBuds(scanResult = scanResult, payload = payload, meta = meta) + val result = repo.search(basic) + + if (result != null) basic = basic.copy(identifier = result.id) + repo.updateHistory(basic) + + if (result == null) return basic + + return basic.copy( + identifier = result.id, + seenFirstAt = result.seenFirstAt, + seenLastAt = scanResult.receivedAt, + seenCounter = result.seenCounter, + reliability = result.reliability, + cachedBatteryPercentage = result.getLatestCaseBattery(), + rssiAverage = result.rssiSmoothed(basic.rssi), + cachedCaseState = result.getLatestCaseLidState(basic) + ) + } + } + + companion object { + private val DEVICE_CODE = 0x1120.toUShort() + private val TAG = logTag("PodDevice", "Beats", "Studio", "Buds") + } +} diff --git a/app/src/main/java/eu/darken/capod/pods/core/apple/ble/devices/beats/BeatsStudioBudsPlus.kt b/app/src/main/java/eu/darken/capod/pods/core/apple/ble/devices/beats/BeatsStudioBudsPlus.kt new file mode 100644 index 00000000..ce7b9eb6 --- /dev/null +++ b/app/src/main/java/eu/darken/capod/pods/core/apple/ble/devices/beats/BeatsStudioBudsPlus.kt @@ -0,0 +1,93 @@ +package eu.darken.capod.pods.core.apple.ble.devices.beats + +import androidx.annotation.DrawableRes +import eu.darken.capod.R +import eu.darken.capod.common.bluetooth.BleScanResult +import eu.darken.capod.common.debug.logging.logTag +import eu.darken.capod.pods.core.apple.ble.BlePodSnapshot +import eu.darken.capod.pods.core.apple.PodModel +import eu.darken.capod.pods.core.apple.ble.devices.ApplePods +import eu.darken.capod.pods.core.apple.ble.devices.ApplePodsFactory +import eu.darken.capod.pods.core.apple.ble.devices.DualApplePods +import eu.darken.capod.pods.core.apple.ble.history.PodHistoryRepo +import eu.darken.capod.pods.core.apple.ble.protocol.ProximityMessage +import eu.darken.capod.pods.core.apple.ble.protocol.ProximityPairing +import eu.darken.capod.pods.core.apple.ble.protocol.ProximityPayload +import java.time.Instant +import javax.inject.Inject + +data class BeatsStudioBudsPlus( + override val identifier: BlePodSnapshot.Id = BlePodSnapshot.Id(), + override val seenLastAt: Instant = Instant.now(), + override val seenFirstAt: Instant = Instant.now(), + override val seenCounter: Int = 1, + override val scanResult: BleScanResult, + override val payload: ProximityPayload, + override val meta: ApplePods.AppleMeta, + override val reliability: Float = BlePodSnapshot.BASE_CONFIDENCE, + private val rssiAverage: Int? = null, + private val cachedBatteryPercentage: Float? = null, + private val cachedCaseState: DualApplePods.LidState? = null +) : DualApplePods { + + override val model: PodModel = PodModel.BEATS_STUDIO_BUDS_PLUS + + @get:DrawableRes + override val leftPodIcon: Int + get() = R.drawable.device_beats_fitpro_left + + @get:DrawableRes + override val rightPodIcon: Int + get() = R.drawable.device_beats_fitpro_right + + @get:DrawableRes + override val caseIcon: Int + get() = R.drawable.device_beats_fitpro_case + + override val batteryCasePercent: Float? + get() = super.batteryCasePercent ?: cachedBatteryPercentage + + override val caseLidState: DualApplePods.LidState + get() = cachedCaseState ?: super.caseLidState + + override val rssi: Int + get() = rssiAverage ?: super.rssi + + class Factory @Inject constructor( + private val repo: PodHistoryRepo, + ) : ApplePodsFactory { + override fun isResponsible(message: ProximityMessage): Boolean = message.run { + getModelInfo().full == DEVICE_CODE && length == ProximityPairing.PAIRING_MESSAGE_LENGTH + } + + override suspend fun create( + scanResult: BleScanResult, + payload: ProximityPayload, + meta: ApplePods.AppleMeta + ): ApplePods { + var basic = BeatsStudioBudsPlus(scanResult = scanResult, payload = payload, meta = meta) + val result = repo.search(basic) + + if (result != null) basic = basic.copy(identifier = result.id) + repo.updateHistory(basic) + + if (result == null) return basic + + return basic.copy( + identifier = result.id, + seenFirstAt = result.seenFirstAt, + seenLastAt = scanResult.receivedAt, + seenCounter = result.seenCounter, + reliability = result.reliability, + cachedBatteryPercentage = result.getLatestCaseBattery(), + rssiAverage = result.rssiSmoothed(basic.rssi), + cachedCaseState = result.getLatestCaseLidState(basic) + ) + } + } + + companion object { + private val DEVICE_CODE = 0x1620.toUShort() + private val TAG = logTag("PodDevice", "Beats", "Studio", "Buds", "Plus") + } +} diff --git a/app/src/main/java/eu/darken/capod/pods/core/apple/ble/devices/beats/BeatsStudioPro.kt b/app/src/main/java/eu/darken/capod/pods/core/apple/ble/devices/beats/BeatsStudioPro.kt new file mode 100644 index 00000000..825e74ae --- /dev/null +++ b/app/src/main/java/eu/darken/capod/pods/core/apple/ble/devices/beats/BeatsStudioPro.kt @@ -0,0 +1,68 @@ +package eu.darken.capod.pods.core.apple.ble.devices.beats + +import eu.darken.capod.common.bluetooth.BleScanResult +import eu.darken.capod.common.debug.logging.logTag +import eu.darken.capod.pods.core.apple.ble.BlePodSnapshot +import eu.darken.capod.pods.core.apple.PodModel +import eu.darken.capod.pods.core.apple.ble.devices.ApplePods +import eu.darken.capod.pods.core.apple.ble.devices.ApplePodsFactory +import eu.darken.capod.pods.core.apple.ble.devices.SingleApplePods +import eu.darken.capod.pods.core.apple.ble.history.PodHistoryRepo +import eu.darken.capod.pods.core.apple.ble.protocol.ProximityMessage +import eu.darken.capod.pods.core.apple.ble.protocol.ProximityPairing +import eu.darken.capod.pods.core.apple.ble.protocol.ProximityPayload +import java.time.Instant +import javax.inject.Inject + +data class BeatsStudioPro( + override val identifier: BlePodSnapshot.Id = BlePodSnapshot.Id(), + override val seenLastAt: Instant = Instant.now(), + override val seenFirstAt: Instant = Instant.now(), + override val seenCounter: Int = 1, + override val scanResult: BleScanResult, + override val payload: ProximityPayload, + override val meta: ApplePods.AppleMeta, + override val reliability: Float = BlePodSnapshot.BASE_CONFIDENCE, + private val rssiAverage: Int? = null, +) : SingleApplePods { + + override val model: PodModel = PodModel.BEATS_STUDIO_PRO + override val rssi: Int + get() = rssiAverage ?: super.rssi + + class Factory @Inject constructor( + private val repo: PodHistoryRepo, + ) : ApplePodsFactory { + override fun isResponsible(message: ProximityMessage): Boolean = message.run { + getModelInfo().full == DEVICE_CODE && length == ProximityPairing.PAIRING_MESSAGE_LENGTH + } + + override suspend fun create( + scanResult: BleScanResult, + payload: ProximityPayload, + meta: ApplePods.AppleMeta + ): ApplePods { + var basic = BeatsStudioPro(scanResult = scanResult, payload = payload, meta = meta) + val result = repo.search(basic) + + if (result != null) basic = basic.copy(identifier = result.id) + repo.updateHistory(basic) + + if (result == null) return basic + + return basic.copy( + identifier = result.id, + seenFirstAt = result.seenFirstAt, + seenLastAt = scanResult.receivedAt, + seenCounter = result.seenCounter, + reliability = result.reliability, + rssiAverage = result.rssiSmoothed(basic.rssi), + ) + } + } + + companion object { + private val DEVICE_CODE = 0x1720.toUShort() + private val TAG = logTag("PodDevice", "Beats", "Studio", "Pro") + } +} diff --git a/app/src/test/java/eu/darken/capod/pods/core/apple/ble/devices/beats/BeatsSolo4Test.kt b/app/src/test/java/eu/darken/capod/pods/core/apple/ble/devices/beats/BeatsSolo4Test.kt new file mode 100644 index 00000000..f6f23bde --- /dev/null +++ b/app/src/test/java/eu/darken/capod/pods/core/apple/ble/devices/beats/BeatsSolo4Test.kt @@ -0,0 +1,20 @@ +package eu.darken.capod.pods.core.apple.ble.devices.beats + +import eu.darken.capod.pods.core.apple.PodModel +import eu.darken.capod.pods.core.apple.ble.devices.BaseBlePodsTest +import io.kotest.matchers.shouldBe +import kotlinx.coroutines.test.runTest +import org.junit.jupiter.api.Test + +class BeatsSolo4Test : BaseBlePodsTest() { + + // TODO Replace with real device data + @Test + fun `default BeatsSolo4`() = runTest { + create("07 19 01 25 20 62 04 80 01 0F 40 0D 70 50 16 F2 40 83 16 BF 10 16 34 9B 74 84 E8") { + pubDeviceModel shouldBe 0x2520.toUShort() + batteryHeadsetPercent shouldBe 0.4f + model shouldBe PodModel.BEATS_SOLO_4 + } + } +} diff --git a/app/src/test/java/eu/darken/capod/pods/core/apple/ble/devices/beats/BeatsSoloBudsTest.kt b/app/src/test/java/eu/darken/capod/pods/core/apple/ble/devices/beats/BeatsSoloBudsTest.kt new file mode 100644 index 00000000..4ebc054f --- /dev/null +++ b/app/src/test/java/eu/darken/capod/pods/core/apple/ble/devices/beats/BeatsSoloBudsTest.kt @@ -0,0 +1,21 @@ +package eu.darken.capod.pods.core.apple.ble.devices.beats + +import eu.darken.capod.pods.core.apple.PodModel +import eu.darken.capod.pods.core.apple.ble.devices.BaseBlePodsTest +import io.kotest.matchers.shouldBe +import kotlinx.coroutines.test.runTest +import org.junit.jupiter.api.Test + +class BeatsSoloBudsTest : BaseBlePodsTest() { + + // TODO Replace with real device data + @Test + fun `default BeatsSoloBuds`() = runTest { + create("07 19 01 26 20 20 FA 8F 01 00 24 9B 9B 23 52 60 5A 8C 32 1C A5 C2 81 51 82 AF C8") { + pubDeviceModel shouldBe 0x2620.toUShort() + batteryLeftPodPercent shouldBe 1.0f + batteryRightPodPercent shouldBe null + model shouldBe PodModel.BEATS_SOLO_BUDS + } + } +} diff --git a/app/src/test/java/eu/darken/capod/pods/core/apple/ble/devices/beats/BeatsSoloProTest.kt b/app/src/test/java/eu/darken/capod/pods/core/apple/ble/devices/beats/BeatsSoloProTest.kt new file mode 100644 index 00000000..67a0762a --- /dev/null +++ b/app/src/test/java/eu/darken/capod/pods/core/apple/ble/devices/beats/BeatsSoloProTest.kt @@ -0,0 +1,20 @@ +package eu.darken.capod.pods.core.apple.ble.devices.beats + +import eu.darken.capod.pods.core.apple.PodModel +import eu.darken.capod.pods.core.apple.ble.devices.BaseBlePodsTest +import io.kotest.matchers.shouldBe +import kotlinx.coroutines.test.runTest +import org.junit.jupiter.api.Test + +class BeatsSoloProTest : BaseBlePodsTest() { + + // TODO Replace with real device data + @Test + fun `default BeatsSoloPro`() = runTest { + create("07 19 01 0C 20 62 04 80 01 0F 40 0D 70 50 16 F2 40 83 16 BF 10 16 34 9B 74 84 E8") { + pubDeviceModel shouldBe 0x0C20.toUShort() + batteryHeadsetPercent shouldBe 0.4f + model shouldBe PodModel.BEATS_SOLO_PRO + } + } +} diff --git a/app/src/test/java/eu/darken/capod/pods/core/apple/ble/devices/beats/BeatsStudioBudsPlusTest.kt b/app/src/test/java/eu/darken/capod/pods/core/apple/ble/devices/beats/BeatsStudioBudsPlusTest.kt new file mode 100644 index 00000000..0da3ec61 --- /dev/null +++ b/app/src/test/java/eu/darken/capod/pods/core/apple/ble/devices/beats/BeatsStudioBudsPlusTest.kt @@ -0,0 +1,21 @@ +package eu.darken.capod.pods.core.apple.ble.devices.beats + +import eu.darken.capod.pods.core.apple.PodModel +import eu.darken.capod.pods.core.apple.ble.devices.BaseBlePodsTest +import io.kotest.matchers.shouldBe +import kotlinx.coroutines.test.runTest +import org.junit.jupiter.api.Test + +class BeatsStudioBudsPlusTest : BaseBlePodsTest() { + + // TODO Replace with real device data + @Test + fun `default BeatsStudioBudsPlus`() = runTest { + create("07 19 01 16 20 20 FA 8F 01 00 24 9B 9B 23 52 60 5A 8C 32 1C A5 C2 81 51 82 AF C8") { + pubDeviceModel shouldBe 0x1620.toUShort() + batteryLeftPodPercent shouldBe 1.0f + batteryRightPodPercent shouldBe null + model shouldBe PodModel.BEATS_STUDIO_BUDS_PLUS + } + } +} diff --git a/app/src/test/java/eu/darken/capod/pods/core/apple/ble/devices/beats/BeatsStudioBudsTest.kt b/app/src/test/java/eu/darken/capod/pods/core/apple/ble/devices/beats/BeatsStudioBudsTest.kt new file mode 100644 index 00000000..9d4b76d3 --- /dev/null +++ b/app/src/test/java/eu/darken/capod/pods/core/apple/ble/devices/beats/BeatsStudioBudsTest.kt @@ -0,0 +1,21 @@ +package eu.darken.capod.pods.core.apple.ble.devices.beats + +import eu.darken.capod.pods.core.apple.PodModel +import eu.darken.capod.pods.core.apple.ble.devices.BaseBlePodsTest +import io.kotest.matchers.shouldBe +import kotlinx.coroutines.test.runTest +import org.junit.jupiter.api.Test + +class BeatsStudioBudsTest : BaseBlePodsTest() { + + // TODO Replace with real device data + @Test + fun `default BeatsStudioBuds`() = runTest { + create("07 19 01 11 20 20 FA 8F 01 00 24 9B 9B 23 52 60 5A 8C 32 1C A5 C2 81 51 82 AF C8") { + pubDeviceModel shouldBe 0x1120.toUShort() + batteryLeftPodPercent shouldBe 1.0f + batteryRightPodPercent shouldBe null + model shouldBe PodModel.BEATS_STUDIO_BUDS + } + } +} diff --git a/app/src/test/java/eu/darken/capod/pods/core/apple/ble/devices/beats/BeatsStudioProTest.kt b/app/src/test/java/eu/darken/capod/pods/core/apple/ble/devices/beats/BeatsStudioProTest.kt new file mode 100644 index 00000000..e144a5f0 --- /dev/null +++ b/app/src/test/java/eu/darken/capod/pods/core/apple/ble/devices/beats/BeatsStudioProTest.kt @@ -0,0 +1,20 @@ +package eu.darken.capod.pods.core.apple.ble.devices.beats + +import eu.darken.capod.pods.core.apple.PodModel +import eu.darken.capod.pods.core.apple.ble.devices.BaseBlePodsTest +import io.kotest.matchers.shouldBe +import kotlinx.coroutines.test.runTest +import org.junit.jupiter.api.Test + +class BeatsStudioProTest : BaseBlePodsTest() { + + // TODO Replace with real device data + @Test + fun `default BeatsStudioPro`() = runTest { + create("07 19 01 17 20 62 04 80 01 0F 40 0D 70 50 16 F2 40 83 16 BF 10 16 34 9B 74 84 E8") { + pubDeviceModel shouldBe 0x1720.toUShort() + batteryHeadsetPercent shouldBe 0.4f + model shouldBe PodModel.BEATS_STUDIO_PRO + } + } +}