diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 0000000..c0351c3 --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,78 @@ +name: Docs + +# Build the MkDocs Material site and deploy it to GitHub Pages. +# +# One-time setup required: in the repo, go to Settings โ†’ Pages and set +# "Source" to "GitHub Actions". After that, every push to main that touches the +# docs builds and publishes automatically. + +on: + push: + branches: [main] + paths: + - docs/** + - mkdocs.yml + - requirements-docs.txt + - .github/workflows/docs.yml + pull_request: + branches: [main] + paths: + - docs/** + - mkdocs.yml + - requirements-docs.txt + - .github/workflows/docs.yml + # Allow manual runs from the Actions tab. + workflow_dispatch: + +# Cancel superseded runs on the same PR/branch to save runner minutes. +concurrency: + group: docs-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + build: + name: Build site + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.x" + cache: pip + cache-dependency-path: requirements-docs.txt + + - name: Install dependencies + run: pip install -r requirements-docs.txt + + # --strict turns warnings (broken nav links, missing images/refs) into + # errors, so a bad doc fails the build instead of shipping silently. + - name: Build site + run: mkdocs build --strict + + - name: Upload Pages artifact + # Only publish from main; PRs build-check only (see deploy job's `if`). + uses: actions/upload-pages-artifact@v3 + with: + path: site + + deploy: + name: Deploy to GitHub Pages + # Only deploy on pushes to main, never on PRs. + if: github.ref == 'refs/heads/main' && github.event_name != 'pull_request' + needs: build + runs-on: ubuntu-latest + permissions: + pages: write + id-token: write + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/.gitignore b/.gitignore index 743bca4..882492a 100644 --- a/.gitignore +++ b/.gitignore @@ -44,6 +44,10 @@ fastlane/test_output # Local scratch / planning notes tasks/ +# Docs site (MkDocs Material) โ€” local build output + virtualenv +site/ +.venv-docs/ + # Misc *.log *~ diff --git a/README.md b/README.md index 149de1e..3572923 100644 --- a/README.md +++ b/README.md @@ -5,23 +5,25 @@ Stars Forks Issues - PRs + PRs CI Platform Swift License + Docs Discord

- - PulseLoop + + PulseLoop

+ ๐Ÿ“š Documentation ยท ๐Ÿ“ฑ Now on Android ยท ๐Ÿ’ฌ Join the Discord ยท ๐Ÿ“– Read the writeup @@ -37,8 +39,6 @@ X post

