🧗 Rock Climbing logger - #2476
Closed
oisinmulvihill wants to merge 15 commits into
Closed
Conversation
Skeletal user app (button + on-screen counter) built and confirmed running in InfiniSim. Proves the scaffold -> register -> launch loop works before building ClimbLogger on top of the same pattern. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Placeholder screen only, registered via the same AppTraits pattern TapCounter proved: enum entry, header/cpp pair, included in UserApps.h. Confirms the build->register->launch loop for the real app name before Step 2 builds the selection UI. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
FontAwesome5 has no climbing-specific glyph (that's a v6 addition), so picked the closest already-licensed icon in the bundled woff: 'mountain' (0xf6fc). Added its codepoint to fonts.json's jetbrains_mono_bold_20 range and defined Symbols::mountain. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…Step 2) Single Screen instance, internal Step enum (Area -> Colour -> Grade -> [Climb, if the filter doesn't land on exactly one] -> Result -> Attempts), rebuilding its lv_btnmatrix/Counter widgets per step rather than pushing separate Screen objects -- same pattern FirmwareUpdate.h uses for its own multi-step flow. - CatalogEntry + an 8-entry hard-coded fixture (2 placeholder areas, mixed boulder/route climbs) stand in for catalog.csv until Step 3. - Result capture (flash/send/fell/project) and the attempts counter reuse lv_btnmatrix and the existing Widgets::Counter, matching how Calculator and Alarm already use them elsewhere in this codebase. - Logging a climb prints a CSV-shaped line via NRF_LOG_INFO (visible on the host running the simulator) and triggers a short haptic buzz via MotorController::RunForDuration -- the "something visible/testable" placeholder Step 2 called for, ahead of Step 4's real log.csv write. - Wired dateTimeController/motorController through AppTraits::Create(). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
lv_btnmatrix fires PRESSED on press-down but VALUE_CHANGED once, on release, after the gesture against the current matrix has fully resolved. OnButtonMatrixEvent rebuilds the whole screen (destroying this exact matrix) in response to a selection, so reacting to PRESSED re-triggered against the freshly-created matrix at the same coordinates while the input device was still mid-gesture -- cascading through several steps on a single tap instead of stopping at the one selected. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The previous fix (PRESSED -> VALUE_CHANGED) was based on a wrong assumption. lv_btnmatrix's ctrl_bits default LV_BTNMATRIX_CTRL_CLICK_TRIG to off (allocate_btn_areas_and_controls memsets ctrl_bits to 0), and with that bit off, lv_btnmatrix's own VALUE_CHANGED signal fires on *press*, same timing problem as PRESSED -- still cascaded. LV_EVENT_CLICKED, sent generically by lv_indev.c itself (the same mechanism the existing, already-correct logButton handler relies on), only fires once a press/release gesture has fully resolved against the current object -- safe to rebuild/destroy the screen in response to. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Replaces the area/colour/grade catalog-matching flow with a simpler 5-step taxonomy that reflects how climbs are actually logged across two gyms: - Gym: The Castle / Climbing District / Other - Style: Boulder / Top Rope / Lead - Type: Slab / Overhang / Vertical / Mixed (wall angle, not gym area) - Grade: V-scale for Boulder, Font-scale for Top Rope/Lead (auto-picked from style, no separate scale-picking step) - Attempt: Send / Did Not Finish -- replaces the numeric attempts counter entirely, so logging now happens the instant Attempt is tapped, with no separate confirm button No more catalog/CatalogEntry -- there's no fixed route list to match against anymore, just a taxonomy of what was climbed. Also adds "remember previous selection": selectedGym/Style/Type/Grade/Attempt are no longer cleared after logging, so they double as next log's defaults, and ShowOptionsStep pre-checks the matching button (lv_btnmatrix_set_btn_ctrl + CTRL_CHECK_STATE, same API Calculator.cpp already uses for its toggle-state operator buttons) so repeating the same climb type is one confirming tap per step. In-memory only for this run of the app; real persistence is a later roadmap step. Grade ladders and gym/type lists are placeholders (still open questions per ROADMAP.md), enough to exercise the flow. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Replaces the NRF_LOG_INFO stdout placeholder from Step 2 with a real append-only write via Controllers::FS, wired through AppTraits::Create() same as motorController/dateTimeController already were. Follows AlarmController::SaveSettingsToFile's established idiom: DirOpen the containing directory and DirCreate it if that fails (first-boot case), then FileOpen with LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND so each log is a cheap single-line append, not a full-file rewrite. Controllers::FS has no locking/queueing -- every call is a direct synchronous lfs_* call -- so, per the existing codebase convention (AlarmController/Settings both do this), it's safe to call straight from this Screen's own event-handling code on the DisplayApp task. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
WriteLogEntry() now logs via NRF_LOG_INFO after a successful file write, reusing the same formatted line (no trailing "\n", added separately for the file) rather than duplicating the format string -- so you can see in the terminal that something was actually appended without a make pull-log round-trip every time. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
WriteLogEntry() now uses dateTimeController.UTCDateTime() (subtracts the BLE-reported timezone/DST offset, 0 if never set e.g. in the simulator) rather than the Year()/Hours()/etc. getters, which read `localTime` -- already offset-adjusted. Formats as "%04d-%02d-%02dT%02d:%02d:%02dZ" (ISO 8601, "Z" = UTC) instead of the previous naive "YYYY-MM-DD HH:MM:SS" with no timezone info at all. Keeps the log unambiguous regardless of whether/where a companion app ever set the watch's timezone correctly. Local-time display, if wanted, is a host-side concern for whatever ingests log.csv later (Step 6), not something to bake into the on-device file. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The firmware's src/CMakeLists.txt SOURCE_FILES list is explicit (no glob, unlike InfiniSim's simulator CMake, so new screens must be added here too or the real hardware build fails to link. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> EOF )
CLIMBLOGGER_BUILD_TAG (CMake cache var, empty by default) appends an "om<NNN>" suffix to the version shown on the System info and post-flash Firmware validation screens, e.g. "1.16.0.om005" instead of "1.16.0" -- makes a custom ClimbLogger build unmistakable from an official InfiniTime release at a glance, without touching the numeric project version used internally by MCUboot. Wired through docker/build.sh so the top-level project's `make firmware` can set it per build. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Remembered per-step defaults previously lived only in the Screen object's memory, so they were lost whenever ClimbLogger was destroyed and recreated (exiting the app, at minimum -- confirmed on real hardware). Now written to /climbs/last_selection.csv after each successful log and read back in the constructor, resolved against the current option lists rather than pointing into a stale buffer, so a changed option list degrades to no pre-check instead of a bogus one. Also fixes format-string warnings in SystemInfo/FirmwareValidation's version display (%ld/%lu vs uint32_t) surfaced while rebuilding for this change -- harmless on the 32-bit ARM firmware target but real on the simulator's 64-bit long. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The previous %u fix compiled fine on the simulator's host toolchain (where uint32_t is unsigned int) but broke the real firmware build with -Werror=format (where uint32_t is unsigned long on this ARM ABI). Neither %u nor %lu is portable across both toolchains. Using PRIu32 from <cinttypes> instead, which resolves correctly on either. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
Build size and comparison to main:
|
Author
|
Opened PR here by accident, only meant to do so on my own fork. |
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 join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
🧗 Rock Climbing logger