package fitparser // Common message numbers const ( MesgNumFileId = 0 MesgNumCapabilities = 1 MesgNumDeviceSettings = 2 MesgNumUserProfile = 3 MesgNumHrmProfile = 4 MesgNumSdmProfile = 5 MesgNumBikeProfile = 6 MesgNumZonesTarget = 7 MesgNumHrZone = 8 MesgNumPowerZone = 9 MesgNumMetZone = 10 MesgNumSport = 12 MesgNumGoal = 15 MesgNumSession = 18 MesgNumLap = 19 MesgNumRecord = 20 MesgNumEvent = 21 MesgNumDeviceInfo = 23 MesgNumWorkout = 26 MesgNumWorkoutStep = 27 MesgNumSchedule = 28 MesgNumActivity = 34 MesgNumSoftware = 35 MesgNumFileCapabilities = 37 MesgNumMesgCapabilities = 38 MesgNumFieldCapabilities = 39 MesgNumFileCreator = 49 MesgNumBloodPressure = 51 MesgNumSpeedZone = 53 MesgNumMonitoring = 55 MesgNumHrv = 78 MesgNumLength = 101 MesgNumMonitoringInfo = 103 MesgNumPad = 105 MesgNumSegmentLap = 142 ) // Common field numbers for FileId message const ( FieldFileIdType = 0 FieldFileIdManufacturer = 1 FieldFileIdProduct = 2 FieldFileIdSerialNumber = 3 FieldFileIdTimeCreated = 4 FieldFileIdNumber = 5 ) // Common field numbers for Record message const ( FieldRecordTimestamp = 253 FieldRecordPositionLat = 0 FieldRecordPositionLong = 1 FieldRecordAltitude = 2 FieldRecordHeartRate = 3 FieldRecordCadence = 4 FieldRecordDistance = 5 FieldRecordSpeed = 6 FieldRecordPower = 7 FieldRecordCompressedSpeedDistance = 8 FieldRecordGrade = 9 FieldRecordResistance = 10 FieldRecordTimeFromCourse = 11 FieldRecordCycleLength = 12 FieldRecordTemperature = 13 ) // Common field numbers for Lap message const ( FieldLapTimestamp = 253 FieldLapEvent = 0 FieldLapEventType = 1 FieldLapStartTime = 2 FieldLapStartPositionLat = 3 FieldLapStartPositionLong = 4 FieldLapEndPositionLat = 5 FieldLapEndPositionLong = 6 FieldLapTotalElapsedTime = 7 FieldLapTotalTimerTime = 8 FieldLapTotalDistance = 9 FieldLapTotalCycles = 10 FieldLapTotalCalories = 11 FieldLapTotalFatCalories = 12 FieldLapAvgSpeed = 13 FieldLapMaxSpeed = 14 FieldLapAvgHeartRate = 15 FieldLapMaxHeartRate = 16 FieldLapAvgCadence = 17 FieldLapMaxCadence = 18 FieldLapAvgPower = 19 FieldLapMaxPower = 20 ) // Common field numbers for Session message const ( FieldSessionTimestamp = 253 FieldSessionEvent = 0 FieldSessionEventType = 1 FieldSessionStartTime = 2 FieldSessionStartPositionLat = 3 FieldSessionStartPositionLong = 4 FieldSessionSport = 5 FieldSessionSubSport = 6 FieldSessionTotalElapsedTime = 7 FieldSessionTotalTimerTime = 8 FieldSessionTotalDistance = 9 FieldSessionTotalCycles = 10 FieldSessionTotalCalories = 11 FieldSessionTotalFatCalories = 13 FieldSessionAvgSpeed = 14 FieldSessionMaxSpeed = 15 FieldSessionAvgHeartRate = 16 FieldSessionMaxHeartRate = 17 FieldSessionAvgCadence = 18 FieldSessionMaxCadence = 19 FieldSessionAvgPower = 20 FieldSessionMaxPower = 21 ) // Common field numbers for Activity message const ( FieldActivityTimestamp = 253 FieldActivityTotalTimerTime = 0 FieldActivityNumSessions = 1 FieldActivityType = 2 FieldActivityEvent = 3 FieldActivityEventType = 4 FieldActivityLocalTimestamp = 5 FieldActivityEventGroup = 6 ) // File types const ( FileTypeDevice = 1 FileTypeSettings = 2 FileTypeSport = 3 FileTypeActivity = 4 FileTypeWorkout = 5 FileTypeCourse = 6 FileTypeSchedules = 7 FileTypeWeight = 9 FileTypeTotals = 10 FileTypeGoals = 11 FileTypeBloodPressure = 14 FileTypeMonitoringA = 15 FileTypeActivitySummary = 20 FileTypeMonitoringDaily = 28 FileTypeMonitoringB = 32 FileTypeSegment = 34 FileTypeSegmentList = 35 ) // Sport types const ( SportGeneric = 0 SportRunning = 1 SportCycling = 2 SportTransition = 3 SportFitnessEquipment = 4 SportSwimming = 5 SportBasketball = 6 SportSoccer = 7 SportTennis = 8 SportAmericanFootball = 9 SportTraining = 10 SportWalking = 11 SportCrossCountrySkiing = 12 SportAlpineSkiing = 13 SportSnowboarding = 14 SportRowing = 15 SportMountaineering = 16 SportHiking = 17 SportMultisport = 18 SportPaddling = 19 ) // GetMessageName returns a human-readable name for a message number func GetMessageName(mesgNum uint16) string { switch mesgNum { case MesgNumFileId: return "FileId" case MesgNumCapabilities: return "Capabilities" case MesgNumDeviceSettings: return "DeviceSettings" case MesgNumUserProfile: return "UserProfile" case MesgNumHrmProfile: return "HrmProfile" case MesgNumSdmProfile: return "SdmProfile" case MesgNumBikeProfile: return "BikeProfile" case MesgNumZonesTarget: return "ZonesTarget" case MesgNumHrZone: return "HrZone" case MesgNumPowerZone: return "PowerZone" case MesgNumMetZone: return "MetZone" case MesgNumSport: return "Sport" case MesgNumGoal: return "Goal" case MesgNumSession: return "Session" case MesgNumLap: return "Lap" case MesgNumRecord: return "Record" case MesgNumEvent: return "Event" case MesgNumDeviceInfo: return "DeviceInfo" case MesgNumActivity: return "Activity" case MesgNumSoftware: return "Software" case MesgNumFileCapabilities: return "FileCapabilities" case MesgNumMesgCapabilities: return "MesgCapabilities" case MesgNumFieldCapabilities: return "FieldCapabilities" case MesgNumFileCreator: return "FileCreator" case MesgNumBloodPressure: return "BloodPressure" case MesgNumSpeedZone: return "SpeedZone" case MesgNumMonitoring: return "Monitoring" case MesgNumHrv: return "Hrv" case MesgNumLength: return "Length" case MesgNumMonitoringInfo: return "MonitoringInfo" case MesgNumPad: return "Pad" case MesgNumSegmentLap: return "SegmentLap" default: return "Unknown" } } // GetFileTypeName returns a human-readable name for a file type func GetFileTypeName(fileType uint8) string { switch fileType { case FileTypeDevice: return "Device" case FileTypeSettings: return "Settings" case FileTypeSport: return "Sport" case FileTypeActivity: return "Activity" case FileTypeWorkout: return "Workout" case FileTypeCourse: return "Course" case FileTypeSchedules: return "Schedules" case FileTypeWeight: return "Weight" case FileTypeTotals: return "Totals" case FileTypeGoals: return "Goals" case FileTypeBloodPressure: return "BloodPressure" case FileTypeMonitoringA: return "MonitoringA" case FileTypeActivitySummary: return "ActivitySummary" case FileTypeMonitoringDaily: return "MonitoringDaily" case FileTypeMonitoringB: return "MonitoringB" case FileTypeSegment: return "Segment" case FileTypeSegmentList: return "SegmentList" default: return "Unknown" } } // GetSportName returns a human-readable name for a sport type func GetSportName(sport uint8) string { switch sport { case SportGeneric: return "Generic" case SportRunning: return "Running" case SportCycling: return "Cycling" case SportTransition: return "Transition" case SportFitnessEquipment: return "FitnessEquipment" case SportSwimming: return "Swimming" case SportBasketball: return "Basketball" case SportSoccer: return "Soccer" case SportTennis: return "Tennis" case SportAmericanFootball: return "AmericanFootball" case SportTraining: return "Training" case SportWalking: return "Walking" case SportCrossCountrySkiing: return "CrossCountrySkiing" case SportAlpineSkiing: return "AlpineSkiing" case SportSnowboarding: return "Snowboarding" case SportRowing: return "Rowing" case SportMountaineering: return "Mountaineering" case SportHiking: return "Hiking" case SportMultisport: return "Multisport" case SportPaddling: return "Paddling" default: return "Unknown" } } // ConvertSemicirclesToDegrees converts a position in semicircles to degrees // FIT files store lat/long as semicircles (2^31 semicircles = 180 degrees) func ConvertSemicirclesToDegrees(semicircles int32) float64 { return float64(semicircles) * (180.0 / 2147483648.0) }