---- - An LLM-native health app for iOS that turns a cheap Bluetooth "smart ring" into a real, conversational health tracker. It currently supports the generic Chinese Jring and the Colmi / Yawell ring family (R02/R0x/R1x/H59), behind a device-agnostic driver layer so @@ -54,24 +54,15 @@ your sleep, heart rate, activity, and recovery. > wearable, and that the "intelligence" should live on the phone, not behind a > paywall. ---- - -## Contents +## Documentation -- [What it does](#what-it-does) -- [Also on Android](#also-on-android) -- [Community](#community) -- [Supported wearables](#supported-wearables) -- [How it works](#how-it-works) -- [Install & try it](#install--try-it) -- [Privacy](#privacy) -- [Contributing](#contributing) -- [Goals / Roadmap](#goals--roadmap) -- [Project layout](#project-layout) -- [Acknowledgements](#acknowledgements) -- [License](#license) +๐Ÿ“š **Full docs: [saksham2001.github.io/PulseLoopiOS](https://saksham2001.github.io/PulseLoopiOS/)** ---- +- [Getting started โ€” iOS](https://saksham2001.github.io/PulseLoopiOS/getting-started/ios/) +- [Getting started โ€” Android](https://saksham2001.github.io/PulseLoopiOS/getting-started/android/) +- [Supported hardware](https://saksham2001.github.io/PulseLoopiOS/hardware/) +- [iOS vs Android](https://saksham2001.github.io/PulseLoopiOS/platforms/ios-vs-android/) +- [Architecture](https://saksham2001.github.io/PulseLoopiOS/project/architecture/) ยท [Roadmap](https://saksham2001.github.io/PulseLoopiOS/project/roadmap/) ยท [Contributing](https://saksham2001.github.io/PulseLoopiOS/project/contributing/) ## What it does @@ -86,7 +77,9 @@ search. Every answer is grounded in your actual ring data. Activity, and a Dynamic Island widget. - **Daily check-in notifications** generated by the coach from your recent trends. -- **Metric & imperial units** and a fully reworked settings pane. + +> ๐Ÿ“š **Diagrams and a full walkthrough: +> [Architecture docs](https://saksham2001.github.io/PulseLoopiOS/project/architecture/).** ### Screenshots @@ -98,8 +91,6 @@ trends. | --- | --- | --- | | [![Activity](https://github.com/saksham2001/PulseLoopiOS/raw/main/screenshots/activity%20page%201.PNG)](/screenshots/activity%20page%201.PNG) | [![Vitals](https://github.com/saksham2001/PulseLoopiOS/raw/main/screenshots/vitals%20page%201.PNG)](/screenshots/vitals%20page%201.PNG) | [![Workout Summary](https://github.com/saksham2001/PulseLoopiOS/raw/main/screenshots/activity%20recording-%20complete%201.PNG)](/screenshots/activity%20recording-%20complete%201.PNG) | ---- - ## Also on Android PulseLoop has a sister project for Android: **[PulseLoopAndroid](https://github.com/foureight84/PulseLoopAndroid)** @@ -113,8 +104,6 @@ Pick the build for your phone โ€” both connect to the same rings. > Coordination, the shared roadmap, and cross-platform discussion all happen in > the [Discord](#community). ---- - ## Community We run a Discord for roadmap planning, getting-started help, and coordinating @@ -131,8 +120,6 @@ New here? Good places to start: - Say hi in Discord and tell us what ring you have โ€” device reports are genuinely useful. ---- - ## Supported Wearables > **Disclaimer:** We have no affiliation with the sellers or manufacturers of @@ -144,76 +131,15 @@ New here? Good places to start: > your own risk and treat any data the ring produces as approximate. PulseLoop is built around a device-agnostic driver layer, so each supported ring -declares exactly what it can do and the app shows only those features. The -tables below break support down by capability. - -**Support status legend** - -| Status | Meaning | -| --- | --- | -| โœ… | **Supported & tested**: Fully verified working on real hardware | -| ๐Ÿงช | **Implemented, needs testing**: code is in place (decoded from the protocol) but not yet tested with that specific model | -| ๐Ÿšง | **Planned / not yet implemented** | -| โ€” | **Not applicable**: the hardware doesn't expose this capability | - -### Ring families +declares exactly what it can do and the app shows only those features. -| Ring | BLE Family | Advertised name | Price | Listing | -| --- | --- | --- | --- | --- | -| jring (generic smart ring) | `56ff` | `SMART_RING` | $7โ€“12 | [AliExpress](https://www.aliexpress.us/item/3256810466598469.html) | -| Colmi / Yawell ring family | `6e40fff0` / `de5bf728` | `R02_โ€ฆ`, `R0xโ€ฆ`, `COLMI R1xโ€ฆ`, `H59_โ€ฆ` | $15โ€“30 | [Colmi store](https://www.colmi.com/) | - -### Capability matrix - -Major functional areas, by device: - -| Capability | jring | Colmi R11 | Other Colmi/Yawellยน | +| Ring | BLE Family | Advertised name | Price | | --- | --- | --- | --- | -| **Connection & pairing** (scan, connect, reconnect, forget) | โœ… | โœ… | ๐Ÿงช | -| **History sync** (pull stored data on connect) | โœ… | โœ… | ๐Ÿงช | -| **Heart rate โ€” spot measurement** | โœ… | โœ… | ๐Ÿงช | -| **Heart rate โ€” history** | โœ… | โœ… | ๐Ÿงช | -| **Heart rate โ€” live (workout)** | โœ… | โœ… | ๐Ÿงช | -| **SpOโ‚‚ โ€” spot measurement** | โœ… | โ€” ยฒ | โ€” ยฒ | -| **SpOโ‚‚ โ€” history** | โœ… | โœ… | ๐Ÿงช | -| **Steps / distance / calories** | โœ… | โœ… ยณ | ๐Ÿงช | -| **Activity / workout recording** (live HR, zones, GPS route) | โœ… | โœ… | ๐Ÿงช | -| **Sleep stages** (light / deep / awake) | โœ… | โœ… | ๐Ÿงช | -| **REM sleep** | โ€” | โœ… | ๐Ÿงช | -| **HRV** | โ€” | โœ… | ๐Ÿงช | -| **Stress** | โ€” | โœ… | ๐Ÿงช | -| **Body temperature** | โ€” | โœ… | ๐Ÿงช | -| **Battery level** | โœ… | โœ… | ๐Ÿงช | -| **Find device** | โœ… | โœ… | ๐Ÿงช | - -ยน Other Colmi/Yawell models recognized by the same driver: **Colmi R02, R03, -R06, R07, R09, R10, R12** and **Yawell R05, R10, R11, H59**. Same protocol as -the R11, so all capabilities are implemented, but not yet hardware-verified -per model. - -ยฒ The Colmi family has no on-demand SpOโ‚‚ reading; SpOโ‚‚ is an all-day background -metric, so only the synced **history/graph** is available (no spot button). - -ยณ Calories from Colmi history are currently hidden pending verification of the -raw value; steps and distance are shown. - ---- - -## How it works +| jring (generic smart ring) | `56ff` | `SMART_RING` | $7โ€“12 | +| Colmi / Yawell ring family | `6e40fff0` / `de5bf728` | `R02_โ€ฆ`, `R0xโ€ฆ`, `COLMI R1xโ€ฆ`, `H59_โ€ฆ` | $15โ€“30 | -**System architecture:** four layers on the phone. Data flows up from the ring into local storage; the coach reads sideways through tools, and the only thing that leaves the device is a coach question you choose to ask. - -[![System architecture](https://github.com/saksham2001/PulseLoopiOS/raw/main/docs/system-architecture.png)](/docs/system-architecture.png) - -**The ring link:** one custom BLE service, fixed 20-byte cleartext packets, commands out and notifications back. - -[![Ring interaction](https://github.com/saksham2001/PulseLoopiOS/raw/main/docs/ble-interaction.png)](/docs/ble-interaction.png) - -**The AI coach:** an agentic loop that calls tools to read your local data, then answers in a structured format. - -[![AI coach](https://github.com/saksham2001/PulseLoopiOS/raw/main/docs/AI-coach-design.png)](/docs/AI-coach-design.png) - ---- +> ๐Ÿ“š **Full hardware specs, per-model capability matrix, and buying guidance: +> [Supported hardware docs](https://saksham2001.github.io/PulseLoopiOS/hardware/).** ## Install & try it @@ -224,50 +150,15 @@ A public TestFlight beta is coming soon. Sign up on the ### ๐Ÿ› ๏ธ Build from source (Xcode) -**Requirements** - -- Xcode 16+ and an iOS 18+ device (Bluetooth and Live Activities need a real -device โ€” the simulator can't reach the ring). -- A compatible `56ff` or Colmi/Yawell BLE ring. -- An OpenAI or Gemini API key (for the Coach features). - -**Run it** - -1. Open `PulseLoop.xcodeproj` in Xcode. -2. Select the `PulseLoop` scheme and your physical device as the run target. -3. Set your own **Team** and a unique **Bundle Identifier** under -*Signing & Capabilities* (the Live Activity extension target needs this too). -4. Build & run (`โŒ˜R`). -5. On first launch, complete onboarding, then keep the ring nearby โ€” the app -auto-scans and connects when Bluetooth powers on. -6. To enable the Coach, open **Settings โ†’ Coach** and paste your API key. It's -stored in the iOS Keychain and never leaves the device except to call the model. -Pick a provider and model. +You'll need Xcode 16+, an iOS 18+ device, a compatible `56ff` or Colmi/Yawell +ring, and (optionally) an OpenAI or Gemini API key for the Coach. Open +`PulseLoop.xcodeproj`, set your **Team** + a unique **Bundle Identifier**, then +build & run on your device. -**Demo data (no ring required)** - -You can explore the UI without hardware: **Settings โ†’ "Reseed demo data"**, or -launch with the `-seedDemo YES` argument. - ---- - -## Privacy - -PulseLoop is built local-first, which is the whole point: - -- **No vendor cloud, no account.** The app talks to the ring directly over BLE. -- **Your data stays on your phone**, persisted locally with SwiftData. -- **AI Coach is off by default and optional.** You can use the app without it, and it is disabled by default in the settings. -- **Nothing leaves the device** except a coach question you explicitly ask โ€” -that single request goes to whichever LLM provider you configured, with the API -key you supply. -- **API keys live in the iOS Keychain.** - -> โš ๏ธ PulseLoop is not a medical device and is not a substitute for professional -> medical advice. Treat all readings as approximate. Always consult a clinician -> for health concerns. - ---- +> ๐Ÿ“š **Full step-by-step build, signing, and demo-data instructions: +> [Getting started โ€” iOS](https://saksham2001.github.io/PulseLoopiOS/getting-started/ios/).** +> Building on Android? See the +> [Android guide](https://saksham2001.github.io/PulseLoopiOS/getting-started/android/). ## Contributing @@ -285,52 +176,9 @@ that should land on Android too. Adding a new ring? The device-agnostic driver layer in `RingProtocol/` is the place to start โ€” ping us in Discord and we'll point you at the right files. ---- - -## Goals / Roadmap - -> Up-to-date plans and what's shipping next now live in the -> [Releases](https://github.com/saksham2001/PulseLoopiOS/releases) and the -> [Discord](#community). High-level direction: - -- [ ] **On-device LLM integration** โ€” run the coach against a local model -(Apple Foundation Models / a quantized on-device LLM) so the app works with -no API key, no network, and full privacy. -- [ ] **Support more cheap rings and other wearables** โ€” generalize the BLE protocol layer to -handle other low-cost ring families beyond the `56ff` devices. -- [ ] **Custom ring firmware** โ€” open firmware to unlock features the stock -ring won't do, e.g. automatic activity/workout detection, higher-rate -sampling, and richer sensor access. -- [ ] **Better onboarding** โ€” smoother first-run pairing, permission, and -setup journey. -- [ ] **LLM tool-call transparency** โ€” surface exactly which tools the coach -called and what data it read, so every answer is auditable. -- [ ] **Multimodal coach input** โ€” let the coach accept image and voice input (e.g. snap a meal, speak a question). -- [ ] **Apple Health integration** โ€” sync data with Apple Health. - ---- - -## Project layout - -``` -PulseLoop/ -โ”œโ”€ RingProtocol/ BLE client + packet decoding for the ring -โ”œโ”€ Models/ SwiftData models (vitals, sleep, activity, coach) -โ”œโ”€ Services/ Sync, workouts, GPS, derived summaries -โ”œโ”€ Coach/ The LLM coach: orchestration, tools, prompts, notifications -โ”‚ โ”œโ”€ Orchestration/ Agentic turn loop, tool execution, fallbacks -โ”‚ โ”œโ”€ Tools/ Retrieval, analysis, charts, memory, web search, actions -โ”‚ โ”œโ”€ OpenAI/ Responses API client -โ”‚ โ”œโ”€ Gemini/ Google Gemini client -โ”‚ โ””โ”€ Notifications/ Daily AI check-ins -โ”œโ”€ Views/ SwiftUI screens (Today, Vitals, Sleep, Activity, Coach) -โ””โ”€ DesignSystem/ Charts, components, theming - -PulseLoopLiveActivity/ Live Activity + Dynamic Island widget -PulseLoopTests/ Unit tests -``` - ---- +> ๐Ÿ“š The [roadmap](https://saksham2001.github.io/PulseLoopiOS/project/roadmap/) and +> [architecture / project layout](https://saksham2001.github.io/PulseLoopiOS/project/architecture/) +> now live in the docs. ## Acknowledgements @@ -339,8 +187,6 @@ PulseLoopTests/ Unit tests - Everyone who's filed an issue, opened a PR, or reported a device โ€” see the [contributors graph](https://github.com/saksham2001/PulseLoopiOS/graphs/contributors). ---- - ## License This project is licensed under [Creative Commons Attribution 4.0 International (CC BY 4.0)](https://github.com/saksham2001/PulseLoopiOS/blob/main/LICENSE). diff --git a/docs/assets/logo.svg b/docs/assets/logo.svg new file mode 100644 index 0000000..4c59d0f --- /dev/null +++ b/docs/assets/logo.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/docs/getting-started/android.md b/docs/getting-started/android.md new file mode 100644 index 0000000..60cc1da --- /dev/null +++ b/docs/getting-started/android.md @@ -0,0 +1,95 @@ +--- +title: Getting Started โ€” Android +description: Install and build PulseLoop for Android, and what the Android port adds. +--- + +# Getting Started on Android + +PulseLoop has a sister project for Android: +**[foureight84/PulseLoopAndroid](https://github.com/foureight84/PulseLoopAndroid)**. + +The two ports are developed hand in hand and share the same BLE protocol work, so +a fix or a newly decoded sensor on one platform usually lands on the other. The +Android build is written in **Jetpack Compose + Material 3** with **Room** for +persistence, and adds several platform-specific niceties on top of the shared +feature set. + +!!! info "Pick a ring first" + PulseLoop talks to a real Bluetooth ring. Check the + [supported hardware](../hardware/index.md) before you start โ€” both + ports connect to the same rings. + +## :material-android: Install + +The Android app is distributed from the +[PulseLoopAndroid repository](https://github.com/foureight84/PulseLoopAndroid). +Check that repo's releases and README for the latest APK and install +instructions. + +## :material-hammer-wrench: Build from source + +!!! note "Build steps live in the Android repo" + Android build instructions are maintained in the + [PulseLoopAndroid README](https://github.com/foureight84/PulseLoopAndroid). + The outline below is the typical Android Studio flow; **follow the Android + repo's README for the authoritative, up-to-date steps.** + + + +1. Clone [foureight84/PulseLoopAndroid](https://github.com/foureight84/PulseLoopAndroid). +2. Open the project in **Android Studio**. +3. Let Gradle sync, then connect a physical Android device โ€” Bluetooth LE needs + real hardware. +4. Build & run the app module to your device. +5. On first launch, grant Bluetooth/Location permissions and keep the ring nearby. +6. To enable the Coach, open **Settings** and add your OpenAI or Gemini API key. + It's stored in `EncryptedSharedPreferences` and only used to call the model + you choose. + +## What the Android port adds + +Beyond the shared dashboards and AI Coach, the Android build includes extra +features that aren't (yet) in the iOS app: + +- **Full `0x24` sensor decoding** โ€” fatigue, stress, blood sugar, and HRV from + the combined-measurement packet. +- **Ring configuration & calibration** โ€” user profile (age/sex/height/weight), + BP cuff-reference calibration, and a blood-sugar lab offset, all in Settings. +- **Bind/unbind protocol** โ€” proper ring claiming on connect and release on + forget, so the ring re-advertises for other apps. +- **Connection reliability** โ€” keepalive pings, a write-ACK timeout, and a + connection watchdog that prevents silent disconnects. +- **Vitals detail screens** โ€” tap any metric for a trend chart, period selector, + stat tiles, and a color-coded threshold bar. +- **Threshold bars everywhere** โ€” color-coded reference ranges (Good โ†’ Normal โ†’ + Borderline โ†’ High) on every vitals panel. +- **Combined measurement button** โ€” one tap for BP + SpOโ‚‚ + stress + fatigue + + blood sugar with a countdown. +- **Pull-to-refresh** โ€” triggers an immediate ring sync from the Today dashboard. + +For the complete, current breakdown, see the +[iOS vs Android comparison](../platforms/ios-vs-android.md). + +## Architecture at a glance + +| Aspect | Android | +| --- | --- | +| UI | Jetpack Compose + Material 3 | +| Persistence | Room (SQLite) | +| BLE | `android.bluetooth.le` | +| HTTP | OkHttp | +| Key storage | `EncryptedSharedPreferences` | +| Background work | WorkManager | +| Charts | Custom Compose Canvas | + +See the [Architecture](../project/architecture.md) page for how both ports map +onto the same data flow. + +## Next steps + +- [Supported hardware](../hardware/index.md) โ€” what each ring can do. +- [iOS vs Android](../platforms/ios-vs-android.md) โ€” where the ports differ today. +- [Contributing](../project/contributing.md) โ€” coordinate cross-platform work in + the [Discord](https://discord.gg/t9y85ebaKD). +- Looking for iOS? See [Getting Started on iOS](ios.md). diff --git a/docs/getting-started/ios.md b/docs/getting-started/ios.md new file mode 100644 index 0000000..31cf67e --- /dev/null +++ b/docs/getting-started/ios.md @@ -0,0 +1,83 @@ +--- +title: Getting Started โ€” iOS +description: Install PulseLoop on iOS via TestFlight or build it from source in Xcode. +--- + +# Getting Started on iOS + +PulseLoop for iOS is a native SwiftUI app with SwiftData persistence, Live +Activities, and a Dynamic Island widget. There are two ways to run it: the +upcoming public TestFlight beta, or building from source in Xcode. + +!!! info "Pick a ring first" + PulseLoop talks to a real Bluetooth ring. Before you start, check the + [supported hardware](../hardware/index.md) to make sure your ring + is one PulseLoop can drive. No ring yet? You can still explore the whole app + with [demo data](#demo-data-no-ring-required). + +## :material-apple: TestFlight beta + +A public TestFlight beta is coming soon. Sign up on the +[Discord](https://discord.gg/t9y85ebaKD) to get the invite link. An IPA release +is also planned. + +## :material-hammer-wrench: Build from source (Xcode) + +### Requirements + +- **Xcode 16+** on macOS. +- An **iOS 18+ physical device** โ€” Bluetooth and Live Activities need real + hardware, so the simulator can't reach the ring. +- A compatible `56ff` or Colmi/Yawell BLE ring (see + [supported rings](../hardware/index.md)). +- An **OpenAI or Gemini API key** โ€” only needed for the AI Coach features. + +### Run it + +1. Open `PulseLoop.xcodeproj` in Xcode. +2. Select the **`PulseLoop`** scheme and your physical device as the run target. +3. Under **Signing & Capabilities**, set your own **Team** and a unique **Bundle + Identifier**. + + !!! warning "The Live Activity extension needs this too" + The `PulseLoopLiveActivity` extension target is a *separate* target โ€” + give it your team and a unique bundle ID as well, or the build will fail + to sign. + +4. Build & run (`โŒ˜R`). +5. On first launch, complete onboarding, then keep the ring nearby โ€” the app + auto-scans and connects when Bluetooth powers on. +6. To enable the Coach, open **Settings โ†’ Coach** and paste your API key, then + pick a provider and model. The key is stored in the iOS Keychain and never + leaves the device except to call the model you chose. + +### Demo data (no ring required) + +You can explore the whole UI and coach without any hardware: + +- **Settings โ†’ "Reseed demo data"**, or +- Launch with the `-seedDemo YES` argument. + +## Running the tests + +The unit tests in `PulseLoopTests/` are hermetic โ€” in-memory SwiftData and a +mocked client, so they need no network and no secrets. + +- In Xcode: `โŒ˜U`. +- From the CLI: + + ```sh + xcodebuild test \ + -project PulseLoop.xcodeproj \ + -scheme PulseLoop \ + -destination 'platform=iOS Simulator,name=iPhone 16' + ``` + +CI runs this exact suite (plus SwiftLint) on every PR. + +## Next steps + +- [Supported hardware](../hardware/index.md) โ€” what each ring can do. +- [Architecture](../project/architecture.md) โ€” how the app is put together. +- [Contributing](../project/contributing.md) โ€” add a ring driver or improve the coach. +- Looking for Android? See [Getting Started on Android](android.md). diff --git a/docs/hardware/colmi.md b/docs/hardware/colmi.md new file mode 100644 index 0000000..4563c60 --- /dev/null +++ b/docs/hardware/colmi.md @@ -0,0 +1,173 @@ +--- +title: Colmi / Yawell (QRing) +description: >- + The $15โ€“30 QRing ring family (R02/R0x/R1x/H59) โ€” Nordic-UART protocol, skin + temperature, REM sleep, and continuous background sync. +--- + +# Colmi / Yawell (QRing) + +**PulseLoop support: โœ… Supported** (R11 tested; rest implemented, needs testing ๐Ÿงช) + +The QRing family โ€” manufactured by Yawell and most commonly sold under the +**Colmi** brand. These $15โ€“30 rings speak a Nordic-UARTโ€“based protocol and bring +sensors the cheaper [56ff / Jring](jring.md) lacks: skin temperature, REM sleep, +HRV, stress, and continuous background sync. + +## At a glance + +| | Detail | +|---|---| +| **SoC** | Realtek RTL8762 family (Realtek AB2026 on R11) | +| **Bluetooth** | BLE 5.0 | +| **PPG sensor** | Vcare VC30F (red + green dual LED) on R10/R11/R12 | +| **Accelerometer** | STK8321 / ST LIS2DOC | +| **Battery / life** | 15โ€“18 mAh ยท ~4โ€“7 days | +| **Waterproof** | IP68 / 3ATMโ€“5ATM (varies by model) | +| **Price** | $15โ€“30 | +| **Protocol** | Nordic-UART QRing (`6e40fff0` / `de5bf728`), 16-byte frames, cleartext | +| **App** | QRing (R11 also: Da Rings) | +| **Custom firmware** | โœ… on R02/R03 (BXMicro); โš ๏ธ unknown on R10/R12 | + +## Manufacturer + +- **Shenzhen Yawell Intelligent Technology Co., Ltd.** (est. 2016, Shenzhen) +- 3 factories, 16 assembly lines, 500+ workers, 100+ R&D engineers +- Largest smart ring factory in South China (5,000 mยฒ, established 2024) +- 150K+ monthly smart ring shipments +- OEM/ODM for Lenovo, Nokia, Skyworth, Noise, Titan, Fire Boltt +- First smart ring launched: 2023 +- Official app: **QRing** (by Yawell) +- **Colmi** (Shenzhen Colmi Technology Co., Ltd.) is the most popular licensed brand selling Yawell's QRing rings +- Website: [yawellfit.com](https://www.yawellfit.com/), [colmi.com](https://www.colmi.com/) + +## Protocol + +| Property | Value | +|---|---| +| **BLE family** | Nordic-UART (`6e40fff0` / `de5bf728`) | +| **App** | QRing | +| **Frame size** | 16 bytes (checksum) | +| **Encryption** | None | + +## Models โ€” QRing platform + +| Model | CPU | Bluetooth | Battery | Waterproof | Display | Sensors | Notes | +|---|---|---|---|---|---|---|---| +| **R02** | Realtek RTL8762 | BLE 5.0 | Varies | IP68/3ATM | No | Unknown | Entry-level, "highly supported" per Gadgetbridge | +| **R03** | Realtek RTL8762 | BLE 5.0 | Varies | Unknown | No | Unknown | | +| **R06** | Realtek RTL8762 | BLE 5.0 | Varies | Unknown | No | Unknown | | +| **R07** | Realtek RTL8762 | BLE 5.0 | Varies | Unknown | No | Unknown | | +| **R09** | Realtek RTL8762 | BLE 5.0 | Varies | Unknown | No | Unknown | | +| **R10** | RTL8762 ESF | BLE 5.0 | 17 mAh | 5ATM | No | Vcare VC30F + STK8321 | Charging case: 200 mAh | +| **R12** | Realtek RTL8762 | BLE 5.0 | 15/18 mAh | IP68 + 1ATM | Yes | Vcare VC30F + ST LIS2DOC | Newest (2025), 4g weight | + +### Yawell-branded QRing models + +- R05, R10, R11, H59 โ€” all use the same QRing protocol + +## Colmi R11 โ€” QRing-Compatible with Fidget Shell + +The Colmi R11 uses a Realtek AB2026 SoC rather than the RTL8762 found in other QRing models, +but speaks the same Nordic-UART QRing protocol. It pairs with both the **Da Rings** app and the +**QRing** app. + +| Component | Detail | +|---|---| +| **CPU** | Realtek AB2026 | +| **Bluetooth** | BLE 5.0 | +| **PPG sensor** | Vcare VC30F (red + green dual LED) | +| **Accelerometer** | STK8321 (3-axis MEMS) | +| **Battery** | 15 mAh (sizes 8โ€“9) / 18 mAh (sizes 10โ€“13) | +| **Charging case** | 200 mAh | +| **Waterproof** | IP68 + 5ATM | +| **Build** | Stainless steel casing with fidget-spinner outer shell | +| **Apps** | Da Rings or QRing (Android 5.1+ / iOS 12.0+) | + +PulseLoop matches R11 rings via the `R11C?_[0-9A-F]{4}$` pattern in the Colmi QRing driver. +Capabilities should match the R10 (same VC30F + STK8321 sensor pair). + +## Sensors + +### Vcare VC30F + +The VC30F is the PPG bio-sensor used in R10, R11, and R12: + +- **Red + green LED emitters** โ€” dual wavelength for HR and SpOโ‚‚ +- **Integrated photodiode** โ€” detects reflected light with ambient light rejection +- **Analog front-end (AFE)** โ€” filters and amplifies raw signal +- **Digital controller** โ€” outputs processed pulse data +- Available on JLCPCB's parts library (traceable component) +- Real-world accuracy: within 1 BPM of medical-grade BP monitor (per R12 review) + +### ST LIS2DOC (R12) / STK8321 (R10, R11) + +3-axis MEMS accelerometer for: + +- Step counting and gesture detection +- Wear detection (wake on motion) +- Raw acceleration data for sleep and activity algorithms + +## Capabilities per model + +| Capability | R10 | R12 | R11 | Other QRingยน | +|---|---|---|---|---| +| **Heart rate โ€” spot** | โœ… | โœ… | โœ… | ๐Ÿงช | +| **Heart rate โ€” history** | โœ… | โœ… | โœ… | ๐Ÿงช | +| **Heart rate โ€” live** | โœ… | โœ… | โœ… | ๐Ÿงช | +| **SpOโ‚‚ โ€” history** | โœ… | โœ… | โœ… | ๐Ÿงช | +| **SpOโ‚‚ โ€” spot** | โ€”ยฒ | โ€”ยฒ | โ€”ยฒ | โ€”ยฒ | +| **Steps / distance / calories** | โœ… | โœ… | โœ… | ๐Ÿงช | +| **Sleep stages** (light/deep/awake) | โœ… | โœ… | โœ… | ๐Ÿงช | +| **REM sleep** | โœ… | โœ… | โœ… | ๐Ÿงช | +| **HRV** | โœ… | โœ… | โœ… | ๐Ÿงช | +| **Stress** | โœ… | โœ… | โœ… | ๐Ÿงช | +| **Body temperature** | โœ… | โœ… | โœ… | ๐Ÿงช | +| **Battery level** | โœ… | โœ… | โœ… | ๐Ÿงช | +| **Find device** | โœ… | โœ… | โœ… | ๐Ÿงช | +| **Blood pressure** | โŒ | โŒ | โŒ | โŒ | +| **Blood sugar** | โŒ | โŒ | โŒ | โŒ | + +ยน R02, R03, R06, R07, R09 + Yawell R05, R10, R11, H59 +ยฒ Colmi family has no on-demand SpOโ‚‚ reading; SpOโ‚‚ is all-day background only +ยณ Colmi has no blood pressure or blood sugar support. Its `userPreferences` (gender/age/height/weight) is for general health metric tuning only โ€” not for BP/BS computation. + +### What the Colmi family CAN do (that 56ff cannot) + +- REM sleep detection +- Body temperature (skin temperature sensor) +- HRV +- Stress scoring +- Continuous background sync (autonomous notifications while worn) + +## Hackability + +### ๐Ÿ† Full-Stack Hackable: Colmi R02 / R03 / R06 + +Per Hackaday's deep-dive by Aaron Christophel, the Colmi R02 is the most hacker-friendly ring: + +| What | Detail | +|---|---| +| **Custom firmware** | Flashable via BLE OTA โ€” **no signing, no encryption** | +| **Debug interface** | SWD pads accessible (scrape epoxy to expose) | +| **MCU** | BXMicro chip, 512 KB flash, 200 KB RAM | +| **SDK** | [BXMicro SDK3](https://gitee.com/BXMicro/SDK3) | +| **Reference FW** | [atc1441/ATC_RF03_Ring](https://github.com/atc1441/ATC_RF03_Ring) | +| **App protocol** | Documented in PulseLoop + Gadgetbridge | +| **Price** | $15โ€“25 | + +The manufacturer publishes firmware update images with no authenticity checks โ€” upload whatever you want over BLE. Combined with SWD debugging, this is the closest thing to an open-source smart ring in production. + +### ๐Ÿฅ‰ Protocol-Documented: the wider QRing family + +- โœ… BLE protocol reverse-engineered (PulseLoop + Gadgetbridge) +- โœ… Nordic-UART based, unencrypted +- โœ… Custom app possible (PulseLoop already does it) +- โš ๏ธ Custom firmware: confirmed possible on R02/R03 (BXMicro); unknown for R10/R12 (Realtek RTL8762) +- **Price:** $15โ€“30 + +--- + +See the [hardware overview](index.md) for the full cross-manufacturer comparison +tables, or the [Jring / 56ff](jring.md) page for the cheaper option (the only one +with BP/blood sugar). diff --git a/docs/hardware/index.md b/docs/hardware/index.md new file mode 100644 index 0000000..da8c07f --- /dev/null +++ b/docs/hardware/index.md @@ -0,0 +1,246 @@ +--- +title: Supported Hardware +description: >- + Hardware specs, capabilities, and hackability for every smart ring PulseLoop + supports โ€” shared across the iOS and Android ports. +--- + +# Supported Hardware + +PulseLoop is built around a **device-agnostic driver layer**, so each supported +ring declares exactly what it can do and the app shows only those features. This +section breaks the hardware down by manufacturer. + +!!! abstract "About these pages" + This is a cross-platform reference shared by both the iOS and Android ports โ€” + they drive the same rings over the same reverse-engineered BLE protocols. + Compiled from project documentation, web research, product pages, and + teardowns. *Last updated: 2026-06-25.* + +!!! warning "No affiliation" + PulseLoop has no affiliation with the sellers or manufacturers of any ring + listed here. Listings are for convenience only โ€” links may break, sellers may + swap hardware under the same name, and your unit may behave differently. Buy + at your own risk and treat any data the ring produces as approximate. + +## Browse by manufacturer + +
+ +- :material-ring: __Jring / 56ff__ + + --- + + The $7โ€“12 commodity ring (keeprapid OEM). Custom `56ff` protocol. The only + PulseLoop-supported ring with blood pressure and blood sugar. + + [:octicons-arrow-right-24: Jring / 56ff](jring.md) + +- :material-ring: __Colmi / Yawell (QRing)__ + + --- + + The $15โ€“30 QRing family โ€” R02/R0x/R1x/H59. Nordic-UART protocol, skin + temperature, REM sleep, and continuous background sync. + + [:octicons-arrow-right-24: Colmi / Yawell](colmi.md) + +- :material-help-circle-outline: __SIMSONLAB__ + + --- + + Not supported โ€” unknown protocol on a Phyplus PHY6222 SoC, with no public + reverse engineering. Documented here for reference. + + [:octicons-arrow-right-24: SIMSONLAB](simsonlab.md) + +- :material-crown-outline: __Premium rings__ + + --- + + Oura, Ultrahuman, and RingConn. Not currently supported (Ultrahuman's + protocol is documented and on the roadmap). Documented for reference. + + [:octicons-arrow-right-24: Premium rings](premium.md) + +
+ +## Supported Rings โ€” Hardware Specs + +!!! info "Legend" + - โœ… โ€” yes / supported + - โŒ โ€” no / not supported + - โ“ โ€” unknown + +| | 56ff / Jring | Colmi R02/R03/etc | Colmi R10 | Colmi R12 | Colmi R11 | +|---|---:|---:|---:|---:|---:| +| **SoC** | Renesas DA14531 | Realtek RTL8762 | RTL8762 ESF | Realtek RTL8762 | Realtek AB2026 | +| **Architecture** | ARM Cortex-M0 | ARM | ARM | ARM | ARM | +| **Bluetooth** | BLE 5.x | BLE 5.0 | BLE 5.0 | BLE 5.0 | BLE 5.0 | +| **PPG sensor** | Unknown (HR/SpOโ‚‚) | Unknown | Vcare VC30F | Vcare VC30F | Vcare VC30F | +| **PPG LEDs** | Unknown | Unknown | Red + green (dual) | Red + green (dual) | Red + green (dual) | +| **Accelerometer** | Yes | Unknown | STK8321 | ST LIS2DOC | STK8321 | +| **Skin temperature** | โŒ | โ“ | โœ… | โœ… | โœ… | +| **Battery** | Unknown | Varies | 17 mAh | 15โ€“18 mAh | 15โ€“18 mAhยน | +| **Battery life** | Unknown | Varies | ~4โ€“7 days | ~4โ€“7 days | ~4โ€“7 days | +| **Charging case** | โŒ | โŒ | โœ… (200 mAh) | โŒ | โœ… (200 mAh) | +| **Display** | โŒ | โŒ | โŒ | โœ… | โŒ | +| **Waterproof** | Varies by seller | IP68 / 3ATM | 5ATM | IP68 + 1ATM | IP68 + 5ATM | +| **Weight** | Unknown | Unknown | Unknown | ~4 g | Unknown | +| **Price** | $7โ€“12 | $15โ€“25 | $15โ€“25 | ~$30 | ~$15โ€“25 | +| **Protocol** | Custom 56ff | Nordic-UART QRing | Nordic-UART QRing | Nordic-UART QRing | Nordic-UART QRingยฒ | +| **Frame size** | Fixed 20 bytes | 16 bytes (checksum) | 16 bytes (checksum) | 16 bytes (checksum) | 16 bytes (checksum) | +| **Encryption** | None | None | None | None | None | +| **FW OTA** | โœ… Renesas SUOTA | โœ… BLE OTA (no sign) | โ“ | โ“ | โ“ | +| **Custom firmware** | โœ… (SR08 ref) | โœ… (RF03 ref) | โ“ | โ“ | โ“ | +| **PulseLoop support** | โœ… | โœ… | โœ… | โœ… | โœ… | + +ยน 15 mAh for sizes 8โ€“9, 18 mAh for sizes 10โ€“13. +ยฒ Works with the QRing app; also has a companion "Da Rings" app. Matched by Colmi driver. + +## Supported Rings โ€” Capabilities + +| Capability | 56ff / Jring | Colmi R02/etc | Colmi R10 | Colmi R12 | Colmi R11 | +|---|---:|---:|---:|---:|---:| +| Heart rate โ€” spot | โœ… | โœ… | โœ… | โœ… | โœ… | +| Heart rate โ€” history | โœ… | โœ… | โœ… | โœ… | โœ… | +| Heart rate โ€” live | โœ… | โœ… | โœ… | โœ… | โœ… | +| SpOโ‚‚ โ€” history | โœ… | โœ… | โœ… | โœ… | โœ… | +| SpOโ‚‚ โ€” spot | โœ… | โŒยน | โŒยน | โŒยน | โŒยน | +| Steps / distance / calories | โœ… | โœ… | โœ… | โœ… | โœ… | +| Sleep (light/deep/awake) | โœ… | โœ… | โœ… | โœ… | โœ… | +| REM sleep | โŒ | โœ… | โœ… | โœ… | โœ… | +| Blood pressure | โœ…ยฒ | โŒ | โŒ | โŒ | โŒ | +| Blood sugar | โœ…ยณ | โŒ | โŒ | โŒ | โŒ | +| HRV | โœ… | โœ… | โœ… | โœ… | โœ… | +| Stress | โœ… | โœ… | โœ… | โœ… | โœ… | +| Fatigue | โœ… | โœ… | โœ… | โœ… | โœ… | +| Skin temperature | โŒ | โœ… | โœ… | โœ… | โœ… | +| Battery level | โœ… | โœ… | โœ… | โœ… | โœ… | +| Find device | โœ… | โœ… | โœ… | โœ… | โœ… | +| Continuous background sync | โŒ | โœ… | โœ… | โœ… | โœ… | +| FW update via app | โœ… | โœ… | โ“ | โ“ | โ“ | + +ยน Colmi family has no on-demand SpOโ‚‚ reading; SpOโ‚‚ is all-day background only. +ยฒ Direct PPG sensor reading, no user profile required. +ยณ Profile-derived estimate from sex/age/height/weight, not a real glucometer reading. + +## Not Supported by PulseLoop + +| Ring | Reason | +|---|---| +| **SIMSONLAB LA380-YJ** | Unknown protocol (PHY6222 SoC), no reverse engineering โ€” see [SIMSONLAB](simsonlab.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) | + +--- + +## Platform Overview + +Multiple hardware platforms span from $7 commodity rings to $350 premium devices: + +### Budget / Commodity Rings + +| Platform | SoC | Protocol | App | Price | Hackable | +|---|---|---|---|---|---| +| **[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 R11](colmi.md#colmi-r11-qring-compatible-with-fidget-shell)** | Realtek AB2026 | Nordic-UART QRing | QRing / Da Rings | ~$15โ€“25 | โœ… App (untested) | +| **[SIMSONLAB](simsonlab.md)** | Phyplus PHY6222 | Unknown | SIMSONLAB app | ~$10โ€“20 | โŒ | + +### Premium Rings + +| Platform | SoC | Protocol | App | Price | Subscription | Hackable | +|---|---|---|---|---|---|---| +| **[Oura Gen 4](premium.md#oura-ring-gen-3-gen-4)** | Nordic nRF52840 | Encrypted proprietary | Oura app | $349 | **$5.99/mo required** | โŒ | +| **[Ultrahuman Ring Air](premium.md#ultrahuman-ring-air)** | nRF52840 + STM32G0 | Documented (Gadgetbridge) | Ultrahuman | $349 | โŒ None | โœ… App protocol | +| **[RingConn Gen 2 Air](premium.md#ringconn-gen-2-gen-2-air)** | Unknown (Nordic likely) | Proprietary | RingConn | $199 | โŒ None | โŒ | + +--- + +## Hackability Summary + +A breakdown of which rings can be used with custom software or firmware. For the +full detail, see each manufacturer's page. + +| Ring | Custom App | Custom Firmware | Price | +|---|---|---|---| +| **[Colmi R02/R03](colmi.md)** | โœ… PulseLoop, Gadgetbridge | โœ… OTA, SWD, SDK | $15โ€“25 | +| **[56ff / Jring](jring.md)** | โœ… PulseLoop, Gadgetbridge | โœ… SUOTA, open-source FW | $7โ€“12 | +| **[Colmi R10/R12](colmi.md)** | โœ… PulseLoop, Gadgetbridge | โ“ Unknown (Realtek locked?) | $15โ€“30 | +| **[Ultrahuman Ring Air](premium.md#ultrahuman-ring-air)** | โœ… Gadgetbridge protocol | โŒ nRF locked | $349 | +| **[RingConn Gen 2](premium.md#ringconn-gen-2-gen-2-air)** | โŒ No public protocol | โŒ | $199โ€“299 | +| **[Oura Ring](premium.md#oura-ring-gen-3-gen-4)** | โŒ Encrypted BLE | โŒ | $349 + sub | +| **[SIMSONLAB](simsonlab.md)** | โŒ Unknown protocol | โŒ | $10โ€“20 | + +### Open-Source DIY Platforms + +| Project | Detail | +|---|---| +| **[Open Ring](https://github.com/stawiski/open-ring)** | Open-source hardware + firmware reference design | +| **KuoQuo's smart ring dev board** | nRF-based I2C sensor platform, designed for firmware hacking | +| **[ATC_SR08_Ring](https://github.com/atc1441/ATC_SR08_Ring)** | Open-source firmware for 56ff/Jring hardware | +| **[ATC_RF03_Ring](https://github.com/atc1441/ATC_RF03_Ring)** | Open-source firmware for Colmi R02/R03 hardware | +| **[ringverse/protocol](https://github.com/ringverse/protocol)** | Community reverse engineering of smart ring protocols | + +--- + +## Quick Comparison + +### Sensor quality + +| | VC30F (Colmi R10/R12) | HX3602 (SIMSONLAB) | Unknown PPG (56ff) | +|---|---|---|---| +| **LEDs** | Red + green (dual) | Unknown | Unknown | +| **SpOโ‚‚ capable** | โœ… (red LED) | โ“ | โœ… | +| **Datasheet** | Public (JLCPCB) | None found | None found | +| **Verified accuracy** | ยฑ1 BPM vs medical device | No testing found | No testing found | + +### Chipset comparison + +| | DA14531 (56ff) | RTL8762 (Colmi QRing) | AB2026 (Colmi R11) | PHY6222 (SIMSONLAB) | +|---|---|---|---|---| +| **Vendor** | Renesas | Realtek | Realtek | Phyplus | +| **Architecture** | ARM Cortex-M0 | ARM | ARM | ARM Cortex-M0 | +| **Bluetooth** | BLE 5.x | BLE 5.0 | BLE 5.2 | BLE 5.1 | +| **Memory** | Unknown | Unknown | Unknown | 512 KB built-in | +| **Known from** | Jring, KeepFit, RWfit, Tag | Colmi R02โ€“R10, R12, Yawell | Colmi R11 | SIMSONLAB LA380-YJ, various watches | + +### Which to choose? + +| If you want... | Pick | +|---|---| +| **Cheapest possible** ($7โ€“12) | [56ff / Jring](jring.md) | +| **Most sensors** (temp, HRV, REM, stress) | [Colmi R10 or R12](colmi.md) ($15โ€“30) | +| **Best battery** | [Colmi R10](colmi.md) (17 mAh + 200 mAh case, no display) | +| **On-ring display** | [Colmi R12](colmi.md) | +| **Best waterproofing** | [Colmi R10 or R11](colmi.md) (5ATM) | +| **Best HR accuracy** | [Colmi R10/R12](colmi.md) (VC30F sensor, verified accuracy) | +| **Works with PulseLoop today** | [56ff Jring](jring.md) or [Colmi QRing family](colmi.md) | + +--- + +## References + +- **56ff protocol reverse-engineering writeup**: [sakshambhutani.xyz/hacking/2_hacking/](https://sakshambhutani.xyz/hacking/2_hacking/) +- **PulseLoop protocol docs** (in the iOS repo): `docs/ring-protocol.md`, `docs/protocol-discoveries.md`, `docs/keepfit-protocol-complete.md` +- **Gadgetbridge Yawell/Colmi page**: [gadgetbridge.org/gadgets/wearables/yawell/](https://gadgetbridge.org/gadgets/wearables/yawell/) +- **Gadgetbridge KeepFit PR**: [#5326](https://codeberg.org/Freeyourgadget/Gadgetbridge/pulls/5326) +- **Open-source ring firmware**: [atc1441/ATC_SR08_Ring](https://github.com/atc1441/ATC_SR08_Ring) +- **Official KeepFit SDK/protocol**: [keeprapid/krwatch](https://github.com/keeprapid/krwatch) +- **Ring reverse engineering**: [ringverse/protocol](https://github.com/ringverse/protocol) +- **Colmi R12 review** (Walter Shillington, Medium, 2026-03-05) +- **Colmi R10 review** (ShaunChng.com) +- **SIMSONLAB LA380-YJ user manual** (device.report) +- **PHY6222 datasheet** (Phyplus Technologies) +- **Yawell company profile**: [yawellfit.com](https://www.yawellfit.com/p/about.html) +- **Colmi official**: [colmi.com](https://www.colmi.com/), [colmi.info](https://www.colmi.info/) +- **Ultrahuman Protocol (Gadgetbridge)**: [gadgetbridge.org/internals/specifics/ultrahuman-protocol/](https://gadgetbridge.org/internals/specifics/ultrahuman-protocol/) +- **Hackaday โ€” Hackable Smart Ring**: [New Part Day: A Hackable Smart Ring](https://hackaday.com/2024/06/16/new-part-day-a-hackable-smart-ring/) +- **ATC_RF03_Ring (custom FW for Colmi R02)**: [github.com/atc1441/ATC_RF03_Ring](https://github.com/atc1441/ATC_RF03_Ring) +- **Open Ring (open-source HW/FW)**: [github.com/stawiski/open-ring](https://github.com/stawiski/open-ring) +- **Ultrahuman Ring Air teardown**: [makingstudio.blog](https://makingstudio.blog/2024/09/10/ultrahuman-ring-air-teardown/) +- **Oura Ring teardown (Becky Stern)**: [beckystern.com](https://beckystern.com/2022/04/17/oura-ring-teardown-gen-3-and-gen-2/) +- **Oura Ring 4 deep-dive (EDN)**: [edn.com](https://www.edn.com/the-oura-ring-4-does-one-more-deliver-much-if-any-more/) +- **Wareable best smart rings 2026**: [wareable.com](https://www.wareable.com/fashion/best-smart-rings-1340) diff --git a/docs/hardware/jring.md b/docs/hardware/jring.md new file mode 100644 index 0000000..ddbf8a5 --- /dev/null +++ b/docs/hardware/jring.md @@ -0,0 +1,132 @@ +--- +title: Jring / 56ff +description: >- + The $7โ€“12 commodity smart ring (keeprapid OEM) with the custom 56ff protocol โ€” + the only PulseLoop-supported ring with blood pressure and blood sugar. +--- + +# Jring / 56ff + +**PulseLoop support: โœ… Supported & tested** + +The cheapest ring PulseLoop drives โ€” a $7โ€“12 commodity device built by the +keeprapid OEM and white-labeled under many brands. It speaks a custom `56ff` BLE +protocol and is the **only** PulseLoop-supported ring that reports blood pressure +and (profile-derived) blood sugar. + +## At a glance + +| | Detail | +|---|---| +| **SoC** | Renesas DA14531 (ARM Cortex-M0) | +| **Bluetooth** | BLE 5.x | +| **PPG sensor** | Unknown (HR/SpOโ‚‚, no skin temperature) | +| **Accelerometer** | Yes | +| **Battery / life** | Unknown | +| **Waterproof** | Varies by seller | +| **Price** | $7โ€“12 | +| **Protocol** | Custom 56ff (SXR KeepFit SDK), fixed 20-byte frames, cleartext | +| **App** | Jring / KeepFit | +| **Custom firmware** | โœ… Renesas SUOTA (SR08 reference) | + +## Manufacturer + +- **keeprapid.com** (ShenXinRui / ๆทฑๆ–ฐ้”) โ€” Chinese OEM +- White-labels under brands: **Jring, KeepFit, JYouPro, RWfit, Tag** +- SDK: SXR KeepFit SDK (`com.sxr.sdk.ble.keepfit`) + +## Hardware + +| Component | Detail | +|---|---| +| **SoC** | Renesas DA14531 (Dialog DA145XX family) | +| **SoC architecture** | ARM Cortex-M0 | +| **PPG sensor** | Unknown (PPG HR/SpOโ‚‚, no skin temperature) | +| **Accelerometer** | Yes (steps, sleep stages, activity) | +| **Memory** | Unknown | +| **Weight** | Unknown | +| **Waterproof** | Unknown (varies by seller) | + +## Protocol + +The `56ff` protocol was reverse-engineered from scratch โ€” see the +[full writeup](https://sakshambhutani.xyz/hacking/2_hacking/) for the BLE +teardown and how the packet formats were decoded. + +| Property | Value | +|---|---| +| **Service UUID** | `000056ff-0000-1000-8000-00805f9b34fb` | +| **Write characteristic** | `000033f3-...` | +| **Notify characteristic** | `000033f4-...` | +| **Additional chars** | `0x33F5`, `0x33F6` (purpose unknown) | +| **Secondary service** | `0x57FF` | +| **SUOTA service** | `0000fef5-...` (firmware OTA) | +| **Frame size** | Fixed 20 bytes | +| **Encryption** | None (cleartext) | +| **Standard BLE services** | DIS (`0x180A`), Heart Rate Service (`0x180D`) | + +## Capabilities + +| Capability | Status | Notes | +|---|:---:|---| +| Heart rate โ€” spot / live / history | โœ… | BPM | +| SpOโ‚‚ โ€” spot / history | โœ… | | +| Steps / distance / calories | โœ… | | +| Sleep (light / deep / awake) | โœ… | No REM | +| Blood pressure | โœ… | Direct sensor reading via `0x23`/`0x24`, no user profile required | +| Blood sugar | โœ… | Profile-derived estimate (not a real glucometer) โ€” requires user profile | +| Stress | โœ… | 0โ€“100 | +| Fatigue | โœ… | 0โ€“100 | +| HRV | โœ… | ms | +| Battery level | โœ… | | +| Find device | โœ… | | +| REM sleep | โŒ | | +| Skin temperature | โŒ | No sensor โ€” official app shows 0ยฐC/32ยฐF placeholder | +| Continuous background sync | โŒ | Command-response only, ~20s idle timeout | + +!!! info "Blood sugar requires a user profile" + Blood sugar is a profile-derived *estimate* from sex/age/height/weight (sent + via `0x02` `CMD_SET_USER_INFO`), not a real glucometer reading โ€” changing the + profile changes the value. + +### What the 56ff ring CANNOT do + +- REM sleep detection +- Body temperature (no skin temperature sensor) +- Continuous streaming (command-response only, ~20s idle timeout) + +## Known models + +- **SR08** โ€” open-source reference hardware ([atc1441/ATC_SR08_Ring](https://github.com/atc1441/ATC_SR08_Ring)) +- Generic "SMART_RING" โ€” sold on AliExpress for $7โ€“12 + +## Firmware + +- Firmware check: `http://download.keeprapid.com/apps/smartband/jring/autoupdater/{device_id}/update.json` +- Binary download: `http://download.keeprapid.com:8181/docs/jring/an_{p1}_{p2}1` +- Flashing: Renesas SUOTA (`0xFEF5` service) to DA14531 +- Version format: `"003A002AV138"` (status hex + V + version number) +- **All API traffic is HTTP (not HTTPS) โ€” unencrypted** + +## Background behavior + +- Idle timeout: ~20 seconds of inactivity +- Keepalive: `0x3A` ping/pong +- Binding: `0x4B` custom protocol (NOT OS `createBond()`) +- Official app runs periodic background sync + +## Hackability + +**๐Ÿฅˆ Protocol-Documented** + +- โœ… Protocol fully reverse-engineered ([writeup](https://sakshambhutani.xyz/hacking/2_hacking/); also the iOS repo's `docs/ring-protocol.md`) +- โœ… Open-source firmware skeleton: [atc1441/ATC_SR08_Ring](https://github.com/atc1441/ATC_SR08_Ring) +- โœ… Official SDK protocol doc: `ๆทฑๆ–ฐ้”่“็‰™ๅ่ฎฎv3.0.docx` (keeprapid/krwatch) +- โœ… Cleartext BLE, no encryption +- โœ… Renesas SUOTA for firmware OTA +- **Price:** $7โ€“12 + +--- + +See the [hardware overview](index.md) for the full cross-manufacturer comparison +tables, or the [Colmi / Yawell](colmi.md) family for the more sensor-rich option. diff --git a/docs/hardware/premium.md b/docs/hardware/premium.md new file mode 100644 index 0000000..78445b9 --- /dev/null +++ b/docs/hardware/premium.md @@ -0,0 +1,102 @@ +--- +title: Premium Rings +description: >- + Oura, Ultrahuman, and RingConn โ€” premium rings not currently supported by + PulseLoop. Ultrahuman's protocol is documented and on the roadmap. +--- + +# Premium Rings + +**PulseLoop support: โŒ Not currently supported** + +These rings compete with Oura on hardware quality but mostly without the +subscription lock-in. None are supported by PulseLoop today, though the +[Ultrahuman Ring Air](#ultrahuman-ring-air) is the most promising candidate โ€” its +protocol is fully documented and it's on the [roadmap](../project/roadmap.md). + +| Ring | Why it isn't supported (yet) | +|---|---| +| **Oura Gen 3/4** | Encrypted BLE, proprietary protocol, subscription required | +| **Ultrahuman Ring Air** | Not yet implemented โ€” but the protocol *is* documented | +| **RingConn Gen 2 / Air** | No public protocol, no reverse engineering | + +## Oura Ring (Gen 3 / Gen 4) + +| Component | Gen 3 (2021) | Gen 4 (2024) | +|---|---|---| +| **SoC** | Nordic nRF52840 (Cortex-M4F, 64 MHz, 1 MB flash, 256 KB RAM) | Nordic nRF52840 | +| **PPG** | 2ร— green LED + red/IR multi-chip LED + 2ร— photodiodes | 2 clusters ร— green/red/IR LEDs + 3ร— photodiodes, 18-path multi-wavelength | +| **Temperature** | NTC thermistor (indirect) | NTC thermistor (indirect) | +| **Accelerometer** | 3-axis | 3-axis | +| **Battery** | 16 mAh (Grepow YE160723G) | 26 mAh | +| **Battery life** | 4โ€“7 days | Up to 8 days | +| **Battery management** | TI BQ25120A | Unknown | +| **Charging** | Wireless inductive | Wireless inductive | +| **Price** | $299+ (discontinued) | $349 + **$5.99/mo subscription required** | +| **BLE** | Encrypted, proprietary | Encrypted, proprietary | +| **Open docs** | โŒ Completely closed | โŒ Completely closed | + +**Hackability:** โŒ Fully locked down โ€” encrypted BLE, proprietary protocol, no +public docs, subscription-gated features. + +## Ultrahuman Ring Air + +| Component | Detail | +|---|---| +| **BLE SoC** | Nordic nRF52840 (Cortex-M4F, 64 MHz, 1 MB flash, 256 KB RAM, BLE 5.0) | +| **Coprocessor** | STM32G0 (STMicro) โ€” dedicated sensor DSP | +| **Sensors** | PPG (HR, HRV, SpOโ‚‚), skin temperature, 3-axis accelerometer | +| **Battery** | ~4โ€“6 days | +| **Price** | $349, **no subscription** | +| **Open docs** | โœ… BLE protocol fully documented by Gadgetbridge | + +**Dual-MCU architecture:** The nRF52840 handles BLE + main processing, while the STM32G0 coprocessor runs sensor data processing and power management โ€” arguably more capable than Oura's single-MCU design. + +**BLE Protocol (Gadgetbridge):** + +- Device name: `UH_XXXXXXXXXXXXXXXX` +- Device State service: `86f61000-f706-58a0-95b2-1fb9261e4dc7` โ€” battery level, charging state, temperature +- Command service: `86f65000-f706-58a0-95b2-1fb9261e4dc7` โ€” opcodes for set time, get recordings, airplane mode, reset, power saving +- All opcodes and payload formats documented + +**Hackability:** ๐Ÿฅˆ Protocol-documented. + +- โœ… Full BLE protocol documented on [Gadgetbridge](https://gadgetbridge.org/internals/specifics/ultrahuman-protocol/) +- โœ… Every service UUID, opcode, and payload layout is public +- โœ… You can write a custom app that talks directly to the ring โ€” no vendor app needed +- โŒ Custom firmware unlikely โ€” nRF52840 typically has readback protection enabled + +!!! tip "On the roadmap" + Because the Ultrahuman protocol is fully public, it's the most realistic + premium ring for PulseLoop to add next. See the + [roadmap](../project/roadmap.md). + +## RingConn Gen 2 / Gen 2 Air + +| Component | Detail | +|---|---| +| **Sensors** | PPG (HR, HRV, SpOโ‚‚), skin temperature, 3-axis accelerometer | +| **Battery** | 10+ days (class-leading) | +| **Price** | Gen 2: $299 / Gen 2 Air: **$199**, **no subscription** | +| **Open docs** | โŒ No known reverse engineering or public protocol docs | + +**Hackability:** โŒ Fully locked down โ€” no known reverse engineering, no public +protocol docs. + +## Premium Ring Comparison + +| | Oura Gen 4 | Ultrahuman Air | RingConn G2 Air | +|---|---|---|---| +| **SoC** | nRF52840 | nRF52840 + STM32G0 | Unknown (likely Nordic) | +| **Architecture** | Cortex-M4F | Cortex-M4F + Cortex-M0 | Unknown | +| **PPG** | Custom 18-path | Multi-LED | Multi-LED | +| **Temperature** | NTC thermistor | โœ… Skin temp | โœ… Skin temp | +| **Battery** | 8 days | 4โ€“6 days | 10+ days | +| **Subscription** | **$5.99/mo required** | โŒ None | โŒ None | +| **Price** | $349 + sub | $349 | $199 | +| **Protocol open** | โŒ | โœ… (Gadgetbridge) | โŒ | +| **Custom firmware** | โŒ | โŒ (nRF locked) | โŒ | + +--- + +See the [hardware overview](index.md) for the rings PulseLoop currently supports. diff --git a/docs/hardware/simsonlab.md b/docs/hardware/simsonlab.md new file mode 100644 index 0000000..7c19ae6 --- /dev/null +++ b/docs/hardware/simsonlab.md @@ -0,0 +1,59 @@ +--- +title: SIMSONLAB +description: >- + The SIMSONLAB LA380-YJ โ€” not supported by PulseLoop. Unknown protocol on a + Phyplus PHY6222 SoC with no public reverse engineering. +--- + +# SIMSONLAB + +**PulseLoop support: โŒ Not supported** + +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 +compatible with any of PulseLoop's existing drivers. It's documented here for +reference and in case the protocol is ever decoded. + +!!! warning "Why it isn't supported" + Unknown, custom BLE protocol โ€” different from both the `56ff` and QRing + families โ€” with no public reverse engineering or datasheet to work from. + +## Manufacturer + +- **SHARE AUDIO HONG KONG LIMITED** (developer of SIMSONLAB app) +- Product appears on Shein, AliExpress, TikTok +- Model: **LA380-YJ** (2025) + +## Hardware + +| Component | Detail | +|---|---| +| **CPU** | Phyplus PHY6222 | +| **SoC architecture** | ARM Cortex-M0 32-bit | +| **Bluetooth** | BLE 5.1 | +| **Memory** | 512 KB built-in, 64 KB SRAM, 128 KBโ€“8 MB flash | +| **HR sensor** | HX3602 | +| **Battery** | 15 mAh (magnetic charging) | +| **Standby** | 10โ€“15 days | +| **Weight** | ~5 g | +| **Material** | Stainless steel outer, epoxy resin body | +| **Waterproof** | IP68 | +| **App** | SIMSONLAB app (iOS + Android) | + +## Protocol + +- **Unknown** โ€” completely different from both 56ff and QRing +- Custom BLE protocol (likely) +- Not compatible with PulseLoop's existing drivers + +## HX3602 Sensor + +- Generic/low-cost heart rate sensor +- Used across many cheap Chinese wearables (SIMSONLAB rings, NKX19 watches, DaintyDelight smartwatches) +- No standalone public datasheet found +- LED configuration unknown (likely single wavelength vs VC30F's dual red+green) +- No independent accuracy testing available + +--- + +See the [hardware overview](index.md) for the rings PulseLoop *does* support. diff --git a/docs/AI-coach-design.png b/docs/images/AI-coach-design.png similarity index 100% rename from docs/AI-coach-design.png rename to docs/images/AI-coach-design.png diff --git a/docs/ble-interaction.png b/docs/images/ble-interaction.png similarity index 100% rename from docs/ble-interaction.png rename to docs/images/ble-interaction.png diff --git a/docs/system-architecture.png b/docs/images/system-architecture.png similarity index 100% rename from docs/system-architecture.png rename to docs/images/system-architecture.png diff --git a/docs/thumbnail.png b/docs/images/thumbnail.png similarity index 100% rename from docs/thumbnail.png rename to docs/images/thumbnail.png diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..d4baa39 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,131 @@ +--- +title: PulseLoop +description: >- + An LLM-native, local-first health app that turns a cheap Bluetooth smart ring + into a real, conversational health tracker โ€” on iOS and Android. +hide: + - navigation + - toc +--- + +
+ +# PulseLoop + +

+A $20 ring + an LLM, instead of a $300 subscription wearable. +PulseLoop turns a cheap Bluetooth "smart ring" into a real, +local-first health tracker with an optional conversational AI coach โ€” +and it runs on both iOS and Android. +

+ +
+[Get started on iOS](getting-started/ios.md){ .md-button .md-button--primary } +[Get started on Android](getting-started/android.md){ .md-button } +[Join the Discord :fontawesome-brands-discord:](https://discord.gg/t9y85ebaKD){ .md-button } +
+ +
+ +!!! tip "Why PulseLoop exists" + The goal is to prove that a **$20 ring + an LLM** can replace a **$300 + subscription wearable** โ€” and that the "intelligence" should live on your + phone, not behind a paywall. No vendor cloud. No account. Your data stays on + your device. + +--- + +## Choose your platform + +
+ +- :material-apple: __iOS__ + + --- + + Native SwiftUI, SwiftData persistence, Live Activities, and a Dynamic Island + widget. Build from source in Xcode, or join the upcoming TestFlight beta. + + [:octicons-arrow-right-24: iOS getting started](getting-started/ios.md) + +- :material-android: __Android__ + + --- + + Jetpack Compose + Material 3, Room persistence, and extra connection-reliability + and calibration features. Developed hand-in-hand with the iOS port. + + [:octicons-arrow-right-24: Android getting started](getting-started/android.md) + +
+ +--- + +## What it does + +- **Connects to the ring over BLE** and decodes its proprietary protocol โ€” heart + rate, SpOโ‚‚, steps, distance, calories, sleep stages, and raw packets. +- **Today / Vitals / Sleep / Activity dashboards** built natively per platform, + backed by on-device storage. +- **AI Coach** โ€” an agentic loop (OpenAI or Google Gemini) with tools for data + retrieval, on-the-fly analysis, chart generation, long-term memory, and web + search. Every answer is grounded in *your* actual ring data. +- **Workout recording** with live heart-rate zones, GPS route maps, and a live + activity widget. +- **Daily check-in notifications** generated by the coach from your recent trends. + +--- + +## The two ports + +PulseLoop ships as two apps that are developed together and share the same +reverse-engineered BLE protocol work, so a fix or a newly decoded sensor on one +platform usually lands on the other. + +| | iOS | Android | +| --- | --- | --- | +| Repo | [saksham2001/PulseLoopiOS](https://github.com/saksham2001/PulseLoopiOS) | [foureight84/PulseLoopAndroid](https://github.com/foureight84/PulseLoopAndroid) | +| UI | SwiftUI | Jetpack Compose + Material 3 | +| Storage | SwiftData | Room (SQLite) | + +See the full [iOS vs Android comparison](platforms/ios-vs-android.md) for an +up-to-date breakdown of where the two ports differ. + +--- + +## Where to next + +
+ +- :material-ring: __Supported hardware__ + + Which rings work, what each one can do, and how hackable they are. + + [:octicons-arrow-right-24: Supported rings](hardware/index.md) + +- :material-map-marker-path: __Roadmap__ + + What's shipping next across both platforms. + + [:octicons-arrow-right-24: Roadmap](project/roadmap.md) + +- :material-sitemap: __Architecture__ + + How data flows from the ring into local storage and out to the coach. + + [:octicons-arrow-right-24: Architecture](project/architecture.md) + +- :material-shield-lock: __Privacy__ + + Local-first by design โ€” what leaves your device and what never does. + + [:octicons-arrow-right-24: Privacy](project/privacy.md) + +
+ +--- + +!!! warning "Not a medical device" + PulseLoop is not a medical device and is not a substitute for professional + medical advice. Treat all readings as approximate, and always consult a + clinician for health concerns. diff --git a/docs/platforms/ios-vs-android.md b/docs/platforms/ios-vs-android.md new file mode 100644 index 0000000..99ae127 --- /dev/null +++ b/docs/platforms/ios-vs-android.md @@ -0,0 +1,210 @@ +--- +title: iOS vs Android +description: >- + A living comparison of where the PulseLoop iOS and Android ports differ โ€” + protocol coverage, settings, UI, and architecture. +--- + +# iOS vs Android + +The iOS and Android ports of PulseLoop are developed hand in hand and share the +same reverse-engineered BLE protocol work. They're not identical, though โ€” each +platform sometimes lands a feature first. This page is a **living comparison** of +where they currently differ. + +!!! note "This is a snapshot" + Things change fast. When a feature lands on both ports, it leaves this page. + *Last updated: 2026-06-25.* For the canonical state, check each repo: + [iOS](https://github.com/saksham2001/PulseLoopiOS) ยท + [Android](https://github.com/foureight84/PulseLoopAndroid). + +Today, the Android port is ahead in a few areas โ€” fuller protocol decoding, ring +configuration/calibration, connection reliability, and richer vitals UI. The +sections below break that down. + +## Protocol & Ring Communication + +### Extended 0x24 Combined Sensor Decoding + +iOS only decodes bytes[1]-[4] (HR + systolic + diastolic + SpOโ‚‚) from the `0x24` combined +measurement packet. Android decodes the full 9 bytes โ€” matching the official Jring app's +`onReceiveSensorData(i, i2, i3, i4, i5, i6, i7, i8)`: + +| Byte | Metric | iOS | Android | +|------|--------|:---:|:-------:| +| 1 | Heart Rate (BPM) | โœ… | โœ… | +| 2 | Systolic (mmHg) | โœ… | โœ… | +| 3 | Diastolic (mmHg) | โœ… | โœ… | +| 4 | SpOโ‚‚ (%) | โœ… | โœ… | +| 5 | **Fatigue** (0โ€“100) | โ€” | โœ… | +| 6 | **Stress** (0โ€“100) | โ€” | โœ… | +| 7 | **Blood Sugar** (mmol/L ร—10 โ†’ mg/dL) | โ€” | โœ… | +| 8 | **HRV** (ms) | โ€” | โœ… | + +**iOS also mislabels the opcodes:** `spo2ResultProgress = 0x24` and `spo2Complete = 0x28`. +These are actually combined sensor data and blood data per the APK decompilation โ€” not +SpOโ‚‚-only packets. The separate SpOโ‚‚ commands are `0x3E`/`0x3F`. + +### Ring Configuration Commands (Android-only) + +| Command | Opcode | Purpose | +|---------|--------|---------| +| **User profile** | `0x02` | Sends age/sex/height/weight to ring. Android pushes real profile from Settings on every connect; iOS sends hardcoded defaults (age 25, male, 184cm, 90kg) with no way to configure. | +| **BP calibration** | `0x33` | Sends reference systolic/diastolic to ring for on-device offset correction. iOS has no equivalent. | +| **App identity** | `0x48` | Claims the ring with a persistent app ID so it streams data to PulseLoop. Prevents mute behavior after another app claimed the ring. iOS doesn't send this. | +| **Bind/unbind** | `0x4B` | Ring-driven pairing handshake (INIT โ†’ APP_START โ†’ ACK โ†’ SUCCESS). Proper unbind (UNBOND โ†’ UNBOND_ACK) on Forget so the ring re-advertises for other apps. iOS has no bind protocol. | +| **Keepalive ping** | `0x3A` | Prevents ring's ~20s idle disconnect. Android pings every 15s. iOS has no keepalive. | + +### Connection Reliability (Android-only) + +- **Keepalive ping** โ€” 15s interval prevents ring idle timeout +- **Write ACK timeout** โ€” 3s timeout unblocks command queue on missed ACKs +- **Connection watchdog** โ€” monitors GATT activity, forces reconnect after 10โ€“20s silence +- **Foreground reconnection** โ€” reconnects on app resume if GATT dropped during sleep +- **Stale-state guard** โ€” resets persisted connection state on app restart +- **Force-close stale GATT** โ€” explicitly disconnects/closes orphaned handles before new connection +- **No OS-level bonding** โ€” avoids Bluetooth status-bar icon and OS-level pairing instability +- **High-priority connection interval** โ€” requests priority on connect +- **Firmware discovery** โ€” scans all BLE services for firmware characteristics, not just standard DIS + +## Settings & Calibration + +### User Profile + +| | iOS | Android | +|---|---|---| +| **Profile form** | Not configurable โ€” hardcoded defaults always sent | Full form (age, sex, height, weight) in Settings | +| **Stored on-device** | N/A | Room database, never transmitted off-device | +| **Synced to ring** | Only hardcoded defaults at startup | Real profile pushed on connect + on save | +| **Colmi handling** | N/A | Form hidden with notice explaining Colmi doesn't need it | + +### BP Calibration + +| | iOS | Android | +|---|---|---| +| **Cuff reference entry** | Not available | Systolic/diastolic fields in Settings | +| **Sent to ring** | N/A | `0x33` command for on-device offset | +| **App-side display** | N/A | Applied in ViewModels | + +### Blood Sugar Calibration + +| | iOS | Android | +|---|---|---| +| **Lab reference entry** | Not available | mg/dL field + Calibrate button in Settings | +| **Offset method** | N/A | `glucoseOffsetMgdl = ref - latestRaw` | +| **Reset** | N/A | Reset button to clear calibration | + +## UI Differences + +### Vitals Dashboard + +| Feature | iOS | Android | +|---------|:---:|:---:| +| Threshold bars on every metric panel | โ€” | โœ… Color-coded (Good โ†’ Normal โ†’ Borderline โ†’ High) | +| Tap-through detail screens per metric | โ€” | โœ… Full trend view with period selector | +| Zone-colored trend charts | โ€” | โœ… Data points colored by threshold zone | +| Range/avg summaries on panels | โ€” | โœ… `Range: min โ€“ max ยท Avg: avg` | +| Combined measurement button | โ€” | โœ… One-tap BP+SpOโ‚‚+stress+fatigue+BS with countdown | +| Pull-to-refresh | โ€” | โœ… Triggers immediate ring sync | + +### Vitals Detail (tap on any metric) + +| Feature | iOS | Android | +|---------|:---:|:---:| +| Period selector (Today / Week / Month) | โ€” | โœ… | +| Date navigator (โ† โ†’ arrows) | โ€” | โœ… | +| Trend arrow + text (rising/falling/stable) | โ€” | โœ… | +| Stat tiles (Latest ยท Avg ยท Min ยท Max) | โ€” | โœ… | +| Threshold bar with zone legend | โ€” | โœ… | +| Metric explainer text | โ€” | โœ… | +| Medical disclaimer card | โ€” | โœ… | + +### Colmi Ring Handling + +| Feature | iOS | Android | +|---------|:---:|:---:| +| BP/blood sugar panels hidden for Colmi | โ€” | โœ… Capability-gated in Today and Vitals | +| Profile/calibration form hidden for Colmi | โ€” | โœ… Notice explaining features are 56ff-only | +| Measure button hidden for Colmi | โ€” | โœ… Gated on `supportsBP || supportsGlucose` | +| Colmi capabilities correctly declared | โ€” | โœ… Fixed (was incorrectly including BP/BS) | + +### Ring Management + +| Feature | iOS | Android | +|---------|:---:|:---:| +| Proper unbind on forget | โ€” | โœ… `0x4B` UNBOND โ†’ UNBOND_ACK before teardown | +| Connection state display | โ€” | โœ… Live status with battery % in Settings | +| Firmware version display | โ€” | โœ… Parsed from `0x0C`/`0xF6` + standard DIS | + +### Sleep View + +| Feature | iOS | Android | +|---------|:---:|:---:| +| Sleep stage breakdown (Deep/Light/Awake %) | โ€” | โœ… Color-coded percentage pills | +| Sleep coach insights | โ€” | โœ… Contextual chip-based recommendations | +| Sleep duration histogram chart | โ€” | โœ… | +| Sleep architecture stages chart | โ€” | โœ… | + +### Activity View + +| Feature | iOS | Android | +|---------|:---:|:---:| +| MetricThreshold reference ranges | โ€” | โœ… Color-coded for steps/calories/distance/active minutes | +| Active minutes card with trend | โ€” | โœ… | + +### Settings Screen + +| Feature | iOS | Android | +|---------|:---:|:---:| +| Profile (age/sex/height/weight) | โ€” | โœ… | +| BP calibration (systolic/diastolic) | โ€” | โœ… | +| Blood sugar calibration (mg/dL offset) | โ€” | โœ… | +| Unit system toggle (Metric / Imperial) | โ€” | โœ… | +| Profile sync to ring on save | โ€” | โœ… | +| Demo data seeder | โ€” | โœ… | +| Ring connection management | โ€” | โœ… Live status, firmware version, forget button | + +## Data Flow + +| Feature | iOS | Android | +|---------|:---:|:---:| +| Blood sugar (profile-derived) displayed | โ€” | โœ… mg/dL with app-side calibration offset | +| Fatigue metric displayed | โ€” | โœ… 0โ€“100 scale from 0x24 byte[5] | +| Sleep REM detection (Colmi) | โ€” | โœ… Via V2 big-data protocol | +| Skin temperature (Colmi) | โ€” | โœ… Via V2 big-data protocol | +| Heart rate history (0x16) multi-packet | โ€” | โœ… With sub-type routing and averaging | +| Reactive Room database with Flow | โ€” | โœ… Live data as ring syncs | +| Local-midnight-aligned day bucketing | โ€” | โœ… Consistent daily stats across timezones | +| Calibrated display pipeline | โ€” | โœ… Offsets applied in ViewModels before UI | + +## Architecture + +| Aspect | iOS | Android | +|--------|-----|---------| +| Persistence | SwiftData | Room (SQLite) with 18 entities, 14 DAOs | +| BLE | CoreBluetooth | android.bluetooth.le | +| UI | SwiftUI | Jetpack Compose + Material 3 | +| HTTP | URLSession | OkHttp | +| Key storage | Keychain | EncryptedSharedPreferences | +| Background work | BGTaskScheduler | WorkManager | +| Live Activity | WidgetKit / Dynamic Island | ForegroundService + notification | +| Charts | Swift Charts | Custom Compose Canvas | +| Maps | MapKit | Canvas polyline | +| Event bus | NotificationCenter | SharedFlow | +| Notifications | UNUserNotificationCenter | NotificationManager + WorkManager | +| DI | @Environment | Manual (ViewModel factories) | + +## Summary: What Android has that iOS doesn't + +1. **Full 0x24 decoding** โ€” fatigue, stress, blood sugar, HRV +2. **Ring configuration** โ€” user profile (0x02), BP calibration (0x33), app ID (0x48) +3. **Bind/unbind protocol** (0x4B) โ€” proper ring claiming and release +4. **Keepalive + connection watchdog** โ€” prevents silent disconnects +5. **Profile & calibration settings** โ€” age/sex/height/weight, BP cuff reference, glucose offset +6. **Colmi-aware UI** โ€” hides BP/BS panels and profile form for Colmi rings +7. **Vitals detail screens** โ€” period selector, trend charts, stat tiles, threshold bars +8. **Threshold bars on all vitals panels** โ€” color-coded reference ranges +9. **Combined measurement button** โ€” one-tap BP+SpOโ‚‚+stress+fatigue+BS with countdown +10. **Pull-to-refresh** โ€” immediate ring sync from Today dashboard +11. **Reactive Room database** โ€” Flow-based live data throughout the app +12. **Calibrated display pipeline** โ€” offsets applied before UI rendering diff --git a/docs/project/architecture.md b/docs/project/architecture.md new file mode 100644 index 0000000..0b0399f --- /dev/null +++ b/docs/project/architecture.md @@ -0,0 +1,75 @@ +--- +title: Architecture +description: How data flows from the ring into local storage and out to the AI coach. +--- + +# Architecture + +PulseLoop is built **local-first**: data flows up from the ring into local +storage on your phone, the coach reads sideways through tools, and the only thing +that ever leaves the device is a coach question you explicitly choose to ask. + +## System architecture + +Four layers on the phone. Data flows up from the ring into local storage; the +coach reads sideways through tools, and the only thing that leaves the device is a +coach question you choose to ask. + +![System architecture](../images/system-architecture.png) + +## The ring link + +One custom BLE service, fixed 20-byte cleartext packets, commands out and +notifications back. + +![Ring interaction](../images/ble-interaction.png) + +## The AI coach + +An agentic loop that calls tools to read your local data, then answers in a +structured format. Every answer is grounded in your actual ring data. + +![AI coach design](../images/AI-coach-design.png) + +## iOS project layout + +```text +PulseLoop/ +โ”œโ”€ RingProtocol/ BLE client + packet decoding for the ring +โ”œโ”€ Models/ SwiftData models (vitals, sleep, activity, coach) +โ”œโ”€ Services/ Sync, workouts, GPS, derived summaries +โ”œโ”€ Coach/ The LLM coach: orchestration, tools, prompts, notifications +โ”‚ โ”œโ”€ Orchestration/ Agentic turn loop, tool execution, fallbacks +โ”‚ โ”œโ”€ Tools/ Retrieval, analysis, charts, memory, web search, actions +โ”‚ โ”œโ”€ OpenAI/ Responses API client +โ”‚ โ”œโ”€ Gemini/ Google Gemini client +โ”‚ โ””โ”€ Notifications/ Daily AI check-ins +โ”œโ”€ Views/ SwiftUI screens (Today, Vitals, Sleep, Activity, Coach) +โ””โ”€ DesignSystem/ Charts, components, theming + +PulseLoopLiveActivity/ Live Activity + Dynamic Island widget +PulseLoopTests/ Unit tests +``` + +## Same data flow, two stacks + +Both ports map the same data flow onto their native platform stack. The ring +protocol layer is the shared core; everything above it is platform-native. + +| Layer | iOS | Android | +|-------|-----|---------| +| UI | SwiftUI | Jetpack Compose + Material 3 | +| Persistence | SwiftData | Room (SQLite) | +| BLE | CoreBluetooth | `android.bluetooth.le` | +| HTTP | URLSession | OkHttp | +| Key storage | Keychain | EncryptedSharedPreferences | +| Background work | BGTaskScheduler | WorkManager | +| Live Activity | WidgetKit / Dynamic Island | ForegroundService + notification | +| Charts | Swift Charts | Custom Compose Canvas | +| Maps | MapKit | Canvas polyline | +| Event bus | NotificationCenter | SharedFlow | +| Notifications | UNUserNotificationCenter | NotificationManager + WorkManager | + +For the full feature-level breakdown between the two ports, see +[iOS vs Android](../platforms/ios-vs-android.md). For the on-the-wire ring +protocol, see [Supported Rings](../hardware/index.md). diff --git a/docs/project/contributing.md b/docs/project/contributing.md new file mode 100644 index 0000000..b1e4e06 --- /dev/null +++ b/docs/project/contributing.md @@ -0,0 +1,127 @@ +--- +title: Contributing +description: How to get set up, the standards PRs are held to, and how to add a new ring. +--- + +# Contributing + +Thank you! PulseLoop is an open, privacy-first health app that turns a cheap +Bluetooth ring into a real, local-first health tracker. Contributions of all +kinds are welcome โ€” bug reports, new ring drivers, coach improvements, UI polish, +and docs. + +!!! tip "Start in the Discord" + The fastest way to get unstuck, claim an issue, or coordinate cross-platform + work is the [PulseLoop Discord](https://discord.gg/t9y85ebaKD). For anything + large, open an issue to discuss the approach **before** writing a lot of code. + +This page summarizes the workflow. The authoritative version lives in each repo: + +- iOS: [`CONTRIBUTING.md`](https://github.com/saksham2001/PulseLoopiOS/blob/main/CONTRIBUTING.md) + and [`CODE_OF_CONDUCT.md`](https://github.com/saksham2001/PulseLoopiOS/blob/main/CODE_OF_CONDUCT.md) +- Android: [PulseLoopAndroid](https://github.com/foureight84/PulseLoopAndroid) + +## Code of conduct + +This project follows a +[Code of Conduct](https://github.com/saksham2001/PulseLoopiOS/blob/main/CODE_OF_CONDUCT.md). +By participating, you're expected to uphold it. Please be kind. + +## Ways to contribute + +- **Report a bug** โ€” open a [bug report](https://github.com/saksham2001/PulseLoopiOS/issues/new?template=bug_report.yml). +- **Request a feature** โ€” open a [feature request](https://github.com/saksham2001/PulseLoopiOS/issues/new?template=feature_request.yml). +- **Add a wearable** โ€” open a [new wearable support](https://github.com/saksham2001/PulseLoopiOS/issues/new?template=new_wearable_support.yml) + issue, ideally with BLE service/characteristic UUIDs and packet captures. +- **Send a pull request** โ€” see below. + +## Development setup (iOS) + +**Requirements** + +- macOS with **Xcode 16+**. +- An **iOS 18+ physical device** for anything touching Bluetooth or Live + Activities โ€” the simulator cannot reach the ring. +- A compatible BLE ring (see [supported rings](../hardware/index.md)), + or use demo data if you don't have hardware. +- An OpenAI/Gemini API key only if you're working on the Coach. + +See [Getting Started on iOS](../getting-started/ios.md) for full build steps, and +[Getting Started on Android](../getting-started/android.md) for the Android flow. + +## Running the tests (iOS) + +The unit tests in `PulseLoopTests/` are **hermetic** โ€” in-memory SwiftData and a +mocked client (`sk-test`), so they need no network and no secrets. + +- In Xcode: `โŒ˜U`. +- From the CLI: + + ```sh + xcodebuild test \ + -project PulseLoop.xcodeproj \ + -scheme PulseLoop \ + -destination 'platform=iOS Simulator,name=iPhone 16' + ``` + +CI runs this exact suite on every PR. **Please add or update tests** for any +behavior you change โ€” especially decoders, capability gating, sleep/activity +math, and coach tools. + +## Code style (iOS) + +- We use **SwiftLint** (config in `.swiftlint.yml`); CI runs it on every PR. + Install locally with `brew install swiftlint` and run `swiftlint` from the repo + root. +- Match the surrounding code: SwiftUI views in `Views/`, models in `Models/`, etc. + Keep changes small and focused. +- Prefer clarity over cleverness. Comments should explain *why*, not *what*. + +## Adding support for a new wearable + +PulseLoop has a **device-agnostic driver layer** (`RingProtocol/` on iOS). Each +device declares the capabilities it supports, and the UI shows only those +features. To add a ring: + +1. **Identify it** โ€” advertised BLE name, primary service UUID, and the + write/notify characteristic UUIDs (use a scanner like LightBlue or nRF Connect). +2. **Decode the protocol** โ€” capture the 20-byte command/notification packets from + the vendor app and map them to metrics. Existing decoders (`RingDecoderTests`, + `ColmiDecoderTests`) are good references and good places to add coverage. +3. **Declare capabilities** โ€” give the driver the right capability set so the app + gates features correctly. +4. **Add tests** โ€” decoder round-trips and capability gating, following the + existing test files. +5. **Update the capability matrix** โ€” add the new model and its support status + (here and in the [Supported Rings](../hardware/index.md) page). + +You don't need the hardware to *start* โ€” a good packet capture in an issue lets +others help. Mark anything you couldn't verify on real hardware as ๐Ÿงช +("implemented, needs testing"). + +## Pull request process + +1. **Fork** the repo and create a branch from `main`: + `git checkout -b feature/short-description`. +2. Make your change, **add tests**, and make sure lint and the test suite pass + locally. +3. **Open a PR** against `main` and fill out the PR template. Link any related + issue (`Closes #123`). +4. **CI must be green** โ€” build, tests, and SwiftLint all pass. +5. **Review** โ€” the maintainer reviews and may request changes. One approving + review is required to merge. +6. Once approved and green, your PR gets merged. ๐ŸŽ‰ + +Keep PRs focused โ€” one logical change per PR is much easier to review. + +!!! warning "Privacy expectations" + PulseLoop's promise is that **your health data stays on your device**. Any PR + that changes what data leaves the device, or how it's stored, must call that + out clearly in the PR description and will get extra scrutiny. Never commit + secrets, API keys, or real personal health data. See [Privacy](privacy.md). + +## License + +By contributing, you agree that your contributions will be licensed under the +project's [CC BY 4.0](https://github.com/saksham2001/PulseLoopiOS/blob/main/LICENSE) +license. diff --git a/docs/project/privacy.md b/docs/project/privacy.md new file mode 100644 index 0000000..4f341fc --- /dev/null +++ b/docs/project/privacy.md @@ -0,0 +1,32 @@ +--- +title: Privacy +description: PulseLoop is local-first by design โ€” what leaves your device and what never does. +--- + +# Privacy + +PulseLoop is built **local-first**, which is the whole point. + +- **No vendor cloud, no account.** The app talks to the ring directly over + Bluetooth LE. +- **Your data stays on your phone**, persisted locally (SwiftData on iOS, Room on + Android). +- **AI Coach is off by default and optional.** You can use the app without it; it + is disabled by default in Settings. +- **Nothing leaves the device** except a coach question you explicitly ask โ€” that + single request goes to whichever LLM provider you configured, with the API key + you supply. +- **API keys are stored securely on-device** โ€” the iOS Keychain, or Android's + `EncryptedSharedPreferences`. + +!!! warning "Not a medical device" + PulseLoop is not a medical device and is not a substitute for professional + medical advice. Treat all readings as approximate. Always consult a clinician + for health concerns. + +## For contributors + +The promise that your health data stays on your device is a hard constraint. Any +change that affects what data leaves the phone, or how it's stored, must be called +out clearly in the PR description and will get extra scrutiny. Never commit +secrets, API keys, or real personal health data. See [Contributing](contributing.md). diff --git a/docs/project/roadmap.md b/docs/project/roadmap.md new file mode 100644 index 0000000..1aa98bf --- /dev/null +++ b/docs/project/roadmap.md @@ -0,0 +1,89 @@ +--- +title: Roadmap +description: Long-term direction and guiding principles for PulseLoop, across both the iOS and Android ports. +--- + +# Roadmap + +!!! tip "Where live planning happens" + Up-to-date plans and what's shipping next live in the + [Releases](https://github.com/saksham2001/PulseLoopiOS/releases) and the + [Discord](https://discord.gg/t9y85ebaKD). This page captures the long-term + direction shared across the project. + +## Principles + +These guide what we build and what we say no to. + +- **Privacy-first**: your health data stays on your device by default. +- **Subscription-free**: every feature, for everyone, no paywalls. +- **Open & transparent**: documented metrics and an auditable coach, no black boxes. +- **Hardware freedom**: cheap devices, your data, and eventually your own firmware. +- **Cross-platform**: one direction shared across iOS and Android. + +## Direction + +### More wearables, more freedom + +- **Open BLE standards**: heart rate (+ HRV), blood pressure, temperature, weight, + and glucose. Supporting the standards adds chest straps, BP cuffs, and scales with + little per-device work. +- **Reverse-engineered protocols**: more rings (Ultrahuman, RingConn, โ€ฆ) and + bands/watches (Amazfit/Zepp, Xiaomi) beyond today's `56ff` and Colmi families. +- **Device-driver SDK**: let contributors add a wearable without touching the core. + +### Own the hardware + +- Reverse-engineer ring firmware and the over-the-air update path. +- Load custom firmware safely: higher sampling rates, longer battery, and access + the stock app blocks. +- Unlock **raw PPG and accelerometer** signals: the basis for everything intelligent. + +### On-device intelligence + +- **Local LLM coach**: run against an on-device model: no API key, no network, full privacy. +- **Automatic workout detection**: recognize runs, rides, and walks with no manual start. +- **Proactive insights**: weekly trends and call-outs the coach surfaces for you. +- **Auditable coach**: show which tools the coach called and what data it read. +- **Personal baselines**: learn what's normal for you and flag meaningful changes. + +### Metrics you can trust + +- **Performance & recovery**: readiness, training/cardio load, HRV and resting-HR + trends, VOโ‚‚max. +- **Health signals**: illness early-warning from shifts in skin temperature, resting + heart rate, and respiration. +- **Cycle tracking**: menstrual cycle and BBT from skin temperature, computed on-device. +- **Energy balance**: calorie-burn estimation paired with food logging via an open + food database. + +### Your data, your way + +- **Optional sync**: Apple Health, Google Health Connect, Strava, Garmin; useful for + export and for cross-checking your readings. +- **Self-hosted export**: Home Assistant, InfluxDB/Grafana, MQTT, and open formats + (FIT, GPX, CSV, JSON). +- **Ownership by default**: your data is portable and never required to leave the device. + +### Everywhere you are + +- **Multiple wearables at once**: aggregate several devices into one picture. +- **watchOS companion**: glanceable data, or use a watch as another sensor. +- **Web app**: a third client alongside iOS and Android. + +## Cross-platform parity + +Because the iOS and Android ports share the same protocol work, a big part of the +roadmap is simply bringing the two ports to feature parity. The Android build is +currently ahead in several areas (fuller protocol decoding, calibration, +connection reliability, richer vitals UI). + +See [iOS vs Android](../platforms/ios-vs-android.md) for the current gap list - +much of it is fair game for contributors who want a well-scoped first task. + +## Want to help? + +- Skim the [open issues](https://github.com/saksham2001/PulseLoopiOS/issues), + especially anything tagged **good first issue**. +- Propose or claim work in the [Discord](https://discord.gg/t9y85ebaKD). Coordinate anything that should land on both platforms. +- See [Contributing](contributing.md) to get set up. \ No newline at end of file diff --git a/docs/stylesheets/extra.css b/docs/stylesheets/extra.css new file mode 100644 index 0000000..b8c5a58 --- /dev/null +++ b/docs/stylesheets/extra.css @@ -0,0 +1,125 @@ +/* =========================================================================== + PulseLoop brand polish for MkDocs Material. + Palette pulled from icon-source.svg + the app's DesignSystem: + violet #7C5CFF / #863bff / #7e14ff + lavender #EDE6FF / #D2CDFF / #8B7CFF + cyan #47BFFF / #2DD4D8 + slate #0E1118 / #080A0F / #0F141F + =========================================================================== */ + +:root { + --pl-violet: #7c5cff; + --pl-violet-deep: #5b3df0; + --pl-lavender: #d2cdff; + --pl-cyan: #47bfff; + --pl-cyan-deep: #2dd4d8; + --pl-ink: #0e1118; + --pl-ink-deep: #080a0f; +} + +/* Brand the primary + accent across both schemes. */ +[data-md-color-primary="deep-purple"] { + --md-primary-fg-color: var(--pl-violet); + --md-primary-fg-color--light: #8b7cff; + --md-primary-fg-color--dark: var(--pl-violet-deep); +} +[data-md-color-accent="cyan"] { + --md-accent-fg-color: var(--pl-cyan); +} + +/* A soft violetโ†’cyan glow on the top header, on both schemes. */ +.md-header { + background-image: linear-gradient( + 100deg, + var(--pl-violet-deep) 0%, + var(--pl-violet) 45%, + var(--pl-cyan) 130% + ); +} +.md-tabs { + background: transparent; +} + +/* Larger brand mark in the top navbar (Material defaults to 1.2rem). */ +.md-header__button.md-logo { + padding: 0.2rem; +} +.md-header__button.md-logo img, +.md-header__button.md-logo svg { + height: 2.2rem; + width: 2.2rem; +} + +/* ---- Dark scheme: lean into the "glow on slate" brand feel. ---- */ +[data-md-color-scheme="slate"] { + --md-default-bg-color: var(--pl-ink); + --md-default-bg-color--light: #11151f; + --md-typeset-a-color: var(--pl-lavender); + --md-footer-bg-color: var(--pl-ink-deep); +} + +/* Radial violet glow behind the main content, top-center โ€” echoes the icon. */ +[data-md-color-scheme="slate"] .md-main { + background: + radial-gradient( + 900px 420px at 50% -8%, + rgba(124, 92, 255, 0.16), + transparent 70% + ), + var(--md-default-bg-color); +} + +/* Links: lavender by default, cyan on hover. */ +.md-typeset a { + text-decoration-color: rgba(124, 92, 255, 0.4); +} +.md-typeset a:hover { + color: var(--pl-cyan); +} + +/* =========================================================================== + Home page "choose your platform" grid cards (attr_list + md_in_html). + Usage in markdown: wrap cards in
...
+ Material already ships .grid.cards; this just adds PulseLoop flavor. + =========================================================================== */ +.md-typeset .grid.cards > :is(ul, ol) > li, +.md-typeset .grid.cards > .card { + border: 1px solid rgba(124, 92, 255, 0.25); + border-radius: 0.6rem; + transition: border-color 160ms ease, box-shadow 160ms ease, transform 160ms ease; +} +.md-typeset .grid.cards > :is(ul, ol) > li:hover, +.md-typeset .grid.cards > .card:hover { + border-color: var(--pl-violet); + box-shadow: 0 8px 28px rgba(124, 92, 255, 0.22); + transform: translateY(-2px); +} + +/* Hero block on the landing page. */ +.pl-hero { + text-align: center; + padding: 1.2rem 0 0.4rem; +} +.pl-hero h1 { + font-weight: 800; + letter-spacing: -0.02em; + background: linear-gradient(92deg, var(--pl-lavender), var(--pl-cyan)); + -webkit-background-clip: text; + background-clip: text; + color: transparent; +} +.pl-hero .pl-tagline { + font-size: 1.05rem; + opacity: 0.85; + max-width: 46rem; + margin: 0.2rem auto 1rem; +} + +/* Buttons (Material .md-button) in a centered row for the hero CTAs. */ +.pl-cta { + display: flex; + flex-wrap: wrap; + gap: 0.6rem; + justify-content: center; + margin: 0.6rem 0 1.4rem; +} diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 0000000..bd32c0a --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,120 @@ +site_name: PulseLoop +site_description: >- + An LLM-native, local-first health app that turns a cheap Bluetooth smart ring + into a real, conversational health tracker โ€” on iOS and Android. +site_author: Saksham Bhutani +# TODO: set this to your real GitHub Pages URL once Pages is enabled. +# For a project site this is https://.github.io// +site_url: https://saksham2001.github.io/PulseLoopiOS/ + +repo_name: saksham2001/PulseLoopiOS +repo_url: https://github.com/saksham2001/PulseLoopiOS +edit_uri: edit/main/docs/ + +copyright: >- + Copyright © 2026 Saksham Bhutani โ€” PulseLoop is licensed under CC BY 4.0. + +theme: + name: material + language: en + logo: assets/logo.svg + favicon: assets/logo.svg + icon: + repo: fontawesome/brands/github + font: + text: Inter + code: JetBrains Mono + palette: + # Dark is the brand default (glow on slate). + - media: "(prefers-color-scheme: dark)" + scheme: slate + primary: deep purple + accent: cyan + toggle: + icon: material/brightness-4 + name: Switch to light mode + - media: "(prefers-color-scheme: light)" + scheme: default + primary: deep purple + accent: cyan + toggle: + icon: material/brightness-7 + name: Switch to dark mode + features: + - navigation.tabs + - navigation.tabs.sticky + - navigation.sections + - navigation.top + - navigation.instant + - navigation.instant.progress + - navigation.footer + - navigation.indexes + - content.code.copy + - content.tabs.link + - search.suggest + - search.highlight + - search.share + - toc.follow + +extra_css: + - stylesheets/extra.css + +markdown_extensions: + - abbr + - admonition + - attr_list + - def_list + - footnotes + - md_in_html + - tables + - toc: + permalink: true + - pymdownx.details + - pymdownx.highlight: + anchor_linenums: true + line_spans: __span + pygments_lang_class: true + - pymdownx.inlinehilite + - pymdownx.snippets + - pymdownx.superfences + - pymdownx.tabbed: + alternate_style: true + - pymdownx.tasklist: + custom_checkbox: true + - pymdownx.emoji: + emoji_index: !!python/name:material.extensions.emoji.twemoji + emoji_generator: !!python/name:material.extensions.emoji.to_svg + +plugins: + - search + +extra: + social: + - icon: fontawesome/brands/github + link: https://github.com/saksham2001/PulseLoopiOS + name: PulseLoop on iOS (GitHub) + - icon: fontawesome/brands/android + link: https://github.com/foureight84/PulseLoopAndroid + name: PulseLoop on Android (GitHub) + - icon: fontawesome/brands/discord + link: https://discord.gg/t9y85ebaKD + name: Join the PulseLoop Discord + +nav: + - Home: index.md + - Getting Started: + - iOS: getting-started/ios.md + - Android: getting-started/android.md + - Hardware: + - Overview: hardware/index.md + - Jring / 56ff: hardware/jring.md + - Colmi / Yawell: hardware/colmi.md + - SIMSONLAB: hardware/simsonlab.md + - Premium Rings: hardware/premium.md + - Platforms: + - iOS vs Android: platforms/ios-vs-android.md + - Project: + - Roadmap: project/roadmap.md + - Architecture: project/architecture.md + - Contributing: project/contributing.md + - Privacy: project/privacy.md diff --git a/requirements-docs.txt b/requirements-docs.txt new file mode 100644 index 0000000..0b9684a --- /dev/null +++ b/requirements-docs.txt @@ -0,0 +1,3 @@ +# Documentation site dependencies (MkDocs Material). +# Build locally with: pip install -r requirements-docs.txt && mkdocs serve +mkdocs-material>=9.5