Files
garminsync-go/internal/parser/parser.go
2025-08-25 15:24:23 -07:00

66 lines
1.5 KiB
Go

package parser
import (
"bytes"
"fmt"
"os"
"time"
"github.com/tormoder/fit"
"github.com/sstent/garminsync-go/internal/models"
)
// Parser handles FIT file parsing
type Parser struct{}
func NewParser() *Parser {
return &Parser{}
}
func (p *Parser) ParseFile(filename string) (*models.ActivityMetrics, error) {
file, err := os.Open(filename)
if err != nil {
return nil, err
}
defer file.Close()
data, err := os.ReadFile(filename)
if err != nil {
return nil, err
}
return p.ParseData(data)
}
func (p *Parser) ParseData(data []byte) (*models.ActivityMetrics, error) {
fitFile, err := fit.Decode(bytes.NewReader(data))
if err != nil {
return nil, fmt.Errorf("failed to decode FIT file: %w", err)
}
activity, err := fitFile.Activity()
if err != nil {
return nil, fmt.Errorf("failed to get activity from FIT: %w", err)
}
if len(activity.Sessions) == 0 {
return nil, fmt.Errorf("no sessions found in FIT file")
}
session := activity.Sessions[0]
metrics := &models.ActivityMetrics{
StartTime: session.StartTime,
Duration: time.Duration(session.TotalTimerTime) * time.Second,
Distance: float64(session.TotalDistance),
AvgHeartRate: int(session.AvgHeartRate),
MaxHeartRate: int(session.MaxHeartRate),
AvgPower: int(session.AvgPower),
Calories: int(session.TotalCalories),
ElevationGain: float64(session.TotalAscent),
ElevationLoss: float64(session.TotalDescent),
Steps: 0, // FIT sessions don't include steps
}
return metrics, nil
}