-
-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: add FIT File Types * docs: update documentation
- Loading branch information
Showing
34 changed files
with
2,217 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
package filedef | ||
|
||
import ( | ||
"github.com/muktihari/fit/factory" | ||
"github.com/muktihari/fit/profile/mesgdef" | ||
"github.com/muktihari/fit/profile/untyped/mesgnum" | ||
"github.com/muktihari/fit/proto" | ||
) | ||
|
||
// ActivitySummary is a compact version of the activity file and contain only activity, session and lap messages | ||
type ActivitySummary struct { | ||
FileId mesgdef.FileId // required fields: type, manufacturer, product, serial_number, time_created | ||
|
||
// Developer Data Lookup | ||
DeveloperDataIds []*mesgdef.DeveloperDataId | ||
FieldDescriptions []*mesgdef.FieldDescription | ||
|
||
Activity *mesgdef.Activity | ||
Sessions []*mesgdef.Session | ||
Laps []*mesgdef.Lap | ||
|
||
// Messages not related to Activity | ||
UnrelatedMessages []proto.Message | ||
} | ||
|
||
var _ File = &ActivitySummary{} | ||
|
||
func NewActivitySummary(mesgs ...proto.Message) *ActivitySummary { | ||
f := &ActivitySummary{} | ||
for i := range mesgs { | ||
f.Add(mesgs[i]) | ||
} | ||
|
||
return f | ||
} | ||
|
||
func (f *ActivitySummary) Add(mesg proto.Message) { | ||
switch mesg.Num { | ||
case mesgnum.FileId: | ||
f.FileId = *mesgdef.NewFileId(&mesg) | ||
case mesgnum.DeveloperDataId: | ||
f.DeveloperDataIds = append(f.DeveloperDataIds, mesgdef.NewDeveloperDataId(&mesg)) | ||
case mesgnum.FieldDescription: | ||
f.FieldDescriptions = append(f.FieldDescriptions, mesgdef.NewFieldDescription(&mesg)) | ||
case mesgnum.Activity: | ||
f.Activity = mesgdef.NewActivity(&mesg) | ||
case mesgnum.Session: | ||
f.Sessions = append(f.Sessions, mesgdef.NewSession(&mesg)) | ||
case mesgnum.Lap: | ||
f.Laps = append(f.Laps, mesgdef.NewLap(&mesg)) | ||
default: | ||
f.UnrelatedMessages = append(f.UnrelatedMessages, mesg) | ||
} | ||
} | ||
|
||
func (f *ActivitySummary) ToFit(fac mesgdef.Factory) proto.Fit { | ||
if fac == nil { | ||
fac = factory.StandardFactory() | ||
} | ||
|
||
var size = 2 // non slice fields | ||
|
||
size += len(f.Sessions) + len(f.Laps) + len(f.DeveloperDataIds) + | ||
len(f.FieldDescriptions) + len(f.UnrelatedMessages) | ||
|
||
fit := proto.Fit{ | ||
Messages: make([]proto.Message, 0, size), | ||
} | ||
|
||
// Should be as ordered: FieldId, DeveloperDataId and FieldDescription | ||
fit.Messages = append(fit.Messages, f.FileId.ToMesg(fac)) | ||
|
||
ToMesgs(&fit.Messages, fac, mesgnum.DeveloperDataId, f.DeveloperDataIds) | ||
ToMesgs(&fit.Messages, fac, mesgnum.FieldDescription, f.FieldDescriptions) | ||
|
||
if f.Activity != nil { | ||
fit.Messages = append(fit.Messages, f.Activity.ToMesg(fac)) | ||
} | ||
|
||
ToMesgs(&fit.Messages, fac, mesgnum.Session, f.Sessions) | ||
ToMesgs(&fit.Messages, fac, mesgnum.Lap, f.Laps) | ||
|
||
fit.Messages = append(fit.Messages, f.UnrelatedMessages...) | ||
|
||
SortMessagesByTimestamp(fit.Messages) | ||
|
||
return fit | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
// Copyright 2023 The Fit SDK for Go Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
package filedef_test | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
"time" | ||
|
||
"github.com/google/go-cmp/cmp" | ||
"github.com/muktihari/fit/factory" | ||
"github.com/muktihari/fit/kit/datetime" | ||
"github.com/muktihari/fit/profile/filedef" | ||
"github.com/muktihari/fit/profile/typedef" | ||
"github.com/muktihari/fit/profile/untyped/fieldnum" | ||
"github.com/muktihari/fit/profile/untyped/mesgnum" | ||
"github.com/muktihari/fit/proto" | ||
) | ||
|
||
func newActivitySummaryMessageForTest(now time.Time) []proto.Message { | ||
return []proto.Message{ | ||
factory.CreateMesgOnly(mesgnum.FileId).WithFields( | ||
factory.CreateField(mesgnum.FileId, fieldnum.FileIdType).WithValue(uint8(typedef.FileActivitySummary)), | ||
factory.CreateField(mesgnum.FileId, fieldnum.FileIdTimeCreated).WithValue(datetime.ToUint32(now)), | ||
), | ||
factory.CreateMesgOnly(mesgnum.DeveloperDataId).WithFields( | ||
factory.CreateField(mesgnum.DeveloperDataId, fieldnum.DeveloperDataIdDeveloperDataIndex).WithValue(uint8(0)), | ||
), | ||
factory.CreateMesgOnly(mesgnum.FieldDescription).WithFields( | ||
factory.CreateField(mesgnum.FieldDescription, fieldnum.FieldDescriptionDeveloperDataIndex).WithValue(uint8(0)), | ||
), | ||
factory.CreateMesgOnly(mesgnum.Lap).WithFields( | ||
factory.CreateField(mesgnum.Lap, fieldnum.LapTimestamp).WithValue(datetime.ToUint32(now)), // intentionally using same timestamp as last messag)e | ||
), | ||
factory.CreateMesgOnly(mesgnum.Session).WithFields( | ||
factory.CreateField(mesgnum.Session, fieldnum.SessionTimestamp).WithValue(datetime.ToUint32(incrementSecond(&now))), | ||
), | ||
factory.CreateMesgOnly(mesgnum.Activity).WithFields( | ||
factory.CreateField(mesgnum.Activity, fieldnum.ActivityTimestamp).WithValue(datetime.ToUint32(incrementSecond(&now))), | ||
), | ||
// Unrelated messages | ||
factory.CreateMesgOnly(mesgnum.BarometerData).WithFields( | ||
factory.CreateField(mesgnum.BarometerData, fieldnum.BarometerDataTimestamp).WithValue(datetime.ToUint32(incrementSecond(&now))), | ||
), | ||
factory.CreateMesgOnly(mesgnum.CoursePoint).WithFields( | ||
factory.CreateField(mesgnum.CoursePoint, fieldnum.CoursePointTimestamp).WithValue(datetime.ToUint32(incrementSecond(&now))), | ||
), | ||
} | ||
} | ||
|
||
func TestActivitySummaryCorrectness(t *testing.T) { | ||
mesgs := newActivitySummaryMessageForTest(time.Now()) | ||
|
||
activitySummary := filedef.NewActivitySummary(mesgs...) | ||
if activitySummary.FileId.Type != typedef.FileActivitySummary { | ||
t.Fatalf("expected: %v, got: %v", typedef.FileActivitySummary, activitySummary.FileId.Type) | ||
} | ||
|
||
fit := activitySummary.ToFit(nil) // use standard factory | ||
|
||
if diff := cmp.Diff(mesgs, fit.Messages, createFieldComparer()); diff != "" { | ||
fmt.Println("messages order:") | ||
for i := range fit.Messages { | ||
mesg := fit.Messages[i] | ||
fmt.Printf("%d: %s\n", mesg.Num, mesg.Num) | ||
} | ||
fmt.Println("") | ||
t.Fatal(diff) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
package filedef | ||
|
||
import ( | ||
"github.com/muktihari/fit/factory" | ||
"github.com/muktihari/fit/profile/mesgdef" | ||
"github.com/muktihari/fit/profile/untyped/mesgnum" | ||
"github.com/muktihari/fit/proto" | ||
) | ||
|
||
// BloodPressure files contain time-stamped discrete measurement data of blood pressure. | ||
type BloodPressure struct { | ||
FileId mesgdef.FileId // required fields: type, manufacturer, product, serial_number | ||
|
||
// Developer Data Lookup | ||
DeveloperDataIds []*mesgdef.DeveloperDataId | ||
FieldDescriptions []*mesgdef.FieldDescription | ||
|
||
UserProfile *mesgdef.UserProfile | ||
BloodPressures []*mesgdef.BloodPressure | ||
DeviceInfos []*mesgdef.DeviceInfo | ||
|
||
UnrelatedMessages []proto.Message | ||
} | ||
|
||
var _ File = &BloodPressure{} | ||
|
||
func NewBloodPressure(mesgs ...proto.Message) *BloodPressure { | ||
f := &BloodPressure{} | ||
for i := range mesgs { | ||
f.Add(mesgs[i]) | ||
} | ||
|
||
return f | ||
} | ||
|
||
func (f *BloodPressure) Add(mesg proto.Message) { | ||
switch mesg.Num { | ||
case mesgnum.FileId: | ||
f.FileId = *mesgdef.NewFileId(&mesg) | ||
case mesgnum.DeveloperDataId: | ||
f.DeveloperDataIds = append(f.DeveloperDataIds, mesgdef.NewDeveloperDataId(&mesg)) | ||
case mesgnum.FieldDescription: | ||
f.FieldDescriptions = append(f.FieldDescriptions, mesgdef.NewFieldDescription(&mesg)) | ||
case mesgnum.UserProfile: | ||
f.UserProfile = mesgdef.NewUserProfile(&mesg) | ||
case mesgnum.BloodPressure: | ||
f.BloodPressures = append(f.BloodPressures, mesgdef.NewBloodPressure(&mesg)) | ||
case mesgnum.DeviceInfo: | ||
f.DeviceInfos = append(f.DeviceInfos, mesgdef.NewDeviceInfo(&mesg)) | ||
default: | ||
f.UnrelatedMessages = append(f.UnrelatedMessages, mesg) | ||
} | ||
} | ||
|
||
func (f *BloodPressure) ToFit(fac mesgdef.Factory) proto.Fit { | ||
if fac == nil { | ||
fac = factory.StandardFactory() | ||
} | ||
|
||
var size = 2 // non slice fields | ||
|
||
size += len(f.BloodPressures) + len(f.DeviceInfos) + | ||
len(f.DeveloperDataIds) + len(f.FieldDescriptions) + len(f.UnrelatedMessages) | ||
|
||
fit := proto.Fit{ | ||
Messages: make([]proto.Message, 0, size), | ||
} | ||
|
||
// Should be as ordered: FieldId, DeveloperDataId and FieldDescription | ||
fit.Messages = append(fit.Messages, f.FileId.ToMesg(fac)) | ||
|
||
ToMesgs(&fit.Messages, fac, mesgnum.DeveloperDataId, f.DeveloperDataIds) | ||
ToMesgs(&fit.Messages, fac, mesgnum.FieldDescription, f.FieldDescriptions) | ||
|
||
if f.UserProfile != nil { | ||
fit.Messages = append(fit.Messages, f.UserProfile.ToMesg(fac)) | ||
} | ||
|
||
ToMesgs(&fit.Messages, fac, mesgnum.BloodPressure, f.BloodPressures) | ||
ToMesgs(&fit.Messages, fac, mesgnum.DeviceInfo, f.DeviceInfos) | ||
|
||
fit.Messages = append(fit.Messages, f.UnrelatedMessages...) | ||
|
||
SortMessagesByTimestamp(fit.Messages) | ||
|
||
return fit | ||
} |
Oops, something went wrong.