Skip to content

Commit 0c8dc83

Browse files
eriedclaude
andcommitted
fix(inmotion-v1): send max-speed little-endian so the wheel stores the right value
Tester set 39 km/h and the V8S recorded 23, and legal mode drifted. Cause: a byte-order bug. setMaxSpeed encoded (kmh*1000) BIG-endian (HIGH byte at slot 4), but the wheel reads the field LITTLE-endian. 39 km/h = 39000 = 0x9858 sent as `98 58` is read back as 0x5898 = 22680 ~= 23 km/h - exactly the reported value. The slow-info confirms LE: the wheel reports 41 km/h as 0xa028 on the wire (`28 a0`). So the parser was already correct; only the write was wrong-endian. Swap to LE (LOW byte slot 4, HIGH byte slot 5). Legal mode compares the written value to the wheel readback, so this fixes that too. The old code comment even flagged this ("spec says LE but worked example takes precedence... verify against a real capture") - the capture proved the worked example wrong. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GADLyChheAoMX9dQbRgRnH
1 parent 93a8594 commit 0c8dc83

1 file changed

Lines changed: 10 additions & 8 deletions

File tree

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

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -94,20 +94,22 @@ object InMotionV1Commands {
9494
// --- Ride mode group (CAN 0x0F550115) ---
9595

9696
/**
97-
* Set max speed (tiltback). Encoded as `(kmh * 1000)` u16 with HIGH byte
98-
* at slot 4 and LOW byte at slot 5, opposite of the rest of the
99-
* protocol's little-endian convention. Spec section 6.2 worked example
100-
* is unambiguous: 30 km/h -> 30000 = 0x7530, wire = `75 30`. The spec's
101-
* type annotation says `LE` but the worked example takes precedence
102-
* here. Verify against a real BLE capture if behaviour looks wrong.
97+
* Set max speed (tiltback). Encoded as `(kmh * 1000)` u16 LITTLE-endian:
98+
* LOW byte at slot 4, HIGH byte at slot 5. A real V8S confirms LE (matching
99+
* the spec's type annotation, NOT the old "worked example" that implied
100+
* HIGH-then-LOW): sending 39 km/h big-endian (`98 58`) made the wheel store
101+
* 0x5898 = 22680 ~= 23 km/h. The slow-info reads the field back LE too
102+
* (41 km/h = 41000 = 0xa028, on the wire as `28 a0`), so write and read now
103+
* agree. This also fixes legal-mode, which compares the written value to the
104+
* wheel's readback.
103105
*/
104106
fun setMaxSpeed(kmh: Float): ByteArray {
105107
val v = (kmh * 1000f).toInt() and 0xFFFF
106-
val hi = ((v ushr 8) and 0xFF).toByte()
107108
val lo = (v and 0xFF).toByte()
109+
val hi = ((v ushr 8) and 0xFF).toByte()
108110
return InMotionV1Protocol.buildFrame(
109111
CanId.RIDE_MODE,
110-
byteArrayOf(0x01, 0, 0, 0, hi, lo, 0, 0)
112+
byteArrayOf(0x01, 0, 0, 0, lo, hi, 0, 0)
111113
)
112114
}
113115

0 commit comments

Comments
 (0)