Repository navigation
OpenVitals 2.17.0
Released 2026-11-15.
OpenVitals hands watches and scales to OpenWatch and keeps the dashboard. Garmin and Wear OS watches and the Xiaomi S400 scale now pair and sync in OpenWatch, a separate app from the same project, which writes what they record to Health Connect for OpenVitals to read; an updated install says so once, and nothing in Health Connect is lost. The two apps talk on the phone: the body profile stays the same in both, a dashboard tile shows your watch with its battery and a sync button, and a recording can use the watch's heart rate. Calorie estimates now rest on published equations and the weight in your body profile, with one maximum heart rate for every estimate, the same numbers OpenWatch gives. The activity detail shows heart rate zones, the CSV importer reads a sleep app's history, and OpenVitals now speaks Ukrainian.
- OpenVitals and OpenWatch work together. Over OpenLink, a connection that never leaves the phone, the two apps keep one body profile, the newest change winning on either side; OpenVitals offers its profile on every start, and Settings, OpenWatch, Sync body profile now sends it on demand. The body profile screen says when it is kept in sync with OpenWatch.
- The OpenWatch tile. The dashboard shows the watch OpenWatch is syncing, else the last one it synced, with its battery, its last sync, how many more it pairs and a Sync watch button; a tap opens OpenWatch. While OpenWatch waits for your answer, the tile says "Allow OpenVitals in OpenWatch" and opens its consent screen. Without OpenWatch, or without a watch in it, there is no tile. Existing layouts gain it too.
- Settings, OpenWatch. One status line says where OpenVitals stands: not installed, with a link to get it; waiting for approval, with a button that opens OpenWatch's consent screen; blocked in OpenWatch; or connected, with the watches it sees. Its screen lists the watches with their connection, battery and last sync, what OpenWatch allows OpenVitals to do, and when the body profile last synced.
- A watch's heart rate in a recording. When a recording starts, OpenVitals asks OpenWatch to keep the watch streaming, and the watch's heart rate is listed as a sensor. It is used and saved with the activity only when no Bluetooth sensor gives a heart rate, and the stream ends with the recording.
- Only the real OpenWatch gets your profile. OpenVitals connects only to an OpenWatch signed by the project's key. An app installed under OpenWatch's name with another key is sent nothing: Settings, OpenWatch shows its key digest and connects only after Connect anyway, and that choice holds for that key.
- Heart rate zones in the activity detail. A card shows the time in five zones on the ACSM's intensity classes (Garber et al. 2011): shares of the heart rate reserve when a resting rate is known, of the maximum heart rate otherwise, from the body profile and the year's highest reading. The limits you set in the Body Energy calibration win when you have set them. The card names its basis, and OpenWatch places one heart rate in the same zone.
- Sleep in the CSV importer. A sleep app's history, such as Sleep Cycle's export, imports into Health Connect, one night per row. The column menu has a Sleep section: Woke up, Time in bed, Time to fall asleep, Time asleep and Sleep notes. A row becomes a session from its date and time to Woke up, or for Time in bed, with its stages: awake while falling asleep, asleep for the time asleep, and awake in bed for the rest, placed at the end since the file does not say when. Durations read in minutes, or in seconds or hours when the header says so, and 7:32 always reads as hours and minutes. A night that will not read costs that night only, and a re-import replaces a night instead of adding it. A quality score, snoring or room noise has no place in Health Connect and stays unmapped.
- Espresso-and-milk drinks. Espresso macchiato, cortado, flat white and latte macchiato join the preset drinks, with the volumes of Nespresso Professional's Momento recipes and the caffeine and nutrients of a 40 ml espresso and whole milk from the USDA. Serving volumes are corrected where a source gives the real size: cappuccino, the Dolce Gusto espresso and lungo, Nespresso Classic and Vertuo pods, and Starbucks espresso.
- Count the rest of a set. In a plan run, holding + adds the reps still missing from the step's target and ends the step, as the last tap did; a tap still adds one.
- Ukrainian. OpenVitals is translated into Ukrainian, complete from the start (#372).
- Watches and scales moved to OpenWatch. Garmin and Wear OS watches and the Xiaomi S400 and S400 Pro scale now pair and sync in OpenWatch, which writes what they record to Health Connect; OpenVitals reads it from there like any other source, and the app is smaller and faster to open for it. An install from before the move sees a notice once, with a button to get OpenWatch; either way out, OpenVitals forgets its watch and scale settings, and Health Connect is untouched. Gone from OpenVitals with them: the watch and scale sections in Settings, the old watch tile, notification forwarding, the Body Energy calibration fitted to a watch's own body energy, and the calendar and companion device permissions. The Garmin measurements Health Connect has no record for, such as stress and Body Battery, were kept only on the phone and are not carried over; OpenWatch keeps them from its first sync. OpenVitals' watch app gets no more updates: install OpenWatch's watch app, and uninstall the old one so the two do not both record the sensors. Staying in OpenVitals: FIT file import, Bluetooth sensors during a recording, phone-to-phone sync and CoMaps.
- Calorie estimates from published equations and your body profile. A workout that measured no calories, whether entered, recorded or imported, is estimated from its heart rate by Keytel et al. 2005 while it lies between 57 and 90 % of your maximum, each reading weighted by the time it covers; else, for a walk or run at a pace ACSM's metabolic equations cover, from its distance; else from the activity's MET in the 2024 Adult Compendium. The resting share taken off is your Mifflin-St Jeor rate, or 1 MET without height and age. A fixed 70 kg is no longer assumed: without a weight there is no estimate, and the entry form names the body profile fields it misses. Body Energy's stand-in for steps without calories is Moore et al. 2021's walking cost at the minute's cadence, and nothing without a weight; Body Energy shows a prompt with Open body profile while a field is missing. Without a sex in the body profile, the calorie estimate and cardio load take the mean of the men's and women's formulas.
- One maximum heart rate. Cardio load, intensity minutes, heart rate recovery, Body Energy, the zones and the calorie estimate all use the maximum you entered, else the highest reading of the year before, else the age formula. Before, each looked in its own window, from the period on screen to 90 days, and Body Energy ignored an entered maximum.
- The same numbers as OpenWatch. OpenVitals and OpenWatch take these calculations from one library, so the two apps give the same figure from the same data.
- Body Energy's moderate zone starts at 40 % of the heart rate reserve, as in the ACSM's position stand, instead of 45 %, so a little more time counts as active (#354).
- Plan and set weights follow the weight unit. The plan builder and the set form take the load in pounds when that is the unit, and the run banner, target line and voice cue say it in that unit.
- OpenVitals is published by Hale. The logo takes Hale's colours with its shape unchanged, Settings shows "Hale · hale.ngo" under the version, the help links open docs.hale.ngo, and donations go to Hale's Liberapay account. The privacy policy names the publisher, MTÜ Hale, a non-profit association registered in Estonia, with hello@hale.ngo as its contact, gains a section on OpenWatch on the same phone, and is offered again once. The crash report draft is addressed to hello@hale.ngo.
- An Apple Health reading re-synced by another app imported several times. A reading's id took in what Apple stamps on every save, so a vendor app that wrote the same reading again produced a new record each time. Single readings and blood pressure now take their id from what was measured, and an export imported before writes nothing again (#370).
- An early bedtime stretched the sleep schedule chart. A night that began shortly before the sleep window's start wrapped a whole day down the week and month chart. The axis now wraps in the middle of the waking day, so an early bedtime sits above the later ones (#345).
The app keeps the same package name and signing certificate, so this installs as a normal update.
Distribution flow:
- GitHub release with signed APK, signed debug APK, and signed Android App Bundle assets.
- Direct Google Play production upload from the approved production run of the release workflow.
Generated from docs/releases/2.17.0.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
- Share With Other Apps
- 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.17.0
- 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