This repository was archived by the owner on May 19, 2026. It is now read-only.
Add Workout App - #60
Merged
Merged
Conversation
…king Introduce the Workout app, an indoor activity tracker derived from the Running app and tailored to a heart-rate-first, GPS-free experience: - Bootstrap from a copy of the Running app, fully renamed (paths, symbols, identifiers, build targets, TouchGFX project, assets). - Drop GPS end-to-end: no GPS sensor connection, no map builder, no fix indicator, no "Acquiring Signal" / pre-fix start confirmation flows. - Remove the Intervals feature in full: Track/Settings types, Commands messages and senders, Service state machine, SettingsSerializer JSON, AppMenu navigation node, GUI screens/containers, and Model/ ModelListener/TrackPresenter callbacks. - HR-centric tracking: new Track::Data fields (hrZone, totalCalories, lapCalories, cumulative time-in-zone) populated by a fixed-weight zone-weighted MET calorie model in the Service. - Reworked GUI: three track faces (HR + calories + total time; lap-avg HR + lap number + lap time; time of day + battery) and a lap popup showing lap number, lap time, lap-avg HR, and lap calories. - FIT export records the session as FIT_SPORT_GENERIC and drops all position/altitude/distance/speed/ascent/descent fields from records, laps, sessions, and the activity summary JSON; collapses unused mFHRecord variants and splits BATTERY into BATTERY_LEVEL/VOLTAGE.
…ories Initialize zone to 0 in getHrZone so HR at or below the lowest kernel threshold returns no zone, matching the on-screen gauge and preventing calorie/zone-time accrual at idle/resting heart rates.
…tabolic_calories
Switch the Workout app over to the newer vendored FIT SDK
(FitSDKRelease_21.202.00, profile RELEASE) so it can write
session.metabolic_calories as a standard FIT field instead of a
developer field. Also adds basal-metabolic-rate (MET 1.0) accumulation
for resting/metabolic calories that always accrue during active
tracking, written as session.metabolic_calories and a per-lap
"resting_calories" developer field.
Build wiring:
- CubeIDE service .project/.cproject point at the new SDK and define
FIT_PRODUCT_RELEASE.
- Workout-CMake CMakeLists overrides UNA_FIT_SDK_DIR before including
una-sdk.cmake and defines FIT_PRODUCT_RELEASE.
- TouchGFX simulator (msvs/gcc) and una/Makefile updated likewise.
Source changes:
- ActivityWriter.{hpp,cpp}: include fit_product.h, drop the
metabolic_calories developer field and add it to the Session message
def, populate session_mesg.metabolic_calories natively, write
per-lap restingCalories as a developer field.
- Track.hpp: add restingCaloriesTotal / restingCaloriesLap.
- Service.cpp: accrue BMR (MET 1.0) every active second regardless of
HR; fall back to MET 1.0 for HR below zone 1; reset per-lap counter
in saveLap.
Other apps continue to build against the existing 21.171.00 EXAMPLE
SDK; this change is opt-in per app.
The Alerts Menu only contains a single item. In this case we want to disable the scroll indicator. We also want to disable the circular list behaviour, so that we don't get a duplicate entry shown.
…alories The TrackAction screen's info carousel cycled through four items (Calories, Avg.HR, total zone time, current zone) but we only want Avg.HR and Total Calories, so the carousel is reduced to those two. - setCount(4) -> setCount(2); cases trimmed accordingly. - Drop now-unused setZoneTimes / setCurrentZone setters and the mZoneTotalSec / mCurrentZone members from TrackActionView. - Drop the matching view.setZoneTimes / view.setCurrentZone calls from TrackActionPresenter::onTrackData.
The summary overview face previously displayed total time, average HR and total calories. For an HR-centric indoor workout, max HR is more informative than calories there (calories are still emitted in the FIT file), and matches the data shown alongside avg HR on the dedicated heart-rate face. Designer changes (already done by the user): - Added a heart icon next to the bottom row. - Renamed the bottom value/text widgets caloriesValue/Text to maxHRValue/Text and pointed the label at T_TEXT_MAX_HR_UC. - Regenerated the gui_generated base, texts and typed-text DB. Code changes: - Replace SummaryFaceOverview::setCalories(float) with setMaxHR(float). Mirrors setAvgHR: shows "---" when hr < App::Display::kMinHR, otherwise the integer bpm value. - TrackSummaryView::setSummary now feeds s.hrMax to the overview face (the dedicated heart-rate face still receives both avg and max).
Insert a dedicated calories face on the TrackSummary screen so the
zone-MET split is visible without rummaging through the FIT file.
Swipe order is now Overview -> Calories -> HeartRate -> Laps.
GUI:
- New SummaryFaceCal container (Designer-authored, added by the user)
showing total active time plus total / active / resting kcal. The
cpp populates totalValue, activeValue, restingValue and the timer
via Unicode::snprintfFloat("%.0f", ...) so values stay whole numbers.
- TrackSummaryView gains a FACE_CALORIES = 1 enumerator, shifting
FACE_HEARTRATE to 2 and FACE_LAPS to 3. scrollIndicator count is
now 3 + lap pages. setSummary forwards s.time, s.calories,
s.activeCalories and s.restingCalories to the new face.
Data model:
- ActivitySummary gains restingCalories and activeCalories (kcal).
The existing 'calories' field still holds the zone-MET total.
- Service::buildPartialSummary populates the new fields from
mTrackData.totalCalories / restingCaloriesTotal, clamping
active = max(0, total - resting) via std::fmax.
- ActivitySummarySerializer writes "resting_calories" /
"active_calories" and tolerates older summaries that only stored
"calories" (treated as active, resting = 0).
Swap the heart-rate face on the TrackSummary screen for a new
SummaryFaceZones that shows the time spent in each of the five HR
zones with a zone number, percentage of total active time, a coloured
progress bar, and the time spent in that zone. Zone 5 is at the top
of the list, zone 1 at the bottom -- matching the in-activity HR-zone
indicator.
Data:
- ActivitySummary gains zoneTimeSec[5] (cumulative seconds in zones
1..5). buildPartialSummary() copies it from Track::Data.
- ActivitySummarySerializer persists/loads the new "zone_times_sec"
array; old summaries without the key keep zeros.
GUI:
- New ZoneInfo row container: setRow(zone, seconds, pct, color)
writes the three wildcard text areas (zone digit, time formatted
via SDK::Utils::toHMS, percent via T_TEXT_PERCENT typed text),
resizes the progress bar to 6..48 px based on pct, retints
barPainter, and hides the bar at 0%.
- New SummaryFaceZones: title set to "HR ZONES", setZoneSummary()
folds any active seconds spent below zone 1 into the displayed
zone-1 row so the five percentages add up to 100% of session time.
- TrackSummaryView: FACE_HEARTRATE -> FACE_ZONES (value still 2),
calls summaryFaceZones.setZoneSummary(s) and toggles its visibility
on swipe.
Cleanup:
- Deleted SummaryFaceHeartRate.{hpp,cpp} and updated the MSVS
simulator project + filters to drop the entries. CubeIDE/gcc
Makefile pick up sources via globs.
Calorie calculations need the user weight. This was previously hard coded at 75kg. Now it will use the weight from the settings.json if it is above zero.
sdvsaienko
approved these changes
May 12, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Generic indoor workout app. Tracks heart rate and calculates calories from time spent in each HR zone and user weight (configured in phone app).