Repository navigation
Body Energy
Status: Current implemented behavior. Audience: Users and contributors. Implementation:
features/bodyenergy,features/readiness,domain/insights/BodyEnergyTimeline.kt,domain/insights/BodyEnergyCalibrationFit.kt. Navigation:Screen.BodyEnergyDetails, widgetBODY_ENERGY, settings sectionRECOVERY. Related: Feature map, Daily readiness, Sleep score and recovery, Home screen widgets.
Body Energy is a local derived view that estimates available energy across the day from supported wellness signals. It is intentionally a selected-day experience rather than a canonical Day / Week / Month / Year metric-detail screen.
Body Energy can appear in:
- Daily Readiness.
- The dashboard.
- A dedicated Body Energy detail flow.
- Android home screen widgets.
The detail view can show a summary, timeline, confidence, and context for the selected day.
Body Energy supports calibration during onboarding and in Recovery settings. Calibration helps the local estimate better fit the user, and can be reset when needed.
The score is a running balance, not a daily reset: a day opens where the previous one closed. Two things push it around.
Charge comes from sleep, and — far more slowly — from genuinely quiet waking time. Sleep charges per minute slept, scaled by three things:
- How well the night went. See below; this is usually the biggest of the three.
- Overnight HRV, against the personal baseline.
- Breathing rate, which penalises a night spent above the usual.
Drain comes from basal metabolism (a gentle downward slope whenever nothing else is happening, scaled by measured BMR), from active energy expenditure, from heart-rate-derived stress, and from recovery debt after a hard session.
Each component is scaled by a personal gain — see Calibration. The gains are the only per-user tuning; everything else above is the same model for everyone.
A night's charge depends on how well it was slept, not only how long.
This is worth stating plainly because it did not used to be true. The charge counted the minutes and read overnight HRV, and never asked how those minutes went — so an unbroken eight hours with a healthy deep and REM share charged within a couple of points of a shallow, repeatedly interrupted eight hours. Two mornings that feel nothing alike arrived at nearly the same number.
What the charge now reads is the quality pillar of the sleep score: sleep efficiency, time awake after falling asleep, and the deep/REM share of the night. That pillar alone, not the whole sleep score — the score's other two pillars are duration and overnight HRV, and the charge already counts both, so folding in the whole score would count them twice and make the factor a duration multiplier under another name.
The rules that keep it honest:
- An ordinary night charges exactly what it always did. The factor is centred, not added: a middling night is neutral, better nights charge more, worse nights less. This is not only taste — a factor that sat above neutral on the ordinary night would inflate every night rather than tell them apart.
- The swing is bounded to ±20%. No single night of broken staging can undo hours actually slept, and duration stays the dominant term.
- A night with no deep/REM staging is left alone. A source that writes only a start and an end has its sleep duration equal its time in bed, so efficiency reads 100% and time awake zero. Read literally that is a flawless night, and it would be handed the full bonus for recording nothing at all. Those nights charge exactly what they charged before.
- A nap is not judged. Under an hour of sleep says nothing about quality.
The charge reads a continuous quality, which is deliberately not the same reading the sleep score displays. The score answers "was this a healthy night" and cites NSF and AASM thresholds to do it: efficiency at or above 85% is good, twenty minutes awake or less is good, and both earn full marks the moment they clear. That is the right shape for a score and the wrong shape for recovery, because it makes a flawless night and a merely good one identical. So the same pillar is also read as a continuous ramp — efficiency all the way to 100%, time awake all the way to none — and the charge uses that. Stage architecture is deliberately not stretched the same way: more deep sleep past the healthy band is not more recovery.
Over eight hours in bed, the charge before other factors runs roughly:
| Night | Charge |
|---|---|
| Flawless: 90 min deep, 115 REM, none awake | ~56 |
| Good: 75 deep, 95 REM, 15 min awake | ~54 |
| Ordinary: 50 deep, 70 REM, 35 min awake | ~48 |
| Poor: 25 deep, 45 REM, 60 min awake | ~39 |
| Broken: 10 deep, 20 REM, 150 min awake | ~38 |
The worst two meet at the floor, which is the bound doing its job.
Changing any of this changes every stored day, so
BodyEnergyTimelineAlgorithmVersion is bumped and the cached timelines
recompute. See domain/insights/BodyEnergyTimeline.kt.
Body Energy is calculated locally from available Health Connect-backed signals and app preferences. Missing or sparse source data lowers confidence instead of pretending the estimate is complete.
Body Energy is not a raw Health Connect record. It is an OpenVitals-derived wellness estimate and should be treated as general guidance, not medical advice.
The calculation runs on device. OpenVitals does not upload Body Energy inputs or results to an OpenVitals server.
Generated from docs/features/body-energy.md. Edit it there; changes made here are overwritten.
This wiki mirrors the Markdown in Hale-MTU/OpenVitals on every push to main.
Features
- Features
- Achievements
- Activity And Training Plans
- Activity Metrics
- Apple Health Import
- Beverage Logging And Caffeine
- Bluetooth LE Sensors
- Body Energy
- Body Metrics
- CoMaps Navigation Context
- CSV Import
- Cycle Tracking
- Daily Readiness
- Elevation Correction
- Feature Map
- FIT Files Import
- Food Logging
- GPX/KML/KMZ/TCX Route Import
- Health Connect Metrics Dashboard
- Health Report Export
- Heart And Vitals
- Heart Rate Recovery
- Home Screen Widgets
- Hydration
- Manual Entry Of Metrics
- Medical Records
- Metric Detail Customization
- Mindfulness
- Non Health Connect Metrics Dashboard
- Nutrition
- Offline Maps Support
- Onboarding And Permissions
- Preloaded Beverage Nutrition Reference
- Privacy, Support, And Diagnostics
- Recording Of Activity
- Reminders
- Settings And Preferences
- Sleep Score And Recovery
- Sleep Tracking
- Statistics
- Sync With Another Phone
How-to
App
- App Guide
- FAQ
- Getting Started
- Health Connect
- Install
- Local And Connected Editions
- Permissions
- Privacy
- Screenshots
- Support
Reference
- Design Reference
- Reference
- Design Guidelines for Offline & Sync
- OpenVitals UI Notes
- Reference: Data Capture
- Reference: Data Display
- Reference: Health Connect Matchmaking
- Reference: Health Connect Onboarding
- Reference: Health Connect Permissions
- Reference: Health Connect UX
- Reference: Promoting Health Connect
Engineering
- Code Analysis
- Engineering
- Flutter ↔ Kotlin test-parity matrix
- apple-health-import
- Architecture
- body-cycle-recovery
- Design system conformance
- Development
- Feature Playbook
- Flutter -> Kotlin test parity: domain/data/core/contract/state/navigation/di/bootstrap/l10n/widget_test
- Flutter → Kotlin test-parity matrix: features section
- Flutter → Kotlin test-parity matrix: ui / goldens / integration / fixtures
- Flutter-to-Kotlin test-parity matrix — dashboard + devicesync
- manual-entry
- Translations
Proposals
- Proposals
- Activity Start Flow Analysis
- Activity Start Flow Simplification Proposals
- Caffeine Detail And Future Sleep Insights
- Cycle Tracking: Design and Status
- Medical Records Through Health Connect
- Medical Records: What Is Left
Releases
- OpenVitals 2.16.0
- OpenVitals 2.15.2
- OpenVitals 2.15.1
- OpenVitals 2.15.0
- OpenVitals 2.14.5
- OpenVitals 2.14.4
- OpenVitals 2.14.3
- OpenVitals 2.14.2
- OpenVitals 2.14.1
- OpenVitals 2.14.0
- OpenVitals 2.13.0
- OpenVitals 2.12.0
- OpenVitals 2.11.2
- OpenVitals 2.11.1
- OpenVitals 2.11.0
- OpenVitals 2.10.1
- OpenVitals 2.10.0
- OpenVitals 2.9.1
- OpenVitals 2.9.0
- OpenVitals 2.8.0
- OpenVitals 2.7.3
- OpenVitals 2.7.2
- OpenVitals 2.7.1
- OpenVitals 2.7.0
- OpenVitals 2.6.6
- OpenVitals 2.6.5
- OpenVitals 2.6.4
- OpenVitals 2.6.3
- OpenVitals 2.6.2
- OpenVitals 2.6.1
- OpenVitals 2.6.0
- OpenVitals 2.5.0
- OpenVitals 2.4.1
- OpenVitals 2.4.0
- OpenVitals 2.3.2
- OpenVitals 2.3.1
- OpenVitals 2.3.0
- OpenVitals 2.2.8
- OpenVitals 2.2.7
- OpenVitals 2.2.6
- OpenVitals 2.2.5
- OpenVitals 2.2.4
- OpenVitals 2.2.3
- OpenVitals 2.2.2
- OpenVitals 2.2.1
- OpenVitals 2.2.0
- OpenVitals 2.1.0
- OpenVitals 2.0.4
- OpenVitals 2.0.3
- OpenVitals 2.0.2
- OpenVitals 2.0.1
- OpenVitals 1.9.0
- OpenVitals 1.8.0
- OpenVitals 1.7.7
- OpenVitals 1.7.6
- OpenVitals 1.7.5
- OpenVitals 1.7.4
- OpenVitals 1.7.3
- OpenVitals 1.7.2
- OpenVitals 1.7.1
- OpenVitals 1.7.0
- OpenVitals 1.6.3
- OpenVitals 1.6.2
- OpenVitals 1.6.1
- OpenVitals 1.6.0
- OpenVitals 1.5.1
- OpenVitals 1.5.0
Project