@garmin/fitsdk 21.201.0 → 21.205.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/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.201.0Release
9
- // Tag = production/release/21.201.0-0-g39a0a60c
8
+ // Profile Version = 21.205.0Release
9
+ // Tag = production/release/21.205.0-0-gb3c261eb
10
10
  /////////////////////////////////////////////////////////////////////////////////////////////
11
11
 
12
12
 
13
13
  const Profile = {
14
14
  version: {
15
15
  major: 21,
16
- minor: 201,
16
+ minor: 205,
17
17
  patch: 0,
18
18
  type: "Release"
19
19
  },
@@ -5887,6 +5887,21 @@ const Profile = {
5887
5887
  hasComponents: true,
5888
5888
  subFields: []
5889
5889
  },
5890
+ 78: {
5891
+ num: 78,
5892
+ name: "activeTime",
5893
+ type: "uint32",
5894
+ baseType: "uint32",
5895
+ array: false,
5896
+ scale: 1000,
5897
+ offset: 0,
5898
+ units: "s",
5899
+ bits: [],
5900
+ components: [],
5901
+ isAccumulated: false,
5902
+ hasComponents: false,
5903
+ subFields: []
5904
+ },
5890
5905
  82: {
5891
5906
  num: 82,
5892
5907
  name: "playerScore",
@@ -8129,6 +8144,21 @@ const Profile = {
8129
8144
  hasComponents: false,
8130
8145
  subFields: []
8131
8146
  },
8147
+ 70: {
8148
+ num: 70,
8149
+ name: "activeTime",
8150
+ type: "uint32",
8151
+ baseType: "uint32",
8152
+ array: false,
8153
+ scale: 1000,
8154
+ offset: 0,
8155
+ units: "s",
8156
+ bits: [],
8157
+ components: [],
8158
+ isAccumulated: false,
8159
+ hasComponents: false,
8160
+ subFields: []
8161
+ },
8132
8162
  71: {
8133
8163
  num: 71,
8134
8164
  name: "wktStepIndex",
@@ -14560,6 +14590,21 @@ const Profile = {
14560
14590
  hasComponents: false,
14561
14591
  subFields: []
14562
14592
  },
14593
+ 78: {
14594
+ num: 78, // Active time of split rounds
14595
+ name: "activeTime",
14596
+ type: "uint32",
14597
+ baseType: "uint32",
14598
+ array: false,
14599
+ scale: 1000,
14600
+ offset: 0,
14601
+ units: "s",
14602
+ bits: [],
14603
+ components: [],
14604
+ isAccumulated: false,
14605
+ hasComponents: false,
14606
+ subFields: []
14607
+ },
14563
14608
  110: {
14564
14609
  num: 110,
14565
14610
  name: "totalMovingTime",
@@ -14777,6 +14822,21 @@ const Profile = {
14777
14822
  hasComponents: false,
14778
14823
  subFields: []
14779
14824
  },
14825
+ 65: {
14826
+ num: 65, // total active time in all split rounds
14827
+ name: "activeTime",
14828
+ type: "uint32",
14829
+ baseType: "uint32",
14830
+ array: false,
14831
+ scale: 1000,
14832
+ offset: 0,
14833
+ units: "s",
14834
+ bits: [],
14835
+ components: [],
14836
+ isAccumulated: false,
14837
+ hasComponents: false,
14838
+ subFields: []
14839
+ },
14780
14840
  77: {
14781
14841
  num: 77,
14782
14842
  name: "totalMovingTime",
@@ -20890,7 +20950,7 @@ const Profile = {
20890
20950
  array: true,
20891
20951
  scale: 1000,
20892
20952
  offset: 0,
20893
- units: "degC",
20953
+ units: "C",
20894
20954
  bits: [],
20895
20955
  components: [],
20896
20956
  isAccumulated: false,
@@ -25044,10 +25104,14 @@ types: {
25044
25104
  4759: "instinct3Solar50mm",
25045
25105
  4775: "tactix8Amoled",
25046
25106
  4776: "tactix8Solar",
25107
+ 4814: "fr170Music",
25108
+ 4815: "fr170",
25047
25109
  4825: "approachJ1",
25048
25110
  4879: "d2Mach2",
25111
+ 4916: "fr702026",
25049
25112
  4678: "instinctCrossoverAmoled",
25050
25113
  4944: "d2AirX15",
25114
+ 5056: "d2Mach2Pro",
25051
25115
  10007: "sdm4", // SDM4 footpod
25052
25116
  10014: "edgeRemote",
25053
25117
  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.201.0Release
9
- // Tag = production/release/21.201.0-0-g39a0a60c
8
+ // Profile Version = 21.205.0Release
9
+ // Tag = production/release/21.205.0-0-gb3c261eb
10
10
  /////////////////////////////////////////////////////////////////////////////////////////////
11
11
 
12
12
 
@@ -14,55 +14,32 @@ import FIT from "./fit.js";
14
14
  import UtilsInternal from "./utils-internal.js";
15
15
 
16
16
  class Stream {
17
- static LITTLE_ENDIAN = true;
18
- static BIG_ENDIAN = false;
19
-
20
17
  #position = 0;
21
18
  #arrayBuffer = null;
19
+ #dataView = null;
22
20
  #textDecoder = new TextDecoder("utf-8", { fatal: false, ignoreBOM: true });
23
21
  #crcCalculator = null;
22
+ #legacyArrayMode = false;
24
23
 
25
- /**
26
- * Convenience method for creating a Stream from a byte array
27
- * @param {Array<number>} data An array of bytes
28
- * @returns {Stream} A new Stream object
29
- * @static
30
- */
31
24
  static fromByteArray(data) {
32
25
  const buf = new Uint8Array(data);
33
26
  return this.fromArrayBuffer(buf.buffer);
34
27
  }
35
28
 
36
- /**
37
- * Convenience method for creating a Stream from a Node Buffer
38
- * @param {Buffer} buffer - Node Buffer of bytes
39
- * @returns {Stream} A new Stream object
40
- * @static
41
- */
42
29
  static fromBuffer(buffer) {
43
30
  const arrayBuffer = buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
44
31
  return this.fromArrayBuffer(arrayBuffer);
45
32
  }
46
33
 
47
- /**
48
- * Convenience method for creating a Stream from an ArrayBuffer
49
- * @param {ArrayBuffer} arrayBuffer - An ArrayBuffer of bytes
50
- * @returns {Stream} A new Stream object
51
- * @static
52
- */
53
34
  static fromArrayBuffer(arrayBuffer) {
54
35
  const stream = new Stream(arrayBuffer);
55
36
  return stream;
56
37
  }
57
38
 
58
- /**
59
- * Creates a Stream containing a FIT file
60
- * @constructor
61
- * @param {ArrayBuffer} stream - ArrayBuffer containing a FIT file
62
- */
63
39
  constructor(arrayBuffer) {
64
40
  this.#position = 0;
65
41
  this.#arrayBuffer = arrayBuffer;
42
+ this.#dataView = new DataView(arrayBuffer);
66
43
  }
67
44
 
68
45
  get length() {
@@ -85,6 +62,14 @@ class Stream {
85
62
  this.#crcCalculator = crcCalculator;
86
63
  }
87
64
 
65
+ get legacyArrayMode() {
66
+ return this.#legacyArrayMode;
67
+ }
68
+
69
+ set legacyArrayMode(legacyArrayMode) {
70
+ this.#legacyArrayMode = legacyArrayMode;
71
+ }
72
+
88
73
  reset() {
89
74
  this.seek(0);
90
75
  }
@@ -98,9 +83,7 @@ class Stream {
98
83
  }
99
84
 
100
85
  peekByte() {
101
- const arrayBuffer = this.#arrayBuffer.slice(this.#position, this.#position + 1);
102
- const dataView = new DataView(arrayBuffer);
103
- return dataView.getUint8(0);
86
+ return this.#dataView.getUint8(this.#position);
104
87
  }
105
88
 
106
89
  readByte() {
@@ -160,14 +143,27 @@ class Stream {
160
143
  return this.readValue(FIT.BaseType.FLOAT64, 8, { convertInvalidToNull: false, ...opts });
161
144
  }
162
145
 
163
- readString(strlen) {
164
- return this.readValue(FIT.BaseType.STRING, strlen);
146
+ readString(strlen, opts = {}) {
147
+ return this.readValue(FIT.BaseType.STRING, strlen, opts);
165
148
  }
166
149
 
167
- readValue(baseType, size, { endianness = Stream.LITTLE_ENDIAN, convertInvalidToNull = true } = {}) {
168
- const baseTypeSize = FIT.BaseTypeDefinitions[baseType].size;
169
- const baseTypeInvalid = FIT.BaseTypeDefinitions[baseType].invalid;
150
+ asUint8Array() {
151
+ return new Uint8Array(this.#arrayBuffer);
152
+ }
170
153
 
154
+ readValue(
155
+ baseType,
156
+ size,
157
+ {
158
+ littleEndian = true,
159
+ convertInvalidToNull = true,
160
+ isArray = false
161
+ } = {}) {
162
+ const baseTypeDef = FIT.BaseTypeDefinitions[baseType];
163
+ const baseTypeSize = baseTypeDef.size;
164
+ const baseTypeInvalid = baseTypeDef.invalid;
165
+
166
+ const startPos = this.#position;
171
167
  const bytes = this.readBytes(size);
172
168
 
173
169
  if (size % baseTypeSize !== 0) {
@@ -186,73 +182,94 @@ class Stream {
186
182
  return null;
187
183
  }
188
184
 
189
- return strings.length === 1 ? strings[0] : strings;
190
- }
185
+ if (this.#legacyArrayMode) {
186
+ return strings.length === 1 ? strings[0] : strings;
187
+ }
191
188
 
192
- const dataView = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
193
- let values = [];
189
+ return strings[0];
190
+ }
194
191
 
195
192
  const count = size / baseTypeSize;
196
193
 
197
- for (let i = 0; i < count; i++) {
194
+ if (count === 1) {
195
+ const value = this.#readSingleValue(baseType, startPos, littleEndian);
196
+
197
+ if (convertInvalidToNull && value === baseTypeInvalid) {
198
+ return null;
199
+ }
198
200
 
199
- switch (baseType) {
200
- case FIT.BaseType.BYTE:
201
- case FIT.BaseType.ENUM:
202
- case FIT.BaseType.UINT8:
203
- case FIT.BaseType.UINT8Z:
204
- values.push(dataView.getUint8(i * baseTypeSize));
205
- break;
206
-
207
- case FIT.BaseType.SINT8:
208
- values.push(dataView.getInt8(i * baseTypeSize));
209
- break;
210
-
211
- case FIT.BaseType.UINT16:
212
- case FIT.BaseType.UINT16Z:
213
- values.push(dataView.getUint16(i * baseTypeSize, endianness));
214
- break;
215
-
216
- case FIT.BaseType.SINT16:
217
- values.push(dataView.getInt16(i * baseTypeSize, endianness));
218
- break;
219
-
220
- case FIT.BaseType.UINT32:
221
- case FIT.BaseType.UINT32Z:
222
- values.push(dataView.getUint32(i * baseTypeSize, endianness));
223
- break;
224
-
225
- case FIT.BaseType.SINT32:
226
- values.push(dataView.getInt32(i * baseTypeSize, endianness));
227
- break;
228
-
229
- case FIT.BaseType.UINT64:
230
- case FIT.BaseType.UINT64Z:
231
- values.push(dataView.getBigUint64(i * baseTypeSize, endianness));
232
- break;
233
- case FIT.BaseType.SINT64:
234
- values.push(dataView.getBigInt64(i * baseTypeSize, endianness));
235
- break;
236
-
237
- case FIT.BaseType.FLOAT32:
238
- values.push(dataView.getFloat32(i * baseTypeSize, endianness));
239
- break;
240
-
241
- case FIT.BaseType.FLOAT64:
242
- values.push(dataView.getFloat64(i * baseTypeSize, endianness));
243
- break;
201
+ if (!this.#legacyArrayMode && !isArray) {
202
+ return value;
244
203
  }
204
+
205
+ return UtilsInternal.sanitizeValues([value], { legacyArrayMode: this.#legacyArrayMode, isArray });
245
206
  }
246
207
 
247
- if (baseType === FIT.BaseType.BYTE) {
248
- return UtilsInternal.onlyInvalidValues(values, baseTypeInvalid) ? null : values;
208
+ let values = [];
209
+
210
+ for (let i = 0; i < count; i++) {
211
+ values.push(this.#readSingleValue(baseType, startPos + i * baseTypeSize, littleEndian));
249
212
  }
250
213
 
251
214
  if (convertInvalidToNull) {
252
- values = values.map(value => value === baseTypeInvalid ? null : value);
215
+ if (UtilsInternal.onlyInvalidValues(values, baseTypeInvalid)) {
216
+ return null;
217
+ }
218
+
219
+ if (baseType !== FIT.BaseType.BYTE) {
220
+ values = values.map(value => value === baseTypeInvalid ? null : value);
221
+ }
253
222
  }
254
223
 
255
- return UtilsInternal.sanitizeValues(values);
224
+ return UtilsInternal.sanitizeValues(
225
+ values,
226
+ {
227
+ legacyArrayMode: this.#legacyArrayMode,
228
+ isArray
229
+ });
230
+ }
231
+
232
+ #readSingleValue(baseType, offset, littleEndian) {
233
+ switch (baseType) {
234
+ case FIT.BaseType.BYTE:
235
+ case FIT.BaseType.ENUM:
236
+ case FIT.BaseType.UINT8:
237
+ case FIT.BaseType.UINT8Z:
238
+ return this.#dataView.getUint8(offset);
239
+
240
+ case FIT.BaseType.SINT8:
241
+ return this.#dataView.getInt8(offset);
242
+
243
+ case FIT.BaseType.UINT16:
244
+ case FIT.BaseType.UINT16Z:
245
+ return this.#dataView.getUint16(offset, littleEndian);
246
+
247
+ case FIT.BaseType.SINT16:
248
+ return this.#dataView.getInt16(offset, littleEndian);
249
+
250
+ case FIT.BaseType.UINT32:
251
+ case FIT.BaseType.UINT32Z:
252
+ return this.#dataView.getUint32(offset, littleEndian);
253
+
254
+ case FIT.BaseType.SINT32:
255
+ return this.#dataView.getInt32(offset, littleEndian);
256
+
257
+ case FIT.BaseType.UINT64:
258
+ case FIT.BaseType.UINT64Z:
259
+ return this.#dataView.getBigUint64(offset, littleEndian);
260
+
261
+ case FIT.BaseType.SINT64:
262
+ return this.#dataView.getBigInt64(offset, littleEndian);
263
+
264
+ case FIT.BaseType.FLOAT32:
265
+ return this.#dataView.getFloat32(offset, littleEndian);
266
+
267
+ case FIT.BaseType.FLOAT64:
268
+ return this.#dataView.getFloat64(offset, littleEndian);
269
+
270
+ default:
271
+ throw new Error(`Unsupported FIT base type: ${baseType}`);
272
+ }
256
273
  }
257
274
  }
258
275
 
@@ -0,0 +1,34 @@
1
+ /////////////////////////////////////////////////////////////////////////////////////////////
2
+ // Copyright 2026 Garmin International, Inc.
3
+ // Licensed under the Flexible and Interoperable Data Transfer (FIT) Protocol License; you
4
+ // may not use this file except in compliance with the Flexible and Interoperable Data
5
+ // Transfer (FIT) Protocol License.
6
+ /////////////////////////////////////////////////////////////////////////////////////////////
7
+ // ****WARNING**** This file is auto-generated! Do NOT edit this file.
8
+ // Profile Version = 21.205.0Release
9
+ // Tag = production/release/21.205.0-0-gb3c261eb
10
+ /////////////////////////////////////////////////////////////////////////////////////////////
11
+
12
+
13
+ /** Computes the 16-bit CRC used to validate FIT file headers and file data. */
14
+ export class CrcCalculator {
15
+ constructor();
16
+ /** The current running CRC value. */
17
+ readonly crc: number;
18
+ /**
19
+ * Feeds a range of bytes into the running CRC.
20
+ * @param buf - The byte array to process.
21
+ * @param start - Inclusive start index within `buf`.
22
+ * @param end - Exclusive end index within `buf`.
23
+ * @returns The updated CRC value.
24
+ */
25
+ addBytes(buf: Uint8Array, start: number, end: number): number;
26
+ /**
27
+ * Computes the CRC for a range of bytes without requiring an instance.
28
+ * @param buf - The byte array to process.
29
+ * @param start - Inclusive start index within `buf`.
30
+ * @param end - Exclusive end index within `buf`.
31
+ * @returns The computed CRC value.
32
+ */
33
+ static calculateCRC(buf: Uint8Array, start: number, end: number): number;
34
+ }
@@ -0,0 +1,140 @@
1
+ /////////////////////////////////////////////////////////////////////////////////////////////
2
+ // Copyright 2026 Garmin International, Inc.
3
+ // Licensed under the Flexible and Interoperable Data Transfer (FIT) Protocol License; you
4
+ // may not use this file except in compliance with the Flexible and Interoperable Data
5
+ // Transfer (FIT) Protocol License.
6
+ /////////////////////////////////////////////////////////////////////////////////////////////
7
+ // ****WARNING**** This file is auto-generated! Do NOT edit this file.
8
+ // Profile Version = 21.205.0Release
9
+ // Tag = production/release/21.205.0-0-gb3c261eb
10
+ /////////////////////////////////////////////////////////////////////////////////////////////
11
+
12
+
13
+ import { Stream } from "./stream";
14
+ import { Mesg } from "./mesg";
15
+ import { FitMessages, DeveloperDataIdMesg, FieldDescriptionMesg } from "./mesgs";
16
+
17
+ /** Decodes FIT binary data from a {@link Stream}. */
18
+ export class Decoder {
19
+ /**
20
+ * Creates a FIT File Decoder.
21
+ * @param stream - Stream representing the FIT file to decode.
22
+ */
23
+ constructor(stream: Stream);
24
+
25
+ /**
26
+ * Inspects the file header to determine if the input stream is a FIT file.
27
+ * @param stream - The stream to inspect.
28
+ * @returns `true` if the stream is a FIT file.
29
+ */
30
+ static isFIT(stream: Stream): boolean;
31
+
32
+ /**
33
+ * Inspects the file header to determine if the input stream is a FIT file.
34
+ * @returns `true` if the stream is a FIT file.
35
+ */
36
+ isFIT(): boolean;
37
+
38
+ /**
39
+ * Checks that the input stream is a FIT file and verifies both the header and file CRC values.
40
+ * @returns `true` if the stream passes the {@link isFIT} and CRC checks.
41
+ */
42
+ checkIntegrity(): boolean;
43
+
44
+ /**
45
+ * Read the messages from the stream.
46
+ * @param options - Read options. See {@link DecoderOptions}.
47
+ * @returns Object containing decoded messages, profile version, and any errors.
48
+ */
49
+ read(options?: DecoderOptions): { messages: FitMessages; profileVersion: ProfileVersion; errors: Error[] };
50
+ }
51
+
52
+ /** Describes a single field within a MesgDefinition. */
53
+ export interface FieldDefinition {
54
+ /** Field definition number identifying the field within its message. */
55
+ fieldDefinitionNumber: number;
56
+ /** Size in bytes of the field. */
57
+ size: number;
58
+ /** FIT base type identifier for this field's values. */
59
+ baseType: number;
60
+ /** The invalid value for this field's base type. */
61
+ invalidValue: number;
62
+ /** Byte size of a single element of this field's base type. */
63
+ baseTypeSize: number;
64
+ }
65
+
66
+ /** Describes a single developer-defined field within a raw FIT message definition record. */
67
+ export interface DeveloperFieldDefinition {
68
+ /** Developer field definition number, scoped to the developer data index. */
69
+ fieldDefinitionNumber: number;
70
+ /** Size in bytes of the field. */
71
+ size: number;
72
+ /** Index identifying the developer application that defined this field. */
73
+ developerDataIndex: number;
74
+ }
75
+
76
+ /** The definition record for a FIT message*/
77
+ export interface MesgDefinition {
78
+ /** Raw record header byte. */
79
+ recordHeader: number;
80
+ /** Local message number used to map messages to a definition. */
81
+ localMesgNum: number;
82
+ /** Reserved byte from the definition record. */
83
+ reserved: number;
84
+ /** Architecture byte: `0` = little-endian, `1` = big-endian. */
85
+ architecture: number;
86
+ /** Endianness derived from `architecture` (`true` == little-endian or `false` == big-endian). */
87
+ endianness: boolean;
88
+ /** Global message number identifying the message type in the FIT profile. */
89
+ globalMessageNumber: number;
90
+ /** Number of fields in the message. */
91
+ numFields: number;
92
+ /** Array of field definitions for the message. */
93
+ fieldDefinitions: FieldDefinition[];
94
+ /** Developer field definitions for the message. */
95
+ developerFieldDefinitions: DeveloperFieldDefinition[];
96
+ /** Total size in bytes of the combined fields. */
97
+ messageSize: number;
98
+ /** Total size in bytes of the combined developer fields. */
99
+ developerDataSize: number;
100
+ }
101
+
102
+ /** Options controlling how {@link Decoder.read} decodes the FIT stream. */
103
+ export interface DecoderOptions {
104
+ /** Callback invoked for each decoded message. */
105
+ mesgListener?: (mesgNum: number, mesg: Mesg) => void;
106
+ /** Callback invoked for each decoded message definition. */
107
+ mesgDefinitionListener?: (mesgDefinition: MesgDefinition) => void;
108
+ /** Callback invoked for each developer field description. */
109
+ fieldDescriptionListener?: (key: number, developerDataIdMesg: DeveloperDataIdMesg, fieldDescriptionMesg: FieldDescriptionMesg) => void;
110
+ /** Expand sub fields. Default: `true`. */
111
+ expandSubFields?: boolean;
112
+ /** Expand component fields. Default: `true`. */
113
+ expandComponents?: boolean;
114
+ /** Apply scale and offset to numeric fields. Default: `true`. */
115
+ applyScaleAndOffset?: boolean;
116
+ /** Convert type values to their string representations. Default: `true`. */
117
+ convertTypesToStrings?: boolean;
118
+ /** Convert FIT epoch timestamps to `Date` objects. Default: `true`. */
119
+ convertDateTimesToDates?: boolean;
120
+ /** Include fields not in the profile. Default: `false`. */
121
+ includeUnknownData?: boolean;
122
+ /** Merge HR messages into record messages. Requires `applyScaleAndOffset` and `expandComponents`. Default: `true`. */
123
+ mergeHeartRates?: boolean;
124
+ /** Decode memo glob messages. Default: `false`. */
125
+ decodeMemoGlobs?: boolean;
126
+ /** Skip the FIT file header. Default: `false`. */
127
+ skipHeader?: boolean;
128
+ /** Decode data bytes only, no header or CRC. Default: `false`. */
129
+ dataOnly?: boolean;
130
+ /** @deprecated Default: `false`. */
131
+ legacyArrayMode?: boolean;
132
+ }
133
+
134
+ /** The FIT profile version embedded in a FIT file header. */
135
+ export interface ProfileVersion {
136
+ /** Major version number. */
137
+ major: number;
138
+ /** Minor version number (tenths). */
139
+ minor: number;
140
+ }
@@ -0,0 +1,69 @@
1
+ /////////////////////////////////////////////////////////////////////////////////////////////
2
+ // Copyright 2026 Garmin International, Inc.
3
+ // Licensed under the Flexible and Interoperable Data Transfer (FIT) Protocol License; you
4
+ // may not use this file except in compliance with the Flexible and Interoperable Data
5
+ // Transfer (FIT) Protocol License.
6
+ /////////////////////////////////////////////////////////////////////////////////////////////
7
+ // ****WARNING**** This file is auto-generated! Do NOT edit this file.
8
+ // Profile Version = 21.205.0Release
9
+ // Tag = production/release/21.205.0-0-gb3c261eb
10
+ /////////////////////////////////////////////////////////////////////////////////////////////
11
+
12
+
13
+ import { Encodable, Mesg } from "./mesg";
14
+ import { DeveloperDataIdMesg, FieldDescriptionMesg } from "./mesgs";
15
+
16
+ export interface FieldDescription {
17
+ /** The Developer Data Id message. */
18
+ developerDataIdMesg: DeveloperDataIdMesg;
19
+ /** The Field Description message. */
20
+ fieldDescriptionMesg: FieldDescriptionMesg;
21
+ }
22
+
23
+ /** Options for constructing an {@link Encoder}. */
24
+ export interface EncoderOptions {
25
+ /** Developer field descriptions keyed by developer data index. Equivalent to calling {@link Encoder.addDeveloperField} for each entry. */
26
+ fieldDescriptions?: Record<number, FieldDescription>;
27
+ }
28
+
29
+ /** Encodes FIT messages into a binary FIT file. */
30
+ export class Encoder {
31
+ /**
32
+ * Creates a FIT File Encoder.
33
+ * @param options - Encoder options. See {@link EncoderOptions}.
34
+ */
35
+ constructor(options?: EncoderOptions);
36
+
37
+ /**
38
+ * Closes the encoder and returns the encoded file data.
39
+ * @returns A `Uint8Array` containing the encoded FIT file.
40
+ */
41
+ close(): Uint8Array;
42
+
43
+ /**
44
+ * Encodes a message into the file.
45
+ * @param mesg - The message data, must include a `mesgNum` property.
46
+ * @returns `this`.
47
+ */
48
+ writeMesg(mesg: Encodable<Mesg>): this;
49
+
50
+ /**
51
+ * Encodes a message into the file.
52
+ * Can be used directly as a {@link DecoderOptions.mesgListener} callback.
53
+ * @param mesgNum - The message number.
54
+ * @param mesg - The message data.
55
+ * @returns `this`.
56
+ */
57
+ onMesg(mesgNum: number, mesg: Mesg): this;
58
+
59
+ /**
60
+ * Adds a Developer Data Field Description and associated Developer Data Id Message to the Encoder.
61
+ * Does not write these messages to the output stream.
62
+ * Can be used directly as a {@link DecoderOptions.fieldDescriptionListener} callback.
63
+ * @param key - The key associated with this developer field pairing.
64
+ * @param developerDataIdMesg - The Developer Data Id message.
65
+ * @param fieldDescriptionMesg - The Field Description message.
66
+ * @returns `this`.
67
+ */
68
+ addDeveloperField(key: number, developerDataIdMesg: DeveloperDataIdMesg, fieldDescriptionMesg: FieldDescriptionMesg): this;
69
+ }