Skip to content

Commit 8197bbd

Browse files
eriedclaude
andcommitted
fix(inmotion-v1): send the PIN handshake on connect (default 000000)
Tester insight: the V8S PIN is 000000 but the app never sent a PIN - the connect log has no 0x0F550307 frame. initSequence only sent the PIN when the pin field was non-null, and with no UI to set it the field was always null, so nothing went out. This matches the failing capture: the wheel broadcasts an identity-only frame (0x0F060101, carrying its serial) for ~30 s after power-on and never streams fast-info until it gives up waiting - which is exactly a wheel waiting for the PIN handshake. The protocol connect procedure is "send PIN if required, then GetSlowInfo" (docs section 7), and the command builder already exists. Always send the PIN on connect now, defaulting to the factory 000000; a wheel with no PIN configured ignores it, so it is safe. A future Saved-PINs preference can set a custom value via the existing pin field. InMotion V1 only. If this lands the wheel should stream immediately instead of after the ~30 s boot-cycle wait. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GADLyChheAoMX9dQbRgRnH
1 parent 1b9f7f5 commit 8197bbd

1 file changed

Lines changed: 18 additions & 9 deletions

File tree

app/src/main/java/com/eried/eucplanet/ble/InMotionV1Adapter.kt

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,19 @@ class InMotionV1Adapter @Inject constructor() : WheelAdapter {
2424
override val familyDisplayName = "InMotion V1 / V3 / V5 / V8"
2525
override val capabilities = WheelCapabilities.INMOTION_V1
2626

27+
companion object {
28+
/** Factory PIN InMotion V1 wheels ship with; sent on connect when no
29+
* custom PIN is set. Wheels with no PIN configured ignore it. */
30+
private const val DEFAULT_PIN = "000000"
31+
}
32+
2733
@Volatile private var detectedModel: InMotionV1Model? = null
2834

2935
/**
30-
* Optional 6-digit PIN for the V1 auth handshake (spec section 7). When
31-
* non-null the adapter sends it on connect; the wheel ignores it when no
32-
* PIN is configured, so it is safe to always send. UI plumbing for
33-
* setting this is out of scope for this commit; the field stays null
34-
* until a "Saved PINs" preference path lands.
36+
* 6-digit PIN for the V1 auth handshake (spec section 7). null means "use
37+
* the factory default" ([DEFAULT_PIN]); a future "Saved PINs" preference
38+
* can set a custom one here. The handshake is sent on every connect - the
39+
* wheel ignores it when no PIN is configured, so it is safe to always send.
3540
*/
3641
@Volatile var pin: String? = null
3742

@@ -55,13 +60,17 @@ class InMotionV1Adapter @Inject constructor() : WheelAdapter {
5560
}
5661

5762
/**
58-
* Slow-info first so the model code + serial come back before realtime
59-
* polling begins. PIN goes ahead of slow-info on firmwares that gate
60-
* settings reads behind it; harmless on the rest.
63+
* PIN handshake first, then slow-info. The V8S sits in an identity-only
64+
* state (broadcasting 0x0F060101, never fast-info) for ~30 s after power-on
65+
* until it receives the PIN; the app never sent one (the pin field was
66+
* always null), so it waited out the wheel's boot on every connect. Always
67+
* send the PIN now, defaulting to the factory 000000 - a wheel with no PIN
68+
* configured ignores it (spec section 7), so it is safe. Slow-info follows
69+
* so the model code + serial come back before realtime polling begins.
6170
*/
6271
override fun initSequence(): List<ByteArray> {
6372
val out = mutableListOf<ByteArray>()
64-
pin?.let { out += InMotionV1Commands.sendPin(it) }
73+
out += InMotionV1Commands.sendPin(pin ?: DEFAULT_PIN)
6574
out += InMotionV1Commands.getSlowInfo()
6675
return out
6776
}

0 commit comments

Comments
 (0)