Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
88 commits
Select commit Hold shift + click to select a range
9ed802c
fix: Typo leading to uint16 to never be invalidated
Sep 17, 2018
1ff0fa4
fix: Adjusted offset for all altitude-related fields
Sep 17, 2018
3eef5f7
chore: preparing to release fork internally
Sep 17, 2018
3dd185e
⏩ [PUB] (release) 1.0.0
Sep 17, 2018
70b3eb6
fix: Applied to src/fit offset adjustments from commit 9ed802
Sep 18, 2018
2ebd036
⏩ [PUB] (release) 1.0.1
Sep 18, 2018
656b159
Merge pull request #1 from PolideaInternal/master
jimmykane Oct 13, 2018
0b00497
wip sdk update
dylandevs Nov 21, 2018
cc2af53
adding exercise names
dylandevs Nov 21, 2018
6f97398
Updating SDK and logging some info for research
dylandevs Nov 21, 2018
e311323
typo
dylandevs Nov 21, 2018
be00bb8
typo
dylandevs Nov 22, 2018
7ccc6e2
typo
dylandevs Nov 22, 2018
eb23ff5
Added diving
dylandevs Nov 22, 2018
e7062b0
Added dive definitions
dylandevs Nov 23, 2018
f286f2f
Updated timestamp
dylandevs Nov 24, 2018
ab6822a
Added parsing for new data types
dylandevs Jan 22, 2019
a44e4db
Merge remote-tracking branch 'JoeTheFkingFrypan/master'
jimmykane Jan 25, 2019
ae10fb3
parse hrv
jimmykane Jan 27, 2019
c3077d6
remove
jimmykane Jan 27, 2019
dd66317
kill this as it breaks deps
jimmykane Jan 27, 2019
b6853e0
Merge branch 'master' into updating-fit-sdk
dylandevs Jan 28, 2019
0d4ec23
Added new data types to src
dylandevs Jan 28, 2019
d178ffb
Better support for uintz types and commenting for my sanity
dylandevs Jan 28, 2019
1e9deef
Added garmin descent as a product
dylandevs Jan 28, 2019
8fc19ed
Merge remote-tracking branch 'PolideaInternal/return-all-field-descri…
jimmykane Feb 18, 2019
0d39634
Merge remote-tracking branch 'PolideaInternal/master'
jimmykane Mar 1, 2019
41b0e17
chore: add support for uint16_array for hrv messages
jimmykane Mar 1, 2019
06f93e6
chore: bump version
jimmykane Mar 1, 2019
e844900
chore: better array support
jimmykane Mar 1, 2019
7e1abcf
chore: bump version
jimmykane Mar 1, 2019
ea9b8eb
chore: release fork as new module for npm
jimmykane Mar 2, 2019
a8ffe12
chore: fixes
jimmykane Mar 2, 2019
85d2ee3
chore: change package name
jimmykane Mar 2, 2019
a9c5c33
Merge remote-tracking branch 'origin/master'
jimmykane Mar 2, 2019
f52ed25
chore: fix npm package
jimmykane Mar 2, 2019
fe0cee3
chore: fix also require
jimmykane Mar 2, 2019
9fcd29a
chore: fix version
jimmykane Mar 2, 2019
57c3bc6
chore: update readme
jimmykane Mar 2, 2019
98740bf
chore: create an activity object
jimmykane Mar 11, 2019
74bf262
fix: typo
jimmykane Mar 11, 2019
81656fe
Merge remote-tracking branch 'Dylan/updating-fit-sdk'
jimmykane Mar 12, 2019
28efc31
chore: bump version
jimmykane Mar 12, 2019
c1b4f6c
fix: readme
jimmykane Mar 17, 2019
3b4f183
Added new fit sdk type
dylandevs Mar 20, 2019
d417ac0
Merge branch 'master' into updating-fit-sdk
dylandevs Mar 20, 2019
11885a6
Rebuilding dist
dylandevs Mar 20, 2019
4e07570
Added multi-gas support
dylandevs Mar 20, 2019
34f7838
Built multi-gas support
dylandevs Mar 20, 2019
b6309c7
Merge pull request #2 from dylandevs/updating-fit-sdk
jimmykane Mar 21, 2019
1b449ee
chore: bump version
jimmykane Mar 21, 2019
043928e
Add `timer_time` field to `record`
nholden Mar 24, 2019
c5b7368
Merge remote-tracking branch 'nholden/master'
jimmykane Mar 30, 2019
8fb0fbd
chore: bump version
jimmykane Mar 30, 2019
b177077
chore: fix developer fields
jimmykane Apr 2, 2019
73b045b
chore: bump version
jimmykane Apr 2, 2019
80cb242
chore: support device type and fix index overrides
jimmykane Apr 18, 2019
1f0f7f7
chore: bump version
jimmykane Apr 18, 2019
257bfba
chore: use numerical index
jimmykane Apr 21, 2019
0c2a2a8
chore: add more session and lap stats
jimmykane Apr 21, 2019
2fac0ea
chore: compile and bump version
jimmykane Apr 21, 2019
9f452c4
Use require 'buffer/' instead of 'buffer'
joecorkerton Jun 2, 2019
7a85223
Merge pull request #3 from joecorkerton/master
jimmykane Jun 2, 2019
288a2af
chore: bump version
jimmykane Jun 2, 2019
eb023da
chore: parse developer fields based on their scale offset etc
jimmykane Jun 5, 2019
f4a6f64
chore: bump version
jimmykane Jun 5, 2019
5b8cada
chore: in case there is an error fallback silently
jimmykane Jun 6, 2019
7ef8282
chore: bump version
jimmykane Jun 6, 2019
43d3bf3
chore: remove debugger
jimmykane Jun 6, 2019
1741053
chore: bump version
jimmykane Jun 6, 2019
713ee4f
chore: try to get the data
jimmykane Jun 6, 2019
eda839c
chore: bump version
jimmykane Jun 6, 2019
7b78fe2
chore: fix vertical speed
jimmykane Jul 26, 2019
6eacf80
fix: fahrenheit
jimmykane Jul 26, 2019
d9772f2
chore: bump version
jimmykane Jul 26, 2019
6631ebf
chore: fix l_r balance and support mask
jimmykane Aug 13, 2019
2d8eee1
chore: add scale and units
jimmykane Aug 13, 2019
5d0ff61
chore: fix stance time balance
jimmykane Aug 29, 2019
e3d6877
fix: vertical_ratio
jimmykane Aug 29, 2019
a17fb45
chore: fix step length scale
jimmykane Aug 29, 2019
2041ed2
chore: fix issue with vertical speed and sint16
jimmykane Sep 2, 2019
68c93fc
store course_points as array rather than just the last one
jamespeek Sep 25, 2019
4ccf94a
Merge pull request #10 from jamespeek/course-points
jimmykane Sep 30, 2019
5baf8a5
chore: bump version
jimmykane Sep 30, 2019
c592628
chore: deps
jimmykane Sep 30, 2019
fed5ee5
chore: add package lock ?
jimmykane Sep 30, 2019
77c15c8
chore: compile binary
jimmykane Sep 30, 2019
833fa9a
Merge remote-tracking branch 'jimmykane/master' into update-master-fr…
dpwiese Nov 13, 2019
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
38 changes: 38 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Change Log

