Conversation
Re-detect the Mi scale variant on connect by probing for the history characteristic under 0x181B (V2) / 0x181D (V1), correcting the ambiguous scan-time name heuristic. The weight-only Mi Smart Scale 2 (XMTZC04HM) advertises "MI SCALE2" and carries the 0x1530 vendor service but serves only 0x181D, so V2 mode subscribed/wrote against a non-existent service and hung in "waiting for measurement" forever. Fail fast with a user-visible error + disconnect when the history characteristic exists under neither service. Adds MiScaleHandlerVariantTest. Fixes oliexdev#1489 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Follow-up to e77aa89, fixing the issues found in review: - supportFor() no longer mutates the session variant field. The handler is a shared singleton and the UI re-queries device support at any time (savedDeviceSupport, scan results), which could silently reset a GATT-corrected variant mid-session and drop live v1 frames. - detectVariantFromGatt() no longer hard-rejects clones that serve a standard service without the vendor history characteristic (live weight via 0x2A9D worked for them before the fail-fast). Service presence acts as a fallback tier; only a device exposing neither 0x181B nor 0x181D aborts, which is also exactly what the user-facing error string claims. - The GATT-detected variant is persisted per device address so later scan-time support queries stop promising v2 capabilities (body composition, unit config) a downgraded device cannot deliver. - Variant tests now run on runTest virtual time instead of racing the real 1-second history-fallback timer, and cancel it via handleDisconnected(); new regression tests cover the clone fallback, the mid-session supportFor() query, and the persisted override. All changes stay within MiScaleHandler and its test, per the how-to-support-a-new-scale ground rules (no shared infrastructure changes). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HkiN1TxugYUaxWx2HbzhbD
- Refine variant determination to rely only on GATT table reads during connection, discarding scan-time heuristics - Add warning to the UI when a device advertises v2 capabilities but is detected as v1 (weight only) - Remove persisted variant setting/retrieval logic for cleaner state management - Update resource strings to reflect the warning about degraded variant capability
|
Not merging yet — please retest on hardware first. I made these changes on top: Removed the persisted variant. It doesn't work as intended: settings is lateinit and only attached in ModernScaleAdapter.init, i.e. after supportFor has already returned, so the first scan of a session always hits the runCatching and reads nothing. From the second session on it puts a runBlocking DataStore read with a 300 ms timeout into supportFor, which runs per scan result. Dropped persistedVariantFor, rememberDetectedVariant and the corresponding test. Replaced it with a warning on connect. The device list keeps showing the scan-time guess, so a downgraded scale is still listed as v2. Instead of correcting the list, onConnected now says it once when the advertised name promises v2 but the GATT table is v1 — new string bt_warn_mi_scale_variant_downgraded, as userWarn since the measurement still works. Shortened bt_error_mi_scale_service_missing to match bt_error_omron_service_missing. The UUIDs stay in the log, they don't belong in a user-facing dialog. Kept as is: the GATT-table detection, the clone fallback tier, the fail-fast, and the side-effect-free supportFor. Please verify with the XMTZC04HM (weight arrives, warning shown once) then I'll merge. |
The weight-only Mi Smart Scale 2 (XMTZC04HM) advertises "MI SCALE2" and even carries the 0x1530 vendor service, so the scan-time heuristic classifies it as v2. Its GATT table, however, only serves the Weight Scale service (0x181D) — there is no Body Composition service (0x181B). The v2 init sequence then subscribes/writes against a non-existent service and the app hangs forever in "waiting for measurement".
Changes:
supportFor()is now side-effect-free. The handler is a shared singleton and the UI re-queries device support while a session is live; previously such a query could reset the GATT-corrected variant mid-session and silently drop live v1 frames.MiScaleHandlerVariantTestcovers scan-time classification, the XMTZC04HM downgrade, genuine v2, the clone fallback (a live 10-byte weight frame is parsed end-to-end), a mid-sessionsupportFor()query not clobbering the session variant, the persisted-variant override, and the neither-service abort. Timer-dependent tests run onrunTestvirtual time instead of racing the real 1-second history-fallback timer.Fixes #1489.