@garmin/fitsdk 21.141.0 → 21.158.0
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/package.json +1 -1
- package/src/accumulator.js +15 -5
- package/src/bit-stream.js +2 -2
- package/src/crc-calculator.js +2 -2
- package/src/decoder.js +80 -24
- package/src/fit.js +2 -2
- package/src/index.js +2 -2
- package/src/profile.js +58 -15
- package/src/stream.js +7 -7
- package/src/utils-hr-mesg.js +2 -2
- package/src/utils-internal.js +2 -2
- package/src/utils.js +2 -2
package/package.json
CHANGED
package/src/accumulator.js
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
// Transfer (FIT) Protocol License.
|
|
6
6
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
7
7
|
// ****WARNING**** This file is auto-generated! Do NOT edit this file.
|
|
8
|
-
// Profile Version = 21.
|
|
9
|
-
// Tag = production/release/21.
|
|
8
|
+
// Profile Version = 21.158.0Release
|
|
9
|
+
// Tag = production/release/21.158.0-0-gc9428aa
|
|
10
10
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
11
11
|
|
|
12
12
|
|
|
@@ -32,16 +32,26 @@ class AccumulatedField {
|
|
|
32
32
|
class Accumulator {
|
|
33
33
|
#messages = {};
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
createAccumulatedField(mesgNum, fieldNum, value) {
|
|
36
|
+
const accumualtedField = new AccumulatedField(value);
|
|
37
|
+
|
|
36
38
|
if (this.#messages[mesgNum] == null) {
|
|
37
39
|
this.#messages[mesgNum] = {};
|
|
38
40
|
}
|
|
39
41
|
|
|
40
|
-
this.#messages[mesgNum][fieldNum] =
|
|
42
|
+
this.#messages[mesgNum][fieldNum] = accumualtedField;
|
|
43
|
+
|
|
44
|
+
return accumualtedField;
|
|
41
45
|
}
|
|
42
46
|
|
|
43
47
|
accumulate(mesgNum, fieldNum, value, bits) {
|
|
44
|
-
|
|
48
|
+
let accumualtedField = this.#messages[mesgNum]?.[fieldNum];
|
|
49
|
+
|
|
50
|
+
if(accumualtedField == null) {
|
|
51
|
+
accumualtedField = this.createAccumulatedField(mesgNum, fieldNum, value);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return accumualtedField.accumulate(value, bits);
|
|
45
55
|
}
|
|
46
56
|
}
|
|
47
57
|
|
package/src/bit-stream.js
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
// Transfer (FIT) Protocol License.
|
|
6
6
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
7
7
|
// ****WARNING**** This file is auto-generated! Do NOT edit this file.
|
|
8
|
-
// Profile Version = 21.
|
|
9
|
-
// Tag = production/release/21.
|
|
8
|
+
// Profile Version = 21.158.0Release
|
|
9
|
+
// Tag = production/release/21.158.0-0-gc9428aa
|
|
10
10
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
11
11
|
|
|
12
12
|
|
package/src/crc-calculator.js
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
// Transfer (FIT) Protocol License.
|
|
6
6
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
7
7
|
// ****WARNING**** This file is auto-generated! Do NOT edit this file.
|
|
8
|
-
// Profile Version = 21.
|
|
9
|
-
// Tag = production/release/21.
|
|
8
|
+
// Profile Version = 21.158.0Release
|
|
9
|
+
// Tag = production/release/21.158.0-0-gc9428aa
|
|
10
10
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
11
11
|
|
|
12
12
|
|
package/src/decoder.js
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
// Transfer (FIT) Protocol License.
|
|
6
6
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
7
7
|
// ****WARNING**** This file is auto-generated! Do NOT edit this file.
|
|
8
|
-
// Profile Version = 21.
|
|
9
|
-
// Tag = production/release/21.
|
|
8
|
+
// Profile Version = 21.158.0Release
|
|
9
|
+
// Tag = production/release/21.158.0-0-gc9428aa
|
|
10
10
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
11
11
|
|
|
12
12
|
|
|
@@ -25,8 +25,17 @@ const MESG_DEFINITION_MASK = 0x40;
|
|
|
25
25
|
const DEV_DATA_MASK = 0x20;
|
|
26
26
|
const MESG_HEADER_MASK = 0x00;
|
|
27
27
|
const LOCAL_MESG_NUM_MASK = 0x0F;
|
|
28
|
+
|
|
29
|
+
const HEADER_WITH_CRC_SIZE = 14;
|
|
30
|
+
const HEADER_WITHOUT_CRC_SIZE = 12;
|
|
28
31
|
const CRC_SIZE = 2;
|
|
29
32
|
|
|
33
|
+
const DecodeMode = Object.freeze({
|
|
34
|
+
NORMAL: "normal",
|
|
35
|
+
SKIP_HEADER: "skipHeader",
|
|
36
|
+
DATA_ONLY: "dataOnly"
|
|
37
|
+
});
|
|
38
|
+
|
|
30
39
|
class Decoder {
|
|
31
40
|
#localMessageDefinitions = [];
|
|
32
41
|
#developerDataDefinitions = {};
|
|
@@ -36,6 +45,8 @@ class Decoder {
|
|
|
36
45
|
#fieldsWithSubFields = [];
|
|
37
46
|
#fieldsToExpand = [];
|
|
38
47
|
|
|
48
|
+
#decodeMode = DecodeMode.NORMAL;
|
|
49
|
+
|
|
39
50
|
#mesgListener = null;
|
|
40
51
|
#optExpandSubFields = true;
|
|
41
52
|
#optExpandComponents = true;
|
|
@@ -67,7 +78,7 @@ class Decoder {
|
|
|
67
78
|
static isFIT(stream) {
|
|
68
79
|
try {
|
|
69
80
|
const fileHeaderSize = stream.peekByte();
|
|
70
|
-
if ([
|
|
81
|
+
if ([HEADER_WITH_CRC_SIZE, HEADER_WITHOUT_CRC_SIZE].includes(fileHeaderSize) != true) {
|
|
71
82
|
return false;
|
|
72
83
|
}
|
|
73
84
|
|
|
@@ -75,7 +86,7 @@ class Decoder {
|
|
|
75
86
|
return false;
|
|
76
87
|
}
|
|
77
88
|
|
|
78
|
-
const fileHeader = Decoder.#readFileHeader(stream, true);
|
|
89
|
+
const fileHeader = Decoder.#readFileHeader(stream, { resetPosition: true, });
|
|
79
90
|
if (fileHeader.dataType !== ".FIT") {
|
|
80
91
|
return false;
|
|
81
92
|
}
|
|
@@ -105,7 +116,7 @@ class Decoder {
|
|
|
105
116
|
return false;
|
|
106
117
|
}
|
|
107
118
|
|
|
108
|
-
const fileHeader = Decoder.#readFileHeader(this.#stream, true);
|
|
119
|
+
const fileHeader = Decoder.#readFileHeader(this.#stream, { resetPosition: true, });
|
|
109
120
|
|
|
110
121
|
if (this.#stream.length < fileHeader.headerSize + fileHeader.dataSize + CRC_SIZE) {
|
|
111
122
|
return false;
|
|
@@ -113,7 +124,7 @@ class Decoder {
|
|
|
113
124
|
|
|
114
125
|
const buf = new Uint8Array(this.#stream.slice(0, this.#stream.length))
|
|
115
126
|
|
|
116
|
-
if (fileHeader.headerSize ===
|
|
127
|
+
if (fileHeader.headerSize === HEADER_WITH_CRC_SIZE && fileHeader.headerCRC !== 0x0000
|
|
117
128
|
&& fileHeader.headerCRC != CrcCalculator.calculateCRC(buf, 0, 12)) {
|
|
118
129
|
return false;
|
|
119
130
|
}
|
|
@@ -150,6 +161,8 @@ class Decoder {
|
|
|
150
161
|
* @param {boolean} [options.convertDateTimesToDates=true] - (optional, default true)
|
|
151
162
|
* @param {Boolean} [options.includeUnknownData=false] - (optional, default false)
|
|
152
163
|
* @param {boolean} [options.mergeHeartRates=true] - (optional, default false)
|
|
164
|
+
* @param {boolean} [options.skipHeader=false] - (optional, default false)
|
|
165
|
+
* @param {boolean} [options.dataOnly=false] - (optional, default false)
|
|
153
166
|
* @return {Object} result - {messages:Array, errors:Array}
|
|
154
167
|
*/
|
|
155
168
|
read({
|
|
@@ -160,7 +173,9 @@ class Decoder {
|
|
|
160
173
|
convertTypesToStrings = true,
|
|
161
174
|
convertDateTimesToDates = true,
|
|
162
175
|
includeUnknownData = false,
|
|
163
|
-
mergeHeartRates = true
|
|
176
|
+
mergeHeartRates = true,
|
|
177
|
+
skipHeader = false,
|
|
178
|
+
dataOnly = false,} = {}) {
|
|
164
179
|
|
|
165
180
|
this.#mesgListener = mesgListener;
|
|
166
181
|
this.#optExpandSubFields = expandSubFields
|
|
@@ -182,7 +197,11 @@ class Decoder {
|
|
|
182
197
|
this.#throwError("mergeHeartRates requires applyScaleAndOffset and expandComponents to be enabled");
|
|
183
198
|
}
|
|
184
199
|
|
|
185
|
-
|
|
200
|
+
if (dataOnly && skipHeader) {
|
|
201
|
+
this.#throwError("dataOnly and skipHeader cannot both be enabled")
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
this.#decodeMode = skipHeader ? DecodeMode.SKIP_HEADER : dataOnly ? DecodeMode.DATA_ONLY : DecodeMode.NORMAL;
|
|
186
205
|
|
|
187
206
|
while (this.#stream.position < this.#stream.length) {
|
|
188
207
|
this.#decodeNextFile();
|
|
@@ -203,23 +222,23 @@ class Decoder {
|
|
|
203
222
|
#decodeNextFile() {
|
|
204
223
|
const position = this.#stream.position;
|
|
205
224
|
|
|
206
|
-
if (!this.isFIT()) {
|
|
225
|
+
if (this.#decodeMode === DecodeMode.NORMAL && !this.isFIT()) {
|
|
207
226
|
this.#throwError("input is not a FIT file");
|
|
208
227
|
}
|
|
209
228
|
|
|
210
229
|
this.#stream.crcCalculator = new CrcCalculator();
|
|
211
230
|
|
|
212
|
-
const
|
|
231
|
+
const { headerSize, dataSize } = Decoder.#readFileHeader(this.#stream, { decodeMode: this.#decodeMode });
|
|
213
232
|
|
|
214
233
|
// Read data messages and definitions
|
|
215
|
-
while (this.#stream.position < (position +
|
|
234
|
+
while (this.#stream.position < (position + headerSize + dataSize)) {
|
|
216
235
|
this.#decodeNextRecord();
|
|
217
236
|
}
|
|
218
237
|
|
|
219
238
|
// Check the CRC
|
|
220
239
|
const calculatedCrc = this.#stream.crcCalculator.crc;
|
|
221
240
|
const crc = this.#stream.readUInt16();
|
|
222
|
-
if (crc !== calculatedCrc) {
|
|
241
|
+
if (this.#decodeMode === DecodeMode.NORMAL && crc !== calculatedCrc) {
|
|
223
242
|
this.#throwError("CRC error");
|
|
224
243
|
}
|
|
225
244
|
}
|
|
@@ -341,7 +360,7 @@ class Decoder {
|
|
|
341
360
|
}
|
|
342
361
|
|
|
343
362
|
if (field?.isAccumulated) {
|
|
344
|
-
this.#
|
|
363
|
+
this.#setAccumulatedField(messageDefinition, message, field, rawFieldValue);
|
|
345
364
|
}
|
|
346
365
|
}
|
|
347
366
|
});
|
|
@@ -530,7 +549,7 @@ class Decoder {
|
|
|
530
549
|
while (this.#fieldsToExpand.length > 0) {
|
|
531
550
|
const name = this.#fieldsToExpand.shift();
|
|
532
551
|
|
|
533
|
-
const { rawFieldValue, fieldDefinitionNumber, isSubField } = message[name];
|
|
552
|
+
const { rawFieldValue, fieldDefinitionNumber, isSubField } = message[name] ?? mesg[name];
|
|
534
553
|
let field = Profile.messages[mesgNum].fields[fieldDefinitionNumber];
|
|
535
554
|
field = isSubField ? this.#lookupSubfield(field, name) : field;
|
|
536
555
|
const baseType = FIT.FieldTypeToBaseType[field.type];
|
|
@@ -546,6 +565,10 @@ class Decoder {
|
|
|
546
565
|
const bitStream = new BitStream(rawFieldValue, baseType);
|
|
547
566
|
|
|
548
567
|
for (let j = 0; j < field.components.length; j++) {
|
|
568
|
+
if (bitStream.bitsAvailable < field.bits[j]) {
|
|
569
|
+
break;
|
|
570
|
+
}
|
|
571
|
+
|
|
549
572
|
const targetField = fields[field.components[j]];
|
|
550
573
|
if (mesg[targetField.name] == null) {
|
|
551
574
|
const baseType = FIT.FieldTypeToBaseType[targetField.type];
|
|
@@ -560,22 +583,22 @@ class Decoder {
|
|
|
560
583
|
};
|
|
561
584
|
}
|
|
562
585
|
|
|
563
|
-
if (bitStream.bitsAvailable < field.bits[j]) {
|
|
564
|
-
break;
|
|
565
|
-
}
|
|
566
|
-
|
|
567
586
|
let value = bitStream.readBits(field.bits[j]);
|
|
568
587
|
|
|
569
|
-
|
|
588
|
+
if (targetField.isAccumulated) {
|
|
589
|
+
value = this.#accumulator.accumulate(mesgNum, targetField.num, value, field.bits[j]);
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
// Undo component scale and offset before applying the destination field's scale and offset
|
|
593
|
+
value = (value / field.scale[j] - field.offset[j]);
|
|
570
594
|
|
|
571
|
-
|
|
595
|
+
const rawValue = (value + targetField.offset) * targetField.scale;
|
|
596
|
+
mesg[targetField.name].rawFieldValue.push(rawValue);
|
|
572
597
|
|
|
573
|
-
if (
|
|
598
|
+
if (rawValue === mesg[targetField.name].invalidValue) {
|
|
574
599
|
mesg[targetField.name].fieldValue.push(null);
|
|
575
600
|
}
|
|
576
601
|
else {
|
|
577
|
-
value = value / field.scale[j] - field.offset[j];
|
|
578
|
-
|
|
579
602
|
if (this.#optConvertTypesToStrings) {
|
|
580
603
|
value = this.#convertTypeToString(mesg, targetField, value);
|
|
581
604
|
}
|
|
@@ -681,6 +704,26 @@ class Decoder {
|
|
|
681
704
|
}
|
|
682
705
|
}
|
|
683
706
|
|
|
707
|
+
#setAccumulatedField(messageDefinition, message, field, rawFieldValue) {
|
|
708
|
+
const rawFieldValues = Array.isArray(rawFieldValue) ? rawFieldValue : [rawFieldValue];
|
|
709
|
+
|
|
710
|
+
rawFieldValues.forEach((value) => {
|
|
711
|
+
Object.values(message).forEach((containingField) => {
|
|
712
|
+
let components = messageDefinition.fields[containingField.fieldDefinitionNumber].components ?? []
|
|
713
|
+
|
|
714
|
+
components.forEach((componentFieldNum, i) => {
|
|
715
|
+
const targetField = messageDefinition.fields[componentFieldNum];
|
|
716
|
+
|
|
717
|
+
if(targetField?.num == field.num && targetField?.isAccumulated) {
|
|
718
|
+
value = (((value / field.scale) - field.offset) + containingField.offset[i]) * containingField.scale[i];
|
|
719
|
+
}
|
|
720
|
+
});
|
|
721
|
+
});
|
|
722
|
+
|
|
723
|
+
this.#accumulator.createAccumulatedField(messageDefinition.num, field.num, value);
|
|
724
|
+
});
|
|
725
|
+
}
|
|
726
|
+
|
|
684
727
|
#convertTypeToString(messageDefinition, field, rawFieldValue) {
|
|
685
728
|
if ([Profile.MesgNum.DEVELOPER_DATA_ID, Profile.MesgNum.FIELD_DESCRIPTION].includes(messageDefinition.globalMessageNumber)) {
|
|
686
729
|
return rawFieldValue;
|
|
@@ -711,9 +754,22 @@ class Decoder {
|
|
|
711
754
|
return subField != null ? subField : {};
|
|
712
755
|
}
|
|
713
756
|
|
|
714
|
-
static #readFileHeader(stream, resetPosition = false) {
|
|
757
|
+
static #readFileHeader(stream, { resetPosition = false, decodeMode = DecodeMode.NORMAL }) {
|
|
715
758
|
const position = stream.position;
|
|
716
759
|
|
|
760
|
+
if(decodeMode !== DecodeMode.NORMAL) {
|
|
761
|
+
if(decodeMode === DecodeMode.SKIP_HEADER) {
|
|
762
|
+
stream.seek(HEADER_WITH_CRC_SIZE);
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
const headerSize = decodeMode === DecodeMode.SKIP_HEADER ? HEADER_WITH_CRC_SIZE : 0;
|
|
766
|
+
|
|
767
|
+
return {
|
|
768
|
+
headerSize,
|
|
769
|
+
dataSize: stream.length - headerSize - CRC_SIZE,
|
|
770
|
+
};
|
|
771
|
+
}
|
|
772
|
+
|
|
717
773
|
const fileHeader = {
|
|
718
774
|
headerSize: stream.readByte(),
|
|
719
775
|
protocolVersion: stream.readByte(),
|
package/src/fit.js
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
// Transfer (FIT) Protocol License.
|
|
6
6
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
7
7
|
// ****WARNING**** This file is auto-generated! Do NOT edit this file.
|
|
8
|
-
// Profile Version = 21.
|
|
9
|
-
// Tag = production/release/21.
|
|
8
|
+
// Profile Version = 21.158.0Release
|
|
9
|
+
// Tag = production/release/21.158.0-0-gc9428aa
|
|
10
10
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
11
11
|
|
|
12
12
|
|
package/src/index.js
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
// Transfer (FIT) Protocol License.
|
|
6
6
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
7
7
|
// ****WARNING**** This file is auto-generated! Do NOT edit this file.
|
|
8
|
-
// Profile Version = 21.
|
|
9
|
-
// Tag = production/release/21.
|
|
8
|
+
// Profile Version = 21.158.0Release
|
|
9
|
+
// Tag = production/release/21.158.0-0-gc9428aa
|
|
10
10
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
11
11
|
|
|
12
12
|
|
package/src/profile.js
CHANGED
|
@@ -5,15 +5,15 @@
|
|
|
5
5
|
// Transfer (FIT) Protocol License.
|
|
6
6
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
7
7
|
// ****WARNING**** This file is auto-generated! Do NOT edit this file.
|
|
8
|
-
// Profile Version = 21.
|
|
9
|
-
// Tag = production/release/21.
|
|
8
|
+
// Profile Version = 21.158.0Release
|
|
9
|
+
// Tag = production/release/21.158.0-0-gc9428aa
|
|
10
10
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
const Profile = {
|
|
14
14
|
version: {
|
|
15
15
|
major: 21,
|
|
16
|
-
minor:
|
|
16
|
+
minor: 158,
|
|
17
17
|
patch: 0,
|
|
18
18
|
type: "Release"
|
|
19
19
|
},
|
|
@@ -16324,6 +16324,20 @@ const Profile = {
|
|
|
16324
16324
|
hasComponents: false,
|
|
16325
16325
|
subFields: []
|
|
16326
16326
|
},
|
|
16327
|
+
17: {
|
|
16328
|
+
num: 17, // Description of the workout
|
|
16329
|
+
name: "wktDescription",
|
|
16330
|
+
type: "string",
|
|
16331
|
+
array: "true",
|
|
16332
|
+
scale: 1,
|
|
16333
|
+
offset: 0,
|
|
16334
|
+
units: "",
|
|
16335
|
+
bits: [],
|
|
16336
|
+
components: [],
|
|
16337
|
+
isAccumulated: false,
|
|
16338
|
+
hasComponents: false,
|
|
16339
|
+
subFields: []
|
|
16340
|
+
},
|
|
16327
16341
|
},
|
|
16328
16342
|
},
|
|
16329
16343
|
158: {
|
|
@@ -18897,7 +18911,7 @@ const Profile = {
|
|
|
18897
18911
|
subFields: []
|
|
18898
18912
|
},
|
|
18899
18913
|
1: {
|
|
18900
|
-
num: 1, // Body battery level
|
|
18914
|
+
num: 1, // Body battery level: [0,100] Blank: -16
|
|
18901
18915
|
name: "level",
|
|
18902
18916
|
type: "sint8",
|
|
18903
18917
|
array: "true",
|
|
@@ -18960,7 +18974,7 @@ const Profile = {
|
|
|
18960
18974
|
subFields: []
|
|
18961
18975
|
},
|
|
18962
18976
|
0: {
|
|
18963
|
-
num: 0, // Event ID
|
|
18977
|
+
num: 0, // Event ID. Health SDK use only
|
|
18964
18978
|
name: "eventId",
|
|
18965
18979
|
type: "uint8",
|
|
18966
18980
|
array: "false",
|
|
@@ -19205,7 +19219,7 @@ const Profile = {
|
|
|
19205
19219
|
subFields: []
|
|
19206
19220
|
},
|
|
19207
19221
|
0: {
|
|
19208
|
-
num: 0, // Processing interval length in seconds
|
|
19222
|
+
num: 0, // Processing interval length in seconds. File start: 0xFFFFFFEF File stop: 0xFFFFFFEE
|
|
19209
19223
|
name: "processingInterval",
|
|
19210
19224
|
type: "uint16",
|
|
19211
19225
|
array: "false",
|
|
@@ -19268,7 +19282,7 @@ const Profile = {
|
|
|
19268
19282
|
subFields: []
|
|
19269
19283
|
},
|
|
19270
19284
|
1: {
|
|
19271
|
-
num: 1, // SpO2 Reading
|
|
19285
|
+
num: 1, // SpO2 Reading: [70,100] Blank: 240
|
|
19272
19286
|
name: "readingSpo2",
|
|
19273
19287
|
type: "uint8",
|
|
19274
19288
|
array: "true",
|
|
@@ -19282,7 +19296,7 @@ const Profile = {
|
|
|
19282
19296
|
subFields: []
|
|
19283
19297
|
},
|
|
19284
19298
|
2: {
|
|
19285
|
-
num: 2, // SpO2 Confidence
|
|
19299
|
+
num: 2, // SpO2 Confidence: [0,254]
|
|
19286
19300
|
name: "confidence",
|
|
19287
19301
|
type: "uint8",
|
|
19288
19302
|
array: "true",
|
|
@@ -19331,7 +19345,7 @@ const Profile = {
|
|
|
19331
19345
|
subFields: []
|
|
19332
19346
|
},
|
|
19333
19347
|
1: {
|
|
19334
|
-
num: 1, // Stress Level
|
|
19348
|
+
num: 1, // Stress Level: [0,100] Off wrist: -1 Excess motion: -2 Not enough data: -3 Recovering from exercise: -4 Unidentified: -5 Blank: -16
|
|
19335
19349
|
name: "stressLevel",
|
|
19336
19350
|
type: "sint8",
|
|
19337
19351
|
array: "true",
|
|
@@ -19380,7 +19394,7 @@ const Profile = {
|
|
|
19380
19394
|
subFields: []
|
|
19381
19395
|
},
|
|
19382
19396
|
1: {
|
|
19383
|
-
num: 1, // Breaths
|
|
19397
|
+
num: 1, // Breaths / min: [1,100] Invalid: 255 Excess motion: 254 Off wrist: 253 Not available: 252 Blank: 2.4
|
|
19384
19398
|
name: "respirationRate",
|
|
19385
19399
|
type: "sint16",
|
|
19386
19400
|
array: "true",
|
|
@@ -19443,7 +19457,7 @@ const Profile = {
|
|
|
19443
19457
|
subFields: []
|
|
19444
19458
|
},
|
|
19445
19459
|
2: {
|
|
19446
|
-
num: 2, // Beats / min
|
|
19460
|
+
num: 2, // Beats / min. Blank: 0
|
|
19447
19461
|
name: "heartRate",
|
|
19448
19462
|
type: "uint8",
|
|
19449
19463
|
array: "true",
|
|
@@ -19478,7 +19492,7 @@ const Profile = {
|
|
|
19478
19492
|
subFields: []
|
|
19479
19493
|
},
|
|
19480
19494
|
0: {
|
|
19481
|
-
num: 0,
|
|
19495
|
+
num: 0, // Encoded configuration data. Health SDK use only
|
|
19482
19496
|
name: "data",
|
|
19483
19497
|
type: "byte",
|
|
19484
19498
|
array: "true",
|
|
@@ -20920,7 +20934,7 @@ const Profile = {
|
|
|
20920
20934
|
subFields: []
|
|
20921
20935
|
},
|
|
20922
20936
|
0: {
|
|
20923
|
-
num: 0, //
|
|
20937
|
+
num: 0, // Millisecond resolution of the timestamp
|
|
20924
20938
|
name: "timestampMs",
|
|
20925
20939
|
type: "uint16",
|
|
20926
20940
|
array: "false",
|
|
@@ -20962,7 +20976,7 @@ const Profile = {
|
|
|
20962
20976
|
subFields: []
|
|
20963
20977
|
},
|
|
20964
20978
|
3: {
|
|
20965
|
-
num: 3,
|
|
20979
|
+
num: 3, // 1 = high confidence. 0 = low confidence. N/A when gap = 1
|
|
20966
20980
|
name: "quality",
|
|
20967
20981
|
type: "uint8",
|
|
20968
20982
|
array: "true",
|
|
@@ -20976,7 +20990,7 @@ const Profile = {
|
|
|
20976
20990
|
subFields: []
|
|
20977
20991
|
},
|
|
20978
20992
|
4: {
|
|
20979
|
-
num: 4,
|
|
20993
|
+
num: 4, // 1 = gap (time represents ms gap length). 0 = BBI data
|
|
20980
20994
|
name: "gap",
|
|
20981
20995
|
type: "uint8",
|
|
20982
20996
|
array: "true",
|
|
@@ -21129,6 +21143,20 @@ const Profile = {
|
|
|
21129
21143
|
hasComponents: false,
|
|
21130
21144
|
subFields: []
|
|
21131
21145
|
},
|
|
21146
|
+
6: {
|
|
21147
|
+
num: 6,
|
|
21148
|
+
name: "standardDeviation",
|
|
21149
|
+
type: "uint32",
|
|
21150
|
+
array: "false",
|
|
21151
|
+
scale: 1000,
|
|
21152
|
+
offset: 0,
|
|
21153
|
+
units: "m/s",
|
|
21154
|
+
bits: [],
|
|
21155
|
+
components: [],
|
|
21156
|
+
isAccumulated: false,
|
|
21157
|
+
hasComponents: false,
|
|
21158
|
+
subFields: []
|
|
21159
|
+
},
|
|
21132
21160
|
},
|
|
21133
21161
|
},
|
|
21134
21162
|
388: {
|
|
@@ -22296,6 +22324,7 @@ types: {
|
|
|
22296
22324
|
4: "positionWaypoint",
|
|
22297
22325
|
5: "positionMarked",
|
|
22298
22326
|
6: "off",
|
|
22327
|
+
13: "autoSelect",
|
|
22299
22328
|
},
|
|
22300
22329
|
lapTrigger: {
|
|
22301
22330
|
0: "manual",
|
|
@@ -22709,6 +22738,8 @@ types: {
|
|
|
22709
22738
|
148: "ezon",
|
|
22710
22739
|
149: "laisi",
|
|
22711
22740
|
150: "myzone",
|
|
22741
|
+
151: "abawo",
|
|
22742
|
+
152: "bafang",
|
|
22712
22743
|
255: "development",
|
|
22713
22744
|
257: "healthandlife",
|
|
22714
22745
|
258: "lezyne",
|
|
@@ -22783,6 +22814,9 @@ types: {
|
|
|
22783
22814
|
327: "magicshine",
|
|
22784
22815
|
328: "ictrainer",
|
|
22785
22816
|
329: "absoluteCycling",
|
|
22817
|
+
330: "eoSwimbetter",
|
|
22818
|
+
331: "mywhoosh",
|
|
22819
|
+
332: "ravemen",
|
|
22786
22820
|
5759: "actigraphcorp",
|
|
22787
22821
|
},
|
|
22788
22822
|
garminProduct: {
|
|
@@ -23082,6 +23116,7 @@ types: {
|
|
|
23082
23116
|
3449: "marqCommanderAsia",
|
|
23083
23117
|
3450: "marqExpeditionAsia",
|
|
23084
23118
|
3451: "marqAthleteAsia",
|
|
23119
|
+
3461: "indexSmartScale2",
|
|
23085
23120
|
3466: "instinctSolar",
|
|
23086
23121
|
3469: "fr45Asia",
|
|
23087
23122
|
3473: "vivoactive3Daimler",
|
|
@@ -23204,10 +23239,18 @@ types: {
|
|
|
23204
23239
|
4426: "vivoactive5",
|
|
23205
23240
|
4432: "fr165",
|
|
23206
23241
|
4433: "fr165Music",
|
|
23242
|
+
4440: "edge1050",
|
|
23207
23243
|
4442: "descentT2",
|
|
23208
23244
|
4446: "hrmFit",
|
|
23209
23245
|
4472: "marqGen2Commander",
|
|
23246
|
+
4477: "lilyAthlete", // aka the Lily 2 Active
|
|
23247
|
+
4532: "fenix8Solar",
|
|
23248
|
+
4533: "fenix8SolarLarge",
|
|
23249
|
+
4534: "fenix8Small",
|
|
23250
|
+
4536: "fenix8",
|
|
23210
23251
|
4556: "d2Mach1Pro",
|
|
23252
|
+
4575: "enduro3",
|
|
23253
|
+
4666: "fenixE",
|
|
23211
23254
|
10007: "sdm4", // SDM4 footpod
|
|
23212
23255
|
10014: "edgeRemote",
|
|
23213
23256
|
20533: "tacxTrainingAppWin",
|
package/src/stream.js
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
// Transfer (FIT) Protocol License.
|
|
6
6
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
7
7
|
// ****WARNING**** This file is auto-generated! Do NOT edit this file.
|
|
8
|
-
// Profile Version = 21.
|
|
9
|
-
// Tag = production/release/21.
|
|
8
|
+
// Profile Version = 21.158.0Release
|
|
9
|
+
// Tag = production/release/21.158.0-0-gc9428aa
|
|
10
10
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
11
11
|
|
|
12
12
|
|
|
@@ -112,10 +112,10 @@ class Stream {
|
|
|
112
112
|
throw Error(`FIT Runtime Error end of stream at byte ${this.#position}`);
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
-
const bytes = this.#arrayBuffer
|
|
115
|
+
const bytes = new Uint8Array(this.#arrayBuffer, this.#position, size);
|
|
116
116
|
this.#position += size;
|
|
117
117
|
|
|
118
|
-
this.#crcCalculator?.addBytes(
|
|
118
|
+
this.#crcCalculator?.addBytes(bytes, 0, size);
|
|
119
119
|
|
|
120
120
|
return bytes;
|
|
121
121
|
}
|
|
@@ -168,14 +168,14 @@ class Stream {
|
|
|
168
168
|
const baseTypeSize = FIT.BaseTypeDefinitions[baseType].size;
|
|
169
169
|
const baseTypeInvalid = FIT.BaseTypeDefinitions[baseType].invalid;
|
|
170
170
|
|
|
171
|
-
const
|
|
171
|
+
const bytes = this.readBytes(size);
|
|
172
172
|
|
|
173
173
|
if (size % baseTypeSize !== 0) {
|
|
174
174
|
return convertInvalidToNull ? null : baseTypeInvalid;
|
|
175
175
|
}
|
|
176
176
|
|
|
177
177
|
if (baseType === FIT.BaseType.STRING) {
|
|
178
|
-
const string = this.#textDecoder.decode(
|
|
178
|
+
const string = this.#textDecoder.decode(bytes).replace(/\uFFFD/g, "");
|
|
179
179
|
const strings = string.split('\0');
|
|
180
180
|
|
|
181
181
|
while (strings[strings.length - 1] === "") {
|
|
@@ -189,7 +189,7 @@ class Stream {
|
|
|
189
189
|
return strings.length === 1 ? strings[0] : strings;
|
|
190
190
|
}
|
|
191
191
|
|
|
192
|
-
const dataView = new DataView(
|
|
192
|
+
const dataView = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
193
193
|
let values = [];
|
|
194
194
|
|
|
195
195
|
const count = size / baseTypeSize;
|
package/src/utils-hr-mesg.js
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
// Transfer (FIT) Protocol License.
|
|
6
6
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
7
7
|
// ****WARNING**** This file is auto-generated! Do NOT edit this file.
|
|
8
|
-
// Profile Version = 21.
|
|
9
|
-
// Tag = production/release/21.
|
|
8
|
+
// Profile Version = 21.158.0Release
|
|
9
|
+
// Tag = production/release/21.158.0-0-gc9428aa
|
|
10
10
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
11
11
|
|
|
12
12
|
|
package/src/utils-internal.js
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
// Transfer (FIT) Protocol License.
|
|
6
6
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
7
7
|
// ****WARNING**** This file is auto-generated! Do NOT edit this file.
|
|
8
|
-
// Profile Version = 21.
|
|
9
|
-
// Tag = production/release/21.
|
|
8
|
+
// Profile Version = 21.158.0Release
|
|
9
|
+
// Tag = production/release/21.158.0-0-gc9428aa
|
|
10
10
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
11
11
|
|
|
12
12
|
|
package/src/utils.js
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
// Transfer (FIT) Protocol License.
|
|
6
6
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
7
7
|
// ****WARNING**** This file is auto-generated! Do NOT edit this file.
|
|
8
|
-
// Profile Version = 21.
|
|
9
|
-
// Tag = production/release/21.
|
|
8
|
+
// Profile Version = 21.158.0Release
|
|
9
|
+
// Tag = production/release/21.158.0-0-gc9428aa
|
|
10
10
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
11
11
|
|
|
12
12
|
|