Skip to content

Rebuild TK5 support on the Yucheng YCBT protocol and add SmartHealth-app Colmi rings#82

Merged
saksham2001 merged 6 commits into
mainfrom
ycbt-protocol-tk5-smarthealth-colmi
Jul 11, 2026
Merged

Rebuild TK5 support on the Yucheng YCBT protocol and add SmartHealth-app Colmi rings#82
saksham2001 merged 6 commits into
mainfrom
ycbt-protocol-tk5-smarthealth-colmi

Conversation

@saksham2001

Copy link
Copy Markdown
Owner

Summary

The TK5's manufacturer supplied the SmartHealth Android app, whose Yucheng YCBT SDK is the
authoritative protocol. Comparing it byte-by-byte against our driver showed TK5 history sync was
fundamentally broken. This rebuilds the driver on the real protocol — and because Colmi rings that ship
with SmartHealth (rather than QRing) speak the same protocol, adds them as a second family off the
shared stack.

What was broken on the TK5:

  • History was never actually requested. Our opcodes (02 24/26/28) are GetCardInfo /
    GetSleepStatus / GetMeasurementFunction. The real flow is 05 <key> query → header → data →
    terminal 05 80 → a mandatory ACK we never sent, so the ring never released the next data type.
  • The "enable monitoring" burst was hitting the Health-DELETE opcodes (05 40…4E), so the ring was
    never told to record the metrics we then tried to read.
  • Records were sliced per-frame, not from the reassembled block — silently dropping any record that
    straddled a GATT boundary. There was no fragment reassembly at all.
  • Whole record types were never synced (SpO₂, BP, HRV/stress/fatigue, steps, temperature, blood sugar);
    setTime's weekday byte was hard-coded (the ring thought every day was Monday); the "user profile"
    was a frozen capture blob rather than the actual user.

New: a protocol-driven history state machine, GATT fragment reassembly, correct settings/monitor
commands, all 9 record types, device-push ACKs, and periodic re-sync. Capabilities are now decided by
the ring
: the handshake reads its capability bitmap (02 01) and we only offer sensors it actually
claims.

Colmi + SmartHealth: a ring's Bluetooth name doesn't say which app it shipped with, so the pairing
screen asks; the choice picks the driver, and a wrong pick fails in 20s with a one-tap "try the other
app" retry.

The AE00 handshake is deliberately not implemented — it's JieLi RCSP and gates only OTA/watch
faces. Confirmed on hardware: a JieLi ring (chipScheme 4) answers every health command in plaintext.

Related issues

Part of #50 (TK5 A840 — this PR is the TK5 driver rebuild; that unit's TK5 A840 name matches the
TK5 <4 hex> pattern, but it hasn't been tested on that ring).

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)

UI: the pairing screen's app-type picker + the wrong-app failure/retry path. Not breaking: every
persisted enum is append-only and jring / QRing-Colmi source files are byte-identical, so existing
users' rings and data are unaffected.

How was this tested?

  • Added / updated unit tests (PulseLoopTests) — 612 passing (461 before this PR)
  • Ran the test suite locally (⌘U in Xcode)
  • Tested on a physical device with a real ring — model: Colmi R09 (SmartHealth, advertises R99 54DC)
  • Tested with demo data (-seedDemo YES, no hardware)
  • N/A (docs / non-code change)

Confirmed on the R09: pairing and app-type selection, plaintext handshake with no AE00 auth on a
JieLi chip, time sync (correct weekday), firmware + battery parse, the 9-query history sync with its
ACKs, live/spot HR, spot SpO₂, blood pressure + calibration, and workout HR/SpO₂.

The hardware session also caught two real bugs, now fixed: HRV was offered on a ring whose bitmap
denies it (it refuses the command outright), and the SpO₂ spot window (40 s) was shorter than the
ring's own sweep (38–41 s).

Not yet exercised on hardware: sleep (the multi-session timeline is decoded from the SDK and
unit-tested, but no YCBT ring has been worn overnight), and the TK5 itself — it shares this driver but
hasn't been re-tested, so it stays 🧪 Limited.

Privacy & data

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

Checklist

  • My code follows the project's style (SwiftLint passes).
  • I ran the tests and they pass.
  • I updated docs / README where relevant — new docs/YCBT-Protocol.md (wire spec), rewritten
    hardware/tk5.md, and a SmartHealth section on hardware/colmi.md.
  • I read the Contributing guide.

@saksham2001
saksham2001 merged commit 902c449 into main Jul 11, 2026
4 checks passed
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.

1 participant