<a name="1.5.4"></a>
## [1.5.4](https://github.com/jimmykane/fit-parser/compare/v1.0.0...v1.5.3) (2019-03-01)
* **Features**: HRV, Developer fields, devices and much more
* **Miscellaneous**: Fix most of the issues parsing fit files

<a name="1.0.1"></a>
## [1.0.1](https://github.com/pierremtb/easy-fit/compare/v1.0.0...v1.0.1) (2018-09-18)


### 😭 Unclassified (not [following convention](https://github.com/sportheroes/bk-conventional-changelog#types-of-commits))

* **Miscellaneous**: fix: Applied to src/fit offset adjustments from commit 9ed802 ([70b3eb6](https://github.com/pierremtb/easy-fit/commit/70b3eb6) - [JoeTheFkingFrypan](https://github.com/JoeTheFkingFrypan))



<a name="1.0.0"></a>
# [1.0.0](https://github.com/pierremtb/easy-fit/compare/0.0.7...1.0.0) (2018-09-17)


### 😭 Unclassified (not [following convention](https://github.com/sportheroes/bk-conventional-changelog#types-of-commits))

* **Miscellaneous**: Fix readme typo ([2282c06](https://github.com/pierremtb/easy-fit/commit/2282c06)))
* **Miscellaneous**: chore: preparing to release fork internally ([3eef5f7](https://github.com/pierremtb/easy-fit/commit/3eef5f7) - [JoeTheFkingFrypan](https://github.com/JoeTheFkingFrypan))
* **Miscellaneous**: fix: Typo leading to uint16 to never be invalidated ([9ed802c](https://github.com/pierremtb/easy-fit/commit/9ed802c) - [JoeTheFkingFrypan](https://github.com/JoeTheFkingFrypan))
* **Miscellaneous**: Merge remote-tracking branch 'jenglert/master' ([819d78e](https://github.com/pierremtb/easy-fit/commit/819d78e)))
* **Miscellaneous**: fix missing buffer dependency and compile dst ([a4b237a](https://github.com/pierremtb/easy-fit/commit/a4b237a)))
* **Miscellaneous**: Merge remote-tracking branch 'FrostDigital/master' ([6fa9258](https://github.com/pierremtb/easy-fit/commit/6fa9258)))
* **Miscellaneous**: Makes parsing of fit files with developer defined fields possible (#1) ([9aea666](https://github.com/pierremtb/easy-fit/commit/9aea666))), closes [#1](https://github.com/pierremtb/easy-fit/issues/1)
* **Miscellaneous**: fix: Adjusted offset for all altitude-related fields ([1ff0fa4](https://github.com/pierremtb/easy-fit/commit/1ff0fa4) - [JoeTheFkingFrypan](https://github.com/JoeTheFkingFrypan))
* **Miscellaneous**: chore(devices): add forerunner 735 xt ([aacaa04](https://github.com/pierremtb/easy-fit/commit/aacaa04)))
* **Miscellaneous**: Compile src ([ee4aa00](https://github.com/pierremtb/easy-fit/commit/ee4aa00)))
* **Miscellaneous**: Add support for other lap types ([dcf42a1](https://github.com/pierremtb/easy-fit/commit/dcf42a1)))
* **Miscellaneous**: Compile src ([50b9b21](https://github.com/pierremtb/easy-fit/commit/50b9b21)))
* **Miscellaneous**: Merge remote-tracking branch 'pierremtb/master' ([f7f5ff0](https://github.com/pierremtb/easy-fit/commit/f7f5ff0)))
* **Miscellaneous**: Add support for more manufacturers ([2d122d2](https://github.com/pierremtb/easy-fit/commit/2d122d2)))
* **Miscellaneous**: Really compiled last changes on binary.js this time, small details on package.json file -> bumped to 0.0.8 ([e5dc98f](https://github.com/pierremtb/easy-fit/commit/e5dc98f)))
25 changes: 13 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
# easy-fit
# fit-file-parser

> Parse your .FIT files easily, directly from JS.
> Written in ES6.
> Written in ES6. (Hope to change)


## Install

```
$ npm install easy-fit --save
$ npm install fit-file-parser --save
```

## How to use
Expand All @@ -16,14 +16,14 @@ See in [examples](./examples) folder:

```javascript
// Require the module
var EasyFit = require('./../dist/easy-fit.js').default;
var FitParser = require('./../dist/fit-file-parser.js').default;

// Read a .FIT file
var fs = require('fs');
fs.readFile('./example.fit', function (err, content) {

// Create a EasyFit instance (options argument is optional)
var easyFit = new EasyFit({
// Create a FitParser instance (options argument is optional)
var fitParser = new FitParser({
force: true,
speedUnit: 'km/h',
lengthUnit: 'km',
Expand All @@ -33,7 +33,7 @@ fs.readFile('./example.fit', function (err, content) {
});

// Parse your file
easyFit.parse(content, function (error, data) {
fitParser.parse(content, function (error, data) {

// Handle result of parse method
if (error) {
Expand All @@ -48,7 +48,7 @@ fs.readFile('./example.fit', function (err, content) {
```

## API Documentation
### new EasyFit(Object _options_)
### new FitParser(Object _options_)
Needed to create a new instance. _options_ is optional, and is used to customize the returned object.

Allowed properties :
Expand All @@ -72,13 +72,14 @@ Allowed properties :
- `true`: Continues even if they are errors (**default for now**)
- `false`: Stops if an error occurs
- `elapsedRecordField`: Boolean
- `true`: Includes a `elapsed_time` field inside each `record` field, containing the elapsed time in seconds since the first record (**default**)
- `false`
- `true`: Includes `elapsed_time`, containing the elapsed time in seconds since the first record, and `timer_time`, containing the time shown on the device, inside each `record` field
- `false` (**default**)

### easyFit.parse(Buffer _file_, Function _callback_)
### fitParser.parse(Buffer _file_, Function _callback_)
_callback_ receives two arguments, the first as a error String, and the second as Object, result of parsing.

## Contributors
All started thanks to [Pierre Jacquier](https://github.com/pierremtb)

Big thanks to [Mikael Lofjärd](https://github.com/mlofjard) for [his early prototype](https://github.com/mlofjard/jsonfit).
See [CONTRIBUTORS](./CONTRIBUTORS.md).
Expand All @@ -87,4 +88,4 @@ See [CONTRIBUTORS](./CONTRIBUTORS.md).

MIT license; see [LICENSE](./LICENSE).

(c) 2016 by Pierre Jacquier
(c) 2019 Dimitrios Kanellopoulos
174 changes: 115 additions & 59 deletions dist/binary.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ var _fit = require('./fit');

var _messages = require('./messages');

var _buffer = require('buffer');
var _buffer = require('buffer/');

function addEndian(littleEndian, bytes) {
var result = 0;
Expand All @@ -24,7 +24,7 @@ function addEndian(littleEndian, bytes) {
return result;
}

function readData(blob, fDef, startIndex) {
function readData(blob, fDef, startIndex, options) {
if (fDef.endianAbility === true) {
var temp = [];
for (var i = 0; i < fDef.size; i++) {
Expand All @@ -34,38 +34,52 @@ function readData(blob, fDef, startIndex) {
var buffer = new Uint8Array(temp).buffer;
var dataView = new DataView(buffer);

switch (fDef.type) {
case 'sint16':
return dataView.getInt16(0, fDef.littleEndian);
case 'uint16':
return dataView.getUint16(0, fDef.littleEndian);
case 'sint32':
return dataView.getInt32(0, fDef.littleEndian);
case 'uint32':
return dataView.getUint32(0, fDef.littleEndian);
case 'float32':
return dataView.getFloat32(0, fDef.littleEndian);
case 'float64':
return dataView.getFloat64(0, fDef.littleEndian);
try {
switch (fDef.type) {
case 'sint16':
return dataView.getInt16(0, fDef.littleEndian);
case 'uint16':
case 'uint16z':
return dataView.getUint16(0, fDef.littleEndian);
case 'sint32':
return dataView.getInt32(0, fDef.littleEndian);
case 'uint32':
case 'uint32z':
return dataView.getUint32(0, fDef.littleEndian);
case 'float32':
return dataView.getFloat32(0, fDef.littleEndian);
case 'float64':
return dataView.getFloat64(0, fDef.littleEndian);
case 'uint16_array':
var array = [];
for (var _i = 0; _i < fDef.size; _i += 2) {
array.push(dataView.getUint16(_i, fDef.littleEndian));
}
return array;
}
} catch (e) {
if (!options.force) {
throw e;
}
}

return addEndian(fDef.littleEndian, temp);
}

if (fDef.type === 'string') {
var _temp = [];
for (var _i = 0; _i < fDef.size; _i++) {
if (blob[startIndex + _i]) {
_temp.push(blob[startIndex + _i]);
for (var _i2 = 0; _i2 < fDef.size; _i2++) {
if (blob[startIndex + _i2]) {
_temp.push(blob[startIndex + _i2]);
}
}
return new _buffer.Buffer(_temp).toString('utf-8');
}

if (fDef.type === 'byte_array') {
var _temp2 = [];
for (var _i2 = 0; _i2 < fDef.size; _i2++) {
_temp2.push(blob[startIndex + _i2]);
for (var _i3 = 0; _i3 < fDef.size; _i3++) {
_temp2.push(blob[startIndex + _i3]);
}
return _temp2;
}
Expand All @@ -76,18 +90,43 @@ function readData(blob, fDef, startIndex) {
function formatByType(data, type, scale, offset) {
switch (type) {
case 'date_time':
case 'local_date_time':
return new Date(data * 1000 + 631065600000);
case 'sint32':
case 'sint16':
return data * _fit.FIT.scConst;
case 'sint16':
case 'uint32':
case 'uint16':
return scale ? data / scale + offset : data;
case 'uint16_array':
return data.map(function (dataItem) {
return scale ? dataItem / scale + offset : dataItem;
});
default:
if (_fit.FIT.types[type]) {
if (!_fit.FIT.types[type]) {
return data;
}
// Quick check for a mask
var values = [];
for (var key in _fit.FIT.types[type]) {
if (_fit.FIT.types[type].hasOwnProperty(key)) {
values.push(_fit.FIT.types[type][key]);
}
}
if (values.indexOf('mask') === -1) {
return _fit.FIT.types[type][data];
}
return data;
var dataItem = {};
for (var key in _fit.FIT.types[type]) {
if (_fit.FIT.types[type].hasOwnProperty(key)) {
if (_fit.FIT.types[type][key] === 'mask') {
dataItem.value = data & key;
} else {
dataItem[_fit.FIT.types[type][key]] = !!((data & key) >> 7); // Not sure if we need the >> 7 and casting to boolean but from all the masked props of fields so far this seems to be the case
}
}
}
return dataItem;
}
}

Expand Down Expand Up @@ -182,7 +221,7 @@ function applyOptions(data, field, options) {
}
}

function readRecord(blob, messageTypes, developerFields, startIndex, options, startDate) {
function readRecord(blob, messageTypes, developerFields, startIndex, options, startDate, pausedTime) {
var recordHeader = blob[startIndex];
var localMessageType = recordHeader & 15;

Expand Down Expand Up @@ -226,30 +265,41 @@ function readRecord(blob, messageTypes, developerFields, startIndex, options, st
mTypeDef.fieldDefs.push(fDef);
}

for (var _i3 = 0; _i3 < numberOfDeveloperDataFields; _i3++) {
var _fDefIndex = startIndex + 6 + numberOfFields * 3 + 1 + _i3 * 3;

var fieldNum = blob[_fDefIndex];
var size = blob[_fDefIndex + 1];
var devDataIndex = blob[_fDefIndex + 2];

var devDef = developerFields[devDataIndex][fieldNum];

var _baseType = devDef.fit_base_type_id;

var _fDef = {
type: _fit.FIT.types.fit_base_type[_baseType],
fDefNo: fieldNum,
size: size,
endianAbility: (_baseType & 128) === 128,
littleEndian: lEnd,
baseTypeNo: _baseType & 15,
name: devDef.field_name,
dataType: (0, _messages.getFitMessageBaseType)(_baseType & 15),
isDeveloperField: true
};

mTypeDef.fieldDefs.push(_fDef);
for (var _i4 = 0; _i4 < numberOfDeveloperDataFields; _i4++) {
// If we fail to parse then try catch
try {
var _fDefIndex = startIndex + 6 + numberOfFields * 3 + 1 + _i4 * 3;

var fieldNum = blob[_fDefIndex];
var size = blob[_fDefIndex + 1];
var devDataIndex = blob[_fDefIndex + 2];

var devDef = developerFields[devDataIndex][fieldNum];

var _baseType = devDef.fit_base_type_id;

var _fDef = {
type: _fit.FIT.types.fit_base_type[_baseType],
fDefNo: fieldNum,
size: size,
endianAbility: (_baseType & 128) === 128,
littleEndian: lEnd,
baseTypeNo: _baseType & 15,
name: devDef.field_name,
dataType: (0, _messages.getFitMessageBaseType)(_baseType & 15),
scale: devDef.scale || 1,
offset: devDef.offset || 0,
developerDataIndex: devDataIndex,
isDeveloperField: true
};

mTypeDef.fieldDefs.push(_fDef);
} catch (e) {
if (options.force) {
continue;
}
throw e;
}
}

messageTypes[localMessageType] = mTypeDef;
Expand All @@ -273,28 +323,34 @@ function readRecord(blob, messageTypes, developerFields, startIndex, options, st
var fields = {};
var message = (0, _messages.getFitMessage)(messageType.globalMessageNumber);

for (var _i4 = 0; _i4 < messageType.fieldDefs.length; _i4++) {
var _fDef2 = messageType.fieldDefs[_i4];
var data = readData(blob, _fDef2, readDataFromIndex);
for (var _i5 = 0; _i5 < messageType.fieldDefs.length; _i5++) {
var _fDef2 = messageType.fieldDefs[_i5];
var data = readData(blob, _fDef2, readDataFromIndex, options);

if (!isInvalidValue(data, _fDef2.type)) {
if (_fDef2.isDeveloperField) {
// Skip format of data if developer field
fields[_fDef2.name] = data;

var field = _fDef2.name;
var type = _fDef2.type;
var scale = _fDef2.scale;
var offset = _fDef2.offset;

fields[_fDef2.name] = applyOptions(formatByType(data, type, scale, offset), field, options);
} else {
var _message$getAttribute2 = message.getAttributes(_fDef2.fDefNo),
field = _message$getAttribute2.field,
type = _message$getAttribute2.type,
scale = _message$getAttribute2.scale,
offset = _message$getAttribute2.offset;
_field = _message$getAttribute2.field,
_type = _message$getAttribute2.type,
_scale = _message$getAttribute2.scale,
_offset = _message$getAttribute2.offset;

if (field !== 'unknown' && field !== '' && field !== undefined) {
fields[field] = applyOptions(formatByType(data, type, scale, offset), field, options);
if (_field !== 'unknown' && _field !== '' && _field !== undefined) {
fields[_field] = applyOptions(formatByType(data, _type, _scale, _offset), _field, options);
}
}

if (message.name === 'record' && options.elapsedRecordField) {
fields.elapsed_time = (fields.timestamp - startDate) / 1000;
fields.timer_time = fields.elapsed_time - pausedTime;
}
}

Expand Down
Loading