### Parse FIT File with fitparse-rs Source: https://github.com/stadelmanma/fitparse-rs/blob/master/README.md Basic example of parsing a FIT file using the `fitparser::from_reader` function. Ensure the file path is correct and the necessary imports are included. ```rust use fitparser; use std::fs::File; use std::io::prelude::*; println!("Parsing FIT files using Profile version: {}", fitparser::profile::VERSION); let mut fp = File::open("tests/fixtures/Activity.fit")?; for data in fitparser::from_reader(&mut fp)? { // print the data in FIT file println!("{{:#?}}", data); } ``` -------------------------------- ### Customized FIT File Parsing Source: https://context7.com/stadelmanma/fitparse-rs/llms.txt Parse FIT files with custom decoding options to control output, handle malformed files, or filter unknown data. This example demonstrates skipping CRC validation, dropping unknown fields/messages, returning numeric enum values, and keeping composite fields. ```rust use fitparser::de::{from_reader_with_options, DecodeOption}; use std::collections::HashSet; use std::fs::File; fn main() -> Result<(), Box> { // Configure decode options let mut options = HashSet::new(); // Skip CRC validation for damaged/partial files options.insert(DecodeOption::SkipHeaderCrcValidation); options.insert(DecodeOption::SkipDataCrcValidation); // Drop fields and messages not defined in the FIT profile options.insert(DecodeOption::DropUnknownFields); options.insert(DecodeOption::DropUnknownMessages); // Return numeric enum values instead of string names options.insert(DecodeOption::ReturnNumericEnumValues); // Keep composite fields that are expanded into components options.insert(DecodeOption::KeepCompositeFields); let mut fp = File::open("Activity.fit")?; let records = from_reader_with_options(&mut fp, &options)?; for record in records.iter().take(2) { println!("Kind: {:?}", record.kind()); for field in record.fields() { // With ReturnNumericEnumValues, enums are i64 instead of strings println!(" {}: {:?}", field.name(), field.value()); } } Ok(()) } ``` -------------------------------- ### Configure FIT Parsing Options Source: https://context7.com/stadelmanma/fitparse-rs/llms.txt Demonstrates how to create a HashSet of DecodeOption enums to customize FIT file parsing behavior, such as dropping unknown fields or validating CRCs. ```rust use fitparser::de::DecodeOption; use std::collections::HashSet; fn configure_options() -> HashSet { let mut opts = HashSet::new(); // DropUnknownFields: Remove fields not in FIT profile opts.insert(DecodeOption::DropUnknownFields); // DropUnknownMessages: Remove entire messages not in FIT profile opts.insert(DecodeOption::DropUnknownMessages); // KeepCompositeFields: Preserve original composite fields // (by default they are replaced by expanded components) opts.insert(DecodeOption::KeepCompositeFields); // ReturnNumericEnumValues: Use integers instead of string names opts.insert(DecodeOption::ReturnNumericEnumValues); // SkipHeaderCrcValidation: Ignore header CRC errors opts.insert(DecodeOption::SkipHeaderCrcValidation); // SkipDataCrcValidation: Ignore data section CRC errors opts.insert(DecodeOption::SkipDataCrcValidation); // UseGenericSubFieldName: Keep generic names for subfields opts.insert(DecodeOption::UseGenericSubFieldName); opts } ``` -------------------------------- ### Read FIT File Header Information Source: https://context7.com/stadelmanma/fitparse-rs/llms.txt This code snippet shows how to extract protocol and profile version information from FIT file headers using `FitStreamProcessor`. It deserializes the header, prints its size, protocol and profile versions, data size, and CRC if available. ```rust use fitparser::de::{FitObject, FitStreamProcessor}; fn read_header_info(data: &[u8]) -> Result<(), Box> { let mut processor = FitStreamProcessor::new(); let (remaining, obj) = processor.deserialize_next(data)?; if let FitObject::Header(header) = obj { println!("Header size: {} bytes", header.header_size()); println!("Protocol version: {}", header.protocol_ver_enc()); println!("Profile version: {}", header.profile_ver_enc()); println!("Data size: {} bytes", header.data_size()); if let Some(crc) = header.crc() { println!("Header CRC: {:#06x}", crc); } else { println!("Header CRC: not present (legacy 12-byte header)"); } } Ok(()) } ``` -------------------------------- ### Serialize FIT Data to JSON Source: https://context7.com/stadelmanma/fitparse-rs/llms.txt Parses a FIT file and serializes its records into a JSON format using Serde. Configures parsing options to drop unknown fields and messages. Requires `serde` and `serde_json` crates. ```rust use fitparser::de::{from_reader_with_options, DecodeOption}; use serde::Serialize; use std::collections::{BTreeMap, HashSet}; use std::fs::File; use std::io::Write; // Custom serialization format with fields as a map #[derive(Serialize)] struct FitDataMap { kind: fitparser::profile::MesgNum, fields: BTreeMap, } impl FitDataMap { fn from_record(record: fitparser::FitDataRecord) -> Self { FitDataMap { kind: record.kind(), fields: record .into_vec() .into_iter() .map(|f| (f.name().to_owned(), fitparser::ValueWithUnits::from(f))) .collect(), } } } fn fit_to_json(input_path: &str, output_path: &str) -> Result<(), Box> { // Configure options for clean output let mut options = HashSet::new(); options.insert(DecodeOption::DropUnknownFields); options.insert(DecodeOption::DropUnknownMessages); // Parse FIT file let mut fp = File::open(input_path)?; let records = from_reader_with_options(&mut fp, &options)?; // Convert to serializable format let data: Vec = records .into_iter() .map(FitDataMap::from_record) .collect(); // Serialize to JSON let json = serde_json::to_string_pretty(&data)?; // Write output let mut output = File::create(output_path)?; output.write_all(json.as_bytes())?; println!("Wrote {} records to {}", data.len(), output_path); Ok(()) } fn main() -> Result<(), Box> { fit_to_json("Activity.fit", "activity.json") } // Output file (activity.json): // [ // { // "kind": "FileId", // "fields": { // "manufacturer": { "value": "garmin", "units": "" }, // "product": { "value": 1623, "units": "" }, // "serial_number": { "value": 3878510123, "units": "" }, // "time_created": { "value": "2019-09-16T14:32:00-04:00", "units": "" }, // "type": { "value": "activity", "units": "" } // } // }, // ... // ] ``` -------------------------------- ### Parse FIT File from Byte Slice Source: https://context7.com/stadelmanma/fitparse-rs/llms.txt Parse FIT data directly from a byte array. This is useful when FIT data is already in memory. Ensure the 'Activity.fit' file exists in the same directory or provide a full path. ```rust use fitparser; fn main() -> Result<(), Box> { // Load FIT file into memory let data = std::fs::read("Activity.fit")?; // Parse from byte slice let records = fitparser::from_bytes(&data)?; println!("Parsed {} data records", records.len()); // Find specific message types let activity_records: Vec<_> = records .iter() .filter(|r| r.kind() == fitparser::profile::MesgNum::Record) .collect(); println!("Found {} GPS/sensor records", activity_records.len()); Ok(()) } ``` -------------------------------- ### Process FIT Data from Streams Source: https://context7.com/stadelmanma/fitparse-rs/llms.txt Illustrates using FitStreamProcessor to deserialize FIT data incrementally from a continuous stream, such as standard input. Handles potential errors and EOF. ```rust use fitparser::de::{FitObject, FitStreamProcessor, DecodeOption}; use fitparser::profile::MesgNum; use std::io::{self, Read}; fn process_streaming_data() -> Result<(), Box> { let stdin = io::stdin(); let mut handle = stdin.lock(); let mut buffer = vec![0u8; 1024]; let mut processor = FitStreamProcessor::new(); // Optionally configure options processor.add_option(DecodeOption::DropUnknownMessages); let mut remainder = 0; loop { let bytes_read = handle.read(&mut buffer[remainder..])?; if bytes_read == 0 { break; // EOF } let mut data = &buffer[0..bytes_read + remainder]; while !data.is_empty() { match processor.deserialize_next(data) { Ok((remaining, obj)) => { match obj { FitObject::Header(hdr) => { processor.reset(); println!( "FIT file: protocol v{}, profile v{}, {} bytes", hdr.protocol_ver_enc(), hdr.profile_ver_enc(), hdr.data_size() ); } FitObject::DataMessage(msg) => { let record = processor.decode_message(msg)?; println!( "{}: {} fields", record.kind(), record.fields().len() ); } FitObject::DefinitionMessage(def) => { println!( "Definition {}: {} (gmn {}), {} fields", def.local_message_number(), MesgNum::from(def.global_message_number()), def.global_message_number(), def.field_definitions().len() ); } FitObject::Crc(crc) => { println!("CRC: {:#06x}", crc); } } data = remaining; } Err(e) => { match *e { fitparser::ErrorKind::UnexpectedEof(_) => { // Need more data, shift remainder and continue reading break; } _ => return Err(Box::new(e)), } } } } // Preserve unprocessed bytes for next iteration remainder = data.len(); buffer[..remainder].copy_from_slice(data); } Ok(()) } ``` -------------------------------- ### Decoding Options Source: https://context7.com/stadelmanma/fitparse-rs/llms.txt This section details how to customize FIT file parsing using various decoding options. ```APIDOC ## from_reader_with_options - Customized Parsing ### Description Parse FIT files with custom decoding options to control output format, handle malformed files, or filter unknown data. ### Method `fitparser::de::from_reader_with_options` ### Endpoint N/A (Rust function) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```rust use fitparser::de::{from_reader_with_options, DecodeOption}; use std::collections::HashSet; use std::fs::File; fn main() -> Result<(), Box> { // Configure decode options let mut options = HashSet::new(); // Skip CRC validation for damaged/partial files options.insert(DecodeOption::SkipHeaderCrcValidation); options.insert(DecodeOption::SkipDataCrcValidation); // Drop fields and messages not defined in the FIT profile options.insert(DecodeOption::DropUnknownFields); options.insert(DecodeOption::DropUnknownMessages); // Return numeric enum values instead of string names options.insert(DecodeOption::ReturnNumericEnumValues); // Keep composite fields that are expanded into components options.insert(DecodeOption::KeepCompositeFields); let mut fp = File::open("Activity.fit")?; let records = from_reader_with_options(&mut fp, &options)?; for record in records.iter().take(2) { println!("Kind: {:?}", record.kind()); for field in record.fields() { // With ReturnNumericEnumValues, enums are i64 instead of strings println!(" {}: {:?}", field.name(), field.value()); } } Ok(()) } ``` ### Response #### Success Response (200) - `Vec` - A vector containing decoded FIT data records with applied options. #### Response Example ``` Kind: FileId type: SInt64(4) manufacturer: SInt64(1) product: UInt16(1623) serial_number: UInt32z(3878510123) time_created: Timestamp(2019-09-16T14:32:00-04:00) ``` ``` -------------------------------- ### Handle FIT Parsing Errors Source: https://context7.com/stadelmanma/fitparse-rs/llms.txt Demonstrates how to handle various error types returned by the fitparser library during file parsing. Imports `fitparser::ErrorKind` and `std::fs::File`. ```rust use fitparser::{self, ErrorKind}; use std::fs::File; fn parse_with_error_handling(path: &str) { let mut fp = match File::open(path) { Ok(f) => f, Err(e) => { eprintln!("Failed to open file: {}", e); return; } }; match fitparser::from_reader(&mut fp) { Ok(records) => { println!("Successfully parsed {} records", records.len()); } Err(e) => { match *e { ErrorKind::InvalidCrc((remaining, obj, expected, calculated)) => { eprintln!( "CRC mismatch: expected {:#06x}, got {:#06x}", expected, calculated ); eprintln!("Remaining bytes: {}", remaining.len()); // Can still access partially parsed object via `obj` } ErrorKind::MissingDefinitionMessage(local_num, position) => { eprintln!( "Missing definition for local message {} at position {:#x}", local_num, position ); } ErrorKind::ParseError(position, kind) => { eprintln!( "Parse error at position {:#x}: {:?}", position, kind ); } ErrorKind::UnexpectedEof(needed) => { eprintln!("Unexpected EOF, need more data: {:?}", needed); } ErrorKind::Io(io_err) => { eprintln!("IO error: {}", io_err); } ErrorKind::ValueError(msg) => { eprintln!("Value error: {}", msg); } ErrorKind::TrailingBytes(count) => { eprintln!("{} unexpected trailing bytes", count); } ErrorKind::MissingDeveloperDefinitionMessage() => { eprintln!("Developer field used before definition"); } } } } } ``` -------------------------------- ### Core Parsing Functions Source: https://context7.com/stadelmanma/fitparse-rs/llms.txt This section covers the primary functions for parsing FIT files using the Fitparser library. ```APIDOC ## from_reader - Parse FIT File from Reader ### Description The primary function for parsing FIT files from any source implementing the `Read` trait. Returns a vector of decoded `FitDataRecord` objects containing all fitness data messages. ### Method `fitparser::from_reader` ### Endpoint N/A (Rust function) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```rust use fitparser; use std::fs::File; use std::io::prelude::*; fn main() -> Result<(), Box> { // Display the FIT profile version being used println!("Parsing FIT files using Profile version: {}", fitparser::profile::VERSION); // Open and parse a FIT file let mut fp = File::open("Activity.fit")?; let records = fitparser::from_reader(&mut fp)?; // Iterate through all data records for record in records { println!("Message type: {:?}", record.kind()); // Access individual fields for field in record.fields() { println!(" {}: {} {}", field.name(), field.value(), field.units()); } } Ok(()) } ``` ### Response #### Success Response (200) - `Vec` - A vector containing decoded FIT data records. #### Response Example ``` Parsing FIT files using Profile version: 21.171.00 Message type: FileId type: activity manufacturer: garmin product: 1623 serial_number: 3878510123 time_created: 2019-09-16 14:32:00 -04:00 Message type: Record timestamp: 2019-09-16 14:32:05 -04:00 position_lat: 42.3601 degrees position_long: -71.0589 degrees heart_rate: 142 bpm ``` ``` ```APIDOC ## from_bytes - Parse FIT File from Byte Slice ### Description Parse FIT data directly from a byte array. Useful when FIT data is already loaded in memory or embedded in application resources. ### Method `fitparser::from_bytes` ### Endpoint N/A (Rust function) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```rust use fitparser; fn main() -> Result<(), Box> { // Load FIT file into memory let data = std::fs::read("Activity.fit")?; // Parse from byte slice let records = fitparser::from_bytes(&data)?; println!("Parsed {} data records", records.len()); // Find specific message types let activity_records: Vec<_> = records .iter() .filter(|r| r.kind() == fitparser::profile::MesgNum::Record) .collect(); println!("Found {} GPS/sensor records", activity_records.len()); Ok(()) } ``` ### Response #### Success Response (200) - `Vec` - A vector containing decoded FIT data records. #### Response Example ``` Parsed 143 data records Found 98 GPS/sensor records ``` ``` -------------------------------- ### Handle FIT Data Values with Value Enum Source: https://context7.com/stadelmanma/fitparse-rs/llms.txt Handles various FIT data types using the Value enum, including conversion to numeric types. Requires importing Value and TryInto. ```rust use fitparser::Value; use std::convert::TryInto; fn handle_values(value: Value) -> Result<(), fitparser::Error> { match &value { // Timestamp (converted to local timezone) Value::Timestamp(dt) => println!("Time: {}", dt), // Integer types Value::SInt8(v) => println!("Signed 8-bit: {}", v), Value::UInt8(v) => println!("Unsigned 8-bit: {}", v), Value::SInt16(v) => println!("Signed 16-bit: {}", v), Value::UInt16(v) => println!("Unsigned 16-bit: {}", v), Value::SInt32(v) => println!("Signed 32-bit: {}", v), Value::UInt32(v) => println!("Unsigned 32-bit: {}", v), Value::SInt64(v) => println!("Signed 64-bit: {}", v), Value::UInt64(v) => println!("Unsigned 64-bit: {}", v), // Zero-invalid integer types Value::UInt8z(v) => println!("Unsigned 8-bit (0=invalid): {}", v), Value::UInt16z(v) => println!("Unsigned 16-bit (0=invalid): {}", v), Value::UInt32z(v) => println!("Unsigned 32-bit (0=invalid): {}", v), Value::UInt64z(v) => println!("Unsigned 64-bit (0=invalid): {}", v), // Floating point Value::Float32(v) => println!("32-bit float: {}", v), Value::Float64(v) => println!("64-bit float: {}", v), // Other types Value::String(s) => println!("String: {}", s), Value::Byte(b) => println!("Byte: {:#04x}", b), Value::Enum(e) => println!("Enum value: {}", e), Value::Array(arr) => println!("Array with {} elements", arr.len()), Value::Invalid => println!("Invalid/missing value"), } // Convert values to numeric types let as_f64: f64 = value.clone().try_into()?; let as_i64: i64 = value.try_into()?; println!("As f64: {}, as i64: {}", as_f64, as_i64); Ok(()) } ``` -------------------------------- ### Parse FIT File from Reader Source: https://context7.com/stadelmanma/fitparse-rs/llms.txt Use this function to parse FIT files from any source implementing the `Read` trait. It returns a vector of decoded `FitDataRecord` objects. Ensure the 'Activity.fit' file exists in the same directory or provide a full path. ```rust use fitparser; use std::fs::File; use std::io::prelude::*; fn main() -> Result<(), Box> { // Display the FIT profile version being used println!("Parsing FIT files using Profile version: {}", fitparser::profile::VERSION); // Open and parse a FIT file let mut fp = File::open("Activity.fit")?; let records = fitparser::from_reader(&mut fp)?; // Iterate through all data records for record in records { println!("Message type: {:?}", record.kind()); // Access individual fields for field in record.fields() { println!(" {}: {} {}", field.name(), field.value(), field.units()); } } Ok(()) } ``` -------------------------------- ### Process FitDataRecords Source: https://context7.com/stadelmanma/fitparse-rs/llms.txt Iterates through FitDataRecords, extracting message kind, fields, and converting them to ValueWithUnits for serialization. Requires importing FitDataRecord, FitDataField, Value, ValueWithUnits, and MesgNum. ```rust use fitparser::{FitDataRecord, FitDataField, Value, ValueWithUnits}; use fitparser::profile::MesgNum; fn process_records(records: Vec) { for record in records { // Get message type let kind: MesgNum = record.kind(); println!("Message: {} (number: {})", kind, kind.as_u16()); // Get fields as slice let fields: &[FitDataField] = record.fields(); for field in fields { // Field metadata let name: &str = field.name(); let number: u8 = field.number(); let units: &str = field.units(); let value: &Value = field.value(); println!(" [{}]: {} {} {}", number, name, value, units); } // Convert record to owned vector for further processing let field_vec: Vec = record.into_vec(); // Convert fields to ValueWithUnits for serialization for field in field_vec { let vwu: ValueWithUnits = ValueWithUnits::from(field); println!(" Formatted: {}", vwu); } } } ``` -------------------------------- ### Parse Custom Developer Fields in FIT Files Source: https://context7.com/stadelmanma/fitparse-rs/llms.txt This snippet demonstrates how to parse FIT files and extract custom developer-defined fields, which contain unique metadata. It iterates through records and fields, printing named developer fields with their values and units, and unknown developer fields by their number. ```rust use fitparser; fn parse_developer_data() -> Result<(), Box> { let data = std::fs::read("DeveloperData.fit")?; let records = fitparser::from_bytes(&data)?; for record in records { println!("Message: {}", record.kind()); for field in record.fields() { // Developer fields have custom names and units defined in the file if field.name().starts_with("unknown_developer_field") { println!(" Unknown dev field #{}: {:?}", field.number(), field.value()); } else { // Named developer field (e.g., "doughnuts_earned") println!( " {} (field #{}) : {} {}", field.name(), field.number(), field.value(), field.units() ); } } } Ok(()) } ``` -------------------------------- ### Update FIT Profile Script Source: https://github.com/stadelmanma/fitparse-rs/blob/master/README.md Shell command to update the FIT profile used by the library. This script requires the path to the Profile.xlsx file and optionally accepts a profile version. ```sh ./bin/update_profile.sh ~/Downloads/FitSDKRelease_21.40.00/Profile.xlsx ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.