Dart FIT SDK
A pure Dart port of the Garmin FIT SDK for encoding and decoding FIT (Flexible and Interoperable Data Transfer) files.
Overview
The FIT (Flexible and Interoperable Data Transfer) protocol is a compact binary format designed for storing and sharing data from fitness, health, and sports devices. This library provides a complete Dart implementation for reading and writing FIT files, making it easy to integrate fitness data into your Dart or Flutter applications.
Features
- ✅ Full FIT Protocol Support: Decode and encode FIT files with complete protocol compliance
- ✅ Compressed Timestamp Headers: Efficient handling of compressed timestamps for compact file sizes
- ✅ Developer Data Fields: Full support for custom developer-defined fields
- ✅ CRC Verification: Built-in data integrity checks with CRC validation
- ✅ Accumulated Fields: Proper handling of accumulated values (e.g., total distance)
- ✅ Field Type Demotion: Automatic handling of variable-sized field definitions
- ✅ Zero Dependencies: Pure Dart implementation with no external dependencies
- ✅ Type-Safe: Strongly-typed message and field definitions
- ✅ Cross-Platform: Works on all Dart platforms (Flutter, Web, Server, CLI)
Installation
Add this to your package's pubspec.yaml file:
dependencies:
fit_sdk: ^0.1.0
Then run:
dart pub get
Or for Flutter projects:
flutter pub get
Quick Start
Decoding a FIT File
import 'dart:io';
import 'package:fit_sdk/fit_sdk.dart';
void main() async {
// Read FIT file
final file = File('activity.fit');
final bytes = await file.readAsBytes();
// Create decoder
final decoder = Decode();
// Set up message listener
decoder.onMesg = (Mesg mesg) {
print('Message: ${mesg.name}');
for (var field in mesg.fields) {
if (field.value != null) {
print(' ${field.name}: ${field.value} ${field.units}');
}
}
};
// Decode the file
decoder.read(bytes);
}
Encoding a FIT File
import 'dart:io';
import 'package:fit_sdk/fit_sdk.dart';
void main() async {
final encoder = Encode();
encoder.open();
// FIT epoch offset (seconds since 1989-12-31 00:00:00 UTC)
const fitEpochOffset = 631065600;
// Create File ID message (required)
final fileIdMesg = Mesg.fromMesgNum(MesgNum.fileId);
fileIdMesg.setFieldValue(0, 4); // type = activity
fileIdMesg.setFieldValue(1, 1); // manufacturer = garmin
fileIdMesg.setFieldValue(4,
(DateTime.now().millisecondsSinceEpoch ~/ 1000) - fitEpochOffset);
final fileIdDef = MesgDefinition.fromMesg(fileIdMesg);
encoder.writeMesgDefinition(fileIdDef);
encoder.writeMesg(fileIdMesg);
// Create Record message
final recordMesg = Mesg.fromMesgNum(MesgNum.record);
recordMesg.setFieldValue(253,
(DateTime.now().millisecondsSinceEpoch ~/ 1000) - fitEpochOffset);
recordMesg.setFieldValue(0, (51.5074 * 11930464.7111).round()); // latitude
recordMesg.setFieldValue(1, (-0.1278 * 11930464.7111).round()); // longitude
recordMesg.setFieldValue(5, 1000); // distance (meters)
recordMesg.setFieldValue(3, 150); // heart rate (bpm)
final recordDef = MesgDefinition.fromMesg(recordMesg);
encoder.writeMesgDefinition(recordDef);
encoder.writeMesg(recordMesg);
// Finalize and save
final fitBytes = encoder.close();
await File('output.fit').writeAsBytes(fitBytes);
}
Examples
The example/ directory contains complete working examples:
decode.dart: Demonstrates how to decode FIT files and display message dataencode.dart: Shows how to create FIT files with various message typesbroadcaster.dart: Example of using the message broadcaster pattern
Run examples:
# Decode a FIT file
dart run example/decode.dart data/Activity.fit
# Create a new FIT file
dart run example/encode.dart output.fit
API Documentation
Core Classes
Decode
Decodes FIT files from binary data.
final decoder = Decode();
decoder.onMesg = (Mesg mesg) { /* handle message */ };
decoder.onMesgDefinition = (MesgDefinition def) { /* handle definition */ };
decoder.read(bytes);
Encode
Encodes FIT messages into binary format.
final encoder = Encode();
encoder.open();
encoder.writeMesgDefinition(definition);
encoder.writeMesg(message);
final bytes = encoder.close();
Mesg
Represents a FIT message with fields.
final mesg = Mesg.fromMesgNum(MesgNum.record);
mesg.setFieldValue(fieldNum, value);
final value = mesg.getFieldValue(fieldNum);
MesgBroadcaster
Event-based message handling with type-specific listeners.
final broadcaster = MesgBroadcaster();
broadcaster.addListener(MesgNum.record, (sender, args) {
final recordMesg = RecordMesg(args.mesg);
print('Heart Rate: ${recordMesg.heartRate}');
});
Message Types
The SDK includes strongly-typed message classes for all standard FIT message types:
FileIdMesg- File identificationRecordMesg- GPS and sensor data pointsSessionMesg- Activity session summaryLapMesg- Lap informationActivityMesg- Activity summaryEventMesg- Event markers- And many more...
FIT File Structure
A typical FIT file contains:
- File Header - Identifies the file as FIT format
- Message Definitions - Describe the structure of data messages
- Data Messages - Actual fitness/health data
- CRC - Data integrity checksum
Supported FIT Profile
This SDK supports the FIT Protocol as defined by Garmin. It includes:
- All standard message types (Activity, Session, Lap, Record, etc.)
- All standard field types and units
- Developer data fields for custom extensions
- Component field expansion
- Accumulated field handling
Compatibility
- Dart SDK: >= 3.0.0 < 4.0.0
- Flutter: Compatible with all Flutter platforms (iOS, Android, Web, Desktop)
- Platforms: Works on all Dart-supported platforms
Project Structure
fit_sdk/
├── lib/
│ ├── fit/ # Core FIT protocol implementation
│ │ ├── profile/ # Generated message and type definitions
│ │ ├── decode.dart # FIT file decoder
│ │ ├── encode.dart # FIT file encoder
│ │ └── ...
│ └── fit_sdk.dart # Main library export
├── example/ # Example applications
├── data/ # Sample FIT files for testing
└── doc/ # Additional documentation
Differences from C# SDK
This Dart port maintains functional parity with the official Garmin C# FIT SDK while adapting to Dart idioms:
- Uses Dart naming conventions (camelCase instead of PascalCase)
- Leverages Dart's null safety features
- Provides async/await support for file I/O
- Includes Flutter-friendly APIs
All core features from the C# SDK have been ported, including:
- ✅ Compressed timestamp headers
- ✅ Developer data lookup
- ✅ CRC verification
- ✅ Accumulated field handling
- ✅ Field type demotion
Contributing
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
Development Setup
# Clone the repository
git clone https://github.com/floatinghotpot/dart_fit_sdk.git
cd dart_fit_sdk
# Install dependencies
dart pub get
# Run tests
dart test
# Run examples
dart run example/decode.dart data/Activity.fit
License
This project is licensed under the MIT License - see the LICENSE file for details.
Acknowledgments
- Based on the Garmin FIT SDK
- Ported from the official C# implementation
- FIT Protocol © Garmin Ltd.
Resources
Support
Note: This is an unofficial port of the Garmin FIT SDK. For the official SDK and protocol documentation, please visit developer.garmin.com/fit.
Libraries
- fit/accumulator
- fit/buffered_mesg_broadcaster
- fit/crc
- fit/decode
- fit/defines
- fit/developer_data_key
- fit/developer_data_lookup
- fit/developer_field
- fit/developer_field_definition
- fit/developer_field_description
- fit/encode
- fit/field
- fit/field_base
- fit/field_component
- fit/field_definition
- fit/fit_exception
- fit/fit_listener
- fit/fit_messages
- fit/header
- fit/i_mesg_broadcast_plugin
- fit/mesg
- fit/mesg_broadcaster
- fit/mesg_definition
- fit/profile
- fit/profile/mesgs/aad_accel_features_mesg
- fit/profile/mesgs/accelerometer_data_mesg
- fit/profile/mesgs/activity_mesg
- fit/profile/mesgs/ant_channel_id_mesg
- fit/profile/mesgs/ant_rx_mesg
- fit/profile/mesgs/ant_tx_mesg
- fit/profile/mesgs/aviation_attitude_mesg
- fit/profile/mesgs/barometer_data_mesg
- fit/profile/mesgs/beat_intervals_mesg
- fit/profile/mesgs/bike_profile_mesg
- fit/profile/mesgs/blood_pressure_mesg
- fit/profile/mesgs/cadence_zone_mesg
- fit/profile/mesgs/camera_event_mesg
- fit/profile/mesgs/capabilities_mesg
- fit/profile/mesgs/chrono_shot_data_mesg
- fit/profile/mesgs/chrono_shot_session_mesg
- fit/profile/mesgs/climb_pro_mesg
- fit/profile/mesgs/connectivity_mesg
- fit/profile/mesgs/course_mesg
- fit/profile/mesgs/course_point_mesg
- fit/profile/mesgs/developer_data_id_mesg
- fit/profile/mesgs/device_aux_battery_info_mesg
- fit/profile/mesgs/device_info_mesg
- fit/profile/mesgs/device_settings_mesg
- fit/profile/mesgs/dive_alarm_mesg
- fit/profile/mesgs/dive_apnea_alarm_mesg
- fit/profile/mesgs/dive_gas_mesg
- fit/profile/mesgs/dive_settings_mesg
- fit/profile/mesgs/dive_summary_mesg
- fit/profile/mesgs/event_mesg
- fit/profile/mesgs/exd_data_concept_configuration_mesg
- fit/profile/mesgs/exd_data_field_configuration_mesg
- fit/profile/mesgs/exd_screen_configuration_mesg
- fit/profile/mesgs/exercise_title_mesg
- fit/profile/mesgs/field_capabilities_mesg
- fit/profile/mesgs/field_description_mesg
- fit/profile/mesgs/file_capabilities_mesg
- fit/profile/mesgs/file_creator_mesg
- fit/profile/mesgs/file_id_mesg
- fit/profile/mesgs/goal_mesg
- fit/profile/mesgs/gps_metadata_mesg
- fit/profile/mesgs/gyroscope_data_mesg
- fit/profile/mesgs/hr_mesg
- fit/profile/mesgs/hr_zone_mesg
- fit/profile/mesgs/hrm_profile_mesg
- fit/profile/mesgs/hrv_mesg
- fit/profile/mesgs/hrv_status_summary_mesg
- fit/profile/mesgs/hrv_value_mesg
- fit/profile/mesgs/hsa_accelerometer_data_mesg
- fit/profile/mesgs/hsa_body_battery_data_mesg
- fit/profile/mesgs/hsa_configuration_data_mesg
- fit/profile/mesgs/hsa_event_mesg
- fit/profile/mesgs/hsa_gyroscope_data_mesg
- fit/profile/mesgs/hsa_heart_rate_data_mesg
- fit/profile/mesgs/hsa_respiration_data_mesg
- fit/profile/mesgs/hsa_spo2_data_mesg
- fit/profile/mesgs/hsa_step_data_mesg
- fit/profile/mesgs/hsa_stress_data_mesg
- fit/profile/mesgs/hsa_wrist_temperature_data_mesg
- fit/profile/mesgs/jump_mesg
- fit/profile/mesgs/lap_mesg
- fit/profile/mesgs/length_mesg
- fit/profile/mesgs/magnetometer_data_mesg
- fit/profile/mesgs/max_met_data_mesg
- fit/profile/mesgs/memo_glob_mesg
- fit/profile/mesgs/mesg_capabilities_mesg
- fit/profile/mesgs/mesgs
- fit/profile/mesgs/met_zone_mesg
- fit/profile/mesgs/monitoring_hr_data_mesg
- fit/profile/mesgs/monitoring_info_mesg
- fit/profile/mesgs/monitoring_mesg
- fit/profile/mesgs/nmea_sentence_mesg
- fit/profile/mesgs/obdii_data_mesg
- fit/profile/mesgs/ohr_settings_mesg
- fit/profile/mesgs/one_d_sensor_calibration_mesg
- fit/profile/mesgs/pad_mesg
- fit/profile/mesgs/power_zone_mesg
- fit/profile/mesgs/raw_bbi_mesg
- fit/profile/mesgs/record_mesg
- fit/profile/mesgs/respiration_rate_mesg
- fit/profile/mesgs/schedule_mesg
- fit/profile/mesgs/sdm_profile_mesg
- fit/profile/mesgs/segment_file_mesg
- fit/profile/mesgs/segment_id_mesg
- fit/profile/mesgs/segment_lap_mesg
- fit/profile/mesgs/segment_leaderboard_entry_mesg
- fit/profile/mesgs/segment_point_mesg
- fit/profile/mesgs/session_mesg
- fit/profile/mesgs/set_mesg
- fit/profile/mesgs/skin_temp_overnight_mesg
- fit/profile/mesgs/slave_device_mesg
- fit/profile/mesgs/sleep_assessment_mesg
- fit/profile/mesgs/sleep_disruption_overnight_severity_mesg
- fit/profile/mesgs/sleep_disruption_severity_period_mesg
- fit/profile/mesgs/sleep_level_mesg
- fit/profile/mesgs/software_mesg
- fit/profile/mesgs/speed_zone_mesg
- fit/profile/mesgs/split_mesg
- fit/profile/mesgs/split_summary_mesg
- fit/profile/mesgs/spo2_data_mesg
- fit/profile/mesgs/sport_mesg
- fit/profile/mesgs/stress_level_mesg
- fit/profile/mesgs/tank_summary_mesg
- fit/profile/mesgs/tank_update_mesg
- fit/profile/mesgs/three_d_sensor_calibration_mesg
- fit/profile/mesgs/time_in_zone_mesg
- fit/profile/mesgs/timestamp_correlation_mesg
- fit/profile/mesgs/totals_mesg
- fit/profile/mesgs/training_file_mesg
- fit/profile/mesgs/training_settings_mesg
- fit/profile/mesgs/user_profile_mesg
- fit/profile/mesgs/video_clip_mesg
- fit/profile/mesgs/video_description_mesg
- fit/profile/mesgs/video_frame_mesg
- fit/profile/mesgs/video_mesg
- fit/profile/mesgs/video_title_mesg
- fit/profile/mesgs/watchface_settings_mesg
- fit/profile/mesgs/weather_alert_mesg
- fit/profile/mesgs/weather_conditions_mesg
- fit/profile/mesgs/weight_scale_mesg
- fit/profile/mesgs/workout_mesg
- fit/profile/mesgs/workout_session_mesg
- fit/profile/mesgs/workout_step_mesg
- fit/profile/mesgs/zones_target_mesg
- fit/profile/types/activity
- fit/profile/types/activity_class
- fit/profile/types/activity_level
- fit/profile/types/activity_subtype
- fit/profile/types/activity_type
- fit/profile/types/analog_watchface_layout
- fit/profile/types/ant_channel_id
- fit/profile/types/ant_network
- fit/profile/types/antplus_device_type
- fit/profile/types/attitude_stage
- fit/profile/types/attitude_validity
- fit/profile/types/auto_activity_detect
- fit/profile/types/auto_sync_frequency
- fit/profile/types/autolap_trigger
- fit/profile/types/autoscroll
- fit/profile/types/backlight_mode
- fit/profile/types/backlight_timeout
- fit/profile/types/banded_exercises_exercise_name
- fit/profile/types/battery_status
- fit/profile/types/battle_rope_exercise_name
- fit/profile/types/bench_press_exercise_name
- fit/profile/types/bike_exercise_name
- fit/profile/types/bike_light_beam_angle_mode
- fit/profile/types/bike_light_network_config_type
- fit/profile/types/bike_outdoor_exercise_name
- fit/profile/types/ble_device_type
- fit/profile/types/body_location
- fit/profile/types/bp_status
- fit/profile/types/calf_raise_exercise_name
- fit/profile/types/camera_event_type
- fit/profile/types/camera_orientation_type
- fit/profile/types/cardio_exercise_name
- fit/profile/types/carry_exercise_name
- fit/profile/types/ccr_setpoint_switch_mode
- fit/profile/types/checksum
- fit/profile/types/chop_exercise_name
- fit/profile/types/climb_pro_event
- fit/profile/types/comm_timeout_type
- fit/profile/types/connectivity_capabilities
- fit/profile/types/core_exercise_name
- fit/profile/types/course_capabilities
- fit/profile/types/course_point
- fit/profile/types/crunch_exercise_name
- fit/profile/types/curl_exercise_name
- fit/profile/types/date_mode
- fit/profile/types/date_time
- fit/profile/types/day_of_week
- fit/profile/types/deadlift_exercise_name
- fit/profile/types/device_index
- fit/profile/types/digital_watchface_layout
- fit/profile/types/display_heart
- fit/profile/types/display_measure
- fit/profile/types/display_orientation
- fit/profile/types/display_position
- fit/profile/types/display_power
- fit/profile/types/dive_alarm_type
- fit/profile/types/dive_alert
- fit/profile/types/dive_backlight_mode
- fit/profile/types/dive_gas_mode
- fit/profile/types/dive_gas_status
- fit/profile/types/elliptical_exercise_name
- fit/profile/types/event
- fit/profile/types/event_type
- fit/profile/types/exd_data_units
- fit/profile/types/exd_descriptors
- fit/profile/types/exd_display_type
- fit/profile/types/exd_layout
- fit/profile/types/exd_qualifiers
- fit/profile/types/exercise_category
- fit/profile/types/favero_product
- fit/profile/types/file
- fit/profile/types/file_flags
- fit/profile/types/fit_base_type
- fit/profile/types/fit_base_unit
- fit/profile/types/fitness_equipment_state
- fit/profile/types/floor_climb_exercise_name
- fit/profile/types/flye_exercise_name
- fit/profile/types/garmin_product
- fit/profile/types/gas_consumption_rate_type
- fit/profile/types/gender
- fit/profile/types/goal
- fit/profile/types/goal_recurrence
- fit/profile/types/goal_source
- fit/profile/types/hip_raise_exercise_name
- fit/profile/types/hip_stability_exercise_name
- fit/profile/types/hip_swing_exercise_name
- fit/profile/types/hr_type
- fit/profile/types/hr_zone_calc
- fit/profile/types/hrv_status
- fit/profile/types/hyperextension_exercise_name
- fit/profile/types/indoor_bike_exercise_name
- fit/profile/types/indoor_row_exercise_name
- fit/profile/types/intensity
- fit/profile/types/ladder_exercise_name
- fit/profile/types/language
- fit/profile/types/language_bits_0
- fit/profile/types/language_bits_1
- fit/profile/types/language_bits_2
- fit/profile/types/language_bits_3
- fit/profile/types/language_bits_4
- fit/profile/types/lap_trigger
- fit/profile/types/lateral_raise_exercise_name
- fit/profile/types/left_right_balance
- fit/profile/types/left_right_balance_100
- fit/profile/types/leg_curl_exercise_name
- fit/profile/types/leg_raise_exercise_name
- fit/profile/types/length_type
- fit/profile/types/local_date_time
- fit/profile/types/local_device_type
- fit/profile/types/lunge_exercise_name
- fit/profile/types/manufacturer
- fit/profile/types/max_met_category
- fit/profile/types/max_met_heart_rate_source
- fit/profile/types/max_met_speed_source
- fit/profile/types/mesg_count
- fit/profile/types/mesg_num
- fit/profile/types/message_index
- fit/profile/types/move_exercise_name
- fit/profile/types/no_fly_time_mode
- fit/profile/types/olympic_lift_exercise_name
- fit/profile/types/plank_exercise_name
- fit/profile/types/plyo_exercise_name
- fit/profile/types/pose_exercise_name
- fit/profile/types/power_phase_type
- fit/profile/types/projectile_type
- fit/profile/types/pull_up_exercise_name
- fit/profile/types/push_up_exercise_name
- fit/profile/types/pwr_zone_calc
- fit/profile/types/radar_threat_level_type
- fit/profile/types/rider_position_type
- fit/profile/types/row_exercise_name
- fit/profile/types/run_exercise_name
- fit/profile/types/run_indoor_exercise_name
- fit/profile/types/sandbag_exercise_name
- fit/profile/types/schedule
- fit/profile/types/segment_delete_status
- fit/profile/types/segment_lap_status
- fit/profile/types/segment_leaderboard_type
- fit/profile/types/segment_selection_type
- fit/profile/types/sensor_type
- fit/profile/types/session_trigger
- fit/profile/types/set_type
- fit/profile/types/shoulder_press_exercise_name
- fit/profile/types/shoulder_stability_exercise_name
- fit/profile/types/shrug_exercise_name
- fit/profile/types/side
- fit/profile/types/sit_up_exercise_name
- fit/profile/types/sled_exercise_name
- fit/profile/types/sledge_hammer_exercise_name
- fit/profile/types/sleep_disruption_severity
- fit/profile/types/sleep_level
- fit/profile/types/source_type
- fit/profile/types/split_type
- fit/profile/types/spo2_measurement_type
- fit/profile/types/sport
- fit/profile/types/sport_bits_0
- fit/profile/types/sport_bits_1
- fit/profile/types/sport_bits_2
- fit/profile/types/sport_bits_3
- fit/profile/types/sport_bits_4
- fit/profile/types/sport_bits_5
- fit/profile/types/sport_bits_6
- fit/profile/types/sport_event
- fit/profile/types/squat_exercise_name
- fit/profile/types/stair_stepper_exercise_name
- fit/profile/types/stroke_type
- fit/profile/types/sub_sport
- fit/profile/types/supported_exd_screen_layouts
- fit/profile/types/suspension_exercise_name
- fit/profile/types/swim_stroke
- fit/profile/types/switch
- fit/profile/types/tap_sensitivity
- fit/profile/types/time_mode
- fit/profile/types/time_zone
- fit/profile/types/timer_trigger
- fit/profile/types/tire_exercise_name
- fit/profile/types/tissue_model_type
- fit/profile/types/tone
- fit/profile/types/total_body_exercise_name
- fit/profile/types/triceps_extension_exercise_name
- fit/profile/types/turn_type
- fit/profile/types/types
- fit/profile/types/user_local_id
- fit/profile/types/warm_up_exercise_name
- fit/profile/types/watchface_mode
- fit/profile/types/water_type
- fit/profile/types/weather_report
- fit/profile/types/weather_severe_type
- fit/profile/types/weather_severity
- fit/profile/types/weather_status
- fit/profile/types/weight
- fit/profile/types/wkt_step_duration
- fit/profile/types/wkt_step_target
- fit/profile/types/workout_capabilities
- fit/profile/types/workout_equipment
- fit/profile/types/workout_hr
- fit/profile/types/workout_power
- fit/protocol_validator
- fit/subfield
- fit_sdk
- FIT SDK for Dart
- utility/endian_binary_reader
- utility/endian_binary_writer