diff --git a/android/app/src/main/java/com/noop/ble/WhoopBleClient.kt b/android/app/src/main/java/com/noop/ble/WhoopBleClient.kt index cca5742ce4..3823ccb39e 100644 --- a/android/app/src/main/java/com/noop/ble/WhoopBleClient.kt +++ b/android/app/src/main/java/com/noop/ble/WhoopBleClient.kt @@ -5073,8 +5073,23 @@ class WhoopBleClient( } // Surface non-success command results in the strap log — a result=UNSUPPORTED line // here is how the MG haptics rejection (#48) would have shown itself in-app. + // + // A reply that DELIVERED ITS VALUE is annotated rather than reported as a bare failure. + // The 4.0 GET_BATTERY_LEVEL replies on record carry a zeroed [seq][result] prefix, so a + // battery read that returned a perfectly good percentage logs as + // "FAILURE(0)" — and a log line saying a battery read failed, next to a battery gauge + // showing 42%, is the kind of artefact that gets quoted in an issue as evidence of a + // fault that is not there. That is how #900 started. The line still prints, because + // hiding it would hide the anomaly itself; it just no longer reads as a failure. if (result != null && !result.startsWith("SUCCESS")) { - log("Command response: ${respCmd ?: "?"} → $result") + val decodedValue = doubleValue(parsed.parsed["battery_pct"]) + val note = if (decodedValue != null) { + " (the reply still carried a value: battery ${"%.1f".format(decodedValue)}%" + + " — the result byte on this reply is not established, see #900)" + } else { + "" + } + log("Command response: ${respCmd ?: "?"} → $result$note") } // Arm-readback diagnostic (#401 close-out): armStrapAlarm follows every WHOOP 4.0 arm // with GET_ALARM_TIME (67) so the log proves what the STRAP believes is armed, not just