Th0rgal/open_oura: a Rust toolkit for the Oura Ring (Gen 3/4/5) A Rust toolkit for reverse-engineering the Oura Ring's BLE protocol enables cloud-free data access from Gen 3/4/5 rings, including live heart rate, SpO2, sleep stages, and activity MET levels, bypassing Oura's cloud dependency. The project reproduces on-device PyTorch models for scores like Readiness and Sleep, but excludes proprietary model files. Reverse-engineering the Oura ring BLE protocol, plus an independent, cloud-free client that reads your data straight from the ring. Tested live against a Ring 3 Horizon and a Ring 5 pairing, auth, and event sync confirmed on both . Designed for Ring 3/4/5, which share the same GATT layout, packet framing, and authentication flow. Straight from the ring, with no Oura account: device info, battery, live heart rate IBI to BPM , latest HR / SpO2, and the full history-event stream. That stream carries raw PPG/IBI/temperature/motion/SpO2 samples plus the ring's on-device sleep stages, activity MET levels, and HRV. The ring itself does not emit the 0-100 Readiness / Sleep / Activity / Stress scores. But those are not computed in Oura's cloud either: they're computed on the phone by the native ecore engine and a set of on-device PyTorch models the same .pt we run here , then uploaded; the cloud only stores and syncs them back. So they're reproducible offline. The one genuine cloud-only step is workout auto-classification POST /api/activity-tagging/v2 . See docs/data-recovery-map.md /Th0rgal/open oura/blob/main/docs/data-recovery-map.md , , and /Th0rgal/open oura/blob/main/docs/algorithms/README.md docs/algorithms/README.md for what runs. /Th0rgal/open oura/blob/main/docs/model-runners.md docs/model-runners.md Those PyTorch models are Oura's proprietary IP and are NOT included in this repo gitignored under notes/models/ . The runners reference them by path; you decrypt and supply your own locally. Nothing model-related is committed or pushed. : the Rust client, split by concern crates/ oura-protocol decode, oura-link fetch, oura-analysis metrics, oura-store SQLite, oura-cli . Start here:and crates/README.md . docs/architecture.md : Python research bench for protocol exploration. tools/ oura protocol.py full command matrix, auth, danger-gated ops, JSONL capture and oura realtime listener.py .: protocol and reverse-engineering reference index below . docs/ : local-only, gitignored. The decompiled app and raw captures which may contain serials, MACs, and auth keys . reverse/ , captures/ cargo build --release ./target/release/oura scan ./target/release/oura --key-file key.hex info See crates/README.md /Th0rgal/open oura/blob/main/crates/README.md for all commands scan , pair , info , sync , latest , live-hr , accel , viz , game , features , rdata , events , redecode , sleep-analyze , sessions and the auth-key details. oura viz opens a real-time 3D motion visualizer in the browser; oura game is a tilt-controlled asteroid game driven by the ring. python3 -m venv .venv && .venv/bin/pip install -r requirements.txt .venv/bin/python tools/oura protocol.py --list State-changing and destructive commands are hidden behind --include-state and --include-danger . On macOS, grant Bluetooth permission to the terminal. : the protocol command reference requests, responses, auth, features , Ring 3. docs/horizon-ring3-protocol-cheatsheet.md : app internals, BLE constants, the auth operations, key generation, and nonce encryption. docs/android-app-reversing.md : what the ring emits vs what only the cloud computes. docs/data-recovery-map.md : when and how the app pulls each data channel, and the minimal client sync recipe. docs/sync-orchestration.md : Ring 5 BLE surface and first-contact findings. docs/ring-5-observations.md : the feature capabilities, runtime modes, what's on by default, and which event each enabled feature produces incl. what docs/ring-features.md experimental does — and doesn't .: running Oura's decrypted on-device models on your synced data — what runs activity, sleep, CVA, SpO2 vs what's blocked. docs/model-runners.md : decoding the raw PPG docs/cva-cardiovascular-age.md cva raw ppg data 0x81 and running the cardiovascular-age model.: turning the SpO2 R-ratio into a percentage with Oura's own calibration. docs/spo2-calibration.md : the DFU/OTA opcodes, the working cloud download pipeline + codename map, per-device encryption status, and why the firmware key is unreachable device-resident; not brute-forceable . docs/firmware-update.md : findings-only notes on the model/firmware encryption the "what", not the "how" — no keys, endpoints, or procedures . docs/security-observations.md : the fetch/interpret/apply crate layering and where to add things. docs/architecture.md : the on-device ecore metric algorithms scores, sleep, baselines and their porting status. docs/algorithms/README.md : porting event-body decoders from the native docs/native-decoder.md libringeventparser.so how the byte layouts were recovered with Ghidra . - Prefer passive, read-only requests. reset / DFU / factory-reset / flight-mode are gated behind explicit flags; do not send them during normal use. - App-gated operations need the ring's 16-byte auth key re-sent each connection . Captures and keys are gitignored. Never commit a key. ringverse Oura Ring 4 BLE notes: https://github.com/ringverse/protocol/blob/main/oura/BLE.md https://github.com/ringverse/protocol/blob/main/oura/BLE.md