Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

reader: intial developer data fields support #65

Merged
merged 3 commits into from
Jan 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,6 @@ checkfull: checkdeps
@$(GO) vet $(FIT_PKGS)
@echo "vet --shadow"
@$(GO) vet -vettool=$(which shadow) $(FIT_PKGS)
@echo "golint"
@! $(BIN)golint $(FIT_PKGS) | grep -vE '(FileId|SegmentId|messages.go|types.*.\go|fitgen/internal/profile)'
@echo "errcheck"
@$(BIN)errcheck -ignore 'fmt:Fprinf*,bytes:Write*,archive/zip:Close,io:Close,Write' $(FIT_PKGS)
@echo "ineffassign"
Expand All @@ -129,7 +127,6 @@ checkdeps:
$(GO_BIN) $(GO) install github.com/gordonklaus/ineffassign
$(GO_BIN) $(GO) install github.com/kisielk/errcheck
$(GO_BIN) $(GO) install github.com/mdempsky/unconvert
$(GO_BIN) $(GO) install golang.org/x/lint/golint
$(GO_BIN) $(GO) install golang.org/x/tools/cmd/goimports
$(GO_BIN) $(GO) install honnef.co/go/tools/cmd/staticcheck
$(GO_BIN) $(GO) install mvdan.cc/gofumpt/gofumports
27 changes: 12 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,25 +21,21 @@ are required for running the full test suite and benchmarks.

_Note:_ 0.6.0 contains a breaking change, see #46.

### FIT SDK Version Support
### Version Support

**Current supported FIT SDK version:** 21.67
The current supported FIT SDK version is **21.67**.

**Warning:** Data Developers Fields are not yet supported (#21).
Developer data fields are currently only _partially_ supported.
At the moment the decoder parses Developer Data Field Descriptions, Developer Data ID Messages and Field Description Messages.
The decoder currently discards developer data fields found in records.

Older supported profile versions:
The encoder will currently (silently) ignore anything related to Developer data fields,
This also means that encoding will not fail if protocol version 2 is specified for a file header.

* 21.60
* 21.40
* 21.38
* 21.32
* 20.90
* 20.43
* 20.27
* 20.14
* 16.20

Other profile versions may work, but have not been tested.
Developer data fields support is tracked by
[#21](https://github.com/tormoder/fit/issues/21)
and
[#64](https://github.com/tormoder/fit/issues/64).

### Features

Expand Down Expand Up @@ -79,3 +75,4 @@ $ go get github.com/tormoder/fit
- [colinrgodsey](https://github.com/colinrgodsey)
- [bpg](https://github.com/bpg)
- [pieterclaerhout](https://github.com/pieterclaerhout)
- [beyoung](https://github.com/beyoung)
1 change: 1 addition & 0 deletions consts.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ const (
compressedLocalMesgNumMask byte = 0x60

mesgDefinitionMask byte = 0x40
devDataMask byte = 0x20
mesgHeaderMask byte = 0x00
localMesgNumMask byte = 0x0F

Expand Down
8 changes: 8 additions & 0 deletions file.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ type File struct {
FileCreator *FileCreatorMsg
TimestampCorrelation *TimestampCorrelationMsg

// Developer data fields.
fieldDescriptionMsgs []*FieldDescriptionMsg
developerDataIdMsgs []*DeveloperDataIdMsg

// UnknownMessages is a slice of unknown messages encountered during
// decoding. It is sorted by message number.
UnknownMessages []UnknownMessage
Expand Down Expand Up @@ -73,6 +77,10 @@ func (f *File) add(msg reflect.Value) {
f.FileCreator = &tmp
case TimestampCorrelationMsg:
f.TimestampCorrelation = &tmp
case FieldDescriptionMsg:
f.fieldDescriptionMsgs = append(f.fieldDescriptionMsgs, &tmp)
case DeveloperDataIdMsg:
f.developerDataIdMsgs = append(f.developerDataIdMsgs, &tmp)
default:
f.msgAdder.add(msg)
}
Expand Down
52 changes: 45 additions & 7 deletions reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -315,17 +315,18 @@ func (d *decoder) readFull(p []byte) error {
}

type defmsg struct {
localMsgType uint8
arch binary.ByteOrder
globalMsgNum MesgNum
fields byte
fieldDefs []fieldDef
localMsgType uint8
arch binary.ByteOrder
globalMsgNum MesgNum
fields byte
fieldDefs []fieldDef
devDataFieldDescs []devDataFieldDesc
}

func (dm defmsg) String() string {
return fmt.Sprintf(
"local: %d | global: %v | arch: %v | fields: %d",
dm.localMsgType, dm.globalMsgNum, dm.arch, dm.fields,
"local: %d | global: %v | arch: %v | fields: %d | data dev fields: %d",
dm.localMsgType, dm.globalMsgNum, dm.arch, dm.fields, len(dm.devDataFieldDescs),
)
}

Expand All @@ -339,6 +340,16 @@ func (fd fieldDef) String() string {
return fmt.Sprintf("num: %d | size: %d | btype: %v", fd.num, fd.size, fd.btype)
}

type devDataFieldDesc struct {
fieldNum byte
size byte
devDataIndex byte
}

func (ddfd devDataFieldDesc) String() string {
return fmt.Sprintf("field number: %d | size: %d | developer data index: %d", ddfd.fieldNum, ddfd.size, ddfd.devDataIndex)
}

func (d *decoder) parseFileIdMsg() error {
b, err := d.readByte()
if err != nil {
Expand Down Expand Up @@ -452,6 +463,26 @@ func (d *decoder) parseDefinitionMessage(recordHeader byte) (*defmsg, error) {
dm.fieldDefs[i] = fd
}

if recordHeader&devDataMask == devDataMask {
numDevFields, err := d.readByte()
if err != nil {
return nil, fmt.Errorf("error reading number of developer data fields: %w", err)
}

if err = d.readFull(d.tmp[0 : 3*uint16(numDevFields)]); err != nil {
return nil, fmt.Errorf("error reading developer data field description data: %w", err)
}

dm.devDataFieldDescs = make([]devDataFieldDesc, numDevFields)
for i, ddfd := range dm.devDataFieldDescs {
ddfd.fieldNum = d.tmp[i*3]
ddfd.size = d.tmp[(i*3)+1]
ddfd.devDataIndex = d.tmp[(i*3)+2]
dm.devDataFieldDescs[i] = ddfd
}

}

if d.debug {
d.opts.logger.Println("definition message parsed:", dm)
}
Expand Down Expand Up @@ -669,6 +700,13 @@ func (d *decoder) parseDataFields(dm *defmsg, knownMsg bool, msgv reflect.Value)
}
}

for i, ddfd := range dm.devDataFieldDescs {
err := d.readFull(d.tmp[0:int(ddfd.size)])
if err != nil {
return reflect.Value{}, fmt.Errorf("error parsing data developer message: %v (field %d [%v] for [%v])", err, i, ddfd, dm)
}
}

if knownMsg && !msgv.IsValid() {
panic("internal decoder error: parse data fields: known message, but not (reflect) valid")
}
Expand Down
Loading