Two targets
Host-file recording
Write the live stream to a local MCAP file:grab() so the file carries
all queued samples even when retrieve_imu() is never called. If the process
stops calling grab(), no new host frames are recorded. close() finalizes
an active host file.
Device-local recording
Record to the M1, disconnect the host, and retrieve the file later:rec_<utc>_<seq>. Device-local recording
cannot start while another recording, upload, update, or conflicting health
sweep is active.
Manage sessions over any control link (USB or BLE):
download_recording() uses the control link in chunks and does not require
WiFi. A failed transfer leaves the partial file at the destination, and a
re-run resumes it after verifying it belongs to the same recording; the file
is not a valid MCAP until a run returns SUCCESS. delete_recording()
returns immediately and reclaims large files in the background.
Deleting the session that is currently recording returns DEVICE_BUSY,
indicating that the call can be retried once the session stops rather than that
it failed outright. When a recording call is refused, last_error_message()
reports the device’s specific reason; the ERROR_CODE provides only the
category.
Stop reasons and power loss
A recording continues until it is stopped, until storage reaches the reserve (10% of the recording store, at which point the session finalizes cleanly on its own), or until power is lost.RecordingStatus::stopped_reason says why a completed session ended: USER,
DISK_FULL, WRITE_ERROR, or INTERRUPTED for a power cut. It reads
UNSPECIFIED while recording and from firmware older than v00.09.16.
After a power loss the M1 recovers the interrupted session on its next boot.
An unencrypted recording is salvaged into a normal, listed, downloadable MCAP
covering everything flushed up to roughly 250 ms before the cut. An encrypted one
cannot be repaired on the device (the ciphertext is opaque to it), so it is listed with
RecordingStatus::partial set and served as-is: download_recording() and
uploads move the partial bytes, and ef-decrypt recovers everything up to the
cut with a truncated-tail warning.
Encrypted recordings
Recordings can be AES-256-GCM encrypted at rest under a per-device key.RecordingStatus::encrypted reports whether a stored recording is, read off the
container on disk rather than from the current setting, so it stays correct for
recordings written before that setting last changed.
Neither download_recording() nor an upload decrypts: the bytes move as they are
stored, so an encrypted recording arrives as ciphertext and needs the key before
any MCAP reader will open it. Decrypt on the host with ef-decrypt. Setting up a
key, and reading a file back, are covered in Access Control and
Encryption.
Uploading from the device
With WiFi provisioned, the M1 can upload a stopped recording with HTTP PUT:upload_recording() starts a background transfer and returns after the M1
accepts the job.
Location metadata
Each recording carries aLocationFix. Set the persistent device location
once with dev.set_location(lat, lon), or override per-session via
RecordingParameters:

