Files
trail-mate/docs/engineering/linux-tracker-storage.md
T
Trail Mate Dev 6e613e382e Add CM0 Linux support and share device services across platforms
Compose the CM0 fullscreen application and standard Debian package, align the
Cardputer Zero shell, and share protocol, configuration, audio and storage
services with embedded targets through existing platform seams.

Add the paginated on-device TMAP creator using Center's published producer,
private workspace recovery and direct keyboard shortcuts. Preserve unfinished
management work behind its existing opt-in capability.

Include native, ARM and shared-core regression fixtures, integration records,
packaging helpers and dependency/license updates. Keep local build trees,
device credentials, produced packages and validation logs outside version control.

Validation before integration: ESP stack hygiene, Reticulum scope guard, staged
whitespace checks and GitNexus scope audit. Prior device/build evidence and
remaining hardware/package boundaries are recorded in the acceptance documents.
2026-10-29 10:29:29 +08:00

4.4 KiB

Native Linux recording storage

The Linux Tracker adapter implements the shared recording API. Storage comes from resolve_paths().sd_root; neither a board name nor a fixed device or mount path enters the adapter. CM0 without a fitted GNSS receiver does not generate location fixes. The regression fixture injects coordinates and clocks and does not claim physical GNSS verification.

Recording ownership and formats

Each start creates an exclusive filename containing UTC seconds, the process ID and a process-local sequence. Repeated starts within one second cannot truncate previous recordings. The recorder retains its file descriptor and an exclusive advisory lock until stop. Each append checks the configured media root and named file identity. A renamed/replaced recording stops rather than writing to the replacement. Changing the requested format takes effect at the next recording; it cannot change the current file's encoding.

GPX uses the shared point writer and a GPX 1.1 namespace. The closing tags are present after creation and each successful point append. A failed append attempts to restore the previous end and then stops. This does not promise recovery from power loss during an overwrite or filesystem failure.

CSV uses the formal IDF header time,lat,lon,alt_m,speed_mps,satellites, with UTC ISO timestamps and a classic numeric locale. As in the IDF format, CSV does not encode altitude/speed validity; the existing browser converter preserves those values as recorded metadata.

Binary uses TMTRK1 followed by explicitly encoded little-endian 20-byte points:

Offset within a point Encoding
0 UTC epoch seconds, unsigned 32-bit
4 Latitude E7, signed 32-bit
8 Longitude E7, signed 32-bit
12 Altitude metres, signed 16-bit
14 Speed centimetres/second, unsigned 16-bit
16 Satellites, unsigned byte
17 Validity flags: altitude bit 0, speed bit 1
18 Two zero padding bytes

Non-finite or unrepresentable optional binary values have cleared validity flags and zero values. Coordinates must be finite and within geographic bounds. Old native TMTK1 and old native CSV files are not silently rewritten; the new writer aligns future recordings with the production reader.

The first valid fix is sampled even at uptime zero. Subsequent sampling uses unsigned elapsed milliseconds across clock wraparound and clamps oversized interval settings before multiplication can overflow. Distance-only mode uses the formal IDF five-metre geographic distance threshold.

Listing and deletion

The list accepts GPX, CSV and BIN suffixes without case sensitivity. It excludes dotfiles, reserved active.bin metadata, symbolic links, multiply linked files and unrelated files. Result storage is bounded by the requested count.

Deletion accepts a direct filename or the absolute path beneath the configured tracks directory, matching the shared Tracker page's contract. Nested paths, outside-root paths, links, metadata and an actively locked recording are refused. The rooted descriptor adapter resolves path components without following symlinks and synchronizes the parent directory after unlink.

Verification

linux_tracker_storage compiles the production adapter with injected GNSS and clock providers. It covers same-second preservation, absolute and relative deletion, a forked process attempting to delete an active recording, GPX closing tags, active-format ownership, exact binary fields/padding, invalid optional values, uptime zero/wraparound, the distance threshold, file replacement and listing/path restrictions.

When TRAIL_MATE_TEST_WEB_CLIENT=ON, linux_tracker_web_client invokes that fixture and feeds its real CSV and binary output to the unchanged production site/tracks/src/recording-convert.js. It asserts decoded coordinates, altitude, speed, point counts and format profiles. These tests passed on native Linux. The ARM fixture also passed on CM0, where Python's XML parser accepted the GPX with two recorded points. The full native suite passed 124/124, and Cardputer Zero passed 14/14 after rebuilding the shared adapter. The exact standard deb passed Lintian, installation/integrity checks, original-logo verification, a 1232 x 568 P4 render and compositor-confirmed fullscreen Alt+F4 exit with code 0 in 0.983 seconds. Artifact and installed executable hashes are recorded in the CM0 integration ledger.