Protocol Pal
Open methodology

How Protocol Pal computes your ring scores

Protocol Pal reads your Oura ring directly over Bluetooth and computes sleep, readiness, and activity scores locally on your device — no cloud, no membership required. This page documents every formula so you can verify the math.

✓ Computed on-device ⚠ Approximation — not Oura's official model Open source · MIT

Data tiers

Not all Oura features can be replicated from raw BLE data. We sort them into three tiers.

Tier 1 — Exact

Ring-computed metrics

The ring's firmware computes these; we decode the BLE packets.

  • Sleep hypnogram (5-min bins)
  • HRV (nightly avg + intervals)
  • Resting heart rate
  • SpO2, respiratory rate
  • Body temperature deviation
  • Steps, active calories
Tier 2 — Approximate

Locally computed 0–100 scores

Formula-based. ~±3–8 pts vs official after 14-day baseline. Labeled ~78 to distinguish from cloud scores.

  • Sleep Score
  • Readiness Score
  • Activity Score
  • Sleep debt
  • VO₂ max estimate
Tier 3 — Unavailable

Cloud ML models

These require Oura's proprietary PyTorch models or clinical data not in the BLE stream.

  • Resilience Score
  • Cardiovascular Age
  • Workout auto-detection
  • Cycle prediction

Data pipeline

BLE data flows through a typed pipeline before reaching the UI. All scoring happens in TypeScript and Rust on-device — nothing is sent to a server.

Oura Ring (Bluetooth)
  ↓  AES-128-ECB auth · TLV packet framing (open_oura, MIT)
OuraBlePlugin.java  ← Android GATT transport
  ↓  JNI bridge (Rust)
native/oura-jni     ← oura-protocol · oura-analysis
  ↓
bleEventMapper.ts   ← RingEventEntry[] → typed records
bleBaseline.ts      ← 30-day rolling HRV / RHR / sleep baseline
bleScoring.ts       ← formula-based 0–100 scores
  ↓
ouraDataStore.ts    ← same schema as cloud API path
  ↓
UI hooks (useReadiness / useSleepSessions …)

Sleep Score

Seven contributors, each mapped to 0–100, combined as a weighted average. Calibration on 20 days of real Oura data: ±2.7 pts MAE vs official.

⚠

Oura's official Sleep Score is produced by a cloud ML model trained on population data. Our formula uses the same inputs and documented contributor weights but will not be identical to the official number.

Sleep Score
±2.7 pts MAE 20-day sample
Contributor Weight Formula
Total sleep
15%
7 h = 100, linear from 5 min = 0
Efficiency
15%
% of time in bed spent asleep (ring-computed)
Restfulness
20%
0 disruptions = 100; −10 per restless period
REM sleep
10%
90 min = 100, linear from 0
Deep sleep
10%
60 min = 100, linear from 0
Latency
10%
≤5 min = 100; ≥60 min = 0; inverted linear
Timing
20%
Sleep midpoint within 1 h of 2 AM = 100; ≥3 h away = 0

Readiness Score

Seven contributors. HRV and RHR sub-scores require a 30-day personal baseline — the score confidence increases over the first 14 days. Calibration: ±5.3 pts MAE vs official.

Readiness Score
±5.3 pts MAE 20-day sample
ContributorWeightFormula
Previous night
35%
Last night's sleep score (above)
HRV balance
25%
recent_HRV ÷ 30-day baseline × 100
Body temperature
10%
Nightly deviation from ring (exact, Tier 1)
Sleep balance
10%
last night ÷ 14-day sleep avg × 100
Resting HR
10%
(baseline_RHR − recent + 10) ÷ 20 × 100
Recovery index
5%
From sleep stage transition quality (ring delta)
Activity balance
5%
vs 7-day activity average

Activity Score

Five contributors. Note: Oura's move every hour contributor tracks per-hour inactivity alerts — this data is not in the BLE stream, so that sub-score defaults to a neutral 70. This is the largest source of activity score error.

Activity Score
±32 pts MAE move_every_hour fixed
ContributorWeightFormula
Meet daily targets
35%
meters completed ÷ meters target; calorie fallback
Stay active
25%
non-sedentary time ÷ waking time × 143
Move every hour
20%
Fixed at 70 — per-hour data not in BLE stream
Training frequency
10%
high-intensity time ÷ 2700 s (45 min target)
Training volume
10%
distance ÷ 8 km, or steps ÷ 10 000

Accuracy

Calibrated against 20 days of real Oura cloud data from a Gen3 ring. MAE = mean absolute error in score points (0–100 scale).

Weight optimization requires ≥70 data points per dimension (10× the number of free parameters). The calibration script re-runs automatically when this threshold is met.

DimensionMAENotes
Sleep Score ±2.7 pts Within Oura's own test-retest variance (~3 pts)
Readiness Score ±5.3 pts Higher variance due to body_temperature approximation in first 14 days
Activity Score ±32 pts move_every_hour sub-score fixed at 70 (no per-hour BLE data)
HRV (nightly avg) Exact Decoded directly from ring firmware (Tier 1)
SpO2 ±2% Ring-computed but calibration coefficients are ring-specific and not in open_oura

Known gaps vs Oura cloud

⚠

Scores labeled ~ are approximations. They are never presented as Oura's official numbers. Oura's 0–100 scores are produced by proprietary PyTorch models trained on population data — we cannot replicate these without Oura's model weights.

Features unavailable without cloud

FeatureWhy unavailable
Resilience Score Requires daytime HRV context + cloud ecore + 14-day PyTorch accumulation
Cardiovascular / Vascular Age PPG pulse wave velocity via deep learning (NUS-validated model); ring-specific PPG calibration also needed
Workout auto-detection Cloud endpoint POST /api/activity-tagging/v2 — not available offline
Cycle prediction Proprietary hormonal cycle model; temperature inputs available but predictive model is not
Move every hour Per-hour inactivity alert data is not in the BLE history stream

Proxy implementations shown in-app

For Resilience and Cardiovascular Age, Protocol Pal shows clearly-labeled proxy cards based on published science — not Oura's model. These are opt-in and only shown when the data source is BLE.

  • Resilience proxy: HRV z-score vs 30-day personal baseline → 0–100
  • HRV Age proxy: rMSSD vs age-group norms (Shaffer & Ginsberg 2017)

Open-source & scientific references

Protocol & software

  • open_oura (MIT) — Oura BLE protocol reverse-engineering, AES-128-ECB auth, packet framing
  • open_ring (GPL-3, reference only) — Control-plane BLE commands; not shipped in Protocol Pal

Science

  • OSSA 2.0 sleep staging validation, 91.7% 2-stage accuracy — doi:10.1016/j.sleep.2024.01.023
  • Shaffer & Ginsberg 2017 — age-group rMSSD norms used in HRV Age proxy
  • Jackson-Blair equation — VO₂ max demographic estimate
  • Oura Resilience Score inputs — ouraring.com/blog
  • NUS Vascular Age validation — ouraring.com/blog