mirror of
https://github.com/d4rken-org/capod.git
synced 2026-09-15 10:46:12 -04:00
refactor: Rename PodDevice to BlePodSnapshot, MonitoredDevice to PodDevice, extract PodModel
Complete type rename chain: PodDevice (interface) becomes BlePodSnapshot, MonitoredDevice (facade) claims PodDevice name, Model enum extracted to top-level PodModel. Delete redundant type alias files. Fix stale comments and log tags.
This commit is contained in:
@@ -9,9 +9,9 @@ import eu.darken.capod.main.core.GeneralSettings
|
||||
import eu.darken.capod.main.core.MonitorMode
|
||||
import eu.darken.capod.main.core.PermissionTool
|
||||
import eu.darken.capod.monitor.core.DeviceMonitor
|
||||
import eu.darken.capod.monitor.core.MonitoredDevice
|
||||
import eu.darken.capod.monitor.core.PodDevice
|
||||
import eu.darken.capod.monitor.core.worker.MonitorControl
|
||||
import eu.darken.capod.pods.core.PodDevice
|
||||
import eu.darken.capod.pods.core.BlePodSnapshot
|
||||
import eu.darken.capod.profiles.core.AppleDeviceProfile
|
||||
import eu.darken.capod.profiles.core.DeviceProfile
|
||||
import eu.darken.capod.profiles.core.DeviceProfilesRepo
|
||||
@@ -32,11 +32,11 @@ import org.junit.jupiter.api.AfterEach
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Nested
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.extension.ExtendWith
|
||||
import testhelpers.BaseTest
|
||||
import testhelpers.coroutine.TestDispatcherProvider
|
||||
import testhelpers.datastore.FakeDataStoreValue
|
||||
import testhelpers.livedata.InstantExecutorExtension
|
||||
import org.junit.jupiter.api.extension.ExtendWith
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
@ExtendWith(InstantExecutorExtension::class)
|
||||
@@ -54,7 +54,7 @@ class OverviewViewModelTest : BaseTest() {
|
||||
private lateinit var profilesRepo: DeviceProfilesRepo
|
||||
|
||||
private lateinit var missingPermissionsFlow: MutableStateFlow<Set<Permission>>
|
||||
private lateinit var devicesFlow: MutableStateFlow<List<MonitoredDevice>>
|
||||
private lateinit var devicesFlow: MutableStateFlow<List<PodDevice>>
|
||||
private lateinit var connectedDevicesFlow: MutableStateFlow<List<BluetoothDevice2>>
|
||||
private lateinit var isBluetoothEnabledFlow: MutableStateFlow<Boolean>
|
||||
private lateinit var profilesFlow: MutableStateFlow<List<DeviceProfile>>
|
||||
@@ -154,7 +154,7 @@ class OverviewViewModelTest : BaseTest() {
|
||||
|
||||
@Test
|
||||
fun `devices passed through when permissions granted`() = runTest(testDispatcher) {
|
||||
val device = MonitoredDevice(ble = mockk(relaxed = true), aap = null)
|
||||
val device = PodDevice(ble = mockk(relaxed = true), aap = null)
|
||||
devicesFlow.value = listOf(device)
|
||||
|
||||
val vm = createViewModel()
|
||||
@@ -165,17 +165,17 @@ class OverviewViewModelTest : BaseTest() {
|
||||
|
||||
@Test
|
||||
fun `profiledDevices returns only devices with non-null profile`() {
|
||||
val withProfile = object : PodDevice.Meta {
|
||||
val withProfile = object : BlePodSnapshot.Meta {
|
||||
override val profile: DeviceProfile = AppleDeviceProfile(label = "Test")
|
||||
}
|
||||
val withoutProfile = object : PodDevice.Meta {
|
||||
val withoutProfile = object : BlePodSnapshot.Meta {
|
||||
override val profile: DeviceProfile? = null
|
||||
}
|
||||
val profiled = MonitoredDevice(
|
||||
val profiled = PodDevice(
|
||||
ble = mockk(relaxed = true) { every { meta } returns withProfile },
|
||||
aap = null,
|
||||
)
|
||||
val unmatched = MonitoredDevice(
|
||||
val unmatched = PodDevice(
|
||||
ble = mockk(relaxed = true) { every { meta } returns withoutProfile },
|
||||
aap = null,
|
||||
)
|
||||
@@ -196,17 +196,17 @@ class OverviewViewModelTest : BaseTest() {
|
||||
|
||||
@Test
|
||||
fun `unmatchedDevices returns only devices with null profile`() {
|
||||
val withProfile = object : PodDevice.Meta {
|
||||
val withProfile = object : BlePodSnapshot.Meta {
|
||||
override val profile: DeviceProfile = AppleDeviceProfile(label = "Test")
|
||||
}
|
||||
val withoutProfile = object : PodDevice.Meta {
|
||||
val withoutProfile = object : BlePodSnapshot.Meta {
|
||||
override val profile: DeviceProfile? = null
|
||||
}
|
||||
val profiled = MonitoredDevice(
|
||||
val profiled = PodDevice(
|
||||
ble = mockk(relaxed = true) { every { meta } returns withProfile },
|
||||
aap = null,
|
||||
)
|
||||
val unmatched = MonitoredDevice(
|
||||
val unmatched = PodDevice(
|
||||
ble = mockk(relaxed = true) { every { meta } returns withoutProfile },
|
||||
aap = null,
|
||||
)
|
||||
|
||||
+20
-20
@@ -1,10 +1,10 @@
|
||||
package eu.darken.capod.monitor.core
|
||||
|
||||
import eu.darken.capod.pods.core.BlePodSnapshot
|
||||
import eu.darken.capod.pods.core.HasCase
|
||||
import eu.darken.capod.pods.core.HasChargeDetectionDual
|
||||
import eu.darken.capod.pods.core.HasEarDetection
|
||||
import eu.darken.capod.pods.core.HasEarDetectionDual
|
||||
import eu.darken.capod.pods.core.PodDevice
|
||||
import eu.darken.capod.pods.core.PodModel
|
||||
import eu.darken.capod.pods.core.apple.DualApplePods
|
||||
import eu.darken.capod.pods.core.apple.protocol.aap.AapConnectionState
|
||||
@@ -20,15 +20,15 @@ import org.junit.jupiter.api.Test
|
||||
import testhelpers.BaseTest
|
||||
import java.time.Instant
|
||||
|
||||
class MonitoredDeviceTest : BaseTest() {
|
||||
class PodDeviceTest : BaseTest() {
|
||||
|
||||
private fun mockDualPod(
|
||||
model: PodModel = PodModel.AIRPODS_PRO3,
|
||||
leftBattery: Float? = 0.8f,
|
||||
rightBattery: Float? = 0.9f,
|
||||
caseBattery: Float? = 0.5f,
|
||||
): PodDevice {
|
||||
// DualApplePods implements DualPodDevice + HasCase + other interfaces
|
||||
): BlePodSnapshot {
|
||||
// DualApplePods implements DualBlePodSnapshot + HasCase + other interfaces
|
||||
return mockk<DualApplePods>(relaxed = true) {
|
||||
every { this@mockk.model } returns model
|
||||
every { batteryLeftPodPercent } returns leftBattery
|
||||
@@ -39,14 +39,14 @@ class MonitoredDeviceTest : BaseTest() {
|
||||
|
||||
@Test
|
||||
fun `BLE-only device exposes battery from BLE`() {
|
||||
val device = MonitoredDevice(ble = mockDualPod(leftBattery = 0.8f), aap = null)
|
||||
val device = PodDevice(ble = mockDualPod(leftBattery = 0.8f), aap = null)
|
||||
device.batteryLeft shouldBe 0.8f
|
||||
device.isAapConnected shouldBe false
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `capabilities come from model features`() {
|
||||
val device = MonitoredDevice(
|
||||
val device = PodDevice(
|
||||
ble = mockDualPod(model = PodModel.AIRPODS_PRO3),
|
||||
aap = null,
|
||||
)
|
||||
@@ -58,7 +58,7 @@ class MonitoredDeviceTest : BaseTest() {
|
||||
|
||||
@Test
|
||||
fun `Beats Solo 3 has no dual pods or case`() {
|
||||
val device = MonitoredDevice(
|
||||
val device = PodDevice(
|
||||
ble = mockk(relaxed = true) { every { model } returns PodModel.BEATS_SOLO_3 },
|
||||
aap = null,
|
||||
)
|
||||
@@ -77,7 +77,7 @@ class MonitoredDeviceTest : BaseTest() {
|
||||
),
|
||||
),
|
||||
)
|
||||
val device = MonitoredDevice(ble = mockDualPod(), aap = aap)
|
||||
val device = PodDevice(ble = mockDualPod(), aap = aap)
|
||||
device.isAapConnected shouldBe true
|
||||
device.ancMode.shouldNotBeNull()
|
||||
device.ancMode!!.current shouldBe AncModeValue.TRANSPARENCY
|
||||
@@ -85,21 +85,21 @@ class MonitoredDeviceTest : BaseTest() {
|
||||
|
||||
@Test
|
||||
fun `ANC mode is null when not AAP connected`() {
|
||||
val device = MonitoredDevice(ble = mockDualPod(), aap = null)
|
||||
val device = PodDevice(ble = mockDualPod(), aap = null)
|
||||
device.ancMode.shouldBeNull()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `null BLE gives UNKNOWN model`() {
|
||||
val device = MonitoredDevice(ble = null, aap = null)
|
||||
val device = PodDevice(ble = null, aap = null)
|
||||
device.model shouldBe PodModel.UNKNOWN
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `identity properties delegate to BLE`() {
|
||||
val id = PodDevice.Id()
|
||||
val meta = mockk<PodDevice.Meta>(relaxed = true)
|
||||
val device = MonitoredDevice(
|
||||
val id = BlePodSnapshot.Id()
|
||||
val meta = mockk<BlePodSnapshot.Meta>(relaxed = true)
|
||||
val device = PodDevice(
|
||||
ble = mockk(relaxed = true) {
|
||||
every { identifier } returns id
|
||||
every { this@mockk.meta } returns meta
|
||||
@@ -112,7 +112,7 @@ class MonitoredDeviceTest : BaseTest() {
|
||||
|
||||
@Test
|
||||
fun `identity properties null when BLE null`() {
|
||||
val device = MonitoredDevice(ble = null, aap = null)
|
||||
val device = PodDevice(ble = null, aap = null)
|
||||
device.identifier.shouldBeNull()
|
||||
device.meta.shouldBeNull()
|
||||
}
|
||||
@@ -121,7 +121,7 @@ class MonitoredDeviceTest : BaseTest() {
|
||||
fun `signal timing properties delegate to BLE`() {
|
||||
val now = Instant.now()
|
||||
val earlier = now.minusSeconds(60)
|
||||
val device = MonitoredDevice(
|
||||
val device = PodDevice(
|
||||
ble = mockk(relaxed = true) {
|
||||
every { seenLastAt } returns now
|
||||
every { seenFirstAt } returns earlier
|
||||
@@ -138,7 +138,7 @@ class MonitoredDeviceTest : BaseTest() {
|
||||
|
||||
@Test
|
||||
fun `signal timing defaults when BLE null`() {
|
||||
val device = MonitoredDevice(ble = null, aap = null)
|
||||
val device = PodDevice(ble = null, aap = null)
|
||||
device.seenLastAt.shouldBeNull()
|
||||
device.seenFirstAt.shouldBeNull()
|
||||
device.signalQuality shouldBe 0f
|
||||
@@ -153,7 +153,7 @@ class MonitoredDeviceTest : BaseTest() {
|
||||
every { (this@mockk as HasChargeDetectionDual).isRightPodCharging } returns false
|
||||
every { (this@mockk as HasCase).isCaseCharging } returns true
|
||||
}
|
||||
val device = MonitoredDevice(ble = mock, aap = null)
|
||||
val device = PodDevice(ble = mock, aap = null)
|
||||
device.isLeftPodCharging shouldBe true
|
||||
device.isRightPodCharging shouldBe false
|
||||
device.isCaseCharging shouldBe true
|
||||
@@ -168,7 +168,7 @@ class MonitoredDeviceTest : BaseTest() {
|
||||
every { (this@mockk as HasEarDetection).isBeingWorn } returns false
|
||||
every { (this@mockk as HasEarDetectionDual).isEitherPodInEar } returns true
|
||||
}
|
||||
val device = MonitoredDevice(ble = mock, aap = null)
|
||||
val device = PodDevice(ble = mock, aap = null)
|
||||
device.isLeftInEar shouldBe true
|
||||
device.isRightInEar shouldBe false
|
||||
device.isBeingWorn shouldBe false
|
||||
@@ -177,7 +177,7 @@ class MonitoredDeviceTest : BaseTest() {
|
||||
|
||||
@Test
|
||||
fun `icon and label properties delegate to BLE`() {
|
||||
val device = MonitoredDevice(
|
||||
val device = PodDevice(
|
||||
ble = mockk(relaxed = true) {
|
||||
every { model } returns PodModel.AIRPODS_PRO3
|
||||
every { iconRes } returns 42
|
||||
@@ -189,7 +189,7 @@ class MonitoredDeviceTest : BaseTest() {
|
||||
|
||||
@Test
|
||||
fun `rawDataHex empty when BLE null`() {
|
||||
val device = MonitoredDevice(ble = null, aap = null)
|
||||
val device = PodDevice(ble = null, aap = null)
|
||||
device.rawDataHex shouldBe emptyList()
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
package eu.darken.capod.pods.core.apple
|
||||
|
||||
import eu.darken.capod.pods.core.PodDevice
|
||||
import eu.darken.capod.pods.core.BlePodSnapshot
|
||||
import eu.darken.capod.pods.core.apple.airpods.AirPodsGen1
|
||||
import eu.darken.capod.pods.core.apple.airpods.AirPodsPro
|
||||
import eu.darken.capod.pods.core.apple.misc.UnknownAppleDevice
|
||||
import eu.darken.capod.pods.core.apple.misc.UnknownAppleSnapshotBle
|
||||
import io.kotest.matchers.shouldBe
|
||||
import io.kotest.matchers.types.instanceOf
|
||||
import kotlinx.coroutines.test.runTest
|
||||
@@ -28,13 +28,13 @@ class AirPodsFactoryTest : BaseAirPodsTest() {
|
||||
@Test
|
||||
fun `unknown AppleDevice`() = runTest {
|
||||
create<ApplePods>("07 19 01 FF FF 2B 99 8F 01 00 >09< 10 30 EE F3 41 B5 D8 9F A3 B0 B4 17 9F 85 97 5F") {
|
||||
this shouldBe instanceOf<UnknownAppleDevice>()
|
||||
this shouldBe instanceOf<UnknownAppleSnapshotBle>()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `invalid data`() = runTest {
|
||||
create<PodDevice?>("abcd") {
|
||||
create<BlePodSnapshot?>("abcd") {
|
||||
this shouldBe null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import eu.darken.capod.common.SystemClockWrap
|
||||
import eu.darken.capod.common.bluetooth.BleScanResult
|
||||
import eu.darken.capod.common.fromHex
|
||||
import eu.darken.capod.common.serialization.SerializationModule
|
||||
import eu.darken.capod.pods.core.PodDevice
|
||||
import eu.darken.capod.pods.core.BlePodSnapshot
|
||||
import eu.darken.capod.pods.core.apple.protocol.ContinuityProtocol
|
||||
import eu.darken.capod.profiles.core.DeviceProfile
|
||||
import eu.darken.capod.profiles.core.DeviceProfilesRepo
|
||||
@@ -60,7 +60,7 @@ abstract class BaseAirPodsTest : BaseTest() {
|
||||
every { SystemClockWrap.elapsedRealtimeNanos } returns 1000L
|
||||
}
|
||||
|
||||
internal suspend inline fun <reified T : PodDevice?> create(
|
||||
internal suspend inline fun <reified T : BlePodSnapshot?> create(
|
||||
hex: String,
|
||||
address: String = "77:49:4C:D8:25:0C",
|
||||
block: T.() -> Unit
|
||||
|
||||
Reference in New Issue
Block a user