mirror of
https://github.com/sstent/go-garth.git
synced 2026-02-06 14:32:22 +00:00
changed go mod name
This commit is contained in:
@@ -2,6 +2,11 @@ package types
|
|||||||
|
|
||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
|
// TokenRefresher is an interface for refreshing a token.
|
||||||
|
type TokenRefresher interface {
|
||||||
|
RefreshSession() error
|
||||||
|
}
|
||||||
|
|
||||||
// OAuthConsumer represents OAuth consumer credentials
|
// OAuthConsumer represents OAuth consumer credentials
|
||||||
type OAuthConsumer struct {
|
type OAuthConsumer struct {
|
||||||
ConsumerKey string `json:"consumer_key"`
|
ConsumerKey string `json:"consumer_key"`
|
||||||
@@ -25,4 +30,18 @@ type OAuth2Token struct {
|
|||||||
Scope string `json:"scope"`
|
Scope string `json:"scope"`
|
||||||
CreatedAt time.Time // Used for expiration tracking
|
CreatedAt time.Time // Used for expiration tracking
|
||||||
ExpiresAt time.Time // Computed expiration time
|
ExpiresAt time.Time // Computed expiration time
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Expired checks if token is expired
|
||||||
|
func (t *OAuth2Token) Expired() bool {
|
||||||
|
return time.Now().After(t.ExpiresAt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RefreshIfNeeded refreshes token if expired
|
||||||
|
func (t *OAuth2Token) RefreshIfNeeded(client TokenRefresher) error {
|
||||||
|
if !t.Expired() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return client.RefreshSession()
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,469 +0,0 @@
|
|||||||
package types
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// TokenRefresher is an interface for refreshing a token.
|
|
||||||
type TokenRefresher interface {
|
|
||||||
RefreshSession() error
|
|
||||||
}
|
|
||||||
|
|
||||||
// OAuthConsumer represents OAuth consumer credentials
|
|
||||||
type OAuthConsumer struct {
|
|
||||||
ConsumerKey string `json:"consumer_key"`
|
|
||||||
ConsumerSecret string `json:"consumer_secret"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// OAuth1Token represents OAuth1 token response
|
|
||||||
type OAuth1Token struct {
|
|
||||||
OAuthToken string `json:"oauth_token"`
|
|
||||||
OAuthTokenSecret string `json:"oauth_token_secret"`
|
|
||||||
MFAToken string `json:"mfa_token,omitempty"`
|
|
||||||
Domain string `json:"domain"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// OAuth2Token represents OAuth2 token response
|
|
||||||
type OAuth2Token struct {
|
|
||||||
AccessToken string `json:"access_token"`
|
|
||||||
TokenType string `json:"token_type"`
|
|
||||||
ExpiresIn int `json:"expires_in"`
|
|
||||||
RefreshToken string `json:"refresh_token"`
|
|
||||||
Scope string `json:"scope"`
|
|
||||||
ExpiresAt time.Time `json:"expires_at"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// SessionData represents the data stored in a session file
|
|
||||||
type SessionData struct {
|
|
||||||
Domain string `json:"domain"`
|
|
||||||
Username string `json:"username"`
|
|
||||||
AuthToken string `json:"auth_token"`
|
|
||||||
OAuth2Token *OAuth2Token `json:"oauth2_token"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Expired checks if token is expired
|
|
||||||
func (t *OAuth2Token) Expired() bool {
|
|
||||||
return time.Now().After(t.ExpiresAt)
|
|
||||||
}
|
|
||||||
|
|
||||||
// RefreshIfNeeded refreshes token if expired
|
|
||||||
func (t *OAuth2Token) RefreshIfNeeded(client TokenRefresher) error {
|
|
||||||
if !t.Expired() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return client.RefreshSession()
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
// Default location for conversions (set to UTC by default)
|
|
||||||
defaultLocation *time.Location
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
var err error
|
|
||||||
defaultLocation, err = time.LoadLocation("UTC")
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseTimestamp converts a millisecond timestamp to time.Time in default location
|
|
||||||
func ParseTimestamp(ts int) time.Time {
|
|
||||||
return time.Unix(0, int64(ts)*int64(time.Millisecond)).In(defaultLocation)
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseAggregationKey is a helper function to parse aggregation key back to a time.Time object
|
|
||||||
func ParseAggregationKey(key, aggregate string) time.Time {
|
|
||||||
switch aggregate {
|
|
||||||
case "day":
|
|
||||||
t, _ := time.Parse("2006-01-02", key)
|
|
||||||
return t
|
|
||||||
case "week":
|
|
||||||
year, _ := strconv.Atoi(key[:4])
|
|
||||||
week, _ := strconv.Atoi(key[6:])
|
|
||||||
t := time.Date(year, 1, 1, 0, 0, 0, 0, time.UTC)
|
|
||||||
// Find the first Monday of the year
|
|
||||||
for t.Weekday() != time.Monday {
|
|
||||||
t = t.AddDate(0, 0, 1)
|
|
||||||
}
|
|
||||||
// Add weeks
|
|
||||||
return t.AddDate(0, 0, (week-1)*7)
|
|
||||||
case "month":
|
|
||||||
t, _ := time.Parse("2006-01", key)
|
|
||||||
return t
|
|
||||||
case "year":
|
|
||||||
t, _ := time.Parse("2006", key)
|
|
||||||
return t
|
|
||||||
}
|
|
||||||
return time.Time{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GarminTime represents Garmin's timestamp format with custom JSON parsing
|
|
||||||
type GarminTime struct {
|
|
||||||
time.Time
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalJSON implements the json.Unmarshaler interface.
|
|
||||||
// It parses Garmin's specific timestamp format.
|
|
||||||
func (gt *GarminTime) UnmarshalJSON(b []byte) (err error) {
|
|
||||||
s := strings.Trim(string(b), `"`)
|
|
||||||
if s == "null" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try parsing with milliseconds (e.g., "2018-09-01T00:13:25.000")
|
|
||||||
// Garmin sometimes returns .0 for milliseconds, which Go's time.Parse handles as .000
|
|
||||||
// The 'Z' in the layout indicates a UTC time without a specific offset, which is often how these are interpreted.
|
|
||||||
// If the input string does not contain 'Z', it will be parsed as local time.
|
|
||||||
// For consistency, we'll assume UTC if no timezone is specified.
|
|
||||||
layouts := []string{
|
|
||||||
"2006-01-02T15:04:05.0", // Example: 2018-09-01T00:13:25.0
|
|
||||||
"2006-01-02T15:04:05", // Example: 2018-09-01T00:13:25
|
|
||||||
"2006-01-02 15:04:05", // Example: 2025-09-18 15:14:40
|
|
||||||
"2006-01-02", // Example: 2018-09-01
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, layout := range layouts {
|
|
||||||
if t, err := time.Parse(layout, s); err == nil {
|
|
||||||
gt.Time = t
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return fmt.Errorf("cannot parse %q into a GarminTime", s)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ActivityType represents the type of activity
|
|
||||||
type ActivityType struct {
|
|
||||||
TypeID int `json:"typeId"`
|
|
||||||
TypeKey string `json:"typeKey"`
|
|
||||||
ParentTypeID *int `json:"parentTypeId,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// EventType represents the event type of an activity
|
|
||||||
type EventType struct {
|
|
||||||
TypeID int `json:"typeId"`
|
|
||||||
TypeKey string `json:"typeKey"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Activity represents a Garmin Connect activity
|
|
||||||
type Activity struct {
|
|
||||||
ActivityID int64 `json:"activityId"`
|
|
||||||
ActivityName string `json:"activityName"`
|
|
||||||
Description string `json:"description"`
|
|
||||||
StartTimeLocal GarminTime `json:"startTimeLocal"`
|
|
||||||
StartTimeGMT GarminTime `json:"startTimeGMT"`
|
|
||||||
ActivityType ActivityType `json:"activityType"`
|
|
||||||
EventType EventType `json:"eventType"`
|
|
||||||
Distance float64 `json:"distance"`
|
|
||||||
Duration float64 `json:"duration"`
|
|
||||||
ElapsedDuration float64 `json:"elapsedDuration"`
|
|
||||||
MovingDuration float64 `json:"movingDuration"`
|
|
||||||
ElevationGain float64 `json:"elevationGain"`
|
|
||||||
ElevationLoss float64 `json:"elevationLoss"`
|
|
||||||
AverageSpeed float64 `json:"averageSpeed"`
|
|
||||||
MaxSpeed float64 `json:"maxSpeed"`
|
|
||||||
Calories float64 `json:"calories"`
|
|
||||||
AverageHR float64 `json:"averageHR"`
|
|
||||||
MaxHR float64 `json:"maxHR"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// UserProfile represents a Garmin user profile
|
|
||||||
type UserProfile struct {
|
|
||||||
UserName string `json:"userName"`
|
|
||||||
DisplayName string `json:"displayName"`
|
|
||||||
LevelUpdateDate GarminTime `json:"levelUpdateDate"`
|
|
||||||
// Add other fields as needed from API response
|
|
||||||
}
|
|
||||||
|
|
||||||
// VO2MaxData represents VO2 max data
|
|
||||||
type VO2MaxData struct {
|
|
||||||
Date time.Time `json:"calendarDate"`
|
|
||||||
VO2MaxRunning *float64 `json:"vo2MaxRunning"`
|
|
||||||
VO2MaxCycling *float64 `json:"vo2MaxCycling"`
|
|
||||||
UserProfilePK int `json:"userProfilePk"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add these new structs
|
|
||||||
type VO2MaxEntry struct {
|
|
||||||
Value float64 `json:"value"`
|
|
||||||
ActivityType string `json:"activityType"` // "running" or "cycling"
|
|
||||||
Date time.Time `json:"date"`
|
|
||||||
Source string `json:"source"` // "user_settings", "activity", etc.
|
|
||||||
}
|
|
||||||
|
|
||||||
type VO2Max struct {
|
|
||||||
Value float64 `json:"vo2Max"`
|
|
||||||
FitnessLevel string `json:"fitnessLevel"`
|
|
||||||
UpdatedDate time.Time `json:"date"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// VO2MaxProfile represents the current VO2 max profile from user settings
|
|
||||||
type VO2MaxProfile struct {
|
|
||||||
UserProfilePK int `json:"userProfilePk"`
|
|
||||||
LastUpdated time.Time `json:"lastUpdated"`
|
|
||||||
Running *VO2MaxEntry `json:"running,omitempty"`
|
|
||||||
Cycling *VO2MaxEntry `json:"cycling,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// SleepLevel represents different sleep stages
|
|
||||||
type SleepLevel struct {
|
|
||||||
StartGMT time.Time `json:"startGmt"`
|
|
||||||
EndGMT time.Time `json:"endGmt"`
|
|
||||||
ActivityLevel float64 `json:"activityLevel"`
|
|
||||||
SleepLevel string `json:"sleepLevel"` // "deep", "light", "rem", "awake"
|
|
||||||
}
|
|
||||||
|
|
||||||
// SleepMovement represents movement during sleep
|
|
||||||
type SleepMovement struct {
|
|
||||||
StartGMT time.Time `json:"startGmt"`
|
|
||||||
EndGMT time.Time `json:"endGmt"`
|
|
||||||
ActivityLevel float64 `json:"activityLevel"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// SleepScore represents detailed sleep scoring
|
|
||||||
type SleepScore struct {
|
|
||||||
Overall int `json:"overall"`
|
|
||||||
Composition SleepScoreBreakdown `json:"composition"`
|
|
||||||
Revitalization SleepScoreBreakdown `json:"revitalization"`
|
|
||||||
Duration SleepScoreBreakdown `json:"duration"`
|
|
||||||
DeepPercentage float64 `json:"deepPercentage"`
|
|
||||||
LightPercentage float64 `json:"lightPercentage"`
|
|
||||||
RemPercentage float64 `json:"remPercentage"`
|
|
||||||
RestfulnessValue float64 `json:"restfulnessValue"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type SleepScoreBreakdown struct {
|
|
||||||
QualifierKey string `json:"qualifierKey"`
|
|
||||||
OptimalStart float64 `json:"optimalStart"`
|
|
||||||
OptimalEnd float64 `json:"optimalEnd"`
|
|
||||||
Value float64 `json:"value"`
|
|
||||||
IdealStartSecs *int `json:"idealStartInSeconds"`
|
|
||||||
IdealEndSecs *int `json:"idealEndInSeconds"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// DetailedSleepData represents comprehensive sleep data
|
|
||||||
type DetailedSleepData struct {
|
|
||||||
UserProfilePK int `json:"userProfilePk"`
|
|
||||||
CalendarDate time.Time `json:"calendarDate"`
|
|
||||||
SleepStartTimestampGMT time.Time `json:"sleepStartTimestampGmt"`
|
|
||||||
SleepEndTimestampGMT time.Time `json:"sleepEndTimestampGmt"`
|
|
||||||
SleepStartTimestampLocal time.Time `json:"sleepStartTimestampLocal"`
|
|
||||||
SleepEndTimestampLocal time.Time `json:"sleepEndTimestampLocal"`
|
|
||||||
UnmeasurableSleepSeconds int `json:"unmeasurableSleepSeconds"`
|
|
||||||
DeepSleepSeconds int `json:"deepSleepSeconds"`
|
|
||||||
LightSleepSeconds int `json:"lightSleepSeconds"`
|
|
||||||
RemSleepSeconds int `json:"remSleepSeconds"`
|
|
||||||
AwakeSleepSeconds int `json:"awakeSleepSeconds"`
|
|
||||||
DeviceRemCapable bool `json:"deviceRemCapable"`
|
|
||||||
SleepLevels []SleepLevel `json:"sleepLevels"`
|
|
||||||
SleepMovement []SleepMovement `json:"sleepMovement"`
|
|
||||||
SleepScores *SleepScore `json:"sleepScores"`
|
|
||||||
AverageSpO2Value *float64 `json:"averageSpO2Value"`
|
|
||||||
LowestSpO2Value *int `json:"lowestSpO2Value"`
|
|
||||||
HighestSpO2Value *int `json:"highestSpO2Value"`
|
|
||||||
AverageRespirationValue *float64 `json:"averageRespirationValue"`
|
|
||||||
LowestRespirationValue *float64 `json:"lowestRespirationValue"`
|
|
||||||
HighestRespirationValue *float64 `json:"highestRespirationValue"`
|
|
||||||
AvgSleepStress *float64 `json:"avgSleepStress"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// HRVBaseline represents HRV baseline data
|
|
||||||
type HRVBaseline struct {
|
|
||||||
LowUpper int `json:"lowUpper"`
|
|
||||||
BalancedLow int `json:"balancedLow"`
|
|
||||||
BalancedUpper int `json:"balancedUpper"`
|
|
||||||
MarkerValue float64 `json:"markerValue"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// DailyHRVData represents comprehensive daily HRV data
|
|
||||||
type DailyHRVData struct {
|
|
||||||
UserProfilePK int `json:"userProfilePk"`
|
|
||||||
CalendarDate time.Time `json:"calendarDate"`
|
|
||||||
WeeklyAvg *float64 `json:"weeklyAvg"`
|
|
||||||
LastNightAvg *float64 `json:"lastNightAvg"`
|
|
||||||
LastNight5MinHigh *float64 `json:"lastNight5MinHigh"`
|
|
||||||
Baseline HRVBaseline `json:"baseline"`
|
|
||||||
Status string `json:"status"`
|
|
||||||
FeedbackPhrase string `json:"feedbackPhrase"`
|
|
||||||
CreateTimeStamp time.Time `json:"createTimeStamp"`
|
|
||||||
HRVReadings []HRVReading `json:"hrvReadings"`
|
|
||||||
StartTimestampGMT time.Time `json:"startTimestampGmt"`
|
|
||||||
EndTimestampGMT time.Time `json:"endTimestampGmt"`
|
|
||||||
StartTimestampLocal time.Time `json:"startTimestampLocal"`
|
|
||||||
EndTimestampLocal time.Time `json:"endTimestampLocal"`
|
|
||||||
SleepStartTimestampGMT time.Time `json:"sleepStartTimestampGmt"`
|
|
||||||
SleepEndTimestampGMT time.Time `json:"sleepEndTimestampGmt"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// BodyBatteryEvent represents events that impact Body Battery
|
|
||||||
type BodyBatteryEvent struct {
|
|
||||||
EventType string `json:"eventType"` // "sleep", "activity", "stress"
|
|
||||||
EventStartTimeGMT time.Time `json:"eventStartTimeGmt"`
|
|
||||||
TimezoneOffset int `json:"timezoneOffset"`
|
|
||||||
DurationInMilliseconds int `json:"durationInMilliseconds"`
|
|
||||||
BodyBatteryImpact int `json:"bodyBatteryImpact"`
|
|
||||||
FeedbackType string `json:"feedbackType"`
|
|
||||||
ShortFeedback string `json:"shortFeedback"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// DetailedBodyBatteryData represents comprehensive Body Battery data
|
|
||||||
type DetailedBodyBatteryData struct {
|
|
||||||
UserProfilePK int `json:"userProfilePk"`
|
|
||||||
CalendarDate time.Time `json:"calendarDate"`
|
|
||||||
StartTimestampGMT time.Time `json:"startTimestampGmt"`
|
|
||||||
EndTimestampGMT time.Time `json:"endTimestampGmt"`
|
|
||||||
StartTimestampLocal time.Time `json:"startTimestampLocal"`
|
|
||||||
EndTimestampLocal time.Time `json:"endTimestampLocal"`
|
|
||||||
MaxStressLevel int `json:"maxStressLevel"`
|
|
||||||
AvgStressLevel int `json:"avgStressLevel"`
|
|
||||||
BodyBatteryValuesArray [][]interface{} `json:"bodyBatteryValuesArray"`
|
|
||||||
StressValuesArray [][]int `json:"stressValuesArray"`
|
|
||||||
Events []BodyBatteryEvent `json:"bodyBatteryEvents"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// TrainingStatus represents current training status
|
|
||||||
type TrainingStatus struct {
|
|
||||||
CalendarDate time.Time `json:"calendarDate"`
|
|
||||||
TrainingStatusKey string `json:"trainingStatusKey"` // "DETRAINING", "RECOVERY", "MAINTAINING", "PRODUCTIVE", "PEAKING", "OVERREACHING", "UNPRODUCTIVE", "NONE"
|
|
||||||
TrainingStatusTypeKey string `json:"trainingStatusTypeKey"`
|
|
||||||
TrainingStatusValue int `json:"trainingStatusValue"`
|
|
||||||
LoadRatio float64 `json:"loadRatio"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// TrainingLoad represents training load data
|
|
||||||
type TrainingLoad struct {
|
|
||||||
CalendarDate time.Time `json:"calendarDate"`
|
|
||||||
AcuteTrainingLoad float64 `json:"acuteTrainingLoad"`
|
|
||||||
ChronicTrainingLoad float64 `json:"chronicTrainingLoad"`
|
|
||||||
TrainingLoadRatio float64 `json:"trainingLoadRatio"`
|
|
||||||
TrainingEffectAerobic float64 `json:"trainingEffectAerobic"`
|
|
||||||
TrainingEffectAnaerobic float64 `json:"trainingEffectAnaerobic"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// FitnessAge represents fitness age calculation
|
|
||||||
type FitnessAge struct {
|
|
||||||
FitnessAge int `json:"fitnessAge"`
|
|
||||||
ChronologicalAge int `json:"chronologicalAge"`
|
|
||||||
VO2MaxRunning float64 `json:"vo2MaxRunning"`
|
|
||||||
LastUpdated time.Time `json:"lastUpdated"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// HeartRateZones represents heart rate zone data
|
|
||||||
type HeartRateZones struct {
|
|
||||||
RestingHR int `json:"resting_hr"`
|
|
||||||
MaxHR int `json:"max_hr"`
|
|
||||||
LactateThreshold int `json:"lactate_threshold"`
|
|
||||||
Zones []HRZone `json:"zones"`
|
|
||||||
UpdatedAt time.Time `json:"updated_at"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// HRZone represents a single heart rate zone
|
|
||||||
type HRZone struct {
|
|
||||||
Zone int `json:"zone"`
|
|
||||||
MinBPM int `json:"min_bpm"`
|
|
||||||
MaxBPM int `json:"max_bpm"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// WellnessData represents additional wellness metrics
|
|
||||||
type WellnessData struct {
|
|
||||||
Date time.Time `json:"calendarDate"`
|
|
||||||
RestingHR *int `json:"resting_hr"`
|
|
||||||
Weight *float64 `json:"weight"`
|
|
||||||
BodyFat *float64 `json:"body_fat"`
|
|
||||||
BMI *float64 `json:"bmi"`
|
|
||||||
BodyWater *float64 `json:"body_water"`
|
|
||||||
BoneMass *float64 `json:"bone_mass"`
|
|
||||||
MuscleMass *float64 `json:"muscle_mass"`
|
|
||||||
// Add more fields as needed
|
|
||||||
}
|
|
||||||
|
|
||||||
// SleepData represents sleep summary data
|
|
||||||
type SleepData struct {
|
|
||||||
Date time.Time `json:"calendarDate"`
|
|
||||||
SleepScore int `json:"sleepScore"`
|
|
||||||
TotalSleepSeconds int `json:"totalSleepSeconds"`
|
|
||||||
DeepSleepSeconds int `json:"deepSleepSeconds"`
|
|
||||||
LightSleepSeconds int `json:"lightSleepSeconds"`
|
|
||||||
RemSleepSeconds int `json:"remSleepSeconds"`
|
|
||||||
AwakeSleepSeconds int `json:"awakeSleepSeconds"`
|
|
||||||
// Add more fields as needed
|
|
||||||
}
|
|
||||||
|
|
||||||
// HrvData represents Heart Rate Variability data
|
|
||||||
type HrvData struct {
|
|
||||||
Date time.Time `json:"calendarDate"`
|
|
||||||
HrvValue float64 `json:"hrvValue"`
|
|
||||||
// Add more fields as needed
|
|
||||||
}
|
|
||||||
|
|
||||||
// HRVStatus represents HRV status and baseline
|
|
||||||
type HRVStatus struct {
|
|
||||||
Status string `json:"status"` // "BALANCED", "UNBALANCED", "POOR"
|
|
||||||
FeedbackPhrase string `json:"feedbackPhrase"`
|
|
||||||
BaselineLowUpper int `json:"baselineLowUpper"`
|
|
||||||
BalancedLow int `json:"balancedLow"`
|
|
||||||
BalancedUpper int `json:"balancedUpper"`
|
|
||||||
MarkerValue float64 `json:"markerValue"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// HRVReading represents an individual HRV reading
|
|
||||||
type HRVReading struct {
|
|
||||||
Timestamp int `json:"timestamp"`
|
|
||||||
StressLevel int `json:"stressLevel"`
|
|
||||||
HeartRate int `json:"heartRate"`
|
|
||||||
RRInterval int `json:"rrInterval"`
|
|
||||||
Status string `json:"status"`
|
|
||||||
SignalQuality float64 `json:"signalQuality"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// TimestampAsTime converts the reading timestamp to time.Time using timeutils
|
|
||||||
func (r *HRVReading) TimestampAsTime() time.Time {
|
|
||||||
return ParseTimestamp(r.Timestamp)
|
|
||||||
}
|
|
||||||
|
|
||||||
// RRSeconds converts the RR interval to seconds
|
|
||||||
func (r *HRVReading) RRSeconds() float64 {
|
|
||||||
return float64(r.RRInterval) / 1000.0
|
|
||||||
}
|
|
||||||
|
|
||||||
// StressData represents stress level data
|
|
||||||
type StressData struct {
|
|
||||||
Date time.Time `json:"calendarDate"`
|
|
||||||
StressLevel int `json:"stressLevel"`
|
|
||||||
RestStressLevel int `json:"restStressLevel"`
|
|
||||||
// Add more fields as needed
|
|
||||||
}
|
|
||||||
|
|
||||||
// BodyBatteryData represents Body Battery data
|
|
||||||
type BodyBatteryData struct {
|
|
||||||
Date time.Time `json:"calendarDate"`
|
|
||||||
BatteryLevel int `json:"batteryLevel"`
|
|
||||||
Charge int `json:"charge"`
|
|
||||||
Drain int `json:"drain"`
|
|
||||||
// Add more fields as needed
|
|
||||||
}
|
|
||||||
|
|
||||||
// StepsData represents steps statistics
|
|
||||||
type StepsData struct {
|
|
||||||
Date time.Time `json:"calendarDate"`
|
|
||||||
Steps int `json:"steps"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// DistanceData represents distance statistics
|
|
||||||
type DistanceData struct {
|
|
||||||
Date time.Time `json:"calendarDate"`
|
|
||||||
Distance float64 `json:"distance"` // in meters
|
|
||||||
}
|
|
||||||
|
|
||||||
// CaloriesData represents calories statistics
|
|
||||||
type CaloriesData struct {
|
|
||||||
Date time.Time `json:"calendarDate"`
|
|
||||||
Calories int `json:"activeCalories"`
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user