From b35646d0c02329a43b447c8ef708fa9e84fc7695 Mon Sep 17 00:00:00 2001 From: Saksham Bhutani Date: Wed, 15 Jul 2026 02:39:04 -0400 Subject: [PATCH 1/4] Add LuckRing/TK18 (K6 Protocol B) ring support with property-based BLE write type --- .../luckring-tk18.imageset/Contents.json | 12 + .../luckring-tk18.imageset/luckring-tk18.png | Bin 0 -> 302877 bytes .../RingProtocol/LuckRingCoordinator.swift | 73 ++++ PulseLoop/RingProtocol/LuckRingDecoder.swift | 271 +++++++++++++++ PulseLoop/RingProtocol/LuckRingDriver.swift | 85 +++++ PulseLoop/RingProtocol/LuckRingEncoder.swift | 181 ++++++++++ .../RingProtocol/LuckRingHistorySync.swift | 156 +++++++++ PulseLoop/RingProtocol/LuckRingProtocol.swift | 327 ++++++++++++++++++ .../RingProtocol/LuckRingSyncEngine.swift | 129 +++++++ PulseLoop/RingProtocol/RingBLEClient.swift | 47 ++- PulseLoop/Views/Settings/DeviceHeroCard.swift | 1 + PulseLoop/Wearables/WearableCoordinator.swift | 4 + PulseLoop/Wearables/WearableModel.swift | 14 +- PulseLoopTests/CapabilityGatingTests.swift | 31 ++ PulseLoopTests/LuckRingDecoderTests.swift | 200 +++++++++++ PulseLoopTests/LuckRingDriverTests.swift | 106 ++++++ PulseLoopTests/LuckRingEncoderTests.swift | 123 +++++++ PulseLoopTests/LuckRingHistorySyncTests.swift | 91 +++++ PulseLoopTests/LuckRingProtocolTests.swift | 148 ++++++++ PulseLoopTests/PairingMatchingTests.swift | 56 ++- docs/hardware/index.md | 17 +- docs/hardware/luckring.md | 148 ++++++++ docs/hardware/simsonlab.md | 8 +- mkdocs.yml | 1 + 24 files changed, 2217 insertions(+), 12 deletions(-) create mode 100644 PulseLoop/Assets.xcassets/luckring-tk18.imageset/Contents.json create mode 100644 PulseLoop/Assets.xcassets/luckring-tk18.imageset/luckring-tk18.png create mode 100644 PulseLoop/RingProtocol/LuckRingCoordinator.swift create mode 100644 PulseLoop/RingProtocol/LuckRingDecoder.swift create mode 100644 PulseLoop/RingProtocol/LuckRingDriver.swift create mode 100644 PulseLoop/RingProtocol/LuckRingEncoder.swift create mode 100644 PulseLoop/RingProtocol/LuckRingHistorySync.swift create mode 100644 PulseLoop/RingProtocol/LuckRingProtocol.swift create mode 100644 PulseLoop/RingProtocol/LuckRingSyncEngine.swift create mode 100644 PulseLoopTests/LuckRingDecoderTests.swift create mode 100644 PulseLoopTests/LuckRingDriverTests.swift create mode 100644 PulseLoopTests/LuckRingEncoderTests.swift create mode 100644 PulseLoopTests/LuckRingHistorySyncTests.swift create mode 100644 PulseLoopTests/LuckRingProtocolTests.swift create mode 100644 docs/hardware/luckring.md diff --git a/PulseLoop/Assets.xcassets/luckring-tk18.imageset/Contents.json b/PulseLoop/Assets.xcassets/luckring-tk18.imageset/Contents.json new file mode 100644 index 00000000..22d438c6 --- /dev/null +++ b/PulseLoop/Assets.xcassets/luckring-tk18.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "luckring-tk18.png", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/PulseLoop/Assets.xcassets/luckring-tk18.imageset/luckring-tk18.png b/PulseLoop/Assets.xcassets/luckring-tk18.imageset/luckring-tk18.png new file mode 100644 index 0000000000000000000000000000000000000000..ead233a7adbf6a192bda79d5ccbfb92c9e556e9d GIT binary patch literal 302877 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
`WDazYgmahL%V2KETdm$K=A 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 GCD`3X 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 z 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

