fix(ble): Drop proximity messages with unsupported payload prefix

AirPods Gen4 emit a one-off type 0x07 frame from their identity address
on connect whose payload prefix is 0x07 instead of 0x01. Its bytes are
not the plaintext status format, but the model bytes happen to match,
so it minted a fresh device tracker and showed as a duplicate device
card until the stale timeout.

Every known plaintext status broadcast (including pairing mode) uses
prefix 0x01; pairing state lives in the suffix byte. Reject anything
else at the decoder, logging the dropped frame's hex.

Fixes #603
This commit is contained in:
darken
2026-06-10 10:44:48 +02:00
committed by Matthias Urhahn
parent 5d30844fa8
commit a1b9abd4cb
2 changed files with 30 additions and 1 deletions
@@ -1,6 +1,7 @@
package eu.darken.capod.pods.core.apple.ble.devices.airpods
import eu.darken.capod.pods.core.apple.PodModel
import eu.darken.capod.pods.core.apple.ble.BlePodSnapshot
import eu.darken.capod.pods.core.apple.ble.devices.BaseBlePodsTest
import eu.darken.capod.pods.core.apple.ble.devices.DualApplePods
import eu.darken.capod.pods.core.apple.ble.devices.HasAppleColor
@@ -43,4 +44,14 @@ class AirPodsGen4Test : BaseBlePodsTest() {
model shouldBe PodModel.AIRPODS_GEN4
}
}
}
@Test
fun `frame with unsupported payload prefix is rejected - #603`() = runTest {
// Captured from AirPods Gen4 on connect: sent from the identity address, payload prefix
// 0x07 instead of 0x01, model bytes match but battery/color bytes are not plaintext.
// Decoding it as a status frame created a duplicate device card.
create<BlePodSnapshot?>("07 19 07 19 20 35 DF DE 46 76 CE 66 5C F4 6E BA B6 AC 1B 69 4C A7 D8 09 BF 9A 04") {
this shouldBe null
}
}
}