fit-file-parser 1.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.idea/dictionaries/dimtrioskanellopoulos.xml +7 -0
- package/.idea/easy-fit.iml +14 -0
- package/.idea/encodings.xml +4 -0
- package/.idea/inspectionProfiles/Project_Default.xml +62 -0
- package/.idea/misc.xml +7 -0
- package/.idea/modules.xml +8 -0
- package/.idea/vcs.xml +6 -0
- package/.idea/workspace.xml +589 -0
- package/CHANGELOG.md +38 -0
- package/CONTRIBUTORS.md +7 -0
- package/LICENSE +23 -0
- package/README.md +91 -0
- package/dist/binary.js +440 -0
- package/dist/fit-parser.js +266 -0
- package/dist/fit.js +4265 -0
- package/dist/messages.js +23 -0
- package/package.json +72 -0
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
|
|
7
|
+
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
|
|
8
|
+
|
|
9
|
+
var _binary = require('./binary');
|
|
10
|
+
|
|
11
|
+
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
12
|
+
|
|
13
|
+
var FitParser = function () {
|
|
14
|
+
function FitParser() {
|
|
15
|
+
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
16
|
+
|
|
17
|
+
_classCallCheck(this, FitParser);
|
|
18
|
+
|
|
19
|
+
this.options = {
|
|
20
|
+
force: options.force != null ? options.force : true,
|
|
21
|
+
speedUnit: options.speedUnit || 'm/s',
|
|
22
|
+
lengthUnit: options.lengthUnit || 'm',
|
|
23
|
+
temperatureUnit: options.temperatureUnit || 'celsius',
|
|
24
|
+
elapsedRecordField: options.elapsedRecordField || false,
|
|
25
|
+
mode: options.mode || 'list'
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
_createClass(FitParser, [{
|
|
30
|
+
key: 'parse',
|
|
31
|
+
value: function parse(content, callback) {
|
|
32
|
+
var blob = new Uint8Array((0, _binary.getArrayBuffer)(content));
|
|
33
|
+
|
|
34
|
+
if (blob.length < 12) {
|
|
35
|
+
callback('File to small to be a FIT file', {});
|
|
36
|
+
if (!this.options.force) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
var headerLength = blob[0];
|
|
42
|
+
if (headerLength !== 14 && headerLength !== 12) {
|
|
43
|
+
callback('Incorrect header size', {});
|
|
44
|
+
if (!this.options.force) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
var fileTypeString = '';
|
|
50
|
+
for (var i = 8; i < 12; i++) {
|
|
51
|
+
fileTypeString += String.fromCharCode(blob[i]);
|
|
52
|
+
}
|
|
53
|
+
if (fileTypeString !== '.FIT') {
|
|
54
|
+
callback('Missing \'.FIT\' in header', {});
|
|
55
|
+
if (!this.options.force) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (headerLength === 14) {
|
|
61
|
+
var crcHeader = blob[12] + (blob[13] << 8);
|
|
62
|
+
var crcHeaderCalc = (0, _binary.calculateCRC)(blob, 0, 12);
|
|
63
|
+
if (crcHeader !== crcHeaderCalc) {
|
|
64
|
+
// callback('Header CRC mismatch', {});
|
|
65
|
+
// TODO: fix Header CRC check
|
|
66
|
+
if (!this.options.force) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
var protocolVersion = blob[1];
|
|
73
|
+
var profileVersion = blob[2] + (blob[3] << 8);
|
|
74
|
+
var dataLength = blob[4] + (blob[5] << 8) + (blob[6] << 16) + (blob[7] << 24);
|
|
75
|
+
var crcStart = dataLength + headerLength;
|
|
76
|
+
var crcFile = blob[crcStart] + (blob[crcStart + 1] << 8);
|
|
77
|
+
var crcFileCalc = (0, _binary.calculateCRC)(blob, headerLength === 12 ? 0 : headerLength, crcStart);
|
|
78
|
+
|
|
79
|
+
if (crcFile !== crcFileCalc) {
|
|
80
|
+
// callback('File CRC mismatch', {});
|
|
81
|
+
// TODO: fix File CRC check
|
|
82
|
+
if (!this.options.force) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
var fitObj = {};
|
|
88
|
+
fitObj.protocolVersion = protocolVersion;
|
|
89
|
+
fitObj.profileVersion = profileVersion;
|
|
90
|
+
|
|
91
|
+
var sessions = [];
|
|
92
|
+
var laps = [];
|
|
93
|
+
var records = [];
|
|
94
|
+
var events = [];
|
|
95
|
+
var hrv = [];
|
|
96
|
+
var devices = [];
|
|
97
|
+
var applications = [];
|
|
98
|
+
var fieldDescriptions = [];
|
|
99
|
+
var dive_gases = [];
|
|
100
|
+
var course_points = [];
|
|
101
|
+
var sports = [];
|
|
102
|
+
var monitors = [];
|
|
103
|
+
var stress = [];
|
|
104
|
+
var definitions = [];
|
|
105
|
+
var file_ids = [];
|
|
106
|
+
var monitor_info = [];
|
|
107
|
+
var lengths = [];
|
|
108
|
+
|
|
109
|
+
var tempLaps = [];
|
|
110
|
+
var tempLengths = [];
|
|
111
|
+
var tempRecords = [];
|
|
112
|
+
|
|
113
|
+
var loopIndex = headerLength;
|
|
114
|
+
var messageTypes = [];
|
|
115
|
+
var developerFields = [];
|
|
116
|
+
|
|
117
|
+
var isModeCascade = this.options.mode === 'cascade';
|
|
118
|
+
var isCascadeNeeded = isModeCascade || this.options.mode === 'both';
|
|
119
|
+
|
|
120
|
+
var startDate = void 0,
|
|
121
|
+
lastStopTimestamp = void 0;
|
|
122
|
+
var pausedTime = 0;
|
|
123
|
+
|
|
124
|
+
while (loopIndex < crcStart) {
|
|
125
|
+
var _readRecord = (0, _binary.readRecord)(blob, messageTypes, developerFields, loopIndex, this.options, startDate, pausedTime),
|
|
126
|
+
nextIndex = _readRecord.nextIndex,
|
|
127
|
+
messageType = _readRecord.messageType,
|
|
128
|
+
message = _readRecord.message;
|
|
129
|
+
|
|
130
|
+
loopIndex = nextIndex;
|
|
131
|
+
|
|
132
|
+
switch (messageType) {
|
|
133
|
+
case 'lap':
|
|
134
|
+
if (isCascadeNeeded) {
|
|
135
|
+
message.records = tempRecords;
|
|
136
|
+
tempRecords = [];
|
|
137
|
+
tempLaps.push(message);
|
|
138
|
+
message.lengths = tempLengths;
|
|
139
|
+
tempLengths = [];
|
|
140
|
+
}
|
|
141
|
+
laps.push(message);
|
|
142
|
+
break;
|
|
143
|
+
case 'session':
|
|
144
|
+
if (isCascadeNeeded) {
|
|
145
|
+
message.laps = tempLaps;
|
|
146
|
+
tempLaps = [];
|
|
147
|
+
}
|
|
148
|
+
sessions.push(message);
|
|
149
|
+
break;
|
|
150
|
+
case 'event':
|
|
151
|
+
if (message.event === 'timer') {
|
|
152
|
+
if (message.event_type === 'stop_all') {
|
|
153
|
+
lastStopTimestamp = message.timestamp;
|
|
154
|
+
} else if (message.event_type === 'start' && lastStopTimestamp) {
|
|
155
|
+
pausedTime += (message.timestamp - lastStopTimestamp) / 1000;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
events.push(message);
|
|
159
|
+
break;
|
|
160
|
+
case 'length':
|
|
161
|
+
if (isCascadeNeeded) {
|
|
162
|
+
tempLengths.push(message);
|
|
163
|
+
}
|
|
164
|
+
lengths.push(message);
|
|
165
|
+
break;
|
|
166
|
+
case 'hrv':
|
|
167
|
+
hrv.push(message);
|
|
168
|
+
break;
|
|
169
|
+
case 'record':
|
|
170
|
+
if (!startDate) {
|
|
171
|
+
startDate = message.timestamp;
|
|
172
|
+
message.elapsed_time = 0;
|
|
173
|
+
message.timer_time = 0;
|
|
174
|
+
}
|
|
175
|
+
records.push(message);
|
|
176
|
+
if (isCascadeNeeded) {
|
|
177
|
+
tempRecords.push(message);
|
|
178
|
+
}
|
|
179
|
+
break;
|
|
180
|
+
case 'field_description':
|
|
181
|
+
fieldDescriptions.push(message);
|
|
182
|
+
break;
|
|
183
|
+
case 'device_info':
|
|
184
|
+
devices.push(message);
|
|
185
|
+
break;
|
|
186
|
+
case 'developer_data_id':
|
|
187
|
+
applications.push(message);
|
|
188
|
+
break;
|
|
189
|
+
case 'dive_gas':
|
|
190
|
+
dive_gases.push(message);
|
|
191
|
+
break;
|
|
192
|
+
case 'course_point':
|
|
193
|
+
course_points.push(message);
|
|
194
|
+
break;
|
|
195
|
+
case 'sport':
|
|
196
|
+
sports.push(message);
|
|
197
|
+
break;
|
|
198
|
+
case 'file_id':
|
|
199
|
+
if (message) {
|
|
200
|
+
file_ids.push(message);
|
|
201
|
+
}
|
|
202
|
+
break;
|
|
203
|
+
case 'definition':
|
|
204
|
+
if (message) {
|
|
205
|
+
definitions.push(message);
|
|
206
|
+
}
|
|
207
|
+
break;
|
|
208
|
+
case 'monitoring':
|
|
209
|
+
monitors.push(message);
|
|
210
|
+
break;
|
|
211
|
+
case 'monitoring_info':
|
|
212
|
+
monitor_info.push(message);
|
|
213
|
+
break;
|
|
214
|
+
case 'stress_level':
|
|
215
|
+
stress.push(message);
|
|
216
|
+
break;
|
|
217
|
+
case 'software':
|
|
218
|
+
fitObj.software = message;
|
|
219
|
+
break;
|
|
220
|
+
default:
|
|
221
|
+
if (messageType !== '') {
|
|
222
|
+
fitObj[messageType] = message;
|
|
223
|
+
}
|
|
224
|
+
break;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if (isCascadeNeeded) {
|
|
229
|
+
fitObj.activity = fitObj.activity || {};
|
|
230
|
+
fitObj.activity.sessions = sessions;
|
|
231
|
+
fitObj.activity.events = events;
|
|
232
|
+
fitObj.activity.hrv = hrv;
|
|
233
|
+
fitObj.activity.device_infos = devices;
|
|
234
|
+
fitObj.activity.developer_data_ids = applications;
|
|
235
|
+
fitObj.activity.field_descriptions = fieldDescriptions;
|
|
236
|
+
fitObj.activity.sports = sports;
|
|
237
|
+
}
|
|
238
|
+
if (!isModeCascade) {
|
|
239
|
+
fitObj.sessions = sessions;
|
|
240
|
+
fitObj.laps = laps;
|
|
241
|
+
fitObj.lengths = lengths;
|
|
242
|
+
fitObj.records = records;
|
|
243
|
+
fitObj.events = events;
|
|
244
|
+
fitObj.device_infos = devices;
|
|
245
|
+
fitObj.developer_data_ids = applications;
|
|
246
|
+
fitObj.field_descriptions = fieldDescriptions;
|
|
247
|
+
fitObj.hrv = hrv;
|
|
248
|
+
fitObj.dive_gases = dive_gases;
|
|
249
|
+
fitObj.course_points = course_points;
|
|
250
|
+
fitObj.sports = sports;
|
|
251
|
+
fitObj.devices = devices;
|
|
252
|
+
fitObj.monitors = monitors;
|
|
253
|
+
fitObj.stress = stress;
|
|
254
|
+
fitObj.file_ids = file_ids;
|
|
255
|
+
fitObj.monitor_info = monitor_info;
|
|
256
|
+
fitObj.definitions = definitions;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
callback(null, fitObj);
|
|
260
|
+
}
|
|
261
|
+
}]);
|
|
262
|
+
|
|
263
|
+
return FitParser;
|
|
264
|
+
}();
|
|
265
|
+
|
|
266
|
+
exports.default = FitParser;
|