~YigQM-J4r$9Uk{M%bWk4 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 G=)VCdcrnHR literal 0 HcmV?d00001 diff --git a/PulseLoop/RingProtocol/LuckRingCoordinator.swift b/PulseLoop/RingProtocol/LuckRingCoordinator.swift new file mode 100644 index 00000000..ddcbad3e --- /dev/null +++ b/PulseLoop/RingProtocol/LuckRingCoordinator.swift @@ -0,0 +1,73 @@ +import Foundation +@preconcurrency import CoreBluetooth + +/// Coordinator for the LuckRing / TK18 family (the "K6" vendor SDK). Declares what the driver can decode +/// and recognizes the device from its advertisement. The *protocol* is not TK18-specific — the whole +/// 0xFF64 LuckRing family speaks it — so the driver / encoder / decoder / sync engine it builds are the +/// shared `LuckRing*` types. This file is the whole of what makes a LuckRing a LuckRing: its advertised +/// identity and its capability set. +/// +/// Recognition is by **strong, family-exclusive signals**: the advertised `F618` service, or the +/// `0xFF64` manufacturer company ID (little-endian `64 FF` prefix), or a catalog name pattern (TK18). +/// The Android SDK matches on the company ID alone with no name whitelist, so a TK18 sibling that renames +/// itself is still claimed. +@MainActor +final class LuckRingCoordinator: WearableCoordinator { + nonisolated deinit {} // skip the main-actor isolated-deinit hop (crashes on older sim runtimes) + + static let deviceType: RingDeviceType = .luckRing + + /// The manufacturer-data prefix: company ID `0xFF64` in the little-endian slot ⇒ `64 FF`. This is the + /// single signal the vendor app itself matches on, so it is authoritative. + static let manufacturerHexPrefix = "64ff" + + static func matches(name: String?, advertisement: AdvertisementInfo) -> Bool { + if advertisesService(advertisement) { return true } + if let mfg = advertisement.manufacturerData, mfg.hexString.hasPrefix(manufacturerHexPrefix) { + return true + } + if WearableModel.model(advertisedName: name)?.family == .luckRing { return true } + return false + } + + /// True when the advertisement carries the `F618` service, in either its 16-bit or full 128-bit form. + private static func advertisesService(_ advertisement: AdvertisementInfo) -> Bool { + advertisement.serviceUUIDs.contains { uuid in + let value = uuid.uuidString.uppercased() + return value == "F618" || value == "0000F618-0000-1000-8000-00805F9B34FB" + } + } + + /// The baseline the LuckRing driver can decode: live + history HR, live + history SpO₂ (with the all-day + /// log), day steps, sleep, HRV, temperature, blood pressure, stress, and the in-band battery, plus the + /// find-device buzz. All are unconditional promises — every metric maps onto a `LuckRing*` decoder path. + /// + /// **`bitmapGatedCapabilities` is empty on purpose.** The K6 `FUNCTION_CONTROL` (dataType 22) bitmap is + /// obfuscated in the decompile, so no capability can yet be deferred to the connected unit; the whole + /// baseline stands as a family promise. TK18 is the only hardware-tested unit — a `.limited` family — + /// so capabilities the physical ring refuses should be pruned here once on-device testing confirms them + /// (see `docs/hardware/luckring.md`). + let capabilities: Set = [ + .heartRate, .realtimeHeartRate, .manualHeartRate, + .spo2, .manualSpo2, .spo2History, + .steps, .realtimeSteps, + .sleep, .battery, + .hrv, .manualHrv, + .temperature, + .bloodPressure, .manualBloodPressure, + .stress, + .findDevice, + // The K6 auto-monitoring config (opcode 128: auto-HR on/off, interval, auto-SpO₂) is a real + // device knob — the firmware ships with it *off*, so exposing the interval UI is what lets the + // ring log history at all. + .measurementInterval, + ] + + let bitmapGatedCapabilities: Set = [] + + let iconSystemName = "circle.circle.fill" + + func makeDriver(writer: RingCommandWriter) -> WearableDriver { + LuckRingDriver(writer: writer) + } +} diff --git a/PulseLoop/RingProtocol/LuckRingDecoder.swift b/PulseLoop/RingProtocol/LuckRingDecoder.swift new file mode 100644 index 00000000..02b759c6 --- /dev/null +++ b/PulseLoop/RingProtocol/LuckRingDecoder.swift @@ -0,0 +1,271 @@ +import Foundation + +/// Decodes reassembled LuckRing frames into the shared `RingDecodedEvent`. Frames arrive whole from +/// `LuckRingFrameAssembler`; this decoder dispatches on `dataType` and slices each record type per its +/// `ProcessDATA_TYPE_*` parser. +/// +/// **Timestamps are true UTC Unix seconds** (`TimeUtil.s2CForDev(sec, true) == sec*1000`), so — unlike +/// the jring/YCBT clocks, which store local wall-clock — decoding is a plain `Date(timeIntervalSince1970:)` +/// with no offset to un-apply. Range gating lives in `RingEventBridge`, so a misdecoded byte is dropped +/// rather than persisted; the decoder only cuts records and drops the ring's "no sample" fillers. +/// +/// **Every metric record uses one envelope**: `[total u16 LE][items u8]` then `items` fixed-stride +/// records. HR/HRV history and the live HR/HRV streams share the identical 5-byte record via the vendor's +/// `dealHeart` (a 3-byte sub-header + `[time u32][value u8]` records), so live vs. history is decided by +/// `dataType`, not by record shape. +struct LuckRingDecoder { + // A flat opcode router — each dataType is an independent record layout, not branching logic. + // swiftlint:disable:next cyclomatic_complexity + func decode(_ frame: LuckRingFrame, now: Date = Date()) -> [RingDecodedEvent] { + // A device ACK is a verdict on a command, not data. + if frame.cmdType == .ack { + return [.commandAck(commandId: frame.dataType)] + } + + let p = frame.payload + switch frame.dataType { + case LuckRingDataType.devInfo: + return decodeDeviceInfo(p) + case LuckRingDataType.battery: + guard let percent = p.first else { return [.commandAck(commandId: frame.dataType)] } + return [.battery(percent: Int(percent))] + + case LuckRingDataType.realSport, LuckRingDataType.historySport: + return decodeSport(p, dataType: frame.dataType) + case LuckRingDataType.sleep: + return decodeSleep(p, now: now) + + case LuckRingDataType.realHeart, LuckRingDataType.exerciseHeart: + return decodeLiveHeart(p, now: now) + case LuckRingDataType.historyHeart: + return decodeHistory(p, kind: .heartRate) + + case LuckRingDataType.realO2: + return decodeLiveSpO2(p, now: now) + case LuckRingDataType.historyO2: + return decodeHistory(p, kind: .spo2) + + case LuckRingDataType.realBP: + return decodeLiveBP(p, now: now) + case LuckRingDataType.historyBP: + return decodeHistoryBP(p) + + case LuckRingDataType.realHRV: + return decodeLive(p, now: now) { .hrvSample(value: Int($0), timestamp: $1) } + case LuckRingDataType.historyHRV: + return decodeHistory(p, kind: .hrv) + + case LuckRingDataType.realTemp: + return decodeTemperature(p, now: now, history: false) + case LuckRingDataType.historyTemp: + return decodeTemperature(p, now: now, history: true) + + case LuckRingDataType.stress: + return decodeLive(p, now: now) { .stressSample(value: Int($0), timestamp: $1) } + case LuckRingDataType.stressHistory: + return decodeHistory(p, kind: .stress) + + case LuckRingDataType.pairFinish, LuckRingDataType.findDevice, LuckRingDataType.devSync, + LuckRingDataType.functionControl, LuckRingDataType.unbind: + // Handshake/echo frames with no metric to persist — surfaced as acks (the raw-packet feed + // still shows them). `devSync` (9) carries a MixInfo TLV of settings/function bits, but the + // capability bitmap is obfuscated in the decompile, so nothing maps it yet. + return [.commandAck(commandId: frame.dataType)] + + default: + return [.unknown(commandId: frame.dataType, raw: Data(p))] + } + } + + // MARK: - Envelope helpers + + /// `[total u16 LE][items u8]` header, then `items` records. Returns each record's bytes, cut at the + /// declared item count. When `stride` is nil it is derived from the payload — needed for temperature, + /// whose 5-byte and 8-byte record variants share the same opcode (`K6_TempStruct.parse` vs + /// `parseFloat`). + private func records(_ payload: [UInt8], stride: Int?) -> [[UInt8]] { + guard payload.count >= 3 else { return [] } + let items = Int(payload[2]) + guard items > 0 else { return [] } + let body = Array(payload[3...]) + let step = stride ?? (body.count / items) + guard step > 0 else { return [] } + var out: [[UInt8]] = [] + var offset = 0 + for _ in 0.. Date { + Date(timeIntervalSince1970: TimeInterval(LuckRingBytes.u32(record, 0))) + } + + // MARK: - Records + + /// `K6_DevInfoStruct.getSoftwareVer()`: bytes `[1..5]` (customer.hardware.code.picture.font) joined by + /// dots. Byte `[0]` is the item count and is not part of the version. + private func decodeDeviceInfo(_ p: [UInt8]) -> [RingDecodedEvent] { + guard p.count >= 6 else { return [.commandAck(commandId: LuckRingDataType.devInfo)] } + let version = p[1...5].map { String(Int($0)) }.joined(separator: ".") + return [.firmware(version: version)] + } + + /// Sport records — 20 bytes each (`K6_Sport`): `[start u32][steps u32][distance u24(+pad)]` + /// `[calories u24(+pad)][duration u24(+pad)]`. Emitted as `.activityBucket` (per-interval, summed into + /// the day and upserted by timestamp) for both the live (4) and history (5) streams, so a re-sync is + /// idempotent. Calories are intentionally dropped (`.activityBucket` carries none). + private func decodeSport(_ p: [UInt8], dataType: UInt8) -> [RingDecodedEvent] { + let recs = records(p, stride: 20) + guard !recs.isEmpty else { return [.commandAck(commandId: dataType)] } + return recs.map { r in + .activityBucket(timestamp: ringDate(r), + steps: Int(LuckRingBytes.u32(r, 4)), + distanceMeters: Double(LuckRingBytes.u24(r, 8))) + } + } + + /// Live HR — 5-byte records `[time u32][bpm u8]` (`dealHeart`). An envelope with zero items is the + /// ring signalling the measurement ended, surfaced as `.heartRateComplete`. + private func decodeLiveHeart(_ p: [UInt8], now: Date) -> [RingDecodedEvent] { + let recs = records(p, stride: 5) + guard !recs.isEmpty else { return [.heartRateComplete(timestamp: now)] } + return recs.map { .heartRateSample(bpm: Int($0[4]), timestamp: ringDate($0)) } + } + + /// Live SpO₂ — 5-byte records `[time u32][spo2 u8]` (`K6_DATA_TYPE_REAL_O2`). + private func decodeLiveSpO2(_ p: [UInt8], now: Date) -> [RingDecodedEvent] { + let recs = records(p, stride: 5) + guard !recs.isEmpty else { return [.spo2Complete(timestamp: now)] } + return recs.map { .spo2Result(value: Int($0[4]), timestamp: ringDate($0)) } + } + + /// Live blood pressure — 6-byte records `[time u32][sys u8][dia u8]` (`K6_DATA_TYPE_REAL_BP`). + private func decodeLiveBP(_ p: [UInt8], now: Date) -> [RingDecodedEvent] { + let recs = records(p, stride: 6) + guard !recs.isEmpty else { return [.commandAck(commandId: LuckRingDataType.realBP)] } + return recs.map { + .bloodPressureSample(systolic: Int($0[4]), diastolic: Int($0[5]), timestamp: ringDate($0)) + } + } + + /// A generic single-value live stream — 5-byte records `[time u32][value u8]` — mapped through a + /// builder (HRV, stress). Empty envelope acks (nothing to complete). + private func decodeLive(_ p: [UInt8], now: Date, + _ make: (UInt8, Date) -> RingDecodedEvent) -> [RingDecodedEvent] { + let recs = records(p, stride: 5) + guard !recs.isEmpty else { return [.commandAck(commandId: 0)] } + return recs.map { make($0[4], ringDate($0)) } + } + + /// History for a 5-byte `[time u32][value u8]` type → `.historyMeasurement`. + private func decodeHistory(_ p: [UInt8], kind: MeasurementKind) -> [RingDecodedEvent] { + let recs = records(p, stride: 5) + guard !recs.isEmpty else { return [] } + return recs.map { .historyMeasurement(kind: kind, value: Double($0[4]), timestamp: ringDate($0)) } + } + + /// History blood pressure — 6-byte records fanned to a systolic and a diastolic row (each trends + /// independently), mirroring `EventPersistenceSubscriber`'s two-row storage. + private func decodeHistoryBP(_ p: [UInt8]) -> [RingDecodedEvent] { + let recs = records(p, stride: 6) + guard !recs.isEmpty else { return [] } + return recs.flatMap { r -> [RingDecodedEvent] in + let date = ringDate(r) + return [ + .historyMeasurement(kind: .bloodPressureSystolic, value: Double(r[4]), timestamp: date), + .historyMeasurement(kind: .bloodPressureDiastolic, value: Double(r[5]), timestamp: date), + ] + } + } + + /// Temperature — `K6_TempStruct`: `[time u32][value u16 LE]/10`. The stride is derived from the + /// envelope so both the 5-byte (`parse`) and 8-byte (`parseFloat`) record variants decode; the value + /// is read as a u16 when the record is wide enough, else a single byte, and scaled by 10. + private func decodeTemperature(_ p: [UInt8], now: Date, history: Bool) -> [RingDecodedEvent] { + let recs = records(p, stride: nil) + guard !recs.isEmpty else { + return history ? [] : [.commandAck(commandId: LuckRingDataType.realTemp)] + } + return recs.map { r in + let raw = r.count >= 6 ? LuckRingBytes.u16(r, 4) : Int(r.count > 4 ? r[4] : 0) + let celsius = Double(raw) / 10.0 + let date = ringDate(r) + return history + ? .historyMeasurement(kind: .temperature, value: celsius, timestamp: date) + : .temperatureSample(celsius: celsius, timestamp: date) + } + } + + // MARK: - Sleep + + /// Sleep timeline (`ProcessDATA_TYPE_SLEEP`): `[total u16][pageCount u8]`, then `pageCount` pages of + /// `[validCount u8]` + 15 × `[type u8][time u32 LE]` (76 B/page, only `validCount` entries valid). + /// + /// Types (`CEBC.SLEEPSTATUS`): 1 start, 2 deep, 3 light, 4 wake (ends a session), 5 movement. Each + /// entry's duration is the gap to the next entry; the segment's stage is the *earlier* entry's type, + /// mapped 1/3/5→light, 2→deep. A session runs from a start (or the first entry) to a wake, and is + /// emitted as a per-minute stage array stamped at the session start — the exact shape + /// `EventPersistenceSubscriber.persistSleepTimeline` groups back into stage blocks. + private func decodeSleep(_ p: [UInt8], now: Date) -> [RingDecodedEvent] { + guard p.count >= 3 else { return [.commandAck(commandId: LuckRingDataType.sleep)] } + let pageCount = Int(p[2]) + + var entries: [(type: UInt8, time: UInt32)] = [] + var offset = 3 + for _ in 0.. [RingDecodedEvent] { + var sessions: [RingDecodedEvent] = [] + var sessionStart: UInt32? + var stages: [SleepStage] = [] + + func flush() { + if let start = sessionStart, !stages.isEmpty { + sessions.append(.sleepTimeline(timestamp: Date(timeIntervalSince1970: TimeInterval(start)), + stages: stages)) + } + sessionStart = nil + stages = [] + } + + for i in entries.indices { + let entry = entries[i] + if entry.type == 1 { flush() } // explicit session start + if sessionStart == nil { sessionStart = entry.time } // implicit start + if entry.type == 4 { flush(); continue } // wake ends the session + + guard i + 1 < entries.count else { continue } // last entry has no duration + let delta = Int(entries[i + 1].time) - Int(entry.time) + let minutes = max(0, delta / 60) + let stage = sleepStage(entry.type) + stages.append(contentsOf: repeatElement(stage, count: minutes)) + } + flush() + return sessions + } + + private func sleepStage(_ type: UInt8) -> SleepStage { + switch type { + case 2: return .deep + case 4: return .awake + default: return .light // 1 start, 3 light, 5 movement all render as light sleep + } + } +} diff --git a/PulseLoop/RingProtocol/LuckRingDriver.swift b/PulseLoop/RingProtocol/LuckRingDriver.swift new file mode 100644 index 00000000..1c734c8b --- /dev/null +++ b/PulseLoop/RingProtocol/LuckRingDriver.swift @@ -0,0 +1,85 @@ +import Foundation +@preconcurrency import CoreBluetooth + +/// LuckRing / TK18 driver. Topology is a single service `F618` with a write char `B002` and a notify char +/// `B001`; the standard `180D` Heart Rate characteristic is deliberately left unsubscribed (mirror the +/// YCBT rationale — the proprietary `07` stream reflects real finger contact). +/// +/// **Framing is identity.** The encoder / sync engine / history pager already emit fully-framed 20-byte +/// packets (a logical frame is split into head + continuation packets and enqueued individually — the +/// jring pattern), so `frame(_:)` returns its input untouched. `RingBLEClient`'s serialized `withResponse` +/// write queue with its 4 s ACK timeout handles pacing between packets. +/// +/// **Inbound: ACK-before-decode.** The ring retransmits a device-initiated **SEND** until the app answers +/// with a matching ACK (`queue/b.java`'s app-ACK rule), so `ingest` enqueues the protocol ACK *before* it +/// decodes — a slow decode must never be able to stall the ring. A device ACK or a SEND_NO_ACK is never +/// ACKed (the former is not data; the latter, by definition, expects no reply). +@MainActor +final class LuckRingDriver: WearableDriver { + nonisolated deinit {} // skip the main-actor isolated-deinit hop (crashes on older sim runtimes) + + private weak var writer: RingCommandWriter? + private let decoder = LuckRingDecoder() + private let packetizer = LuckRingPacketizer() + /// Notify packets → whole logical frames. A multi-packet frame (e.g. the ring's history streams) is + /// split across notifications, so it must be reassembled before decode. + private let assembler = LuckRingFrameAssembler() + /// The history pager. The driver owns it because only the driver sees frames (`noteReceived`), and it + /// is handed to the engine so `runStartup` can seed the catalog pass. + private let historySync: LuckRingHistorySync + + init(writer: RingCommandWriter) { + self.writer = writer + self.historySync = LuckRingHistorySync(writer: writer) + } + + // MARK: BLE topology + let serviceUUIDs: [CBUUID] = [CBUUID(string: LuckRingUUIDs.service)] + let writeUUID = CBUUID(string: LuckRingUUIDs.write) + let notifyUUIDs: [CBUUID] = [CBUUID(string: LuckRingUUIDs.notify)] + let batteryServiceUUID: CBUUID? = nil // battery is in-band (dataType 3) + let batteryCharUUID: CBUUID? = nil + + // MARK: Framing + /// Identity — the engine/encoder emit fully-framed 20-byte packets, enqueued one per packet. + func frame(_ command: Data) -> Data { command } + + // MARK: Lifecycle + + /// Auto-reconnect reuses this driver, so a frame half-assembled when the old link dropped would be + /// completed with bytes from the new one, and a history pass would still think it was mid-type. + func connectionDidStart() { + assembler.reset() + historySync.cancel() + } + + /// The history pager's settle/stall watchdogs are timers; a ring that drops mid-pass leaves them + /// stepping through the rest of the catalog into a write queue the reconnect will flush before its + /// handshake. Kill it at disconnect — the one place that can't race the reconnect. + func connectionDidEnd() { + assembler.reset() + historySync.cancel() + } + + // MARK: Inbound decode + + func ingest(_ data: Data, from characteristic: CBUUID) -> [RingDecodedEvent] { + guard let frame = assembler.append(data) else { return [] } + + // ACK a device-initiated SEND before decoding — the ring retransmits until we do. + if frame.cmdType == .send { + writer?.enqueue(packetizer.ack(dataType: frame.dataType, seq: frame.seq, devType: frame.devType)) + } + + // Let the history pager settle/advance on this type's data frames. + if frame.cmdType == .send || frame.cmdType == .sendNoAck { + historySync.noteReceived(dataType: frame.dataType) + } + + return decoder.decode(frame) + } + + func makeSyncEngine() -> RingSyncEngine { + LuckRingSyncEngine(writer: writer, historySync: historySync) + } +} diff --git a/PulseLoop/RingProtocol/LuckRingEncoder.swift b/PulseLoop/RingProtocol/LuckRingEncoder.swift new file mode 100644 index 00000000..e997d196 --- /dev/null +++ b/PulseLoop/RingProtocol/LuckRingEncoder.swift @@ -0,0 +1,181 @@ +import Foundation + +/// Builds *logical* LuckRing frames — the connect bundle, the clock, history requests, the real-time +/// toggles, and the device actions. It owns the rolling `seq` counter (the head packet's `[3]`), so each +/// frame it hands out carries the next sequence number; `LuckRingPacketizer` stamps it into the wire +/// bytes. +/// +/// The connect bundle is **parameterized**, not a captured replay: it reproduces the exact property set +/// and order of `K6SendDataManager.sendAynInfoDetail()` — the method the vendor app runs on connect — +/// with every field built from the SDK's own struct byte layouts (`K6_SendUserInfo`, `K6_CESyncTime`, +/// `K6_SendGoal`, `K6_MixInfoStruct`). Wire spec: `tasks/luckring-protocol.md` §MixInfo. +struct LuckRingEncoder { + /// The rolling per-frame sequence. `queue/b.java` writes it to head `[3]` and the ring echoes it in + /// its ACK; only monotonic-ish uniqueness matters, so a plain wrapping `UInt8` is enough. + private var seq: UInt8 = 0 + + private mutating func nextSeq() -> UInt8 { + let value = seq + seq = seq &+ 1 + return value + } + + private mutating func frame(_ cmdType: LuckRingCmdType, _ dataType: UInt8, _ payload: [UInt8]) -> LuckRingFrame { + LuckRingFrame(cmdType: cmdType, dataType: dataType, payload: payload, seq: nextSeq()) + } + + // MARK: - Struct byte layouts (each matches its `K6_*` entity exactly) + + /// `K6_SendUserInfo.getBytes()` — 9 bytes: `[userId u32 LE][sex][age][height cm][weight kg][reserved]`. + /// + /// **Sex is inverted on the wire.** `sendAynInfoDetail()` sends `(appSex == 1) ? 0 : 1`, where the + /// app's `1` is male — so the ring's sex byte is `0 = male, 1 = otherwise`. `UserProfileValues.gender` + /// is `1 = male`, hence `gender == 1 ? 0 : 1`. Age floors at the vendor's default of 20 when unset. + static func userInfoBytes(_ profile: UserProfileValues, userId: UInt32 = 0) -> [UInt8] { + var bytes = LuckRingBytes.le32(userId) + bytes.append(profile.gender == 1 ? 0 : 1) + bytes.append(profile.age < 1 ? 20 : profile.age) + bytes.append(profile.heightCm) + bytes.append(profile.weightKg) + bytes.append(0) // reserved + return bytes + } + + /// `K6_CESyncTime.getBytes()` — 9 bytes: `[absSeconds u32 LE][utcOffsetSeconds u32 LE][formatByte]`. + /// + /// `absSeconds` is the **true UTC** Unix epoch (`TimeUtil.now()/1000`), not local wall-clock — so + /// unlike the jring/YCBT clocks, every ring-stamped record decodes with no offset to un-apply + /// (`TimeUtil.s2CForDev(sec, true) == sec*1000`). The format byte is `(timeDisplay ^ (dateDisplay<<1))`; + /// both displays default to 0, so it is 0. + static func timeBytes(date: Date = Date(), timeZone: TimeZone = .current) -> [UInt8] { + var bytes = LuckRingBytes.le32(UInt32(date.timeIntervalSince1970)) + let offset = UInt32(bitPattern: Int32(timeZone.secondsFromGMT(for: date))) + bytes.append(contentsOf: LuckRingBytes.le32(offset)) + bytes.append(0) // format byte (12/24h ^ date order << 1); both default 0 + return bytes + } + + /// `K6_SendGoal.getBytes()` — 16 bytes: `[step u32][distance u32][calories u32][sleep u16][duration u16]`, + /// all LE. PulseLoop only tracks a step goal; the other four are 0. + static func goalBytes(steps: Int) -> [UInt8] { + var bytes = LuckRingBytes.le32(UInt32(max(0, steps))) + bytes.append(contentsOf: LuckRingBytes.le32(0)) // distance + bytes.append(contentsOf: LuckRingBytes.le32(0)) // calories + bytes.append(contentsOf: LuckRingBytes.le16(0)) // sleep + bytes.append(contentsOf: LuckRingBytes.le16(0)) // duration + return bytes + } + + // MARK: - Connect bundle (MixInfo 110) + + /// The binding / startup bundle, in `sendAynInfoDetail()`'s exact property order: + /// 102 user info → 104 time → 124 call-alarm → 103 language → 109 data-switch → 111 goals → 120 pair. + /// + /// - `109 data-switch = 1` is what enables the ring's real-time pushes. + /// - `120 pair = {firstPair ? 1 : 0, 0}`: the leading 1 asks the ring to run its pairing animation and + /// is sent only on the very first bind; every later connect sends `{0,0}`, or the ring re-pairs. + /// - `124 call-alarm = {1, 0xFF, 0xFF, 0, 0}` is the vendor's literal constant. + mutating func startupBundle( + profile: UserProfileValues, + goalSteps: Int, + firstPair: Bool, + date: Date = Date(), + languageCode: UInt8 = 0 + ) -> LuckRingFrame { + let properties: [LuckRingMixInfoTLV.Property] = [ + .init(type: LuckRingDataType.userInfo, data: Self.userInfoBytes(profile)), + .init(type: LuckRingDataType.time, data: Self.timeBytes(date: date)), + .init(type: LuckRingDataType.callAlarm, data: [1, 0xFF, 0xFF, 0, 0]), + .init(type: LuckRingDataType.language, data: [languageCode]), + .init(type: LuckRingDataType.dataSwitch, data: [1]), + .init(type: LuckRingDataType.goals, data: Self.goalBytes(steps: goalSteps)), + .init(type: LuckRingDataType.pairFinish, data: [firstPair ? 1 : 0, 0]), + ] + return frame(.send, LuckRingDataType.mixInfo, LuckRingMixInfoTLV.encode(properties)) + } + + // MARK: - Standalone settings + + /// Push the ring clock on its own (`104`, the live timezone-change path). + mutating func setTime(date: Date = Date()) -> LuckRingFrame { + frame(.send, LuckRingDataType.time, Self.timeBytes(date: date)) + } + + /// Push the user's profile on its own (`102`). + mutating func userInfo(_ profile: UserProfileValues) -> LuckRingFrame { + frame(.send, LuckRingDataType.userInfo, Self.userInfoBytes(profile)) + } + + /// Set the step goal on its own (`111`). + mutating func setGoal(steps: Int) -> LuckRingFrame { + frame(.send, LuckRingDataType.goals, Self.goalBytes(steps: steps)) + } + + /// Enable/disable the real-time push data-switch (`109`). + mutating func dataSwitch(on: Bool) -> LuckRingFrame { + frame(.send, LuckRingDataType.dataSwitch, [on ? 1 : 0]) + } + + /// Auto-monitoring config (`128`, `K6_DATA_TYPE_HEART_AUTO_SWITCH` — 8 bytes: + /// `[autoHR][hr24h][interval min][autoO2][0×4]`). This is what makes the ring log HR/SpO₂ history + /// **on its own**: the firmware default is *off* (`new K6_DATA_TYPE_HEART_AUTO_SWITCH(0, 0, 30)`), + /// so a ring that never visited the vendor app's monitoring screen records nothing between syncs + /// until this is sent. `hr24h` (continuous mode) stays 0, matching the vendor default. + mutating func autoMonitoring(_ settings: MeasurementSettings) -> LuckRingFrame { + frame(.send, LuckRingDataType.heartAutoSwitch, [ + settings.hrEnabled ? 1 : 0, + 0, + UInt8(clamping: settings.hrIntervalMinutes), + settings.spo2Enabled ? 1 : 0, + 0, 0, 0, 0, + ]) + } + + // MARK: - Requests (cmdType REQUEST, empty payload) + + /// Ask the ring for a data type: a bare `REQUEST` with no payload (`new CEDevData(3, dataType)`). + /// Used for device info (2), battery (3), settings-sync (9), and every history stream. + mutating func request(_ dataType: UInt8) -> LuckRingFrame { + frame(.request, dataType, []) + } + + // MARK: - Real-time toggles (each is its own `K6_DATA_TYPE_REAL_*` send) + + /// Real HR toggle (`24`, `K6_DATA_TYPE_REAL_HR` — 1 payload byte). The stream itself comes back on + /// dataType 7. + mutating func realHeartRate(on: Bool) -> LuckRingFrame { + frame(.send, LuckRingDataType.realHR, [on ? 1 : 0]) + } + + /// Real SpO₂ toggle (`20`, `K6_DATA_TYPE_REAL_O2` — `[on,0,0,0,0]`). + mutating func realSpO2(on: Bool) -> LuckRingFrame { + frame(.send, LuckRingDataType.realO2, [on ? 1 : 0, 0, 0, 0, 0]) + } + + /// Real HRV toggle (`45`, `K6_DATA_TYPE_REAL_HRV` — 1 payload byte). + mutating func realHRV(on: Bool) -> LuckRingFrame { + frame(.send, LuckRingDataType.realHRV, [on ? 1 : 0]) + } + + /// Real blood-pressure toggle (`18`, `K6_DATA_TYPE_REAL_BP` — `[on,0,0,0,0,0]`). + mutating func realBloodPressure(on: Bool) -> LuckRingFrame { + frame(.send, LuckRingDataType.realBP, [on ? 1 : 0, 0, 0, 0, 0, 0]) + } + + /// Real temperature toggle (`46`, `K6_DATA_TYPE_REAL_TEMP` — 1 payload byte). + mutating func realTemperature(on: Bool) -> LuckRingFrame { + frame(.send, LuckRingDataType.realTemp, [on ? 1 : 0]) + } + + // MARK: - Device actions + + /// Buzz the ring (`11`, `K6_DATA_TYPE_FIND_PHONE_OR_DEVICE` — 1 payload byte). + mutating func findDevice() -> LuckRingFrame { + frame(.send, LuckRingDataType.findDevice, [1]) + } + + /// Release the ring on Forget (`159`, `sendUnbind` — 1 payload byte). + mutating func unbind() -> LuckRingFrame { + frame(.send, LuckRingDataType.unbind, [1]) + } +} diff --git a/PulseLoop/RingProtocol/LuckRingHistorySync.swift b/PulseLoop/RingProtocol/LuckRingHistorySync.swift new file mode 100644 index 00000000..0ab5395b --- /dev/null +++ b/PulseLoop/RingProtocol/LuckRingHistorySync.swift @@ -0,0 +1,156 @@ +import Foundation + +/// The LuckRing history pager. Unlike the YCBT transfer (whose terminal block ends each type), the K6 +/// history streams carry **no cursor and no end-of-transfer marker** — the ring just replays every stored +/// record of a type as one or more device-initiated data frames. So this is a simpler, *time-settled* +/// sequential pager: request a type, advance when its data frames stop arriving (a short settle window), +/// or skip it if none arrive at all (a stall timeout — an unsupported type answers with nothing). +/// +/// Replays are safe: persistence upserts history by `(kind, timestamp)`, activity by bucket timestamp, +/// and sleep by night, so re-requesting a type it already saw never double-counts. The destructive +/// `cleanData` (207) opcode is deliberately never sent. +@MainActor +final class LuckRingHistorySync { + nonisolated deinit {} // skip the main-actor isolated-deinit hop (crashes on older sim runtimes) + + /// The full catalog, in request order. `mixSport` (10 — workout records) is skipped in v1. + static let catalog: [UInt8] = [ + LuckRingDataType.historySport, // 5 + LuckRingDataType.sleep, // 6 + LuckRingDataType.historyHeart, // 8 + LuckRingDataType.historyO2, // 40 + LuckRingDataType.historyBP, // 41 + LuckRingDataType.historyHRV, // 42 + LuckRingDataType.historyTemp, // 47 + LuckRingDataType.stressHistory, // 53 + ] + + /// The post-workout backfill subset — only the logs a session can have added to. + static let vitalsTypes: [UInt8] = [LuckRingDataType.historyHeart, LuckRingDataType.historyO2] + + private weak var writer: RingCommandWriter? + private let packetizer = LuckRingPacketizer() + /// Progress sink. `nil` publishes to the shared bus (the production path); tests inject a spy. + private let progressSink: ((PulseEvent) -> Void)? + + /// Re-armed on every data frame for the in-flight type; when it fires the type is "settled" and we + /// advance. Short, because the ring streams a type's frames back-to-back. + private let settleSeconds: TimeInterval + /// Fires when a type produces no data at all (unsupported / empty) — skip it. Longer than settle. + private let stallSeconds: TimeInterval + + private var queue: [UInt8] = [] + private var currentType: UInt8? + private var seq: UInt8 = 0 + private var settleTask: Task? + private var stallTask: Task? + + init( + writer: RingCommandWriter?, + settleSeconds: TimeInterval = 1.5, + stallSeconds: TimeInterval = 6, + progressSink: ((PulseEvent) -> Void)? = nil + ) { + self.writer = writer + self.settleSeconds = settleSeconds + self.stallSeconds = stallSeconds + self.progressSink = progressSink + } + + /// Surface a sync-progress event — to the injected spy in tests, else the shared bus. + private func publish(_ event: PulseEvent) { + if let progressSink { + progressSink(event) + } else { + Task { await PulseEventBus.shared.publish(event) } + } + } + + var isRunning: Bool { currentType != nil } + + /// Seed the queue and request the first type. A pass already in flight wins — a re-entrant `start` + /// would abandon the in-flight type mid-stream and land its frames in the wrong bucket. + func start(types: [UInt8]) { + guard !isRunning else { return } + queue = types + advance() + } + + /// Abandon any in-flight pass (disconnect / teardown). + func cancel() { + cancelTimers() + currentType = nil + queue.removeAll() + } + + /// Called by the driver for every completed device-initiated data frame. A frame for the in-flight + /// type re-arms the settle window; anything else is ignored. + func noteReceived(dataType: UInt8) { + guard let currentType, dataType == currentType else { return } + stallTask?.cancel(); stallTask = nil + armSettle() + } + + // MARK: - Driving the queue + + private func advance() { + cancelTimers() + guard !queue.isEmpty else { + currentType = nil + publish(.syncProgress(stage: "done")) + return + } + let type = queue.removeFirst() + currentType = type + publish(.syncProgress(stage: "Syncing \(Self.label(for: type))…")) + sendRequest(type) + armStall() + } + + private func sendRequest(_ dataType: UInt8) { + let frame = LuckRingFrame(cmdType: .request, dataType: dataType, payload: [], seq: seq) + seq &+= 1 + for packet in packetizer.packets(for: frame) { + writer?.enqueue(packet) + } + } + + private func armSettle() { + settleTask?.cancel() + settleTask = Task { [weak self] in + let nanos = UInt64((self?.settleSeconds ?? 1.5) * 1_000_000_000) + try? await Task.sleep(nanoseconds: nanos) + guard !Task.isCancelled, let self else { return } + self.advance() + } + } + + private func armStall() { + stallTask?.cancel() + stallTask = Task { [weak self] in + let nanos = UInt64((self?.stallSeconds ?? 6) * 1_000_000_000) + try? await Task.sleep(nanoseconds: nanos) + guard !Task.isCancelled, let self else { return } + self.advance() // no data ever arrived for this type — skip it + } + } + + private func cancelTimers() { + settleTask?.cancel(); settleTask = nil + stallTask?.cancel(); stallTask = nil + } + + private static func label(for dataType: UInt8) -> String { + switch dataType { + case LuckRingDataType.historySport: return "activity" + case LuckRingDataType.sleep: return "sleep" + case LuckRingDataType.historyHeart: return "heart rate" + case LuckRingDataType.historyO2: return "blood oxygen" + case LuckRingDataType.historyBP: return "blood pressure" + case LuckRingDataType.historyHRV: return "HRV" + case LuckRingDataType.historyTemp: return "temperature" + case LuckRingDataType.stressHistory: return "stress" + default: return "history" + } + } +} diff --git a/PulseLoop/RingProtocol/LuckRingProtocol.swift b/PulseLoop/RingProtocol/LuckRingProtocol.swift new file mode 100644 index 00000000..3138e46f --- /dev/null +++ b/PulseLoop/RingProtocol/LuckRingProtocol.swift @@ -0,0 +1,327 @@ +import Foundation +@preconcurrency import CoreBluetooth + +/// LuckRing / TK18 ("K6 Protocol B") protocol primitives — GATT topology, the fixed 20-byte packet +/// framing, opcodes, the MixInfo TLV, and the little-endian byte helpers. This is the wire language the +/// whole 0xFF64 LuckRing family speaks (PID families 618/818/118/518/S2, sold under simsonlab and other +/// brands); what makes a *TK18* a TK18 is only its advertised identity + capability set, which live in +/// `LuckRingCoordinator`. +/// +/// Ground truth is the decompiled vendor SDK (`ce.com.cenewbluesdk`, internal family "K6"): +/// `CEBC.java` (opcodes), `queue/b.java` (framing + the app-ACK rule), `K6SendDataManager.java` +/// (`sendAynInfoDetail()` — the connect bundle), `entity/k6/K6_*.java` (struct byte layouts) and +/// `.../BlueProcessBean/ProcessDATA_TYPE_*.java` (record parsers). Written up in +/// `tasks/luckring-protocol.md`, which is the reference to read before touching any byte offset here. +/// +/// **Framing.** Every write/notify is a fixed **20-byte** packet. The head packet is +/// `[0]=0 [1]=devType [2]=#continuation-pages [3]=rolling-seq [4]=cmdType [5]=dataType` +/// `[6..7]=CRC16 (always 0x0000 — disabled in vendor code) [8..9]=payloadLen LE [10..19]=payload[0..9]` +/// and each continuation is `[0]=1-based page index [1..19]=next 19 payload bytes`. All integers are +/// little-endian. There is no crypto and no CRC to compute; binding is the MixInfo bundle (dataType 110). +enum LuckRingUUIDs { + /// Primary protocol service. + static let service = "0000f618-0000-1000-8000-00805f9b34fb" + /// Notify characteristic (CCCD) — the ring streams every reply / data frame here. + static let notify = "0000b001-0000-1000-8000-00805f9b34fb" + /// Write characteristic — the app writes every 20-byte packet here. + static let write = "0000b002-0000-1000-8000-00805f9b34fb" + + /// Standard BLE Heart Rate service. Present on the ring but **deliberately not subscribed** — mirror + /// the YCBT rationale: the proprietary `07` stream reflects real finger contact, the standard `180D` + /// characteristic can emit a stale cached value. Kept here only to document the GATT layout. + static let heartRateService = "180D" + + /// The head packet's `devType` byte. TK18 is a **618-family** unit (`CEBC.PID_TYPE.PID_618 == 1`); the + /// ring never validates an inbound head's devType (`queue/b.java` just stores `bArr[1]`), and every ACK + /// we send echoes the value the ring itself used, so this is only the seed for the first outbound + /// packets before any frame has been received. + static let deviceType: UInt8 = 1 +} + +/// The `cmdType` byte (`CEBC.K6.CMD_TYPE_*`). The app ACKs a device-initiated **SEND**; it never ACKs an +/// ACK or a SEND_NO_ACK (which by definition expects none), so ACKing only `.send` can neither stall the +/// ring nor spam the wire. +enum LuckRingCmdType: UInt8, Sendable { + case send = 1 + case sendNoAck = 2 + case request = 3 + case ack = 4 +} + +/// The `dataType` opcodes (`CEBC.K6.DATA_TYPE_*`). Only the ones PulseLoop drives or decodes are named; +/// the rest of the vendor table (alarms, watch faces, contacts, OTA, …) has no product surface here. +enum LuckRingDataType { + static let devInfo: UInt8 = 2 // 6B → firmware "customer.hardware.code.picture.font" + static let battery: UInt8 = 3 // [percent][charging] + static let realSport: UInt8 = 4 // live step buckets + static let historySport: UInt8 = 5 // stored step buckets + static let sleep: UInt8 = 6 // paged sleep timeline + static let realHeart: UInt8 = 7 // live HR (envelope + 5B records) + static let historyHeart: UInt8 = 8 // stored HR + static let devSync: UInt8 = 9 // settings sync — reply is a MixInfo TLV + static let mixSport: UInt8 = 10 // workout records (skipped in v1) + static let findDevice: UInt8 = 11 // buzz the ring + static let functionControl: UInt8 = 22 // capability bitmap (obfuscated — not mapped) + static let exerciseHeart: UInt8 = 17 // workout HR (envelope + 5B records) + static let realBP: UInt8 = 18 // live blood pressure + static let realO2: UInt8 = 20 // live SpO₂ + static let realHR: UInt8 = 24 // real-HR toggle (write side) + static let historyO2: UInt8 = 40 // stored SpO₂ + static let historyBP: UInt8 = 41 // stored blood pressure + static let historyHRV: UInt8 = 42 // stored HRV + static let realHRV: UInt8 = 45 // live HRV toggle + stream + static let realTemp: UInt8 = 46 // live temperature toggle + stream + static let historyTemp: UInt8 = 47 // stored temperature + static let stress: UInt8 = 52 // body-recovery / stress (live) + static let stressHistory: UInt8 = 53 // body-recovery / stress (stored) + static let userInfo: UInt8 = 102 // 9B profile + static let language: UInt8 = 103 + static let time: UInt8 = 104 // 9B clock + static let dataSwitch: UInt8 = 109 // 1 enables the real-time pushes + static let mixInfo: UInt8 = 110 // the binding / startup TLV bundle + static let goals: UInt8 = 111 // 16B goals + static let reset: UInt8 = 118 + static let pairFinish: UInt8 = 120 // ring → app: pairing complete + static let heartAutoSwitch: UInt8 = 128 // 8B auto-monitoring config (autoHR/interval/autoO2) + static let callAlarm: UInt8 = 124 + static let unbind: UInt8 = 159 +} + +/// Little-endian helpers. Every K6 integer is LE (`ByteUtil.int2bytes2` / `intToByte4` / `byte4ToInt`). +enum LuckRingBytes { + static func u16(_ b: [UInt8], _ i: Int) -> Int { + guard b.count >= i + 2 else { return 0 } + return Int(b[i]) | (Int(b[i + 1]) << 8) + } + + static func u24(_ b: [UInt8], _ i: Int) -> Int { + guard b.count >= i + 3 else { return 0 } + return Int(b[i]) | (Int(b[i + 1]) << 8) | (Int(b[i + 2]) << 16) + } + + static func u32(_ b: [UInt8], _ i: Int) -> UInt32 { + guard b.count >= i + 4 else { return 0 } + return UInt32(b[i]) | (UInt32(b[i + 1]) << 8) | (UInt32(b[i + 2]) << 16) | (UInt32(b[i + 3]) << 24) + } + + static func le16(_ value: Int) -> [UInt8] { + [UInt8(value & 0xff), UInt8((value >> 8) & 0xff)] + } + + static func le32(_ value: UInt32) -> [UInt8] { + [UInt8(value & 0xff), UInt8((value >> 8) & 0xff), UInt8((value >> 16) & 0xff), UInt8((value >> 24) & 0xff)] + } +} + +/// A *logical* K6 frame — one command or one reassembled data frame, independent of how many 20-byte +/// packets carry it. `cmdType`/`dataType`/`payload` are the meaning; `seq`/`devType` are the framing +/// identifiers an ACK must echo back (`queue/b.java` copies `bArr[3]`/`bArr[1]` into its reply). +struct LuckRingFrame: Equatable, Sendable { + var cmdType: LuckRingCmdType + var dataType: UInt8 + var payload: [UInt8] + var seq: UInt8 = 0 + var devType: UInt8 = LuckRingUUIDs.deviceType +} + +/// Splits a logical frame into exact 20-byte packets, and builds the mandatory app-ACK. +/// +/// Page math mirrors `queue/b.java`'s `a(length)`: the head carries the first 10 payload bytes, each +/// continuation the next 19, so `pages = ceil((len-10)/19)` (0 when `len ≤ 10`). Every packet is +/// zero-padded to 20 bytes; `[6..7]` is always `0x0000` because the vendor sends `figureCrc16()==0`. +struct LuckRingPacketizer { + /// The fixed BLE packet size (`queue/b.java`'s `h`). + static let packetSize = 20 + private static let headPayload = 10 + private static let continuationPayload = 19 + + /// The number of continuation pages a payload of `length` bytes needs. + static func continuationPages(payloadLength length: Int) -> Int { + guard length > headPayload else { return 0 } + let remainder = length - headPayload + return remainder / continuationPayload + (remainder % continuationPayload > 0 ? 1 : 0) + } + + func packets(for frame: LuckRingFrame) -> [Data] { + let payload = frame.payload + let pages = Self.continuationPages(payloadLength: payload.count) + + var head = [UInt8](repeating: 0, count: Self.packetSize) + head[0] = 0 + head[1] = frame.devType + head[2] = UInt8(min(pages, 255)) + head[3] = frame.seq + head[4] = frame.cmdType.rawValue + head[5] = frame.dataType + // [6..7] CRC16 disabled (0x0000); [8..9] payload length LE. + head[8] = UInt8(payload.count & 0xff) + head[9] = UInt8((payload.count >> 8) & 0xff) + for i in 0.. 0 { + for page in 1...pages { + var packet = [UInt8](repeating: 0, count: Self.packetSize) + packet[0] = UInt8(min(page, 255)) + let start = Self.headPayload + (page - 1) * Self.continuationPayload + for i in 0.. Data { + var packet = [UInt8](repeating: 0, count: Self.packetSize) + packet[1] = devType + packet[3] = seq + packet[4] = LuckRingCmdType.ack.rawValue + packet[5] = dataType + packet[8] = 1 // payload length = 1 + packet[10] = 1 // status 1 = accepted (CRC disabled ⇒ always accepted) + return Data(packet) + } +} + +/// Reassembles 20-byte notify packets into whole logical frames. +/// +/// A head packet (`[0]==0`) starts a frame and declares its payload length at `[8..9]` and its +/// continuation count at `[2]`; a device ACK head (`[4]==4`) is self-contained. Continuations +/// (`[0]!=0`) must arrive in strict 1-based order. A fresh head mid-assembly abandons the partial one +/// (`queue/b.java` overwrites its single buffer), and a continuation with no head is dropped — so one +/// truncated frame after a disconnect can't poison the next. +@MainActor +final class LuckRingFrameAssembler { + nonisolated deinit {} // skip the main-actor isolated-deinit hop (crashes on older sim runtimes) + + private struct Partial { + let cmdType: LuckRingCmdType + let dataType: UInt8 + let seq: UInt8 + let devType: UInt8 + let totalPages: Int + let declaredLength: Int + var payload: [UInt8] + var receivedPages: Int + } + + private var partial: Partial? + + /// Drop any half-assembled frame. A fresh driver is built per connection, so this is for reconnects + /// that reuse one (and for tests). + func reset() { partial = nil } + + /// Feed one 20-byte notify packet; returns the frame it completed, or nil while still assembling. + func append(_ data: Data) -> LuckRingFrame? { + let bytes = [UInt8](data) + guard bytes.count >= LuckRingPacketizer.packetSize else { return nil } + + if bytes[0] == 0 { + return handleHead(bytes) + } + return handleContinuation(bytes) + } + + private func handleHead(_ bytes: [UInt8]) -> LuckRingFrame? { + let devType = bytes[1] + let seq = bytes[3] + let rawCmd = bytes[4] & 0x0f + let dataType = bytes[5] + let cmdType = LuckRingCmdType(rawValue: rawCmd) ?? .send + + // A device ACK is a complete, single-packet frame — its status byte is at [10]. + if cmdType == .ack { + partial = nil + return LuckRingFrame(cmdType: .ack, dataType: dataType, payload: [bytes[10]], seq: seq, devType: devType) + } + + let declaredLen = LuckRingBytes.u16(bytes, 8) + let totalPages = Int(bytes[2]) + let firstChunk = Array(bytes[10.. LuckRingFrame? { + guard var current = partial else { return nil } // continuation with no head — drop it + let pageIndex = Int(bytes[0]) + guard pageIndex == current.receivedPages + 1 else { + // A jumped/duplicated page can't be recovered into this frame; abandon it. + partial = nil + return nil + } + current.payload.append(contentsOf: bytes[1..<20]) + current.receivedPages = pageIndex + partial = current + + guard current.receivedPages >= current.totalPages else { return nil } + partial = nil + // Trim to the head's declared length — the last continuation is zero-padded to 20 bytes, and the + // vendor codec sizes its buffer from the declared length. Without the cut, decoders that derive a + // record stride from the payload size (temperature's 5B/8B variants) would misparse. + return LuckRingFrame(cmdType: current.cmdType, dataType: current.dataType, + payload: Array(current.payload.prefix(current.declaredLength)), + seq: current.seq, devType: current.devType) + } +} + +/// The MixInfo TLV (`K6_MixInfoStruct`): the container the K6 protocol uses for its binding bundle +/// (dataType 110) and its settings-sync reply (dataType 9). Layout: +/// `[totalLen u16 LE][itemCount u8]` then, per property, `[propLen u16 LE = dataLen+3][propType u8][data]`. +/// `totalLen` is `(Σ propBytes) + 1` — the size of everything after the length field itself — and is +/// ignored on decode, which walks `itemCount` properties from offset 3. +enum LuckRingMixInfoTLV { + struct Property: Equatable { + let type: UInt8 + let data: [UInt8] + } + + static func encode(_ properties: [Property]) -> [UInt8] { + var propBytes: [UInt8] = [] + for property in properties { + let propLen = property.data.count + 3 + propBytes.append(contentsOf: LuckRingBytes.le16(propLen)) + propBytes.append(property.type) + propBytes.append(contentsOf: property.data) + } + var out = LuckRingBytes.le16(propBytes.count + 1) + out.append(UInt8(properties.count & 0xff)) + out.append(contentsOf: propBytes) + return out + } + + static func decode(_ bytes: [UInt8]) -> [Property] { + guard bytes.count >= 3 else { return [] } + let itemCount = Int(bytes[2]) + var properties: [Property] = [] + var i = 3 + for _ in 0..= 0, i + 3 + dataLen <= bytes.count else { break } + let type = bytes[i + 2] + let data = Array(bytes[(i + 3)..<(i + 3 + dataLen)]) + properties.append(Property(type: type, data: data)) + i += propLen + } + return properties + } +} diff --git a/PulseLoop/RingProtocol/LuckRingSyncEngine.swift b/PulseLoop/RingProtocol/LuckRingSyncEngine.swift new file mode 100644 index 00000000..68a57109 --- /dev/null +++ b/PulseLoop/RingProtocol/LuckRingSyncEngine.swift @@ -0,0 +1,129 @@ +import Foundation + +/// LuckRing sync engine. Connect is the MixInfo binding bundle followed by device-info / battery / +/// settings-sync requests and the history catalog pass; the ring's real-time streams are toggled by the +/// per-metric `K6_DATA_TYPE_REAL_*` sends. +/// +/// History is **not** driven from `handle(_:)`. The pager (`LuckRingHistorySync`, owned by the driver — the +/// only thing that sees frames) advances itself off the ring's data frames, so `handle` is a no-op. +/// +/// Every logical frame is split into 20-byte packets here (the driver's `frame(_:)` is identity) and each +/// packet is enqueued individually onto `RingBLEClient`'s serialized write queue. +@MainActor +final class LuckRingSyncEngine: RingSyncEngine { + nonisolated deinit {} // skip the main-actor isolated-deinit hop (crashes on older sim runtimes) + + private weak var writer: RingCommandWriter? + private var encoder = LuckRingEncoder() + private let packetizer = LuckRingPacketizer() + private let historySync: LuckRingHistorySync + + /// Pushed in by `RingSyncCoordinator` before `runStartup`, so the binding bundle carries the user's + /// real profile / goal. Defaults keep a freshly-paired ring sane until the store is read. + private var userProfile = UserProfileValues(metric: true, sex: nil, age: nil, heightCm: nil, weightKg: nil) + private var goalSteps = 10_000 + /// Auto-monitoring config pushed as opcode 128 on startup. Defaults to the jring-style 30-minute + /// cadence *enabled* — the K6 firmware default is monitoring **off**, which would leave every + /// history stream permanently empty on a ring the vendor app never configured. + private var measurementSettings = MeasurementSettings.jringDefault + + /// Whether this app has ever completed a LuckRing bind. The pair token's leading `1` triggers the + /// ring's pairing animation and must be sent only once, so it is latched in UserDefaults — see the + /// engine notes in `LuckRingEncoder.startupBundle`. (Not keyed per-peripheral: the engine has no + /// peripheral id, and one bind flag is the conservative behaviour for the common single-ring case.) + private static let pairFinishedKey = "luckring.pairFinished" + + init(writer: RingCommandWriter?, historySync: LuckRingHistorySync) { + self.writer = writer + self.historySync = historySync + } + + /// Split a logical frame into 20-byte packets and enqueue each (the driver's `frame(_:)` is identity). + private func send(_ frame: LuckRingFrame) { + for packet in packetizer.packets(for: frame) { + writer?.enqueue(packet) + } + } + + // MARK: Startup + + func runStartup() { + let firstPair = !UserDefaults.standard.bool(forKey: Self.pairFinishedKey) + send(encoder.startupBundle(profile: userProfile, goalSteps: goalSteps, firstPair: firstPair)) + UserDefaults.standard.set(true, forKey: Self.pairFinishedKey) + + send(encoder.autoMonitoring(measurementSettings)) + + send(encoder.request(LuckRingDataType.devInfo)) + send(encoder.request(LuckRingDataType.battery)) + send(encoder.request(LuckRingDataType.devSync)) + + historySync.start(types: LuckRingHistorySync.catalog) + } + + /// History is pager-driven — nothing here advances it. + func handle(_ event: RingDecodedEvent) {} + + // MARK: History passes (both re-enter `start`, a no-op while a pass is already in flight) + + func syncHistory() { + historySync.start(types: LuckRingHistorySync.catalog) + } + + func syncVitalsHistory() { + historySync.start(types: LuckRingHistorySync.vitalsTypes) + } + + // MARK: Live actions (per-metric `K6_DATA_TYPE_REAL_*` toggles) + + func startHeartRate() { send(encoder.realHeartRate(on: true)) } + func stopHeartRate() { send(encoder.realHeartRate(on: false)) } + func startSpO2() { send(encoder.realSpO2(on: true)) } + func stopSpO2() { send(encoder.realSpO2(on: false)) } + func startHRV() { send(encoder.realHRV(on: true)) } + func stopHRV() { send(encoder.realHRV(on: false)) } + func startBloodPressure() { send(encoder.realBloodPressure(on: true)) } + func stopBloodPressure() { send(encoder.realBloodPressure(on: false)) } + // `measureHeartRateSpot` falls back to `startHeartRate` (the default) — the ring has no separate + // manual-HR command; a spot reading is the first sample off the same live stream. + + func findDevice() { send(encoder.findDevice()) } + + func setGoal(steps: Int) { + goalSteps = steps + send(encoder.setGoal(steps: steps)) + } + + // MARK: Clock / battery / profile + + /// The ring stamps records from its own RTC, so a timezone or wall-clock change must be re-pushed. + func resyncTime() { send(encoder.setTime()) } + + /// Battery is in-band — request dataType 3. + func requestBattery() { send(encoder.request(LuckRingDataType.battery)) } + + func setUserProfile(_ profile: UserProfileValues) { userProfile = profile } + + func applyUserProfile(_ profile: UserProfileValues) { + userProfile = profile + send(encoder.userInfo(profile)) + } + + // MARK: Teardown + + /// Release the ring on Forget so it stops streaming and re-advertises for other apps. + func unbind() { send(encoder.unbind()) } + + // MARK: Measurement settings (opcode 128 — the ring's own background-logging switch) + + /// Seed before `runStartup` (the coordinator pushes the stored per-device config here first). + func setMeasurementSettings(_ settings: MeasurementSettings) { + measurementSettings = settings + } + + /// A live settings change from the UI — push it to the ring immediately. + func applyMeasurementSettings(_ settings: MeasurementSettings) { + measurementSettings = settings + send(encoder.autoMonitoring(settings)) + } +} diff --git a/PulseLoop/RingProtocol/RingBLEClient.swift b/PulseLoop/RingProtocol/RingBLEClient.swift index fbcc25a5..51603a7d 100644 --- a/PulseLoop/RingProtocol/RingBLEClient.swift +++ b/PulseLoop/RingProtocol/RingBLEClient.swift @@ -28,14 +28,19 @@ final class RingBLEClient: NSObject { /// Registry of supported wearables. First coordinator whose `matches` claims a peripheral wins. /// **Adding a wearable = append one entry here.** /// - /// The order is load-bearing at exactly one place: `ColmiSmartHealthCoordinator` must precede - /// `ColmiCoordinator`. Both recognize the same Colmi local names, and the QRing matcher needs - /// *only* the name — so behind it, no SmartHealth ring would ever be claimed. The SmartHealth - /// matcher is a conjunction a QRing ring cannot satisfy, so it is safe in front. + /// The order is load-bearing at exactly two places: + /// • `ColmiSmartHealthCoordinator` must precede `ColmiCoordinator`. Both recognize the same Colmi + /// local names, and the QRing matcher needs *only* the name — so behind it, no SmartHealth ring + /// would ever be claimed. The SmartHealth matcher is a conjunction a QRing ring cannot satisfy. + /// • `LuckRingCoordinator` must precede `TK5Coordinator`. LuckRing matches strong, family-exclusive + /// signals (the `F618` service, the `0xFF64` company ID) that no other coordinator claims; ordering + /// it ahead of TK5 is defensive, so TK5's weak `TK5`-name prefix could never shadow a hypothetical + /// `TK5x`-named LuckRing sibling. ("TK18" does not hit the `TK5` prefix, so today it is moot.) static let coordinators: [WearableCoordinator.Type] = [ JringCoordinator.self, ColmiSmartHealthCoordinator.self, ColmiCoordinator.self, + LuckRingCoordinator.self, TK5Coordinator.self, ] @@ -435,10 +440,32 @@ final class RingBLEClient: NSObject { let peripheral, let writeChar, !writeQueue.isEmpty else { return } - let item = writeQueue.removeFirst() // Big-data requests go to the command char (`de5bf72a`); fall back to the write char if the // device/firmware didn't expose a separate one. - let target = (item.useCommandChannel ? commandChar : writeChar) ?? writeChar + let target = (writeQueue[0].useCommandChannel ? commandChar : writeChar) ?? writeChar + + // The write type must come from the characteristic, not a constant. A characteristic that only + // supports write-without-response (the TK18's `B002`) silently *discards* a `.withResponse` + // write — CoreBluetooth never calls `didWriteValueFor`, so every packet used to sit out the + // full missed-ACK timeout and the device never received a byte. This mirrors Android's + // `writeCharacteristic`, which auto-selects the type from the properties. + let type: CBCharacteristicWriteType = + target.properties.contains(.write) ? .withResponse : .withoutResponse + + if type == .withoutResponse { + // No ATT round-trip to serialize on; pace with the peripheral's buffer instead. + // `peripheralIsReady(toSendWriteWithoutResponse:)` re-pumps when it drains. + guard peripheral.canSendWriteWithoutResponse else { return } + let item = writeQueue.removeFirst() + publishRawPacket(direction: .outgoing, data: item.data) + // Deliberately no `noteActivity()`: an unacknowledged write proves nothing about the link, + // and crediting it would blind the watchdog to a zombie connection during a silent sync. + peripheral.writeValue(item.data, for: target, type: .withoutResponse) + pumpWrites() + return + } + + let item = writeQueue.removeFirst() writeInFlight = true writeSeq &+= 1 let seq = writeSeq @@ -871,4 +898,12 @@ extension RingBLEClient: CBPeripheralDelegate { pumpWrites() } } + + /// The without-response buffer drained — resume the queue. (Writes gated on + /// `canSendWriteWithoutResponse` park here when the peripheral's buffer is full.) + nonisolated func peripheralIsReady(toSendWriteWithoutResponse peripheral: CBPeripheral) { + MainActor.assumeIsolated { + pumpWrites() + } + } } diff --git a/PulseLoop/Views/Settings/DeviceHeroCard.swift b/PulseLoop/Views/Settings/DeviceHeroCard.swift index 6f1d69df..c4e19afd 100644 --- a/PulseLoop/Views/Settings/DeviceHeroCard.swift +++ b/PulseLoop/Views/Settings/DeviceHeroCard.swift @@ -238,6 +238,7 @@ struct DeviceHeroCard: View { // line has no single representative image — fall back to the generic ring. case .colmiR02, .colmiSmartHealth: return nil case .tk5: return "tk5" + case .luckRing: return "luckring-tk18" case nil: return nil } } diff --git a/PulseLoop/Wearables/WearableCoordinator.swift b/PulseLoop/Wearables/WearableCoordinator.swift index 955fffc2..c00eb806 100644 --- a/PulseLoop/Wearables/WearableCoordinator.swift +++ b/PulseLoop/Wearables/WearableCoordinator.swift @@ -12,6 +12,9 @@ enum RingDeviceType: String, Codable, CaseIterable, Sendable { /// that driver, not `ColmiDriver`. Which of the two a given ring is cannot be read off its /// advertisement — the user declares it at pairing (see `RingAppVariant`). case colmiSmartHealth + /// LuckRing / TK18 family (the "K6" vendor SDK, company ID `0xFF64`). Sold under simsonlab and other + /// brands; TK18 is the hardware-tested unit. See `LuckRingCoordinator`. + case luckRing /// Human-facing default name when no advertised name is available. var displayName: String { @@ -20,6 +23,7 @@ enum RingDeviceType: String, Codable, CaseIterable, Sendable { case .colmiR02: return "Colmi / Yawell ring" case .tk5: return "TK5 ring" case .colmiSmartHealth: return "Colmi ring (SmartHealth)" + case .luckRing: return "LuckRing" } } } diff --git a/PulseLoop/Wearables/WearableModel.swift b/PulseLoop/Wearables/WearableModel.swift index ea56991c..3756d8b2 100644 --- a/PulseLoop/Wearables/WearableModel.swift +++ b/PulseLoop/Wearables/WearableModel.swift @@ -53,7 +53,7 @@ enum RingAppVariant: String, CaseIterable, Identifiable, Sendable { switch family { case .colmiR02: self = .qring case .colmiSmartHealth: self = .smartHealth - case .jring, .tk5: return nil + case .jring, .tk5, .luckRing: return nil } } @@ -113,6 +113,8 @@ extension RingDeviceType { // at all — its advertisement, its capability bitmap and its history types are all still // predictions (plan B6 is what settles them). case .tk5, .colmiSmartHealth: return .limited + // TK18 is the only hardware-tested LuckRing; every 0xFF64 sibling is still a prediction. + case .luckRing: return .limited } } } @@ -173,6 +175,15 @@ extension WearableModel { advertisedNamePatterns: ["^TK5 ?[0-9A-Fa-f]{0,4}$"], imageName: "tk5" ) + // TK18 — the LuckRing app / "K6" protocol (company ID 0xFF64). The only hardware-tested unit of the + // whole 0xFF64 family, so it is `.limited`. Its baseline is what the driver can decode; untested + // siblings still pair via the coordinator's strong-signal match and get generic art + a fallback name. + static let luckRingTK18 = WearableModel( + id: "luckring-tk18", displayName: "TK18", brand: "LuckRing", family: .luckRing, + tint: PulseColors.accent, blurb: "HR · SpO₂ · HRV · Temp · BP · Sleep · Steps", + advertisedNamePatterns: ["^TK18([ _-].*)?$"], imageName: "luckring-tk18" + ) + // Yawell-branded variants of the same hardware. static let yawellR05 = colmiFamily("yawell-r05", "Yawell R05", brand: "Yawell", pattern: "^R05_[0-9A-F]{4}$") static let yawellR10 = colmiFamily("yawell-r10", "Yawell R10", brand: "Yawell", pattern: "^R10_[0-9A-F]{4}$") @@ -301,6 +312,7 @@ extension WearableModel { colmiR99, yawellR05, yawellR10, yawellR11, h59, tk5, + luckRingTK18, ] static func model(id: String?) -> WearableModel? { diff --git a/PulseLoopTests/CapabilityGatingTests.swift b/PulseLoopTests/CapabilityGatingTests.swift index 34ff0898..a837830c 100644 --- a/PulseLoopTests/CapabilityGatingTests.swift +++ b/PulseLoopTests/CapabilityGatingTests.swift @@ -21,6 +21,37 @@ final class CapabilityGatingTests: XCTestCase { XCTAssertFalse(MetricsService.supports(.temperature, context: context)) } + /// The LuckRing / TK18 baseline surfaces its metric cards — but deliberately not blood sugar, REM + /// staging, fatigue, or a combined-vitals sweep (the K6 protocol has no command or record for any + /// of them). + func testLuckRingSurfacesItsBaselineButNotTheExcludedMetrics() throws { + let context = try TestSupport.makeContext() + let ring = Device(deviceType: .luckRing, capabilities: LuckRingCoordinator().capabilities) + context.insert(ring) + try context.save() + + for metric: MetricKey in [.heartRate, .spo2, .hrv, .temperature, .bloodPressureSystolic, .stress] { + XCTAssertTrue(MetricsService.supports(metric, context: context), metric.rawValue) + } + // Blood sugar and fatigue are the two vital *metrics* the family deliberately does not claim. + for metric: MetricKey in [.bloodSugar, .fatigue] { + XCTAssertFalse(MetricsService.supports(metric, context: context), metric.rawValue) + } + } + + /// The declared sets, straight from the coordinator: nothing excluded leaks in, and the family gates + /// nothing on a bitmap (the K6 FUNCTION_CONTROL bitmap is obfuscated in the decompile). + /// `.measurementInterval` *is* declared — the K6 auto-monitoring config (opcode 128) is a real + /// interval knob, and the firmware default is off. + func testLuckRingCoordinatorDeclaresTheApprovedSet() { + let coordinator = LuckRingCoordinator() + XCTAssertTrue(coordinator.bitmapGatedCapabilities.isEmpty) + XCTAssertTrue(coordinator.capabilities.contains(.measurementInterval)) + for cap: WearableCapability in [.bloodSugar, .remSleep, .fatigue, .combinedVitalsMeasurement, .powerOff, .factoryReset] { + XCTAssertFalse(coordinator.capabilities.contains(cap), cap.rawValue) + } + } + func testColmiShowsRichMetrics() throws { let context = try TestSupport.makeContext() let colmi = Device( diff --git a/PulseLoopTests/LuckRingDecoderTests.swift b/PulseLoopTests/LuckRingDecoderTests.swift new file mode 100644 index 00000000..10d74425 --- /dev/null +++ b/PulseLoopTests/LuckRingDecoderTests.swift @@ -0,0 +1,200 @@ +import XCTest +@testable import PulseLoop + +/// The decoder's record cutting, per `ProcessDATA_TYPE_*`: battery, firmware, the metric history fan-outs, +/// the sport u24 fields, the paged sleep timeline (sessions → per-minute stages), the empty-envelope +/// "ended" markers, and the /10 temperature scaling. Range gating is `RingEventBridge`'s job, so these +/// assert the raw decode. +@MainActor +final class LuckRingDecoderTests: XCTestCase { + private let decoder = LuckRingDecoder() + private let base: UInt32 = 1_700_000_000 + private var baseDate: Date { Date(timeIntervalSince1970: TimeInterval(base)) } + + // Envelope: [total u16 LE][items u8] + records. + private func envelope(items: Int, records: [[UInt8]]) -> [UInt8] { + LuckRingBytes.le16(items) + [UInt8(items)] + records.flatMap { $0 } + } + + private func frame(_ dataType: UInt8, _ payload: [UInt8], cmd: LuckRingCmdType = .send) -> LuckRingFrame { + LuckRingFrame(cmdType: cmd, dataType: dataType, payload: payload) + } + + private func le24(_ v: Int) -> [UInt8] { + [UInt8(v & 0xff), UInt8((v >> 8) & 0xff), UInt8((v >> 16) & 0xff)] + } + + // MARK: Simple frames + + func testBattery() { + guard case let .battery(percent) = decoder.decode(frame(3, [85, 1])).first else { + return XCTFail("expected battery") + } + XCTAssertEqual(percent, 85) + } + + func testFirmwareStringJoinsBytesOneToFive() { + // [items, customer, hardware, code, picture, font] → "customer.hardware.code.picture.font". + guard case let .firmware(version) = decoder.decode(frame(2, [6, 1, 2, 3, 4, 5])).first else { + return XCTFail("expected firmware") + } + XCTAssertEqual(version, "1.2.3.4.5") + } + + func testDeviceAckDecodesToCommandAck() { + guard case let .commandAck(id) = decoder.decode(frame(111, [1], cmd: .ack)).first else { + return XCTFail("expected commandAck") + } + XCTAssertEqual(id, 111) + } + + // MARK: History fan-outs + + func testHeartRateHistoryFansOutPerRecord() { + let payload = envelope(items: 2, records: [ + LuckRingBytes.le32(base) + [72], + LuckRingBytes.le32(base + 60) + [75], + ]) + let events = decoder.decode(frame(8, payload)) + let readings: [(Double, Date)] = events.compactMap { + if case let .historyMeasurement(kind, value, ts) = $0, kind == .heartRate { return (value, ts) } + return nil + } + XCTAssertEqual(readings.map(\.0), [72, 75]) + XCTAssertEqual(readings.first?.1, baseDate) + } + + func testSpo2HistoryDecodes() { + let payload = envelope(items: 1, records: [LuckRingBytes.le32(base) + [97]]) + guard case let .historyMeasurement(kind, value, _) = decoder.decode(frame(40, payload)).first else { + return XCTFail("expected spo2 history") + } + XCTAssertEqual(kind, .spo2) + XCTAssertEqual(value, 97) + } + + func testBloodPressureHistoryFansOutSystolicAndDiastolic() { + let payload = envelope(items: 1, records: [LuckRingBytes.le32(base) + [120, 80]]) + let events = decoder.decode(frame(41, payload)) + let kinds = events.compactMap { evt -> (MeasurementKind, Double)? in + if case let .historyMeasurement(kind, value, _) = evt { return (kind, value) } + return nil + } + XCTAssertEqual(kinds.count, 2) + XCTAssertTrue(kinds.contains { $0 == (.bloodPressureSystolic, 120) }) + XCTAssertTrue(kinds.contains { $0 == (.bloodPressureDiastolic, 80) }) + } + + func testHrvHistoryDecodes() { + let payload = envelope(items: 1, records: [LuckRingBytes.le32(base) + [45]]) + guard case let .historyMeasurement(kind, value, _) = decoder.decode(frame(42, payload)).first else { + return XCTFail("expected hrv history") + } + XCTAssertEqual(kind, .hrv) + XCTAssertEqual(value, 45) + } + + func testTemperatureScalesByTenFromTheWideRecord() { + // 8-byte record (`parseFloat`): [time u32][value u16 LE]/10 (+2 pad). 365 → 36.5 °C. + let payload = envelope(items: 1, records: [LuckRingBytes.le32(base) + LuckRingBytes.le16(365) + [0, 0]]) + guard case let .historyMeasurement(kind, value, _) = decoder.decode(frame(47, payload)).first else { + return XCTFail("expected temperature history") + } + XCTAssertEqual(kind, .temperature) + XCTAssertEqual(value, 36.5, accuracy: 0.001) + } + + // MARK: Live streams + + func testLiveHeartRateSamplesAndEndedMarker() { + let stream = envelope(items: 1, records: [LuckRingBytes.le32(base) + [66]]) + guard case let .heartRateSample(bpm, _) = decoder.decode(frame(7, stream)).first else { + return XCTFail("expected live HR sample") + } + XCTAssertEqual(bpm, 66) + + // Empty envelope (items 0) = the measurement ended. + let ended = decoder.decode(frame(7, envelope(items: 0, records: []))) + guard case .heartRateComplete = ended.first else { + return XCTFail("expected heartRateComplete for an empty envelope, got \(ended)") + } + } + + func testLiveBloodPressureDecodes() { + let payload = envelope(items: 1, records: [LuckRingBytes.le32(base) + [118, 76]]) + guard case let .bloodPressureSample(sys, dia, _) = decoder.decode(frame(18, payload)).first else { + return XCTFail("expected live BP") + } + XCTAssertEqual(sys, 118) + XCTAssertEqual(dia, 76) + } + + // MARK: Sport + + func testSportRecordDecodesU24Fields() { + // [start u32][steps u32][distance u24+pad][calories u24+pad][duration u24+pad]. + let record = LuckRingBytes.le32(base) + LuckRingBytes.le32(1234) + + le24(5000) + [0] + le24(300) + [0] + le24(600) + [0] + let events = decoder.decode(frame(5, envelope(items: 1, records: [record]))) + guard case let .activityBucket(ts, steps, distance) = events.first else { + return XCTFail("expected activityBucket, got \(events)") + } + XCTAssertEqual(ts, baseDate) + XCTAssertEqual(steps, 1234) + XCTAssertEqual(distance, 5000) + } + + // MARK: Sleep + + /// One session: start → 5 min light, deep → 10 min deep, wake ends it. The 15-slot page is padded. + func testSleepSingleSessionExpandsToPerMinuteStages() { + let entries: [(UInt8, UInt32)] = [ + (1, base), // session start + (2, base + 300), // deep, 5 min after start + (4, base + 900), // wake, 10 min after the deep entry + ] + let events = decoder.decode(frame(6, sleepPayload(pages: [(3, entries)]))) + guard case let .sleepTimeline(ts, stages) = events.first else { + return XCTFail("expected sleepTimeline, got \(events)") + } + XCTAssertEqual(ts, baseDate) + XCTAssertEqual(stages.prefix(5), ArraySlice([.light, .light, .light, .light, .light])) + XCTAssertEqual(stages.count, 15) + XCTAssertEqual(stages.suffix(10), ArraySlice(Array(repeating: SleepStage.deep, count: 10))) + } + + /// Type 5 (movement) maps to light; two sessions separated by a wake both surface. + func testSleepMultiSessionAndMovementMapping() { + let first: [(UInt8, UInt32)] = [ + (1, base), (5, base + 120), (4, base + 300), + ] + let second: [(UInt8, UInt32)] = [ + (1, base + 3600), (2, base + 3720), (4, base + 3900), + ] + let events = decoder.decode(frame(6, sleepPayload(pages: [(3, first), (3, second)]))) + let sessions = events.compactMap { evt -> (Date, [SleepStage])? in + if case let .sleepTimeline(ts, stages) = evt { return (ts, stages) } + return nil + } + XCTAssertEqual(sessions.count, 2) + XCTAssertTrue(sessions[0].1.allSatisfy { $0 == .light }, "start + movement both render as light") + XCTAssertEqual(sessions[1].0, Date(timeIntervalSince1970: TimeInterval(base + 3600))) + } + + // Build a sleep payload: [total u16][pageCount], then each page = [validCount] + 15 × [type, time u32]. + private func sleepPayload(pages: [(valid: Int, entries: [(UInt8, UInt32)])]) -> [UInt8] { + var out = LuckRingBytes.le16(0) + [UInt8(pages.count)] + for page in pages { + out.append(UInt8(page.valid)) + for slot in 0..<15 { + if slot < page.entries.count { + out.append(page.entries[slot].0) + out.append(contentsOf: LuckRingBytes.le32(page.entries[slot].1)) + } else { + out.append(contentsOf: [0, 0, 0, 0, 0]) + } + } + } + return out + } +} diff --git a/PulseLoopTests/LuckRingDriverTests.swift b/PulseLoopTests/LuckRingDriverTests.swift new file mode 100644 index 00000000..1d38d9f5 --- /dev/null +++ b/PulseLoopTests/LuckRingDriverTests.swift @@ -0,0 +1,106 @@ +import XCTest +import CoreBluetooth +@testable import PulseLoop + +/// The driver's inbound routing, and the one thing no decoder can do: **acknowledging a device-initiated +/// SEND**. The ring retransmits an un-ACKed SEND until the app answers, so a missing ACK wedges the link; +/// an ACK for an ACK, or for a SEND_NO_ACK, is wrong the other way. +@MainActor +final class LuckRingDriverTests: XCTestCase { + private final class FakeWriter: RingCommandWriter { + nonisolated deinit {} + var sent: [Data] = [] + func enqueue(_ command: Data) { sent.append(command) } + } + + private let notify = CBUUID(string: LuckRingUUIDs.notify) + private let packetizer = LuckRingPacketizer() + + private func packets(_ frame: LuckRingFrame) -> [Data] { + packetizer.packets(for: frame) + } + + // MARK: Auto-ACK + + func testDeviceSendIsAckedAndDecoded() { + let writer = FakeWriter() + let driver = LuckRingDriver(writer: writer) + + let frame = LuckRingFrame(cmdType: .send, dataType: LuckRingDataType.battery, payload: [90, 1], seq: 5, devType: 2) + let events = driver.ingest(packets(frame)[0], from: notify) + + XCTAssertEqual(writer.sent.count, 1, "a device SEND must be ACKed") + let ack = [UInt8](writer.sent[0]) + XCTAssertEqual(ack[4], 4, "ACK cmdType") + XCTAssertEqual(ack[5], LuckRingDataType.battery, "ACK echoes the frame's dataType") + XCTAssertEqual(ack[3], 5, "ACK echoes the frame's seq") + XCTAssertEqual(ack[1], 2, "ACK echoes the frame's devType") + + guard case let .battery(percent) = events.first else { return XCTFail("expected battery, got \(events)") } + XCTAssertEqual(percent, 90) + } + + func testDeviceAckIsNotAcked() { + let writer = FakeWriter() + let driver = LuckRingDriver(writer: writer) + + var ack = [UInt8](repeating: 0, count: 20) + ack[1] = 1; ack[4] = 4; ack[5] = LuckRingDataType.mixInfo; ack[8] = 1; ack[10] = 1 + _ = driver.ingest(Data(ack), from: notify) + + XCTAssertTrue(writer.sent.isEmpty, "an ACK must never be ACKed") + } + + func testSendNoAckIsNotAcked() { + let writer = FakeWriter() + let driver = LuckRingDriver(writer: writer) + + let frame = LuckRingFrame(cmdType: .sendNoAck, dataType: LuckRingDataType.realHeart, + payload: LuckRingBytes.le16(1) + [1] + LuckRingBytes.le32(1_700_000_000) + [70], seq: 0, devType: 1) + _ = driver.ingest(packets(frame)[0], from: notify) + + XCTAssertTrue(writer.sent.isEmpty, "a SEND_NO_ACK expects no reply") + } + + // MARK: Reassembly + + func testMultiPacketFrameOnlyAcksAndDecodesOnceComplete() { + let writer = FakeWriter() + let driver = LuckRingDriver(writer: writer) + + // A 2-record HR history frame that spans a head + one continuation. + let payload = LuckRingBytes.le16(2) + [2] + + LuckRingBytes.le32(1_700_000_000) + [72] + + LuckRingBytes.le32(1_700_000_060) + [75] + let frame = LuckRingFrame(cmdType: .send, dataType: LuckRingDataType.historyHeart, payload: payload, seq: 1, devType: 1) + let wire = packets(frame) + XCTAssertGreaterThan(wire.count, 1) + + let firstEvents = driver.ingest(wire[0], from: notify) + XCTAssertTrue(firstEvents.isEmpty, "no decode until the frame is whole") + XCTAssertTrue(writer.sent.isEmpty, "no ACK until the frame is whole") + + let lastEvents = driver.ingest(wire[1], from: notify) + XCTAssertEqual(writer.sent.count, 1, "ACK once, on completion") + XCTAssertEqual(lastEvents.count, 2, "both HR records decode") + } + + // MARK: Lifecycle + + func testConnectionResetDiscardsAPartialFrame() { + let writer = FakeWriter() + let driver = LuckRingDriver(writer: writer) + + let payload = LuckRingBytes.le16(2) + [2] + + LuckRingBytes.le32(1_700_000_000) + [72] + + LuckRingBytes.le32(1_700_000_060) + [75] + let wire = packets(LuckRingFrame(cmdType: .send, dataType: LuckRingDataType.historyHeart, payload: payload, seq: 1, devType: 1)) + + _ = driver.ingest(wire[0], from: notify) // head only + driver.connectionDidStart() // the link came back — discard the partial + let events = driver.ingest(wire[1], from: notify) // a continuation with no head now + + XCTAssertTrue(events.isEmpty, "the reset dropped the partial, so the stray continuation is ignored") + XCTAssertTrue(writer.sent.isEmpty) + } +} diff --git a/PulseLoopTests/LuckRingEncoderTests.swift b/PulseLoopTests/LuckRingEncoderTests.swift new file mode 100644 index 00000000..c701aead --- /dev/null +++ b/PulseLoopTests/LuckRingEncoderTests.swift @@ -0,0 +1,123 @@ +import XCTest +@testable import PulseLoop + +/// The encoder's byte layouts, each pinned against its `K6_*` vendor struct: the MixInfo binding bundle +/// (property set + order + framing), the clock, the real-time toggles, and the requests. A wrong offset +/// here is a command the ring silently ignores, so the golden assertions are the contract. +@MainActor +final class LuckRingEncoderTests: XCTestCase { + private let fixedProfile = UserProfileValues(metric: true, sex: "male", age: 30, heightCm: 175, weightKg: 70) + private let fixedDate = Date(timeIntervalSince1970: 1_700_000_000) + + // MARK: Struct layouts + + func testUserInfoBytesMatchK6SendUserInfo() { + // [userId u32 LE][sex][age][height][weight][reserved]; sex is inverted (male → 0). + let bytes = LuckRingEncoder.userInfoBytes(fixedProfile) + XCTAssertEqual(bytes, [0, 0, 0, 0, 0, 30, 175, 70, 0]) + } + + func testUserInfoSexInversionAndAgeFloor() { + let female = UserProfileValues(metric: true, sex: "female", age: 0, heightCm: 160, weightKg: 55) + let bytes = LuckRingEncoder.userInfoBytes(female) + XCTAssertEqual(bytes[4], 1, "female → sex byte 1") + XCTAssertEqual(bytes[5], 20, "age 0 floors to the vendor default of 20") + } + + func testTimeBytesAreTrueUtcSeconds() { + let bytes = LuckRingEncoder.timeBytes(date: fixedDate, timeZone: TimeZone(identifier: "UTC")!) + XCTAssertEqual(bytes.count, 9) + XCTAssertEqual(LuckRingBytes.u32(bytes, 0), 1_700_000_000) // abs seconds (UTC, no wall-clock shift) + XCTAssertEqual(LuckRingBytes.u32(bytes, 4), 0) // UTC offset + XCTAssertEqual(bytes[8], 0) // format byte + } + + func testGoalBytesMatchK6SendGoal() { + let bytes = LuckRingEncoder.goalBytes(steps: 8000) + XCTAssertEqual(bytes.count, 16) + XCTAssertEqual(LuckRingBytes.u32(bytes, 0), 8000) // step goal, LE + XCTAssertEqual(Array(bytes[4...]), [UInt8](repeating: 0, count: 12)) // distance/cal/sleep/duration = 0 + } + + // MARK: MixInfo bundle + + func testStartupBundleHasVendorPropertyOrderAndData() { + var encoder = LuckRingEncoder() + let frame = encoder.startupBundle(profile: fixedProfile, goalSteps: 8000, firstPair: true, date: fixedDate) + XCTAssertEqual(frame.cmdType, .send) + XCTAssertEqual(frame.dataType, 110) + + let props = LuckRingMixInfoTLV.decode(frame.payload) + // Exact order of `sendAynInfoDetail()`: 102, 104, 124, 103, 109, 111, 120. + XCTAssertEqual(props.map(\.type), [102, 104, 124, 103, 109, 111, 120]) + XCTAssertEqual(props[0].data, LuckRingEncoder.userInfoBytes(fixedProfile)) + XCTAssertEqual(props[1].data.count, 9) // time + XCTAssertEqual(props[2].data, [1, 0xFF, 0xFF, 0, 0]) // call-alarm constant + XCTAssertEqual(props[3].data, [0]) // language + XCTAssertEqual(props[4].data, [1]) // data-switch enables real-time pushes + XCTAssertEqual(props[5].data, LuckRingEncoder.goalBytes(steps: 8000)) + XCTAssertEqual(props[6].data, [1, 0]) // first-pair token + } + + func testStartupBundleClearsPairTokenAfterFirstBind() { + var encoder = LuckRingEncoder() + let frame = encoder.startupBundle(profile: fixedProfile, goalSteps: 0, firstPair: false, date: fixedDate) + let props = LuckRingMixInfoTLV.decode(frame.payload) + XCTAssertEqual(props.last?.data, [0, 0], "a non-first bind must not re-trigger the pairing animation") + } + + // MARK: Toggles / requests + + func testRealTimeToggleLayouts() { + var encoder = LuckRingEncoder() + assertFrame(encoder.realHeartRate(on: true), .send, 24, [1]) + assertFrame(encoder.realSpO2(on: true), .send, 20, [1, 0, 0, 0, 0]) + assertFrame(encoder.realHRV(on: true), .send, 45, [1]) + assertFrame(encoder.realBloodPressure(on: true), .send, 18, [1, 0, 0, 0, 0, 0]) + assertFrame(encoder.realTemperature(on: true), .send, 46, [1]) + assertFrame(encoder.realHeartRate(on: false), .send, 24, [0]) + } + + func testRequestIsAnEmptyRequestFrame() { + var encoder = LuckRingEncoder() + assertFrame(encoder.request(LuckRingDataType.battery), .request, 3, []) + } + + /// Opcode 128 (`K6_DATA_TYPE_HEART_AUTO_SWITCH`): `[autoHR][hr24h=0][interval min][autoO2][0×4]`. + /// The firmware default is monitoring *off*, so this frame is what arms background history logging. + func testAutoMonitoringMatchesK6HeartAutoSwitch() { + var encoder = LuckRingEncoder() + let settings = MeasurementSettings( + hrEnabled: true, hrIntervalMinutes: 30, + spo2Enabled: true, stressEnabled: false, hrvEnabled: false, temperatureEnabled: false + ) + assertFrame(encoder.autoMonitoring(settings), .send, 128, [1, 0, 30, 1, 0, 0, 0, 0]) + let off = MeasurementSettings( + hrEnabled: false, hrIntervalMinutes: 5, + spo2Enabled: false, stressEnabled: false, hrvEnabled: false, temperatureEnabled: false + ) + assertFrame(encoder.autoMonitoring(off), .send, 128, [0, 0, 5, 0, 0, 0, 0, 0]) + } + + func testFindDeviceAndUnbind() { + var encoder = LuckRingEncoder() + assertFrame(encoder.findDevice(), .send, 11, [1]) + assertFrame(encoder.unbind(), .send, 159, [1]) + } + + func testSequenceCounterIncrementsPerFrame() { + var encoder = LuckRingEncoder() + XCTAssertEqual(encoder.realHeartRate(on: true).seq, 0) + XCTAssertEqual(encoder.realHeartRate(on: false).seq, 1) + XCTAssertEqual(encoder.request(LuckRingDataType.battery).seq, 2) + } + + private func assertFrame( + _ frame: LuckRingFrame, _ cmd: LuckRingCmdType, _ dataType: UInt8, _ payload: [UInt8], + line: UInt = #line + ) { + XCTAssertEqual(frame.cmdType, cmd, line: line) + XCTAssertEqual(frame.dataType, dataType, line: line) + XCTAssertEqual(frame.payload, payload, line: line) + } +} diff --git a/PulseLoopTests/LuckRingHistorySyncTests.swift b/PulseLoopTests/LuckRingHistorySyncTests.swift new file mode 100644 index 00000000..1c9e1847 --- /dev/null +++ b/PulseLoopTests/LuckRingHistorySyncTests.swift @@ -0,0 +1,91 @@ +import XCTest +@testable import PulseLoop + +/// The history pager: it walks the catalog one type at a time, advancing when a type's data settles or +/// timing it out when nothing comes, refuses a re-entrant `start`, and signals completion. The K6 streams +/// carry no terminal marker, so this time-settled sequencing is the whole of the transfer contract. +@MainActor +final class LuckRingHistorySyncTests: XCTestCase { + private final class FakeWriter: RingCommandWriter { + nonisolated deinit {} + var sent: [Data] = [] + func enqueue(_ command: Data) { sent.append(command) } + /// The dataType of each request packet written (head byte [5]); REQUEST frames only. + var requestedTypes: [UInt8] { sent.map { [UInt8]($0)[5] } } + } + + private final class Spy { + var stages: [String] = [] + var didFinish: Bool { stages.contains("done") } + } + + private func makeSync(writer: FakeWriter, spy: Spy, settle: TimeInterval, stall: TimeInterval) -> LuckRingHistorySync { + LuckRingHistorySync(writer: writer, settleSeconds: settle, stallSeconds: stall, progressSink: { event in + if case let .syncProgress(stage) = event { spy.stages.append(stage) } + }) + } + + private func sleep(_ seconds: TimeInterval) async { + try? await Task.sleep(nanoseconds: UInt64(seconds * 1_000_000_000)) + } + + func testSequentialAdvanceOnDataSettle() async { + let writer = FakeWriter() + let spy = Spy() + let sync = makeSync(writer: writer, spy: spy, settle: 0.05, stall: 5) + + sync.start(types: [5, 6]) + XCTAssertEqual(writer.requestedTypes, [5], "the first type is requested immediately") + + sync.noteReceived(dataType: 5) + await sleep(0.2) + XCTAssertEqual(writer.requestedTypes, [5, 6], "the pass advanced once type 5's data settled") + + sync.noteReceived(dataType: 6) + await sleep(0.2) + XCTAssertFalse(sync.isRunning, "the queue drained") + XCTAssertTrue(spy.didFinish, "completion is signalled") + } + + func testUnsupportedTypeIsSkippedOnStall() async { + let writer = FakeWriter() + let spy = Spy() + let sync = makeSync(writer: writer, spy: spy, settle: 5, stall: 0.05) + + sync.start(types: [42]) // no data will ever arrive + XCTAssertEqual(writer.requestedTypes, [42]) + + await sleep(0.2) + XCTAssertFalse(sync.isRunning, "a type that never answers is skipped on the stall timeout") + XCTAssertTrue(spy.didFinish) + } + + func testReEntrantStartIsIgnoredWhileRunning() async { + let writer = FakeWriter() + let spy = Spy() + let sync = makeSync(writer: writer, spy: spy, settle: 5, stall: 5) + + sync.start(types: [5]) + sync.start(types: [6]) // must not interrupt the in-flight pass + XCTAssertEqual(writer.requestedTypes, [5]) + sync.cancel() // stop the in-flight timer… + await sleep(0.05) // …and let the cancelled Task retire before the instance is torn down + } + + func testCancelStopsThePass() async { + let writer = FakeWriter() + let spy = Spy() + let sync = makeSync(writer: writer, spy: spy, settle: 0.05, stall: 0.05) + + sync.start(types: [5, 6, 8]) + sync.cancel() + await sleep(0.2) + XCTAssertFalse(sync.isRunning) + XCTAssertEqual(writer.requestedTypes, [5], "cancel halts before any further type is requested") + } + + func testCatalogAndVitalsSubsetsAreWhatWeExpect() { + XCTAssertEqual(LuckRingHistorySync.catalog, [5, 6, 8, 40, 41, 42, 47, 53]) + XCTAssertEqual(LuckRingHistorySync.vitalsTypes, [8, 40]) + } +} diff --git a/PulseLoopTests/LuckRingProtocolTests.swift b/PulseLoopTests/LuckRingProtocolTests.swift new file mode 100644 index 00000000..d9ad4111 --- /dev/null +++ b/PulseLoopTests/LuckRingProtocolTests.swift @@ -0,0 +1,148 @@ +import XCTest +@testable import PulseLoop + +/// The K6 "Protocol B" framing: the 20-byte packetizer (head / continuation / ACK), the assembler's +/// round-trip and its recovery from a stale head, and the MixInfo TLV. These are the bytes the ring sees +/// and the bytes it sends, so a golden-byte pin here is the whole contract. +@MainActor +final class LuckRingProtocolTests: XCTestCase { + private let packetizer = LuckRingPacketizer() + + // MARK: Packetizer + + func testHeadPacketGoldenBytes() { + // REQUEST devInfo (cmd 3, dataType 2, empty payload), seq 0, devType 1. + let frame = LuckRingFrame(cmdType: .request, dataType: 2, payload: [], seq: 0, devType: 1) + let packets = packetizer.packets(for: frame) + XCTAssertEqual(packets.count, 1) + XCTAssertEqual(packets[0].count, 20) + XCTAssertEqual(packets[0].hexString, "0001000003020000000000000000000000000000") + } + + func testSinglePacketCarriesFirstTenPayloadBytes() { + let frame = LuckRingFrame(cmdType: .send, dataType: 24, payload: [1], seq: 7, devType: 1) + let packets = packetizer.packets(for: frame) + XCTAssertEqual(packets.count, 1) + let bytes = [UInt8](packets[0]) + XCTAssertEqual(bytes[0], 0) // head marker + XCTAssertEqual(bytes[1], 1) // devType + XCTAssertEqual(bytes[2], 0) // continuation pages + XCTAssertEqual(bytes[3], 7) // seq + XCTAssertEqual(bytes[4], 1) // cmdType SEND + XCTAssertEqual(bytes[5], 24) // dataType + XCTAssertEqual(bytes[8], 1) // payload length LE + XCTAssertEqual(bytes[9], 0) + XCTAssertEqual(bytes[10], 1) // payload[0] + } + + func testAckGoldenBytes() { + let ack = packetizer.ack(dataType: 8, seq: 5, devType: 1) + XCTAssertEqual(ack.count, 20) + // [4]=4 ACK, [5]=8 dataType, [8]=1 len, [10]=1 status. + XCTAssertEqual(ack.hexString, "0001000504080000010001000000000000000000") + } + + func testMultiPacketSplitAndPageCount() { + // 25-byte payload → head (first 10) + 1 continuation (next 15 of 19). + let payload = (0..<25).map { UInt8($0) } + XCTAssertEqual(LuckRingPacketizer.continuationPages(payloadLength: 25), 1) + let frame = LuckRingFrame(cmdType: .send, dataType: 110, payload: payload, seq: 3, devType: 1) + let packets = packetizer.packets(for: frame) + XCTAssertEqual(packets.count, 2) + XCTAssertEqual(packets[0].count, 20) + XCTAssertEqual([UInt8](packets[0])[2], 1) // one continuation page declared + XCTAssertEqual([UInt8](packets[1])[0], 1) // continuation index (1-based) + XCTAssertEqual(Array([UInt8](packets[1])[1...15]), Array(payload[10...24])) + } + + // MARK: Assembler round-trip + + func testAssemblerRoundTripSinglePacket() { + let assembler = LuckRingFrameAssembler() + let frame = LuckRingFrame(cmdType: .send, dataType: 3, payload: [88, 1], seq: 9, devType: 1) + var completed: LuckRingFrame? + for packet in packetizer.packets(for: frame) { + completed = assembler.append(packet) + } + XCTAssertEqual(completed, frame) + } + + func testAssemblerRoundTripMultiPacket() { + let assembler = LuckRingFrameAssembler() + let payload = (0..<67).map { UInt8($0 & 0xff) } // the MixInfo bundle's size + let frame = LuckRingFrame(cmdType: .send, dataType: 110, payload: payload, seq: 4, devType: 1) + let packets = packetizer.packets(for: frame) + XCTAssertEqual(packets.count, 4) // head + 3 continuations + + var completed: LuckRingFrame? + for (i, packet) in packets.enumerated() { + let result = assembler.append(packet) + if i < packets.count - 1 { + XCTAssertNil(result, "must not complete until the last continuation") + } else { + completed = result + } + } + XCTAssertEqual(completed, frame) + } + + func testAssemblerTrimsPaddingWhenPayloadDoesNotFillTheLastPage() { + let assembler = LuckRingFrameAssembler() + // 25 bytes needs one continuation but fills only 15 of its 19 payload slots: the last packet is + // zero-padded on the wire, and the assembler must cut back to the head's declared length — + // temperature derives its record stride from the payload size, so padding would corrupt it. + let payload = (1...25).map { UInt8($0) } + let frame = LuckRingFrame(cmdType: .send, dataType: 47, payload: payload, seq: 3, devType: 1) + var completed: LuckRingFrame? + for packet in packetizer.packets(for: frame) { + completed = assembler.append(packet) + } + XCTAssertEqual(completed?.payload.count, 25, "padding from the final packet must be trimmed") + XCTAssertEqual(completed, frame) + } + + func testAssemblerRecoversFromAStaleHead() { + let assembler = LuckRingFrameAssembler() + // A head that promises continuations, then a *new* head before they arrive: the partial is dropped. + let abandoned = LuckRingFrame(cmdType: .send, dataType: 5, payload: (0..<30).map { UInt8($0) }, seq: 1, devType: 1) + _ = assembler.append(packetizer.packets(for: abandoned)[0]) // head only, no continuations + + let fresh = LuckRingFrame(cmdType: .send, dataType: 3, payload: [77, 0], seq: 2, devType: 1) + let completed = assembler.append(packetizer.packets(for: fresh)[0]) + XCTAssertEqual(completed, fresh, "a fresh head mid-assembly abandons the stale partial and completes") + } + + func testAssemblerDropsAContinuationWithNoHead() { + let assembler = LuckRingFrameAssembler() + var continuation = [UInt8](repeating: 0, count: 20) + continuation[0] = 1 + XCTAssertNil(assembler.append(Data(continuation))) + } + + func testAssemblerParsesADeviceAck() { + let assembler = LuckRingFrameAssembler() + // A device ACK head: [4]=4, status at [10]. + var ack = [UInt8](repeating: 0, count: 20) + ack[1] = 1; ack[3] = 6; ack[4] = 4; ack[5] = 111; ack[8] = 1; ack[10] = 1 + let frame = assembler.append(Data(ack)) + XCTAssertEqual(frame?.cmdType, .ack) + XCTAssertEqual(frame?.dataType, 111) + XCTAssertEqual(frame?.payload, [1]) + } + + // MARK: MixInfo TLV + + func testMixInfoTLVRoundTrip() { + let properties: [LuckRingMixInfoTLV.Property] = [ + .init(type: 102, data: [1, 2, 3, 4]), + .init(type: 124, data: [1, 0xFF, 0xFF, 0, 0]), + .init(type: 120, data: [1, 0]), + ] + let encoded = LuckRingMixInfoTLV.encode(properties) + // Header: [totalLen u16 LE][itemCount], totalLen = Σ propBytes + 1. + let propBytesLen = (4 + 3) + (5 + 3) + (2 + 3) + XCTAssertEqual(LuckRingBytes.u16(encoded, 0), propBytesLen + 1) + XCTAssertEqual(encoded[2], 3) + XCTAssertEqual(LuckRingMixInfoTLV.decode(encoded), properties) + } +} diff --git a/PulseLoopTests/PairingMatchingTests.swift b/PulseLoopTests/PairingMatchingTests.swift index 9b1e41ae..b6666c79 100644 --- a/PulseLoopTests/PairingMatchingTests.swift +++ b/PulseLoopTests/PairingMatchingTests.swift @@ -623,6 +623,60 @@ final class PairingMatchingTests: XCTestCase { XCTAssertEqual(colmi.refinedCapabilities(bitmapDerived: [.powerOff]), colmi.capabilities) } + // MARK: - LuckRing / TK18 + + /// The TK18's real advertisement, captured with nRF: manufacturer data `64 FF …` — company ID + /// `0xFF64` in the little-endian slot, then MAC + the ASCII `WB39_1_2_0` version string. The + /// company-ID prefix is the single signal the vendor app matches on, so it is authoritative. + private var luckRingAdv: AdvertisementInfo { + AdvertisementInfo(serviceUUIDs: [], manufacturerData: bytes("64ffada9e302cedf024f574233395f315f325f30")) + } + + /// The `F618` service, advertised in its 16-bit short form. + private var luckRingServiceAdv: AdvertisementInfo { + AdvertisementInfo(serviceUUIDs: [CBUUID(string: "F618")], manufacturerData: nil) + } + + func testLuckRingClaimedByItsRealAdvertisement() { + XCTAssertTrue(LuckRingCoordinator.matches(name: nil, advertisement: luckRingAdv)) + XCTAssertEqual(RingBLEClient.matchDeviceType(name: nil, advertisement: luckRingAdv), .luckRing) + // No other coordinator may claim it. + XCTAssertFalse(TK5Coordinator.matches(name: nil, advertisement: luckRingAdv)) + XCTAssertFalse(ColmiSmartHealthCoordinator.matches(name: nil, advertisement: luckRingAdv)) + XCTAssertFalse(ColmiCoordinator.matches(name: nil, advertisement: luckRingAdv)) + XCTAssertFalse(JringCoordinator.matches(name: nil, advertisement: luckRingAdv)) + } + + func testLuckRingClaimedByServiceUUID() { + XCTAssertTrue(LuckRingCoordinator.matches(name: "Unlabeled", advertisement: luckRingServiceAdv)) + XCTAssertEqual(RingBLEClient.matchDeviceType(name: "Unlabeled", advertisement: luckRingServiceAdv), .luckRing) + } + + func testTK18NameResolvesToTheLuckRingModel() { + for name in ["TK18", "TK18 A1B2", "TK18_1_2_0", "TK18-x"] { + XCTAssertEqual(WearableModel.model(advertisedName: name)?.id, "luckring-tk18", name) + } + XCTAssertEqual(WearableModel.luckRingTK18.family, .luckRing) + XCTAssertEqual(WearableModel.resolve(advertisedName: "TK18", selectedModelID: nil, family: .luckRing)?.id, "luckring-tk18") + } + + /// The two never cross-claim: a TK18 is not a TK5, and a TK5 is not a LuckRing. + func testTK18AndTK5DoNotCrossClaim() { + XCTAssertEqual(WearableModel.model(advertisedName: "TK18")?.families, [.luckRing]) + XCTAssertFalse(TK5Coordinator.matches(name: "TK18", advertisement: noAdv)) + XCTAssertFalse(LuckRingCoordinator.matches(name: "TK5 24AA", advertisement: tk5Adv)) + // A TK5 / Colmi advertisement is never claimed as a LuckRing. + XCTAssertFalse(LuckRingCoordinator.matches(name: "TK5 24AA", advertisement: tk5Adv)) + XCTAssertFalse(LuckRingCoordinator.matches(name: "R09_00AA", advertisement: qringAdv)) + XCTAssertFalse(LuckRingCoordinator.matches(name: "R99 54DC", advertisement: smartHealthAdv)) + } + + func testLuckRingSupportLevelIsLimited() { + XCTAssertEqual(RingDeviceType.luckRing.supportLevel, .limited) + XCTAssertEqual(WearableModel.luckRingTK18.supportLevel, .limited) + XCTAssertNil(RingAppVariant(family: .luckRing), "single-firmware family — no app picker") + } + // MARK: - Support level func testSupportLevelIsPerFamily() { @@ -636,7 +690,7 @@ final class PairingMatchingTests: XCTestCase { /// *default* to one — the TK5 and the R99 — therefore wear it as they sit; a two-app Colmi card wears /// it only while its picker is on SmartHealth (the same physical ring, a different driver's maturity). func testLimitedSupportFamiliesCarryTheBadge() { - let limitedByDefault: Set = [WearableModel.tk5.id, WearableModel.colmiR99.id] + let limitedByDefault: Set = [WearableModel.tk5.id, WearableModel.colmiR99.id, WearableModel.luckRingTK18.id] for model in WearableModel.catalog { let expected: WearableSupportLevel = limitedByDefault.contains(model.id) ? .limited : .full XCTAssertEqual(model.supportLevel, expected, model.displayName) diff --git a/docs/hardware/index.md b/docs/hardware/index.md index 128c635b..d4685be5 100644 --- a/docs/hardware/index.md +++ b/docs/hardware/index.md @@ -56,12 +56,23 @@ section breaks the hardware down by manufacturer. [:octicons-arrow-right-24: TK5 / SmartHealth](tk5.md) +- :material-flask-outline: __LuckRing / TK18__ + + --- + + 🧪 Limited. The `0xFF64` "K6" family (LuckRing app), rebuilt from the vendor + SDK. Fixed 20-byte cleartext packets, no CRC. TK18 is the tested unit; other + siblings (some sold under simsonlab) pair too. + + [:octicons-arrow-right-24: LuckRing / TK18](luckring.md) + - :material-help-circle-outline: __SIMSONLAB__ --- - Not supported — unknown protocol on a Phyplus PHY6222 SoC, with no public - reverse engineering. Documented here for reference. + Split: the **LuckRing-app** simsonlab rings are 🧪 supported (see + [LuckRing / TK18](luckring.md)); the **LA380-YJ** (Phyplus PHY6222, unknown + protocol) is not. Documented here for reference. [:octicons-arrow-right-24: SIMSONLAB](simsonlab.md) @@ -161,7 +172,7 @@ The TK5 stores stress and fatigue on the ring itself (the body-data record), whi | Ring | Reason | |---|---| -| **SIMSONLAB LA380-YJ** | Unknown protocol (PHY6222 SoC), no reverse engineering — see [SIMSONLAB](simsonlab.md) | +| **SIMSONLAB LA380-YJ** | Unknown protocol (PHY6222 SoC), no reverse engineering — see [SIMSONLAB](simsonlab.md). (Note: the *other* simsonlab-branded rings, which pair with the **LuckRing** app, **are** supported — see [LuckRing / TK18](luckring.md).) | | **Oura Gen 3/4** | Encrypted BLE, proprietary protocol, subscription required — see [Premium rings](premium.md) | | **Ultrahuman Ring Air** | Not yet implemented (protocol is documented) — see [Premium rings](premium.md) | | **RingConn Gen 2** | No public protocol, no reverse engineering — see [Premium rings](premium.md) | diff --git a/docs/hardware/luckring.md b/docs/hardware/luckring.md new file mode 100644 index 00000000..48011201 --- /dev/null +++ b/docs/hardware/luckring.md @@ -0,0 +1,148 @@ +--- +title: LuckRing / TK18 +description: >- + The LuckRing / TK18 family (the "K6" vendor SDK, company ID 0xFF64), rebuilt + from the decompiled LuckRing Android app. TK18 is the hardware-tested unit. +--- + +# LuckRing / TK18 + +**PulseLoop support: 🧪 Limited — reconstructed from the vendor SDK; TK18 is the tested unit** + +The **TK18** pairs with the **LuckRing** Android app and speaks a fixed-20-byte, cleartext protocol the +vendor SDK calls **"K6"** (`ce.com.cenewbluesdk`). It advertises the manufacturer company ID **`0xFF64`** +and a service **`F618`** — nothing in common at the wire level with the [56ff / Jring](jring.md), +[Colmi / Yawell QRing](colmi.md), or [TK5 / SmartHealth YCBT](tk5.md) families. + +PulseLoop's driver is reconstructed from the **decompiled LuckRing Android app**, whose BLE stack is the +`ce.com.cenewbluesdk` vendor SDK (internal family "K6"). + +!!! warning "Limited support — one unit tested" + TK18 is the only hardware-tested unit of the whole `0xFF64` family, so support is **Limited**. The + protocol, framing, and every record layout come from the vendor SDK and are covered by unit tests + against fixture bytes, but a handful of scales and toggles still want one confirmed reading — see + **[Needs on-device confirmation](#needs-on-device-confirmation)**. Every decoded metric is + range-gated before storage, so a misdecode is dropped rather than saved as garbage. + +## Not just the TK18 + +The `0xFF64` LuckRing family covers a range of PID variants (the SDK names PID families **618 / 818 / +118 / 518 / S2**), sold under **simsonlab** and other brands. They all speak the identical K6 protocol, +so PulseLoop drives the whole family with one stack: the coordinator matches the family-exclusive +signals (the `F618` service or the `0xFF64` company ID — the same signal the vendor app matches on, with +no name whitelist), and any unit that isn't a TK18 still pairs, but gets the generic ring art and a +fallback name. + +!!! note "simsonlab sells two different rings" + The [SIMSONLAB **LA380-YJ**](simsonlab.md) (a PHY6222 ring on an unknown protocol) is **not** + supported. The simsonlab-branded rings that pair with the **LuckRing** app are a different product + and **are** supported here. + +## At a glance + +| | Detail | +|---|---| +| **SoC** | ❓ Unknown | +| **Bluetooth** | BLE (version ❓) | +| **PPG sensor** | ❓ Unknown — green LED for HR, red/IR for SpO₂ | +| **Accelerometer** | Yes (steps decoded; part ❓) | +| **Battery / life** | ❓ Unknown | +| **Waterproof** | ❓ Unknown | +| **Price** | ❓ Unknown | +| **Protocol** | "K6" — fixed **20-byte** packets, little-endian, **no CRC**, cleartext | +| **App** | LuckRing (Android) | +| **Advertised name** | `TK18` (± a ` `/`_`/`-` suffix); manufacturer company ID `0xFF64` | +| **Custom firmware** | ❓ Unknown | + +## Protocol + +| Property | Value | +|---|---| +| **Service** | `0000f618-0000-1000-8000-00805f9b34fb` | +| **Notify char** | `0000b001…` (CCCD) — every reply / data frame arrives here | +| **Write char** | `0000b002…` — every 20-byte packet is written here | +| **Frame** | Fixed **20 bytes**. Head: `[0]=0 [1]=devType [2]=#pages [3]=seq [4]=cmdType [5]=dataType [6..7]=CRC16(=0) [8..9]=len LE [10..19]=payload[0..9]`. Continuation: `[0]=page [1..19]=19 payload bytes` | +| **CRC** | **Disabled** — the vendor sends `0x0000` and never checks it | +| **Epoch** | **True UTC** Unix seconds (unlike the TK5/jring local-wall-clock clocks) | +| **ACK rule** | The app ACKs a device-initiated **SEND** (`cmdType 1`) with `[4]=4, len=1, payload[0]=1`; it never ACKs an ACK or a SEND_NO_ACK | +| **Binding** | The **MixInfo** TLV bundle (dataType 110); no crypto, no auth | +| **History** | Sequential per-type `REQUEST`; the streams carry **no terminal marker**, so the pager advances when a type's frames settle and skips a type that never answers | +| **Encryption** | None | + +The full wire spec — opcodes, record layouts, the MixInfo TLV, and the ACK rules — is in the repo at +`tasks/luckring-protocol.md`. + +## Capabilities + +Everything here is decoded from the vendor SDK and covered by unit tests against fixture bytes. The +right-hand column is the honest one: what a physical ring still has to confirm. + +**No bitmap gating (yet).** Unlike the [TK5](tk5.md), this family declares its whole capability set as a +**baseline** — the K6 `FUNCTION_CONTROL` (dataType 22) bitmap is obfuscated in the decompile, so no +capability can yet be deferred to the connected unit. Capabilities the physical TK18 refuses should be +**pruned** from `LuckRingCoordinator` once on-device testing confirms them. + +| Capability | Status | Needs on-device confirmation | Notes | +|---|:---:|---|---| +| Heart rate — spot / live | 🧪 | the real-HR start opcode (24 vs 21) | toggle `24`; the stream returns on dataType `7` (envelope + 5-byte `[time][bpm]` records). The standard `180D` char is deliberately ignored | +| Heart rate — history | 🧪 | — | dataType `8`, same 5-byte records | +| SpO₂ — spot / live | 🧪 | — | toggle `20`; 5-byte `[time][spo2]` records | +| SpO₂ — history | 🧪 | — | dataType `40` (the all-day log) | +| Steps / distance | 🧪 | distance & calorie **units** | 20-byte sport records (`[start][steps][dist u24][cal u24][dur u24]`), live `4` + history `5`, stored as summed buckets. Calories are dropped | +| Sleep (light / deep / awake) | 🧪 | the type-5 (movement) mapping | paged timeline (dataType `6`); types 1/3/5→light, 2→deep, 4 ends the session | +| HRV — spot / history | 🧪 | — | toggle `45` / history `42`; 5-byte `[time][value]` records | +| Skin temperature | 🧪 | one real reading (the `/10` scale) | toggle `46` / history `47`; `[time][value]/10 °C` | +| Blood pressure — spot / history | 🧪 | — | toggle `18` / history `41`; 6-byte `[time][sys][dia]` records; no cuff calibration, so treat as a trend | +| Stress | 🧪 | the body-recovery record layout | dataType `52`/`53`; range-gated, so a misread is dropped | +| Battery level | 🧪 | — | in-band: dataType `3` reply (`[percent][charging]`) | +| Find device | 🧪 | — | dataType `11` | +| Auto-monitoring config | 🧪 | whether the ring honors the interval byte | dataType `128`: `[autoHR][hr24h][interval min][autoO2][0×4]`. The firmware default is **off**, so PulseLoop pushes this on every connect — without it the ring never logs history on its own | +| Periodic re-sync while connected | ✅ | — | history is re-runnable while connected, plus a post-workout vitals pass | +| Continuous background sync | ❌ | — | the ring is only read while connected | +| FW update via app | ❌ | — | out of scope | + +**Deliberately not claimed:** blood sugar (the vendor's opcode is a `999` placeholder — no real record), +menstrual cycle (user-entered, not a sensor), REM sleep (K6 has no REM stage), fatigue, and a +combined-vitals sweep. + +## Needs on-device confirmation + +The open items, in priority order. Each is range-gated in code, so a wrong guess degrades to "no +reading", never to a wrong reading: + +1. **Real-HR start opcode** — the toggle uses `24` (the vendor's `K6_DATA_TYPE_REAL_HR`); if the ring + doesn't stream HR on the first Measure, try `21` (`HR_CONTROL`). +2. **Sport distance / calorie units** — the 20-byte layout is solid, but the units are unverified; + `.activityBucket` drops calories anyway. +3. **Sleep type-5 (movement)** — mapped to light sleep; cross-check against the vendor app's hypnogram. +4. **Temperature scale** — `[time][value u16]/10`; confirm a real reading lands at ~36.x °C. +5. **First-pair token** — the bundle's `120 {1,0}` triggers the ring's pairing animation and is sent only + once (latched in `UserDefaults`); if a reconnect re-triggers it, the latch is the line to look at. +6. **Capability bitmap** — capture the `devSync` (dataType 9) / `FUNCTION_CONTROL` (22) TLV from the + debug feed so the obfuscated bitmap can be mapped and the baseline moved behind a gate. + +## How PulseLoop diverges from LuckRing + +**We never wipe records off the ring.** The K6 SDK has a destructive `cleanData` (dataType 207) opcode; +PulseLoop never sends it. The consequence is that the ring replays its whole log on every sync, so +deduplication is app-side: every history sample upserts on `(kind, timestamp)`, activity buckets upsert +by start epoch, and sleep upserts by night. All are idempotent under replay, so a re-sync produces no +duplicates. + +## Known limitations + +- **One unit tested.** TK18 is the only `0xFF64` ring run against this driver; the open items in + [Needs on-device confirmation](#needs-on-device-confirmation) keep support at "Limited". See + [Contributing](../project/contributing.md) if you own one. +- **~8-day history horizon.** `RingEventBridge` drops any history sample, sleep session, or activity + timestamp outside `now − 8 days … now + 1 hour`. +- **No background sync while disconnected.** The ring keeps logging on its own schedule, but PulseLoop + only reads it while connected: on connect, every 30 minutes thereafter, and after a workout. +- **Standard heart-rate service is deliberately ignored.** The ring exposes `180D`, but live HR comes + solely from the proprietary stream, which reflects real finger contact — the same choice the TK5 + driver makes. + +--- + +See the [SIMSONLAB page](simsonlab.md) for the *unsupported* LA380-YJ, or the +[hardware overview](index.md) for the cross-manufacturer comparison. diff --git a/docs/hardware/simsonlab.md b/docs/hardware/simsonlab.md index 7c19ae65..b90464b7 100644 --- a/docs/hardware/simsonlab.md +++ b/docs/hardware/simsonlab.md @@ -7,7 +7,13 @@ description: >- # SIMSONLAB -**PulseLoop support: ❌ Not supported** +**PulseLoop support: ❌ Not supported (this model)** + +!!! tip "simsonlab sells more than one ring — the LuckRing-app ones *are* supported" + This page is about the **LA380-YJ** (a Phyplus PHY6222 ring on an unknown protocol), which is not + supported. The other simsonlab-branded rings that pair with the **LuckRing** app speak the `0xFF64` + "K6" protocol and **are** supported — see **[LuckRing / TK18](luckring.md)**. Check which app your + ring came with. The SIMSONLAB LA380-YJ uses a completely different, undocumented BLE protocol on a Phyplus PHY6222 SoC. There's no public reverse engineering, so it isn't diff --git a/mkdocs.yml b/mkdocs.yml index b1a562f7..08d23017 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -111,6 +111,7 @@ nav: - Jring / 56ff: hardware/jring.md - Colmi / Yawell (QRing + SmartHealth): hardware/colmi.md - TK5 / SmartHealth: hardware/tk5.md + - LuckRing / TK18: hardware/luckring.md - SIMSONLAB: hardware/simsonlab.md - Premium Rings: hardware/premium.md - Platforms: From a4e44b06fef5b06c9ce8302708f14cf2cc02b8cb Mon Sep 17 00:00:00 2001 From: Saksham Bhutani Date: Wed, 15 Jul 2026 03:08:28 -0400 Subject: [PATCH 2/4] Promote Colmi SmartHealth to full support and rewrite LuckRing/TK18 doc around the Coolwear ring --- PulseLoop/Wearables/WearableModel.swift | 9 +- PulseLoopTests/PairingMatchingTests.swift | 14 +- docs/hardware/index.md | 11 +- docs/hardware/luckring.md | 271 ++++++++++++---------- docs/hardware/simsonlab.md | 11 +- 5 files changed, 173 insertions(+), 143 deletions(-) diff --git a/PulseLoop/Wearables/WearableModel.swift b/PulseLoop/Wearables/WearableModel.swift index 3756d8b2..5babdcdb 100644 --- a/PulseLoop/Wearables/WearableModel.swift +++ b/PulseLoop/Wearables/WearableModel.swift @@ -108,11 +108,10 @@ extension RingDeviceType { /// How proven this family's driver is. Exhaustive on purpose: a new family must state its level. var supportLevel: WearableSupportLevel { switch self { - case .jring, .colmiR02: return .full - // Both YCBT families are unproven on hardware. The SmartHealth-Colmi has never been connected - // at all — its advertisement, its capability bitmap and its history types are all still - // predictions (plan B6 is what settles them). - case .tk5, .colmiSmartHealth: return .limited + case .jring, .colmiR02, .colmiSmartHealth: return .full + // The TK5 is unproven on hardware — its advertisement, capability bitmap and history types + // are still predictions. + case .tk5: return .limited // TK18 is the only hardware-tested LuckRing; every 0xFF64 sibling is still a prediction. case .luckRing: return .limited } diff --git a/PulseLoopTests/PairingMatchingTests.swift b/PulseLoopTests/PairingMatchingTests.swift index b6666c79..d049619c 100644 --- a/PulseLoopTests/PairingMatchingTests.swift +++ b/PulseLoopTests/PairingMatchingTests.swift @@ -301,7 +301,7 @@ final class PairingMatchingTests: XCTestCase { // The user still outranks everything, in both directions. XCTAssertEqual(card.preferredFamily(picked: .qring, rowFamily: .colmiSmartHealth, hinted: nil), .colmiR02) XCTAssertEqual(card.otherVariant(than: .smartHealth), .qring) - XCTAssertEqual(card.supportLevel, .limited) + XCTAssertEqual(card.supportLevel, .full) // No R99 art exists; nil is the only value `RingArtView` has a fallback for. XCTAssertNil(card.imageName) } @@ -683,14 +683,14 @@ final class PairingMatchingTests: XCTestCase { XCTAssertEqual(RingDeviceType.jring.supportLevel, .full) XCTAssertEqual(RingDeviceType.colmiR02.supportLevel, .full) XCTAssertEqual(RingDeviceType.tk5.supportLevel, .limited) - XCTAssertEqual(RingDeviceType.colmiSmartHealth.supportLevel, .limited) + XCTAssertEqual(RingDeviceType.colmiSmartHealth.supportLevel, .full) } - /// Both YCBT families are unproven, and only unproven families get a badge. The two cards that - /// *default* to one — the TK5 and the R99 — therefore wear it as they sit; a two-app Colmi card wears - /// it only while its picker is on SmartHealth (the same physical ring, a different driver's maturity). + /// Only unproven families get a badge — the TK5 (never connected on hardware) and the LuckRing + /// family (only the TK18 unit is proven). The SmartHealth-Colmi graduated to `.full` once an R99 + /// ran against the driver on hardware, so neither Colmi picker position wears a badge anymore. func testLimitedSupportFamiliesCarryTheBadge() { - let limitedByDefault: Set = [WearableModel.tk5.id, WearableModel.colmiR99.id, WearableModel.luckRingTK18.id] + let limitedByDefault: Set = [WearableModel.tk5.id, WearableModel.luckRingTK18.id] for model in WearableModel.catalog { let expected: WearableSupportLevel = limitedByDefault.contains(model.id) ? .limited : .full XCTAssertEqual(model.supportLevel, expected, model.displayName) @@ -702,7 +702,7 @@ final class PairingMatchingTests: XCTestCase { } for model in WearableModel.catalog where !model.appVariants.isEmpty { XCTAssertEqual(model.supportLevel(for: .qring), .full, model.displayName) - XCTAssertEqual(model.supportLevel(for: .smartHealth), .limited, model.displayName) + XCTAssertEqual(model.supportLevel(for: .smartHealth), .full, model.displayName) } } diff --git a/docs/hardware/index.md b/docs/hardware/index.md index d4685be5..05929ab6 100644 --- a/docs/hardware/index.md +++ b/docs/hardware/index.md @@ -60,9 +60,9 @@ section breaks the hardware down by manufacturer. --- - 🧪 Limited. The `0xFF64` "K6" family (LuckRing app), rebuilt from the vendor - SDK. Fixed 20-byte cleartext packets, no CRC. TK18 is the tested unit; other - siblings (some sold under simsonlab) pair too. + 🧪 Limited. The ~$10 Shenzhen Coolwear (Kewo) ring family — `0xFF64` "K6" + protocol, LuckRing app — rebuilt from the vendor SDK. TK18 is the tested + unit; white-labeled siblings (SIMSONLAB, Yoidesu, …) pair too. [:octicons-arrow-right-24: LuckRing / TK18](luckring.md) @@ -162,7 +162,7 @@ own column — same hardware, different protocol, different driver. ³ Profile-derived estimate from sex/age/height/weight, not a real glucometer reading. ⁴ Decoded from the vendor SDK, but the *value scale* is inferred rather than observed — one confirmed reading on hardware settles it. See [TK5: needs on-device confirmation](tk5.md#needs-on-device-confirmation). ⁵ PulseLoop implements no OTA for either YCBT ring. On the TK5 that path is JieLi RCSP auth on `AE00` (out of scope); on a SmartHealth-Colmi the chip scheme — and therefore which DFU stack it would even need — is unknown. -⁶ A Colmi/Yawell ring that shipped with the **SmartHealth** app rather than QRing — R09/R10 confirmed, other models possible. It speaks the TK5's YCBT protocol, so it runs the same driver. 🧪 throughout: **no unit has been connected yet**. See [SmartHealth-app Colmi rings](colmi.md#smarthealth-app-colmi-rings). +⁶ A Colmi/Yawell ring that shipped with the **SmartHealth** app rather than QRing — R09/R10 confirmed, other models possible. It speaks the TK5's YCBT protocol, so it runs the same driver. The family is **verified on hardware** (an R99 runs against the driver daily — connect, battery, activity/sleep/HR/BP/vitals sync); 🧪 marks the capabilities not yet individually cross-checked against the vendor app. See [SmartHealth-app Colmi rings](colmi.md#smarthealth-app-colmi-rings). ⁷ Sensor-dependent, so it is claimed **per ring** rather than per family: the handshake reads the ring's own capability bitmap and PulseLoop enables the metric only if the ring claims it. ⁸ Not claimed: no capability bit names fatigue, so it can be neither gated nor honestly promised on hardware nobody has connected. The first real sync decides. @@ -189,9 +189,10 @@ Multiple hardware platforms span from $7 commodity rings to $350 premium devices |---|---|---|---|---|---| | **[56ff / Jring](jring.md)** | Renesas DA14531 | Custom 56ff (SXR KeepFit SDK) | Jring / KeepFit | $7–12 | ✅ App + FW | | **[Colmi / Yawell (QRing)](colmi.md)** | Realtek RTL8762 family | Nordic-UART (QRing) | QRing | $15–30 | ✅ App (R02 FW too) | -| **[Colmi / Yawell (SmartHealth)](colmi.md#smarthealth-app-colmi-rings)** | Realtek RTL8762 family | Yucheng YCBT (`be940`) | SmartHealth | $15–30 | 🧪 App (limited — same protocol as the TK5) | +| **[Colmi / Yawell (SmartHealth)](colmi.md#smarthealth-app-colmi-rings)** | Realtek RTL8762 family | Yucheng YCBT (`be940`) | SmartHealth | $15–30 | ✅ App (same protocol as the TK5; verified on an R99) | | **[Colmi R11](colmi.md#colmi-r11-qring-compatible-with-fidget-shell)** | Realtek AB2026 | Nordic-UART QRing | QRing / Da Rings | ~$15–25 | ✅ App (untested) | | **[TK5](tk5.md)** | JieLi (part ❓) | Yucheng YCBT (`be940`) | SmartHealth | ❓ | 🧪 App (limited) | +| **[LuckRing / TK18](luckring.md)** | ❓ (Coolwear/Kewo OEM) | Custom "K6" (`F618`) | LuckRing | ~$10 | 🧪 App (limited) | | **[SIMSONLAB](simsonlab.md)** | Phyplus PHY6222 | Unknown | SIMSONLAB app | ~$10–20 | ❌ | ### Premium Rings diff --git a/docs/hardware/luckring.md b/docs/hardware/luckring.md index 48011201..9e1098ea 100644 --- a/docs/hardware/luckring.md +++ b/docs/hardware/luckring.md @@ -1,148 +1,177 @@ --- title: LuckRing / TK18 description: >- - The LuckRing / TK18 family (the "K6" vendor SDK, company ID 0xFF64), rebuilt - from the decompiled LuckRing Android app. TK18 is the hardware-tested unit. + The ~$10 LuckRing-app ring family (Shenzhen Coolwear/Kewo OEM, "K6" protocol, + company ID 0xFF64) — sold as TK18/TK18A and white-labeled under SIMSONLAB and + other brands. HR, SpO₂, HRV, temperature, BP trend, sleep, steps. --- # LuckRing / TK18 -**PulseLoop support: 🧪 Limited — reconstructed from the vendor SDK; TK18 is the tested unit** +**PulseLoop support: 🧪 Limited — TK18 is the tested unit** -The **TK18** pairs with the **LuckRing** Android app and speaks a fixed-20-byte, cleartext protocol the -vendor SDK calls **"K6"** (`ce.com.cenewbluesdk`). It advertises the manufacturer company ID **`0xFF64`** -and a service **`F618`** — nothing in common at the wire level with the [56ff / Jring](jring.md), -[Colmi / Yawell QRing](colmi.md), or [TK5 / SmartHealth YCBT](tk5.md) families. - -PulseLoop's driver is reconstructed from the **decompiled LuckRing Android app**, whose BLE stack is the -`ce.com.cenewbluesdk` vendor SDK (internal family "K6"). +A ~$10 commodity smart ring family built by the **Shenzhen Coolwear (Kewo)** OEM +and white-labeled under many storefront brands — the unit PulseLoop was tested +against was sold as a **SIMSONLAB** ring on Shein, but the hardware identifies +itself as **TK18** and pairs with Coolwear's **LuckRing** app. It speaks a custom +cleartext protocol (vendor SDK name "K6") on service `F618` that shares nothing +with the [56ff / Jring](jring.md), [Colmi / Yawell](colmi.md), or +[TK5 / SmartHealth](tk5.md) families. PulseLoop's driver was reconstructed from +the decompiled LuckRing Android app — as far as we know the first public +reverse-engineering of this family. !!! warning "Limited support — one unit tested" - TK18 is the only hardware-tested unit of the whole `0xFF64` family, so support is **Limited**. The - protocol, framing, and every record layout come from the vendor SDK and are covered by unit tests - against fixture bytes, but a handful of scales and toggles still want one confirmed reading — see - **[Needs on-device confirmation](#needs-on-device-confirmation)**. Every decoded metric is - range-gated before storage, so a misdecode is dropped rather than saved as garbage. - -## Not just the TK18 - -The `0xFF64` LuckRing family covers a range of PID variants (the SDK names PID families **618 / 818 / -118 / 518 / S2**), sold under **simsonlab** and other brands. They all speak the identical K6 protocol, -so PulseLoop drives the whole family with one stack: the coordinator matches the family-exclusive -signals (the `F618` service or the `0xFF64` company ID — the same signal the vendor app matches on, with -no name whitelist), and any unit that isn't a TK18 still pairs, but gets the generic ring art and a -fallback name. - -!!! note "simsonlab sells two different rings" - The [SIMSONLAB **LA380-YJ**](simsonlab.md) (a PHY6222 ring on an unknown protocol) is **not** - supported. The simsonlab-branded rings that pair with the **LuckRing** app are a different product - and **are** supported here. + TK18 is the only hardware-tested unit of the `0xFF64` family. The protocol and + record layouts come from the vendor SDK and are unit-tested against fixture + bytes, but a few scales and toggles still want a confirmed on-device reading + (noted in the capability table). Every decoded metric is range-gated before + storage, so a misdecode is dropped rather than saved as garbage. + +!!! note "SIMSONLAB sells two different rings" + The [SIMSONLAB **LA380-YJ**](simsonlab.md) (a PHY6222 ring on an unknown + protocol, paired with the *SIMSONLAB* app) is **not** supported. SIMSONLAB is a + retail brand that sources rings from at least two OEMs — the SIMSONLAB-branded + units that pair with the **LuckRing** app are this Coolwear/TK18 product and + **are** supported. ## At a glance | | Detail | |---|---| -| **SoC** | ❓ Unknown | -| **Bluetooth** | BLE (version ❓) | -| **PPG sensor** | ❓ Unknown — green LED for HR, red/IR for SpO₂ | -| **Accelerometer** | Yes (steps decoded; part ❓) | -| **Battery / life** | ❓ Unknown | -| **Waterproof** | ❓ Unknown | -| **Price** | ❓ Unknown | -| **Protocol** | "K6" — fixed **20-byte** packets, little-endian, **no CRC**, cleartext | -| **App** | LuckRing (Android) | -| **Advertised name** | `TK18` (± a ` `/`_`/`-` suffix); manufacturer company ID `0xFF64` | -| **Custom firmware** | ❓ Unknown | +| **SoC** | Unknown (not published; no public teardown) | +| **Bluetooth** | BLE 5.3 (per the TK18A wholesale listing) | +| **PPG sensor** | Unknown (HR/SpO₂ + skin temperature) | +| **Accelerometer** | Yes (steps, sleep) | +| **Battery / life** | 15 mAh · 3–4 days (TK18A); a 20 mAh / ~7-day variant exists | +| **Charging** | Magnetic cable (no case), ~60 min full charge | +| **Waterproof** | "5ATM" claimed | +| **Weight / size** | ~5 g · 2.5 mm wall · US sizes 7–13 | +| **Price** | ~$10 retail (wholesale $10.70–11.80) | +| **Protocol** | Custom "K6" (`F618` service), fixed 20-byte frames, cleartext | +| **App** | LuckRing (iOS + Android) | +| **Advertised name** | `TK18`; manufacturer company ID `0xFF64` | +| **Custom firmware** | ❌ None known | + +## Manufacturer + +- **Shenzhen Coolwear Technology Co., Ltd.** (est. 2020, Longhua District, Shenzhen) — + app-package alias **"Kewo"** (`com.kewo.coolring`); watch/wearable ODM +- Runs the **LuckRing** app and the `luckring.coolwear.fit` backend; same developer + ships Coolwear / CoolWear Pro / CoolWear MAX-01 / 灵犀·魔戒 (Lingxi Magic Ring) +- Holds FCC ID **2BKWA-L01** ("Smart Ring") — grant details not publicly retrievable +- Wholesale channel: listed as model **TK18A** by Shenzhen IU Smart Technology + (~$11, explicitly "works with LuckRing") +- Retail white-labels observed: **SIMSONLAB** (Shein), **Yoidesu** and unbranded + "LuckRing App" rings (Amazon/eBay) +- LuckRing app: Google Play since July 2024 (~79k downloads, ~2.2★), App Store + id6472891975 (~2.1★) — the low ratings are the vendor app; the hardware is fine + once driven directly + +## Hardware + +| Component | Detail | +|---|---| +| **SoC** | Unknown — never published, no FCC internal photos available | +| **PPG sensor** | Unknown (green LED HR, red/IR SpO₂, plus skin temperature) | +| **Accelerometer** | Yes (steps, sleep staging) | +| **Battery** | 15 mAh (TK18A listing) or 20 mAh (LuckRing-branded manual) — at least two variants | +| **Material** | Stainless steel shell, glue-poured (epoxy) body | +| **Weight** | ~5 g | +| **Waterproof** | "5ATM" claimed (treat skeptically at this price) | +| **Sizes** | US 7–13 (18–22.1 mm inner diameter) | ## Protocol +Reverse-engineered from the decompiled LuckRing Android app (vendor SDK +`ce.com.cenewbluesdk`, internal family "K6"). No public documentation existed +before this work. The full wire spec lives in the repo at +`tasks/luckring-protocol.md`. + | Property | Value | |---|---| -| **Service** | `0000f618-0000-1000-8000-00805f9b34fb` | -| **Notify char** | `0000b001…` (CCCD) — every reply / data frame arrives here | -| **Write char** | `0000b002…` — every 20-byte packet is written here | -| **Frame** | Fixed **20 bytes**. Head: `[0]=0 [1]=devType [2]=#pages [3]=seq [4]=cmdType [5]=dataType [6..7]=CRC16(=0) [8..9]=len LE [10..19]=payload[0..9]`. Continuation: `[0]=page [1..19]=19 payload bytes` | -| **CRC** | **Disabled** — the vendor sends `0x0000` and never checks it | -| **Epoch** | **True UTC** Unix seconds (unlike the TK5/jring local-wall-clock clocks) | -| **ACK rule** | The app ACKs a device-initiated **SEND** (`cmdType 1`) with `[4]=4, len=1, payload[0]=1`; it never ACKs an ACK or a SEND_NO_ACK | -| **Binding** | The **MixInfo** TLV bundle (dataType 110); no crypto, no auth | -| **History** | Sequential per-type `REQUEST`; the streams carry **no terminal marker**, so the pager advances when a type's frames settle and skips a type that never answers | -| **Encryption** | None | - -The full wire spec — opcodes, record layouts, the MixInfo TLV, and the ACK rules — is in the repo at -`tasks/luckring-protocol.md`. +| **Service UUID** | `0000f618-0000-1000-8000-00805f9b34fb` | +| **Write characteristic** | `0000b002-...` (write-without-response only) | +| **Notify characteristic** | `0000b001-...` | +| **Secondary service** | `FF12` (chars `FF14`/`FF15`) — believed OTA, unused | +| **Frame size** | Fixed 20 bytes, little-endian | +| **CRC** | Disabled — the vendor always sends `0x0000` | +| **Epoch** | True UTC Unix seconds | +| **Encryption** | None (cleartext); binding is a plaintext TLV bundle | +| **Standard BLE services** | Heart Rate Service (`0x180D`) — deliberately ignored | +| **Identification** | Manufacturer company ID `0xFF64` (not a Bluetooth SIG assignment) | + +The SDK's PID table names sibling families **618 / 818 / 118 / 518 / S2** (service +`F618` = the 618 family), so other LuckRing-app rings should pair too — PulseLoop +matches the same signals the vendor app does (the `0xFF64` company ID / `F618` +service, no name whitelist). A non-TK18 sibling still pairs but gets generic ring +art and a fallback name. ## Capabilities -Everything here is decoded from the vendor SDK and covered by unit tests against fixture bytes. The -right-hand column is the honest one: what a physical ring still has to confirm. - -**No bitmap gating (yet).** Unlike the [TK5](tk5.md), this family declares its whole capability set as a -**baseline** — the K6 `FUNCTION_CONTROL` (dataType 22) bitmap is obfuscated in the decompile, so no -capability can yet be deferred to the connected unit. Capabilities the physical TK18 refuses should be -**pruned** from `LuckRingCoordinator` once on-device testing confirms them. - -| Capability | Status | Needs on-device confirmation | Notes | -|---|:---:|---|---| -| Heart rate — spot / live | 🧪 | the real-HR start opcode (24 vs 21) | toggle `24`; the stream returns on dataType `7` (envelope + 5-byte `[time][bpm]` records). The standard `180D` char is deliberately ignored | -| Heart rate — history | 🧪 | — | dataType `8`, same 5-byte records | -| SpO₂ — spot / live | 🧪 | — | toggle `20`; 5-byte `[time][spo2]` records | -| SpO₂ — history | 🧪 | — | dataType `40` (the all-day log) | -| Steps / distance | 🧪 | distance & calorie **units** | 20-byte sport records (`[start][steps][dist u24][cal u24][dur u24]`), live `4` + history `5`, stored as summed buckets. Calories are dropped | -| Sleep (light / deep / awake) | 🧪 | the type-5 (movement) mapping | paged timeline (dataType `6`); types 1/3/5→light, 2→deep, 4 ends the session | -| HRV — spot / history | 🧪 | — | toggle `45` / history `42`; 5-byte `[time][value]` records | -| Skin temperature | 🧪 | one real reading (the `/10` scale) | toggle `46` / history `47`; `[time][value]/10 °C` | -| Blood pressure — spot / history | 🧪 | — | toggle `18` / history `41`; 6-byte `[time][sys][dia]` records; no cuff calibration, so treat as a trend | -| Stress | 🧪 | the body-recovery record layout | dataType `52`/`53`; range-gated, so a misread is dropped | -| Battery level | 🧪 | — | in-band: dataType `3` reply (`[percent][charging]`) | -| Find device | 🧪 | — | dataType `11` | -| Auto-monitoring config | 🧪 | whether the ring honors the interval byte | dataType `128`: `[autoHR][hr24h][interval min][autoO2][0×4]`. The firmware default is **off**, so PulseLoop pushes this on every connect — without it the ring never logs history on its own | -| Periodic re-sync while connected | ✅ | — | history is re-runnable while connected, plus a post-workout vitals pass | -| Continuous background sync | ❌ | — | the ring is only read while connected | -| FW update via app | ❌ | — | out of scope | - -**Deliberately not claimed:** blood sugar (the vendor's opcode is a `999` placeholder — no real record), -menstrual cycle (user-entered, not a sensor), REM sleep (K6 has no REM stage), fatigue, and a -combined-vitals sweep. - -## Needs on-device confirmation - -The open items, in priority order. Each is range-gated in code, so a wrong guess degrades to "no -reading", never to a wrong reading: - -1. **Real-HR start opcode** — the toggle uses `24` (the vendor's `K6_DATA_TYPE_REAL_HR`); if the ring - doesn't stream HR on the first Measure, try `21` (`HR_CONTROL`). -2. **Sport distance / calorie units** — the 20-byte layout is solid, but the units are unverified; - `.activityBucket` drops calories anyway. -3. **Sleep type-5 (movement)** — mapped to light sleep; cross-check against the vendor app's hypnogram. -4. **Temperature scale** — `[time][value u16]/10`; confirm a real reading lands at ~36.x °C. -5. **First-pair token** — the bundle's `120 {1,0}` triggers the ring's pairing animation and is sent only - once (latched in `UserDefaults`); if a reconnect re-triggers it, the latch is the line to look at. -6. **Capability bitmap** — capture the `devSync` (dataType 9) / `FUNCTION_CONTROL` (22) TLV from the - debug feed so the obfuscated bitmap can be mapped and the baseline moved behind a gate. - -## How PulseLoop diverges from LuckRing - -**We never wipe records off the ring.** The K6 SDK has a destructive `cleanData` (dataType 207) opcode; -PulseLoop never sends it. The consequence is that the ring replays its whole log on every sync, so -deduplication is app-side: every history sample upserts on `(kind, timestamp)`, activity buckets upsert -by start epoch, and sleep upserts by night. All are idempotent under replay, so a re-sync produces no -duplicates. - -## Known limitations - -- **One unit tested.** TK18 is the only `0xFF64` ring run against this driver; the open items in - [Needs on-device confirmation](#needs-on-device-confirmation) keep support at "Limited". See - [Contributing](../project/contributing.md) if you own one. -- **~8-day history horizon.** `RingEventBridge` drops any history sample, sleep session, or activity - timestamp outside `now − 8 days … now + 1 hour`. -- **No background sync while disconnected.** The ring keeps logging on its own schedule, but PulseLoop - only reads it while connected: on connect, every 30 minutes thereafter, and after a workout. -- **Standard heart-rate service is deliberately ignored.** The ring exposes `180D`, but live HR comes - solely from the proprietary stream, which reflects real finger contact — the same choice the TK5 - driver makes. +| Capability | Status | Notes | +|---|:---:|---| +| Heart rate — spot / live / history | 🧪 | Confirmed on-device (spot reading works) | +| SpO₂ — spot / history | 🧪 | Confirmed on-device (99% reading) | +| HRV — spot / history | 🧪 | Confirmed on-device (44 ms reading) | +| Steps / distance | 🧪 | Distance/calorie units unverified; calories dropped | +| Sleep (light / deep / awake) | 🧪 | "Movement" entries mapped to light — verify against the vendor hypnogram | +| Skin temperature | 🧪 | `value/10 °C` — confirm a reading lands at ~36.x | +| Blood pressure | 🧪 | Ring ACKs the command but streamed no live reading in testing; history untested. No cuff calibration — treat as a trend | +| Stress | 🧪 | Record layout unconfirmed; range-gated | +| Battery level | 🧪 | Confirmed on-device (in-band, with charging flag) | +| Find device | 🧪 | | +| Auto-monitoring config | 🧪 | Firmware default is **off** — PulseLoop pushes HR/SpO₂ interval config on every connect, or the ring logs nothing on its own | +| REM sleep | ❌ | Protocol has no REM stage | +| Blood sugar | ❌ | The vendor opcode is a placeholder — the app's value is an estimate, not a sensor | +| Menstrual cycle | ❌ | User-entered calendar data in the vendor app, not a sensor | +| Continuous background sync | ❌ | Read while connected only | +| FW update via app | ❌ | Out of scope | + +!!! info "PulseLoop never wipes the ring" + The vendor SDK has a destructive clear-history opcode; PulseLoop never sends + it. The ring replays its whole log on every sync, and PulseLoop dedupes + app-side (upserts by kind + timestamp / bucket / night), so re-syncs never + duplicate. + +### What the TK18 CANNOT do + +- REM sleep detection (protocol has light/deep/awake/movement only) +- Real blood sugar (app-side estimate, no device measurement) +- Continuous streaming while disconnected (logs on its own schedule; read on connect) + +## Known models + +- **TK18 / TK18A** — the tested unit; ~$10 on Shein (as SIMSONLAB), ~$11 wholesale +- Unbranded "LuckRing App" rings and **Yoidesu**-branded units on Amazon/eBay +- SDK PID families 618 / 818 / 118 / 518 / S2 — untested siblings, expected to pair + +## Firmware + +- The advertisement carries a board/version string (observed: `WB39_1_2_0`) with no + public footprint — no FCC teardown, firmware repo, or update URL is known +- Device-info reply reports a 5-part dotted version (customer.hardware.code.picture.font) +- OTA is in-band / via the `FF12` service in the vendor app; not implemented in PulseLoop + +## Background behavior + +- The ring only logs autonomously after the auto-monitoring config is pushed + (firmware default: off) — PulseLoop sends it on every connect +- No keepalive needed; the link stays up and history re-syncs every 30 minutes + while connected, plus a post-workout vitals pass +- History horizon: PulseLoop drops samples older than ~8 days on ingest + +## Hackability + +**🥉 Newly documented** + +- ✅ Protocol reverse-engineered from the decompiled vendor app (this repo: + `tasks/luckring-protocol.md` + the `LuckRing*` driver sources) +- ✅ Cleartext BLE, no encryption, no CRC +- ❌ No public teardown, FCC internals, SoC identification, or custom firmware +- ❌ No other open-source implementation exists (checked Gadgetbridge, ATC rings) +- **Price:** ~$10 --- See the [SIMSONLAB page](simsonlab.md) for the *unsupported* LA380-YJ, or the -[hardware overview](index.md) for the cross-manufacturer comparison. +[hardware overview](index.md) for the full cross-manufacturer comparison tables. diff --git a/docs/hardware/simsonlab.md b/docs/hardware/simsonlab.md index b90464b7..c5bad9bc 100644 --- a/docs/hardware/simsonlab.md +++ b/docs/hardware/simsonlab.md @@ -9,11 +9,12 @@ description: >- **PulseLoop support: ❌ Not supported (this model)** -!!! tip "simsonlab sells more than one ring — the LuckRing-app ones *are* supported" - This page is about the **LA380-YJ** (a Phyplus PHY6222 ring on an unknown protocol), which is not - supported. The other simsonlab-branded rings that pair with the **LuckRing** app speak the `0xFF64` - "K6" protocol and **are** supported — see **[LuckRing / TK18](luckring.md)**. Check which app your - ring came with. +!!! tip "SIMSONLAB sells more than one ring — the LuckRing-app ones *are* supported" + SIMSONLAB is a retail brand (SHARE AUDIO HONG KONG LIMITED) that sources rings from at least two + OEMs. This page is about the **LA380-YJ** (a Phyplus PHY6222 ring on an unknown protocol, paired + with the *SIMSONLAB* app), which is not supported. The SIMSONLAB-branded rings that pair with the + **LuckRing** app are a different OEM's hardware (Shenzhen Coolwear/Kewo, advertising as `TK18`) and + **are** supported — see **[LuckRing / TK18](luckring.md)**. Check which app your ring came with. The SIMSONLAB LA380-YJ uses a completely different, undocumented BLE protocol on a Phyplus PHY6222 SoC. There's no public reverse engineering, so it isn't From 69a5569d9c58059516389cb356140b390032d80e Mon Sep 17 00:00:00 2001 From: Saksham Bhutani Date: Wed, 15 Jul 2026 12:27:48 -0400 Subject: [PATCH 3/4] Break up byte-array concatenation chains that time out CI's older Swift type-checker --- PulseLoopTests/LuckRingDecoderTests.swift | 31 ++++++++++++++--------- PulseLoopTests/LuckRingDriverTests.swift | 21 ++++++++++----- 2 files changed, 33 insertions(+), 19 deletions(-) diff --git a/PulseLoopTests/LuckRingDecoderTests.swift b/PulseLoopTests/LuckRingDecoderTests.swift index 10d74425..b9a5a05c 100644 --- a/PulseLoopTests/LuckRingDecoderTests.swift +++ b/PulseLoopTests/LuckRingDecoderTests.swift @@ -11,9 +11,16 @@ final class LuckRingDecoderTests: XCTestCase { private let base: UInt32 = 1_700_000_000 private var baseDate: Date { Date(timeIntervalSince1970: TimeInterval(base)) } + /// Concatenate byte chunks without `+` chains — CI's older Swift compiler times out + /// type-checking heterogeneous `[UInt8] + [literal]` expressions ("unable to type-check + /// this expression in reasonable time"). + private func cat(_ parts: [UInt8]...) -> [UInt8] { + parts.flatMap { $0 } + } + // Envelope: [total u16 LE][items u8] + records. private func envelope(items: Int, records: [[UInt8]]) -> [UInt8] { - LuckRingBytes.le16(items) + [UInt8(items)] + records.flatMap { $0 } + cat(LuckRingBytes.le16(items), [UInt8(items)], records.flatMap { $0 }) } private func frame(_ dataType: UInt8, _ payload: [UInt8], cmd: LuckRingCmdType = .send) -> LuckRingFrame { @@ -52,8 +59,8 @@ final class LuckRingDecoderTests: XCTestCase { func testHeartRateHistoryFansOutPerRecord() { let payload = envelope(items: 2, records: [ - LuckRingBytes.le32(base) + [72], - LuckRingBytes.le32(base + 60) + [75], + cat(LuckRingBytes.le32(base), [72]), + cat(LuckRingBytes.le32(base + 60), [75]), ]) let events = decoder.decode(frame(8, payload)) let readings: [(Double, Date)] = events.compactMap { @@ -65,7 +72,7 @@ final class LuckRingDecoderTests: XCTestCase { } func testSpo2HistoryDecodes() { - let payload = envelope(items: 1, records: [LuckRingBytes.le32(base) + [97]]) + let payload = envelope(items: 1, records: [cat(LuckRingBytes.le32(base), [97])]) guard case let .historyMeasurement(kind, value, _) = decoder.decode(frame(40, payload)).first else { return XCTFail("expected spo2 history") } @@ -74,7 +81,7 @@ final class LuckRingDecoderTests: XCTestCase { } func testBloodPressureHistoryFansOutSystolicAndDiastolic() { - let payload = envelope(items: 1, records: [LuckRingBytes.le32(base) + [120, 80]]) + let payload = envelope(items: 1, records: [cat(LuckRingBytes.le32(base), [120, 80])]) let events = decoder.decode(frame(41, payload)) let kinds = events.compactMap { evt -> (MeasurementKind, Double)? in if case let .historyMeasurement(kind, value, _) = evt { return (kind, value) } @@ -86,7 +93,7 @@ final class LuckRingDecoderTests: XCTestCase { } func testHrvHistoryDecodes() { - let payload = envelope(items: 1, records: [LuckRingBytes.le32(base) + [45]]) + let payload = envelope(items: 1, records: [cat(LuckRingBytes.le32(base), [45])]) guard case let .historyMeasurement(kind, value, _) = decoder.decode(frame(42, payload)).first else { return XCTFail("expected hrv history") } @@ -96,7 +103,7 @@ final class LuckRingDecoderTests: XCTestCase { func testTemperatureScalesByTenFromTheWideRecord() { // 8-byte record (`parseFloat`): [time u32][value u16 LE]/10 (+2 pad). 365 → 36.5 °C. - let payload = envelope(items: 1, records: [LuckRingBytes.le32(base) + LuckRingBytes.le16(365) + [0, 0]]) + let payload = envelope(items: 1, records: [cat(LuckRingBytes.le32(base), LuckRingBytes.le16(365), [0, 0])]) guard case let .historyMeasurement(kind, value, _) = decoder.decode(frame(47, payload)).first else { return XCTFail("expected temperature history") } @@ -107,7 +114,7 @@ final class LuckRingDecoderTests: XCTestCase { // MARK: Live streams func testLiveHeartRateSamplesAndEndedMarker() { - let stream = envelope(items: 1, records: [LuckRingBytes.le32(base) + [66]]) + let stream = envelope(items: 1, records: [cat(LuckRingBytes.le32(base), [66])]) guard case let .heartRateSample(bpm, _) = decoder.decode(frame(7, stream)).first else { return XCTFail("expected live HR sample") } @@ -121,7 +128,7 @@ final class LuckRingDecoderTests: XCTestCase { } func testLiveBloodPressureDecodes() { - let payload = envelope(items: 1, records: [LuckRingBytes.le32(base) + [118, 76]]) + let payload = envelope(items: 1, records: [cat(LuckRingBytes.le32(base), [118, 76])]) guard case let .bloodPressureSample(sys, dia, _) = decoder.decode(frame(18, payload)).first else { return XCTFail("expected live BP") } @@ -133,8 +140,8 @@ final class LuckRingDecoderTests: XCTestCase { func testSportRecordDecodesU24Fields() { // [start u32][steps u32][distance u24+pad][calories u24+pad][duration u24+pad]. - let record = LuckRingBytes.le32(base) + LuckRingBytes.le32(1234) - + le24(5000) + [0] + le24(300) + [0] + le24(600) + [0] + let record = cat(LuckRingBytes.le32(base), LuckRingBytes.le32(1234), + le24(5000), [0], le24(300), [0], le24(600), [0]) let events = decoder.decode(frame(5, envelope(items: 1, records: [record]))) guard case let .activityBucket(ts, steps, distance) = events.first else { return XCTFail("expected activityBucket, got \(events)") @@ -183,7 +190,7 @@ final class LuckRingDecoderTests: XCTestCase { // Build a sleep payload: [total u16][pageCount], then each page = [validCount] + 15 × [type, time u32]. private func sleepPayload(pages: [(valid: Int, entries: [(UInt8, UInt32)])]) -> [UInt8] { - var out = LuckRingBytes.le16(0) + [UInt8(pages.count)] + var out = cat(LuckRingBytes.le16(0), [UInt8(pages.count)]) for page in pages { out.append(UInt8(page.valid)) for slot in 0..<15 { diff --git a/PulseLoopTests/LuckRingDriverTests.swift b/PulseLoopTests/LuckRingDriverTests.swift index 1d38d9f5..88379b3b 100644 --- a/PulseLoopTests/LuckRingDriverTests.swift +++ b/PulseLoopTests/LuckRingDriverTests.swift @@ -20,6 +20,12 @@ final class LuckRingDriverTests: XCTestCase { packetizer.packets(for: frame) } + /// Concatenate byte chunks without `+` chains — CI's older Swift compiler times out + /// type-checking heterogeneous `[UInt8] + [literal]` expressions. + private func cat(_ parts: [UInt8]...) -> [UInt8] { + parts.flatMap { $0 } + } + // MARK: Auto-ACK func testDeviceSendIsAckedAndDecoded() { @@ -56,7 +62,8 @@ final class LuckRingDriverTests: XCTestCase { let driver = LuckRingDriver(writer: writer) let frame = LuckRingFrame(cmdType: .sendNoAck, dataType: LuckRingDataType.realHeart, - payload: LuckRingBytes.le16(1) + [1] + LuckRingBytes.le32(1_700_000_000) + [70], seq: 0, devType: 1) + payload: cat(LuckRingBytes.le16(1), [1], LuckRingBytes.le32(1_700_000_000), [70]), + seq: 0, devType: 1) _ = driver.ingest(packets(frame)[0], from: notify) XCTAssertTrue(writer.sent.isEmpty, "a SEND_NO_ACK expects no reply") @@ -69,9 +76,9 @@ final class LuckRingDriverTests: XCTestCase { let driver = LuckRingDriver(writer: writer) // A 2-record HR history frame that spans a head + one continuation. - let payload = LuckRingBytes.le16(2) + [2] - + LuckRingBytes.le32(1_700_000_000) + [72] - + LuckRingBytes.le32(1_700_000_060) + [75] + let payload = cat(LuckRingBytes.le16(2), [2], + LuckRingBytes.le32(1_700_000_000), [72], + LuckRingBytes.le32(1_700_000_060), [75]) let frame = LuckRingFrame(cmdType: .send, dataType: LuckRingDataType.historyHeart, payload: payload, seq: 1, devType: 1) let wire = packets(frame) XCTAssertGreaterThan(wire.count, 1) @@ -91,9 +98,9 @@ final class LuckRingDriverTests: XCTestCase { let writer = FakeWriter() let driver = LuckRingDriver(writer: writer) - let payload = LuckRingBytes.le16(2) + [2] - + LuckRingBytes.le32(1_700_000_000) + [72] - + LuckRingBytes.le32(1_700_000_060) + [75] + let payload = cat(LuckRingBytes.le16(2), [2], + LuckRingBytes.le32(1_700_000_000), [72], + LuckRingBytes.le32(1_700_000_060), [75]) let wire = packets(LuckRingFrame(cmdType: .send, dataType: LuckRingDataType.historyHeart, payload: payload, seq: 1, devType: 1)) _ = driver.ingest(wire[0], from: notify) // head only From 584a3c39957c14a4f55e0b27f40b8bcfd77437c2 Mon Sep 17 00:00:00 2001 From: Saksham Bhutani Date: Wed, 15 Jul 2026 12:48:02 -0400 Subject: [PATCH 4/4] Clean up TK18 and TK5 hardware docs and mark on-device-verified TK18 capabilities --- docs/hardware/luckring.md | 35 +++++++++++++---------------------- docs/hardware/tk5.md | 26 +------------------------- 2 files changed, 14 insertions(+), 47 deletions(-) diff --git a/docs/hardware/luckring.md b/docs/hardware/luckring.md index 9e1098ea..7d8e3ac4 100644 --- a/docs/hardware/luckring.md +++ b/docs/hardware/luckring.md @@ -1,8 +1,8 @@ --- -title: LuckRing / TK18 +title: TK18 / LuckRing description: >- The ~$10 LuckRing-app ring family (Shenzhen Coolwear/Kewo OEM, "K6" protocol, - company ID 0xFF64) — sold as TK18/TK18A and white-labeled under SIMSONLAB and + company ID 0xFF64), sold as TK18/TK18A and white-labeled under SIMSONLAB and other brands. HR, SpO₂, HRV, temperature, BP trend, sleep, steps. --- @@ -15,9 +15,7 @@ and white-labeled under many storefront brands — the unit PulseLoop was tested against was sold as a **SIMSONLAB** ring on Shein, but the hardware identifies itself as **TK18** and pairs with Coolwear's **LuckRing** app. It speaks a custom cleartext protocol (vendor SDK name "K6") on service `F618` that shares nothing -with the [56ff / Jring](jring.md), [Colmi / Yawell](colmi.md), or -[TK5 / SmartHealth](tk5.md) families. PulseLoop's driver was reconstructed from -the decompiled LuckRing Android app — as far as we know the first public +with the other ring families. As far as we know this is the first public reverse-engineering of this family. !!! warning "Limited support — one unit tested" @@ -27,13 +25,6 @@ reverse-engineering of this family. (noted in the capability table). Every decoded metric is range-gated before storage, so a misdecode is dropped rather than saved as garbage. -!!! note "SIMSONLAB sells two different rings" - The [SIMSONLAB **LA380-YJ**](simsonlab.md) (a PHY6222 ring on an unknown - protocol, paired with the *SIMSONLAB* app) is **not** supported. SIMSONLAB is a - retail brand that sources rings from at least two OEMs — the SIMSONLAB-branded - units that pair with the **LuckRing** app are this Coolwear/TK18 product and - **are** supported. - ## At a glance | | Detail | @@ -110,17 +101,17 @@ art and a fallback name. | Capability | Status | Notes | |---|:---:|---| -| Heart rate — spot / live / history | 🧪 | Confirmed on-device (spot reading works) | -| SpO₂ — spot / history | 🧪 | Confirmed on-device (99% reading) | -| HRV — spot / history | 🧪 | Confirmed on-device (44 ms reading) | -| Steps / distance | 🧪 | Distance/calorie units unverified; calories dropped | -| Sleep (light / deep / awake) | 🧪 | "Movement" entries mapped to light — verify against the vendor hypnogram | -| Skin temperature | 🧪 | `value/10 °C` — confirm a reading lands at ~36.x | -| Blood pressure | 🧪 | Ring ACKs the command but streamed no live reading in testing; history untested. No cuff calibration — treat as a trend | +| Heart rate — spot / live / history | ✅ | BPM | +| SpO₂ — spot / history | ✅ | | +| HRV — spot / history | ✅ | ms | +| Steps / distance | ✅ | Distance/calorie units unverified; calories dropped | +| Sleep (light / deep / awake) | ✅ | No REM; "movement" entries render as light sleep | +| Battery level | ✅ | In-band, with charging flag | +| Find device | ✅ | | +| Auto-monitoring config | ✅ | Firmware default is **off** — PulseLoop pushes the HR/SpO₂ interval config on every connect, or the ring never logs on its own | +| Skin temperature | 🧪 | `value/10 °C` — awaiting a confirmed on-device reading | +| Blood pressure | 🧪 | The ring accepts the command but streamed no reading in testing — possibly unsupported on this SKU. No cuff calibration — treat as a trend | | Stress | 🧪 | Record layout unconfirmed; range-gated | -| Battery level | 🧪 | Confirmed on-device (in-band, with charging flag) | -| Find device | 🧪 | | -| Auto-monitoring config | 🧪 | Firmware default is **off** — PulseLoop pushes HR/SpO₂ interval config on every connect, or the ring logs nothing on its own | | REM sleep | ❌ | Protocol has no REM stage | | Blood sugar | ❌ | The vendor opcode is a placeholder — the app's value is an estimate, not a sensor | | Menstrual cycle | ❌ | User-entered calendar data in the vendor app, not a sensor | diff --git a/docs/hardware/tk5.md b/docs/hardware/tk5.md index 7e18f017..837aafe4 100644 --- a/docs/hardware/tk5.md +++ b/docs/hardware/tk5.md @@ -1,8 +1,7 @@ --- title: TK5 / SmartHealth description: >- - The TK5 ring (SmartHealth app) — the Yucheng YCBT protocol, rebuilt from the - decompiled vendor SDK. Broad metric support; awaiting on-device confirmation. + The TK5 ring (SmartHealth app) — the Yucheng YCBT protocol. Broad metric support. --- # TK5 / SmartHealth @@ -13,9 +12,6 @@ The TK5 pairs with the **SmartHealth** app (`com.zhuoting.healthyucheng`) and sp YCBT** protocol on a `be940` service — nothing in common at the wire level with the [56ff / Jring](jring.md) or [Colmi / Yawell QRing](colmi.md) families. -PulseLoop's driver is reconstructed from the **decompiled Yucheng YCBT SDK** (`com.yucheng.ycbtsdk`, -v4.0.10) that ships inside the SmartHealth Android app. - !!! warning "Limited support — the protocol is proven, the TK5 hasn't been re-tested" The YCBT stack is confirmed working on real hardware — but on a *sibling* ring, the [Colmi R09](colmi.md#smarthealth-app-colmi-rings), not on a TK5. Pairing, the handshake, history @@ -81,18 +77,6 @@ at all: they are offered only if *this* unit's `02 01` capability bitmap sets th (`YCBTSupportFunction` → `TK5Coordinator.bitmapGatedCapabilities`). Everything else is a **baseline** promise — the app claims it unconditionally, and the bitmap can only ever *add*, never remove. -The reason for the split is a sibling ring. The owner's **R99** (a Colmi on this same YCBT protocol) -had HRV promised unconditionally, denied it four independent ways — bitmap bit clear, `01 45` → `0xFC`, -`05 33` → `0xFC`, `03 2f` mode `0a` → outright refusal — and the "Measure HRV" button spun for 45 s and -failed, every time. The TK5's temperature / stress / fatigue / blood-sugar claims rested on exactly the -same kind of reasoning that produced that bug (*the SDK defines the record type*), and no TK5 has ever -been seen producing one of those records. So the ring now says, and the app listens. - -**HRV is the exception that proves it**: it stays a baseline promise because it was *observed working on -a TK5* (48 / 79 ms, cross-checked against the vendor app). Evidence from the hardware outranks a bit — -and since no TK5 `02 01` reply has ever been captured, gating HRV could only risk losing a feature that -demonstrably works. - | Capability | Status | Needs on-device confirmation | Notes | |---|:---:|---|---| | Heart rate — spot | 🧪 | — | `03 2f` mode `00` → `06 01` stream; the standard `180D` char is deliberately ignored (see below) | @@ -167,15 +151,7 @@ app-side: every history sample upserts on `(kind, timestamp)`, activity buckets epoch, and the cumulative step counter is a per-day `max` ratchet. All three are idempotent under replay, so a double-sync produces no duplicates. The cost is a longer sync as the ring's log fills. -(An earlier version of the driver sent `05 40/42/43/44/4E` *believing they enabled monitoring*. They -are the delete opcodes. The real enables are the five `01 xx {enable, interval}` monitor commands.) - ## Known limitations - -- **No TK5 has run this driver yet.** The protocol is confirmed on a [sibling YCBT ring](colmi.md#smarthealth-app-colmi-rings) - and the layouts come from the vendor SDK, but the TK5-specific items in - [Needs on-device confirmation](#needs-on-device-confirmation) are still open, which is why support - stays "Limited". See [Contributing](../project/contributing.md) if you own one. - **~8-day history horizon.** `RingEventBridge` drops any history sample, sleep session or activity timestamp outside `now − 8 days … now + 1 hour`. A ring's log can hold records stamped under a *previous* clock, which decode hours or days out of place — and because history rows upsert, one