Skip to content

Erase ring history after sync and fix per-ring sync stalls - #142

Open
saksham2001 wants to merge 5 commits into
mainfrom
feat/ring-clear-after-sync
Open

saksham2001 wants to merge 5 commits into
mainfrom
feat/ring-clear-after-sync

Conversation

@saksham2001

Copy link
Copy Markdown
Owner

Summary

PulseLoop never cleared a ring's stored history after syncing, so every sync re-sent the full log. This PR copies what each vendor app actually does, taken from the decompiled apps and vendor SDKs, and fixes the timeout stalls that slowed down the rings that have no clear command.

Clearing stored history (0441a3a)

  • Saved before cleared. A new RingHistoryCommit check makes the app save everything synced so far to disk (a save that reports failure) before any ring history is erased. Sync engines call it through RingCommandWriter.commitDeliveredHistory. If the save fails, times out, or no one is listening, nothing is erased; the ring keeps its data and the next sync reads it again.
  • YCBT (SmartHealth Colmi incl. R99, TK5, R10M).
    • After the queries finish and the save succeeds, each data type that returned records is deleted one at a time with 05 <0x40…0x4E> 02, as SmartHealth's DataSyncUtils does.
    • The temperature delete is 0x47, not 0x46.
    • Nothing is erased until the ring has sent its 02 01 capability list on this connection.
    • This should fix the R99's automatic SpO₂ freezing after ~1.5 days: its combined "All" log was never cleared and appears to fill up.
  • RWfit. History is now deleted page by page (05 xx 30), matching the vendor's per-page loop. Each page is saved first. Empty pages are never deleted.
  • LuckRing. The vendor app never clears the ring after a sync; opcode 207 is only sent from a manual "Clear data" button. What the vendor does do is ACK every completed frame except dataType 144 (CEProtocolB.Analysis), so we now do the same.
  • Jring, Colmi QRing, CRP. No vendor clear command exists; these rings keep a fixed per-day store. Tests now check that a sync never sends their factory-reset, shutdown or restart frames.

Sync stalls

  • CRP (1cd4782): a timing stream that hasn't sent its first frame within 5 s no longer holds the pass open. A ring that ignores stress now finishes in ~5 s instead of the 15 s watchdog.
  • Colmi QRing (9d4962e):
    • Heart-rate, stress and HRV days now end on the page count in the day's first packet. Before, HR days never ended on their own, so the watchdog skipped days 1–7 entirely.
    • The sleep request now uses QRing's bc 27 02 00 81 80 ff 01.
    • The HR request now uses local midnight plus the UTC offset, like Gadgetbridge and the Android port.
  • YCBT (2923565): a dedicated SpO₂ or temperature log that never answers (the R99's 05 1a) costs one 10 s timeout per connection instead of one on every sync. Core logs are always asked again.
  • Jring (024a6b8): history is synced day by day (10 dd → 16 dd) from the last finished sync, up to 6 days back, matching the vendor app. Before, only today was ever requested. 0x10 step history is now decoded.

Related issues

Closes #91

Type of change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature (non-breaking change that adds functionality)
  • 📟 New / improved wearable support (BLE driver layer)
  • 🤖 Coach / LLM change (tools, prompts, orchestration)
  • 🎨 UI / DesignSystem change
  • 🧹 Refactor / chore (no behavior change)
  • 📝 Docs only
  • ⚠️ Breaking change (existing data, settings, or APIs change)

How was this tested?

  • Added / updated unit tests (PulseLoopTests)
  • Ran the test suite locally (⌘U in Xcode): 1246 tests, 0 failures
  • Tested on a physical device with a real ring — model: not yet
  • Tested with demo data (-seedDemo YES, no hardware)
  • N/A (docs / non-code change)

Needs checking on hardware before merge:

  • Whether the R99 answers 02 01, and what YCBT rings reply to a delete.
  • Whether RWfit moves to the next page only after a delete.
  • Whether LuckRing's next sync is smaller once every frame is ACKed.
  • The new QRing sleep request on older R02 firmware.
  • Whether Jring 0x10 values really are steps per minute.

Privacy & data

  • This change does not send health data off-device without explicit user action.
  • No secrets, API keys, or personal data are committed.
  • N/A

Screenshots / recordings

N/A — no UI changes.

Checklist

  • My code follows the project's style (SwiftLint passes).
  • I ran the tests and they pass.
  • I updated docs / README where relevant.
  • I read the Contributing guide.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Ring data never cleared

1 participant