fit-file-parser 5.2.0 → 6.0.2
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/CHANGELOG.md +18 -187
- package/PROFILE.md +43 -0
- package/README.md +75 -81
- package/dist/binary.d.ts +2 -0
- package/dist/binary.js +28 -58
- package/dist/cjs/binary.d.ts +2 -0
- package/dist/cjs/binary.js +28 -58
- package/dist/cjs/fit-parser.d.ts +2 -0
- package/dist/cjs/fit-parser.js +25 -3
- package/dist/cjs/fit.d.ts +0 -6
- package/dist/cjs/fit.js +4 -114
- package/dist/cjs/fit_types.d.ts +1 -0
- package/dist/cjs/profile.d.ts +9 -0
- package/dist/{garmin_profile.generated.js → cjs/profile.js} +285 -8
- package/dist/cjs/type_generator.js +1 -0
- package/dist/fit-parser.d.ts +2 -0
- package/dist/fit-parser.js +25 -3
- package/dist/fit.d.ts +0 -6
- package/dist/fit.js +3 -113
- package/dist/fit_types.d.ts +1 -0
- package/dist/profile.d.ts +9 -0
- package/dist/{cjs/garmin_profile.generated.js → profile.js} +282 -11
- package/dist/type_generator.js +1 -0
- package/package.json +10 -9
- package/dist/cjs/garmin_profile.generated.d.ts +0 -9
- package/dist/garmin_profile.generated.d.ts +0 -9
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PROFILE_TYPES = exports.PROFILE_MESSAGES = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Static, community-maintained FIT interoperability profile.
|
|
6
|
+
*
|
|
7
|
+
* This table is ordinary project source maintained under the repository's MIT
|
|
8
|
+
* license. See PROFILE.md for the maintenance and verification policy.
|
|
9
|
+
*/
|
|
10
|
+
exports.PROFILE_MESSAGES = {
|
|
8
11
|
0: {
|
|
9
12
|
0: {
|
|
10
13
|
field: 'type',
|
|
@@ -2586,6 +2589,13 @@ export const GARMIN_MESSAGES = {
|
|
|
2586
2589
|
offset: 0,
|
|
2587
2590
|
units: 'Breaths/min',
|
|
2588
2591
|
},
|
|
2592
|
+
178: {
|
|
2593
|
+
field: 'est_sweat_loss',
|
|
2594
|
+
type: 'uint16',
|
|
2595
|
+
scale: 1,
|
|
2596
|
+
offset: 0,
|
|
2597
|
+
units: 'ml',
|
|
2598
|
+
},
|
|
2589
2599
|
180: {
|
|
2590
2600
|
field: 'enhanced_min_respiration_rate',
|
|
2591
2601
|
type: 'uint16',
|
|
@@ -2640,6 +2650,13 @@ export const GARMIN_MESSAGES = {
|
|
|
2640
2650
|
offset: 0,
|
|
2641
2651
|
units: 'Flow',
|
|
2642
2652
|
},
|
|
2653
|
+
188: {
|
|
2654
|
+
field: 'primary_benefit',
|
|
2655
|
+
type: 'uint8',
|
|
2656
|
+
scale: 1,
|
|
2657
|
+
offset: 0,
|
|
2658
|
+
units: '',
|
|
2659
|
+
},
|
|
2643
2660
|
192: {
|
|
2644
2661
|
field: 'workout_feel',
|
|
2645
2662
|
type: 'uint8',
|
|
@@ -2721,6 +2738,27 @@ export const GARMIN_MESSAGES = {
|
|
|
2721
2738
|
offset: 0,
|
|
2722
2739
|
units: 'm',
|
|
2723
2740
|
},
|
|
2741
|
+
205: {
|
|
2742
|
+
field: 'beginning_potential_stamina',
|
|
2743
|
+
type: 'uint8',
|
|
2744
|
+
scale: 1,
|
|
2745
|
+
offset: 0,
|
|
2746
|
+
units: 'percent',
|
|
2747
|
+
},
|
|
2748
|
+
206: {
|
|
2749
|
+
field: 'ending_potential_stamina',
|
|
2750
|
+
type: 'uint8',
|
|
2751
|
+
scale: 1,
|
|
2752
|
+
offset: 0,
|
|
2753
|
+
units: 'percent',
|
|
2754
|
+
},
|
|
2755
|
+
207: {
|
|
2756
|
+
field: 'min_stamina',
|
|
2757
|
+
type: 'uint8',
|
|
2758
|
+
scale: 1,
|
|
2759
|
+
offset: 0,
|
|
2760
|
+
units: 'percent',
|
|
2761
|
+
},
|
|
2724
2762
|
208: {
|
|
2725
2763
|
field: 'avg_core_temperature',
|
|
2726
2764
|
type: 'uint16',
|
|
@@ -4419,6 +4457,13 @@ export const GARMIN_MESSAGES = {
|
|
|
4419
4457
|
offset: 0,
|
|
4420
4458
|
units: 'm',
|
|
4421
4459
|
},
|
|
4460
|
+
90: {
|
|
4461
|
+
field: 'garmin_performance_condition',
|
|
4462
|
+
type: 'sint8',
|
|
4463
|
+
scale: 1,
|
|
4464
|
+
offset: 0,
|
|
4465
|
+
units: '',
|
|
4466
|
+
},
|
|
4422
4467
|
91: {
|
|
4423
4468
|
field: 'absolute_pressure',
|
|
4424
4469
|
type: 'uint32',
|
|
@@ -4626,6 +4671,20 @@ export const GARMIN_MESSAGES = {
|
|
|
4626
4671
|
offset: 0,
|
|
4627
4672
|
units: 'percent',
|
|
4628
4673
|
},
|
|
4674
|
+
137: {
|
|
4675
|
+
field: 'potential_stamina',
|
|
4676
|
+
type: 'uint8',
|
|
4677
|
+
scale: 1,
|
|
4678
|
+
offset: 0,
|
|
4679
|
+
units: 'percent',
|
|
4680
|
+
},
|
|
4681
|
+
138: {
|
|
4682
|
+
field: 'stamina',
|
|
4683
|
+
type: 'uint8',
|
|
4684
|
+
scale: 1,
|
|
4685
|
+
offset: 0,
|
|
4686
|
+
units: 'percent',
|
|
4687
|
+
},
|
|
4629
4688
|
139: {
|
|
4630
4689
|
field: 'core_temperature',
|
|
4631
4690
|
type: 'uint16',
|
|
@@ -4956,6 +5015,13 @@ export const GARMIN_MESSAGES = {
|
|
|
4956
5015
|
offset: 0,
|
|
4957
5016
|
units: '',
|
|
4958
5017
|
},
|
|
5018
|
+
24: {
|
|
5019
|
+
field: 'ant_id',
|
|
5020
|
+
type: 'uint32z',
|
|
5021
|
+
scale: 1,
|
|
5022
|
+
offset: 0,
|
|
5023
|
+
units: '',
|
|
5024
|
+
},
|
|
4959
5025
|
25: {
|
|
4960
5026
|
field: 'source_type',
|
|
4961
5027
|
type: 'source_type',
|
|
@@ -6398,6 +6464,107 @@ export const GARMIN_MESSAGES = {
|
|
|
6398
6464
|
},
|
|
6399
6465
|
name: 'hrv',
|
|
6400
6466
|
},
|
|
6467
|
+
79: {
|
|
6468
|
+
0: {
|
|
6469
|
+
field: 'vo2_max',
|
|
6470
|
+
type: 'uint16',
|
|
6471
|
+
scale: 292.57142857142856,
|
|
6472
|
+
offset: 0,
|
|
6473
|
+
units: 'ml/kg/min',
|
|
6474
|
+
},
|
|
6475
|
+
1: {
|
|
6476
|
+
field: 'age',
|
|
6477
|
+
type: 'uint8',
|
|
6478
|
+
scale: 1,
|
|
6479
|
+
offset: 0,
|
|
6480
|
+
units: 'years',
|
|
6481
|
+
},
|
|
6482
|
+
2: {
|
|
6483
|
+
field: 'height',
|
|
6484
|
+
type: 'uint8',
|
|
6485
|
+
scale: 100,
|
|
6486
|
+
offset: 0,
|
|
6487
|
+
units: 'm',
|
|
6488
|
+
},
|
|
6489
|
+
3: {
|
|
6490
|
+
field: 'weight',
|
|
6491
|
+
type: 'uint16',
|
|
6492
|
+
scale: 10,
|
|
6493
|
+
offset: 0,
|
|
6494
|
+
units: 'kg',
|
|
6495
|
+
},
|
|
6496
|
+
4: {
|
|
6497
|
+
field: 'gender',
|
|
6498
|
+
type: 'gender',
|
|
6499
|
+
scale: 1,
|
|
6500
|
+
offset: 0,
|
|
6501
|
+
units: '',
|
|
6502
|
+
},
|
|
6503
|
+
6: {
|
|
6504
|
+
field: 'max_heart_rate',
|
|
6505
|
+
type: 'uint8',
|
|
6506
|
+
scale: 1,
|
|
6507
|
+
offset: 0,
|
|
6508
|
+
units: 'bpm',
|
|
6509
|
+
},
|
|
6510
|
+
8: {
|
|
6511
|
+
field: 'remaining_recovery_time',
|
|
6512
|
+
type: 'uint16',
|
|
6513
|
+
scale: 1,
|
|
6514
|
+
offset: 0,
|
|
6515
|
+
units: '',
|
|
6516
|
+
},
|
|
6517
|
+
11: {
|
|
6518
|
+
field: 'lthr',
|
|
6519
|
+
type: 'uint16',
|
|
6520
|
+
scale: 1,
|
|
6521
|
+
offset: 0,
|
|
6522
|
+
units: 'bpm',
|
|
6523
|
+
},
|
|
6524
|
+
12: {
|
|
6525
|
+
field: 'ltpower',
|
|
6526
|
+
type: 'uint16',
|
|
6527
|
+
scale: 1,
|
|
6528
|
+
offset: 0,
|
|
6529
|
+
units: 'watts',
|
|
6530
|
+
},
|
|
6531
|
+
13: {
|
|
6532
|
+
field: 'ltspeed',
|
|
6533
|
+
type: 'uint16',
|
|
6534
|
+
scale: 1000,
|
|
6535
|
+
offset: 0,
|
|
6536
|
+
units: 'm/s',
|
|
6537
|
+
},
|
|
6538
|
+
16: {
|
|
6539
|
+
field: 'start_of_activity',
|
|
6540
|
+
type: 'date_time',
|
|
6541
|
+
scale: 1,
|
|
6542
|
+
offset: 0,
|
|
6543
|
+
units: '',
|
|
6544
|
+
},
|
|
6545
|
+
19: {
|
|
6546
|
+
field: 'first_vo2_max',
|
|
6547
|
+
type: 'uint32',
|
|
6548
|
+
scale: 18724.571428571428,
|
|
6549
|
+
offset: 0,
|
|
6550
|
+
units: 'ml/kg/min',
|
|
6551
|
+
},
|
|
6552
|
+
35: {
|
|
6553
|
+
field: 'end_of_previous_activity',
|
|
6554
|
+
type: 'date_time',
|
|
6555
|
+
scale: 1,
|
|
6556
|
+
offset: 0,
|
|
6557
|
+
units: '',
|
|
6558
|
+
},
|
|
6559
|
+
253: {
|
|
6560
|
+
field: 'timestamp',
|
|
6561
|
+
type: 'date_time',
|
|
6562
|
+
scale: 1,
|
|
6563
|
+
offset: 0,
|
|
6564
|
+
units: '',
|
|
6565
|
+
},
|
|
6566
|
+
name: 'user_metrics',
|
|
6567
|
+
},
|
|
6401
6568
|
80: {
|
|
6402
6569
|
0: {
|
|
6403
6570
|
field: 'fractional_timestamp',
|
|
@@ -7253,6 +7420,93 @@ export const GARMIN_MESSAGES = {
|
|
|
7253
7420
|
},
|
|
7254
7421
|
name: 'hr',
|
|
7255
7422
|
},
|
|
7423
|
+
140: {
|
|
7424
|
+
1: {
|
|
7425
|
+
field: 'new_max_heart_rate',
|
|
7426
|
+
type: 'uint8',
|
|
7427
|
+
scale: 1,
|
|
7428
|
+
offset: 0,
|
|
7429
|
+
units: 'bpm',
|
|
7430
|
+
},
|
|
7431
|
+
4: {
|
|
7432
|
+
field: 'aerobic_training_effect',
|
|
7433
|
+
type: 'uint8',
|
|
7434
|
+
scale: 10,
|
|
7435
|
+
offset: 0,
|
|
7436
|
+
units: '',
|
|
7437
|
+
},
|
|
7438
|
+
7: {
|
|
7439
|
+
field: 'vo2_max',
|
|
7440
|
+
type: 'uint32',
|
|
7441
|
+
scale: 18724.571428571428,
|
|
7442
|
+
offset: 0,
|
|
7443
|
+
units: 'ml/kg/min',
|
|
7444
|
+
},
|
|
7445
|
+
9: {
|
|
7446
|
+
field: 'recovery_time',
|
|
7447
|
+
type: 'uint16',
|
|
7448
|
+
scale: 1,
|
|
7449
|
+
offset: 0,
|
|
7450
|
+
units: 'min',
|
|
7451
|
+
},
|
|
7452
|
+
11: {
|
|
7453
|
+
field: 'sport',
|
|
7454
|
+
type: 'sport',
|
|
7455
|
+
scale: 1,
|
|
7456
|
+
offset: 0,
|
|
7457
|
+
units: '',
|
|
7458
|
+
},
|
|
7459
|
+
20: {
|
|
7460
|
+
field: 'anaerobic_training_effect',
|
|
7461
|
+
type: 'uint8',
|
|
7462
|
+
scale: 10,
|
|
7463
|
+
offset: 0,
|
|
7464
|
+
units: '',
|
|
7465
|
+
},
|
|
7466
|
+
29: {
|
|
7467
|
+
field: 'first_vo2_max',
|
|
7468
|
+
type: 'uint32',
|
|
7469
|
+
scale: 18724.571428571428,
|
|
7470
|
+
offset: 0,
|
|
7471
|
+
units: 'ml/kg/min',
|
|
7472
|
+
},
|
|
7473
|
+
41: {
|
|
7474
|
+
field: 'primary_benefit',
|
|
7475
|
+
type: 'uint8',
|
|
7476
|
+
scale: 1,
|
|
7477
|
+
offset: 0,
|
|
7478
|
+
units: '',
|
|
7479
|
+
},
|
|
7480
|
+
60: {
|
|
7481
|
+
field: 'total_ascent',
|
|
7482
|
+
type: 'uint16',
|
|
7483
|
+
scale: 1,
|
|
7484
|
+
offset: 0,
|
|
7485
|
+
units: 'm',
|
|
7486
|
+
},
|
|
7487
|
+
61: {
|
|
7488
|
+
field: 'total_descent',
|
|
7489
|
+
type: 'uint16',
|
|
7490
|
+
scale: 1,
|
|
7491
|
+
offset: 0,
|
|
7492
|
+
units: 'm',
|
|
7493
|
+
},
|
|
7494
|
+
62: {
|
|
7495
|
+
field: 'avg_power',
|
|
7496
|
+
type: 'uint16',
|
|
7497
|
+
scale: 1,
|
|
7498
|
+
offset: 0,
|
|
7499
|
+
units: 'watts',
|
|
7500
|
+
},
|
|
7501
|
+
63: {
|
|
7502
|
+
field: 'avg_heart_rate',
|
|
7503
|
+
type: 'uint8',
|
|
7504
|
+
scale: 1,
|
|
7505
|
+
offset: 0,
|
|
7506
|
+
units: 'bpm',
|
|
7507
|
+
},
|
|
7508
|
+
name: 'activity_metrics',
|
|
7509
|
+
},
|
|
7256
7510
|
142: {
|
|
7257
7511
|
0: {
|
|
7258
7512
|
field: 'event',
|
|
@@ -11787,6 +12041,27 @@ export const GARMIN_MESSAGES = {
|
|
|
11787
12041
|
offset: 0,
|
|
11788
12042
|
units: 's',
|
|
11789
12043
|
},
|
|
12044
|
+
107: {
|
|
12045
|
+
field: 'beginning_potential_stamina',
|
|
12046
|
+
type: 'uint8',
|
|
12047
|
+
scale: 1,
|
|
12048
|
+
offset: 0,
|
|
12049
|
+
units: 'percent',
|
|
12050
|
+
},
|
|
12051
|
+
108: {
|
|
12052
|
+
field: 'ending_potential_stamina',
|
|
12053
|
+
type: 'uint8',
|
|
12054
|
+
scale: 1,
|
|
12055
|
+
offset: 0,
|
|
12056
|
+
units: 'percent',
|
|
12057
|
+
},
|
|
12058
|
+
109: {
|
|
12059
|
+
field: 'min_stamina',
|
|
12060
|
+
type: 'uint8',
|
|
12061
|
+
scale: 1,
|
|
12062
|
+
offset: 0,
|
|
12063
|
+
units: 'percent',
|
|
12064
|
+
},
|
|
11790
12065
|
110: {
|
|
11791
12066
|
field: 'total_moving_time',
|
|
11792
12067
|
type: 'uint32',
|
|
@@ -13032,7 +13307,7 @@ export const GARMIN_MESSAGES = {
|
|
|
13032
13307
|
name: 'sleep_disruption_overnight_severity',
|
|
13033
13308
|
},
|
|
13034
13309
|
};
|
|
13035
|
-
|
|
13310
|
+
exports.PROFILE_TYPES = {
|
|
13036
13311
|
activity: {
|
|
13037
13312
|
0: 'manual',
|
|
13038
13313
|
1: 'auto_multi_sport',
|
|
@@ -15762,6 +16037,7 @@ export const GARMIN_TYPES = {
|
|
|
15762
16037
|
55: 'monitoring',
|
|
15763
16038
|
72: 'training_file',
|
|
15764
16039
|
78: 'hrv',
|
|
16040
|
+
79: 'user_metrics',
|
|
15765
16041
|
80: 'ant_rx',
|
|
15766
16042
|
81: 'ant_tx',
|
|
15767
16043
|
82: 'ant_channel_id',
|
|
@@ -15774,6 +16050,7 @@ export const GARMIN_TYPES = {
|
|
|
15774
16050
|
129: 'weather_alert',
|
|
15775
16051
|
131: 'cadence_zone',
|
|
15776
16052
|
132: 'hr',
|
|
16053
|
+
140: 'activity_metrics',
|
|
15777
16054
|
142: 'segment_lap',
|
|
15778
16055
|
145: 'memo_glob',
|
|
15779
16056
|
148: 'segment_id',
|
|
@@ -285,6 +285,7 @@ function generateFitType() {
|
|
|
285
285
|
generateProperty('messages', typescript_1.default.factory.createTypeReferenceNode('ParsedMessages')),
|
|
286
286
|
generateArrayProperty('raw_developer_fields', typescript_1.default.factory.createTypeReferenceNode('ParsedRawDeveloperField')),
|
|
287
287
|
generateArrayProperty('raw_messages', typescript_1.default.factory.createTypeReferenceNode('ParsedRawFitMessage')),
|
|
288
|
+
generateArrayProperty('unmapped_messages', typescript_1.default.factory.createTypeReferenceNode('ParsedRawFitMessage')),
|
|
288
289
|
...Object.keys(referenceProperties).map(prop => generateProperty(prop, typescript_1.default.factory.createTypeReferenceNode(snakeToCamel(referenceProperties[prop].replace('?', ''))), referenceProperties[prop].startsWith('?'))),
|
|
289
290
|
...Object.keys(collectionProperties).map(prop => generateArrayProperty(prop, collectionProperties[prop] === 'unknown'
|
|
290
291
|
? typescript_1.default.factory.createKeywordTypeNode(typescript_1.default.SyntaxKind.UnknownKeyword)
|
package/dist/fit-parser.d.ts
CHANGED
|
@@ -15,6 +15,8 @@ export interface FitParserOptions {
|
|
|
15
15
|
includeRawDeveloperFields?: boolean | readonly number[];
|
|
16
16
|
/** Retains exact native and developer fields for all or selected global message numbers. */
|
|
17
17
|
includeRawMessages?: boolean | readonly number[];
|
|
18
|
+
/** Retains exact bytes for fields that have no semantic profile mapping. */
|
|
19
|
+
includeUnmappedMessages?: boolean;
|
|
18
20
|
/** Returns only parser metadata and retained raw messages instead of decoded activity collections. */
|
|
19
21
|
rawMessagesOnly?: boolean;
|
|
20
22
|
}
|
package/dist/fit-parser.js
CHANGED
|
@@ -3,7 +3,7 @@ import { mapDataIntoLap, mapDataIntoSession } from './helper.js';
|
|
|
3
3
|
export { FitBaseType, FitEncoder } from './fit-encoder.js';
|
|
4
4
|
export default class FitParser {
|
|
5
5
|
constructor(options = {}) {
|
|
6
|
-
var _a, _b, _c;
|
|
6
|
+
var _a, _b, _c, _d;
|
|
7
7
|
this.options = {
|
|
8
8
|
force: options.force != null ? options.force : true,
|
|
9
9
|
speedUnit: options.speedUnit || 'm/s',
|
|
@@ -14,7 +14,8 @@ export default class FitParser {
|
|
|
14
14
|
mode: options.mode || 'list',
|
|
15
15
|
includeRawDeveloperFields: (_a = options.includeRawDeveloperFields) !== null && _a !== void 0 ? _a : false,
|
|
16
16
|
includeRawMessages: (_b = options.includeRawMessages) !== null && _b !== void 0 ? _b : false,
|
|
17
|
-
|
|
17
|
+
includeUnmappedMessages: (_c = options.includeUnmappedMessages) !== null && _c !== void 0 ? _c : false,
|
|
18
|
+
rawMessagesOnly: (_d = options.rawMessagesOnly) !== null && _d !== void 0 ? _d : false,
|
|
18
19
|
};
|
|
19
20
|
}
|
|
20
21
|
parseAsync(content) {
|
|
@@ -125,6 +126,7 @@ export default class FitParser {
|
|
|
125
126
|
|| Array.isArray(this.options.includeRawMessages)
|
|
126
127
|
? []
|
|
127
128
|
: undefined;
|
|
129
|
+
const unmappedMessages = this.options.includeUnmappedMessages ? [] : undefined;
|
|
128
130
|
const messageCountsByGlobalNumber = new Map();
|
|
129
131
|
let loopIndex = headerLength;
|
|
130
132
|
const messageTypes = [];
|
|
@@ -136,7 +138,7 @@ export default class FitParser {
|
|
|
136
138
|
let lastStopTimestamp;
|
|
137
139
|
let pausedTime = 0;
|
|
138
140
|
while (loopIndex < crcStart) {
|
|
139
|
-
const { globalMessageNumber, littleEndian, message, messageType, nextIndex, compressedTimestamp, rawFields: recordRawFields, rawDeveloperFields: recordRawDeveloperFields, } = readRecord(blob, messageTypes, developerFields, loopIndex, this.options, startDate, pausedTime, dataView, decoderState, crcStart);
|
|
141
|
+
const { globalMessageNumber, littleEndian, message, messageType, nextIndex, compressedTimestamp, rawFields: recordRawFields, rawDeveloperFields: recordRawDeveloperFields, unmappedFields: recordUnmappedFields, unmappedDeveloperFields: recordUnmappedDeveloperFields, } = readRecord(blob, messageTypes, developerFields, loopIndex, this.options, startDate, pausedTime, dataView, decoderState, crcStart);
|
|
140
142
|
loopIndex = nextIndex;
|
|
141
143
|
if (globalMessageNumber !== undefined) {
|
|
142
144
|
const messageIndex = (_a = messageCountsByGlobalNumber.get(globalMessageNumber)) !== null && _a !== void 0 ? _a : 0;
|
|
@@ -163,6 +165,20 @@ export default class FitParser {
|
|
|
163
165
|
raw_value: field.rawValue,
|
|
164
166
|
});
|
|
165
167
|
});
|
|
168
|
+
if (littleEndian !== undefined
|
|
169
|
+
&& ((recordUnmappedFields === null || recordUnmappedFields === void 0 ? void 0 : recordUnmappedFields.length) || (recordUnmappedDeveloperFields === null || recordUnmappedDeveloperFields === void 0 ? void 0 : recordUnmappedDeveloperFields.length))) {
|
|
170
|
+
unmappedMessages === null || unmappedMessages === void 0 ? void 0 : unmappedMessages.push(Object.assign(Object.assign({ global_message_number: globalMessageNumber, message_index: messageIndex, little_endian: littleEndian }, (compressedTimestamp === undefined
|
|
171
|
+
? {}
|
|
172
|
+
: { compressed_timestamp: compressedTimestamp })), { fields: (recordUnmappedFields !== null && recordUnmappedFields !== void 0 ? recordUnmappedFields : []).map(field => ({
|
|
173
|
+
field_definition_number: field.fieldDefinitionNumber,
|
|
174
|
+
base_type: field.baseType,
|
|
175
|
+
raw_value: field.rawValue,
|
|
176
|
+
})), developer_fields: (recordUnmappedDeveloperFields !== null && recordUnmappedDeveloperFields !== void 0 ? recordUnmappedDeveloperFields : []).map(field => ({
|
|
177
|
+
developer_data_index: field.developerDataIndex,
|
|
178
|
+
field_definition_number: field.fieldDefinitionNumber,
|
|
179
|
+
raw_value: field.rawValue,
|
|
180
|
+
})) }));
|
|
181
|
+
}
|
|
166
182
|
}
|
|
167
183
|
if (this.options.rawMessagesOnly) {
|
|
168
184
|
continue;
|
|
@@ -293,6 +309,9 @@ export default class FitParser {
|
|
|
293
309
|
if (rawMessages) {
|
|
294
310
|
fitObj.raw_messages = rawMessages;
|
|
295
311
|
}
|
|
312
|
+
if (unmappedMessages && unmappedMessages.length > 0) {
|
|
313
|
+
fitObj.unmapped_messages = unmappedMessages;
|
|
314
|
+
}
|
|
296
315
|
callback(undefined, fitObj);
|
|
297
316
|
return;
|
|
298
317
|
}
|
|
@@ -321,6 +340,9 @@ export default class FitParser {
|
|
|
321
340
|
if (rawMessages) {
|
|
322
341
|
fitObj.raw_messages = rawMessages;
|
|
323
342
|
}
|
|
343
|
+
if (unmappedMessages && unmappedMessages.length > 0) {
|
|
344
|
+
fitObj.unmapped_messages = unmappedMessages;
|
|
345
|
+
}
|
|
324
346
|
if (isCascadeNeeded) {
|
|
325
347
|
laps = mapDataIntoLap(laps, 'records', records);
|
|
326
348
|
laps = mapDataIntoLap(laps, 'lengths', lengths);
|
package/dist/fit.d.ts
CHANGED
|
@@ -37,10 +37,4 @@ export interface FitType {
|
|
|
37
37
|
messages: Record<number, Message>;
|
|
38
38
|
types: Record<string, Record<number, string | number>>;
|
|
39
39
|
}
|
|
40
|
-
/**
|
|
41
|
-
* Garmin fields observed in the external FIT corpus but absent from the pinned
|
|
42
|
-
* public SDK profile. These additions may not replace standard SDK fields.
|
|
43
|
-
*/
|
|
44
|
-
export declare const FIT_VENDOR_MESSAGE_EXTENSIONS: Record<number, Message>;
|
|
45
|
-
export declare const FIT_VENDOR_TYPE_EXTENSIONS: Record<string, Record<number, string>>;
|
|
46
40
|
export declare const FIT: FitType;
|
package/dist/fit.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { PROFILE_MESSAGES, PROFILE_TYPES } from './profile.js';
|
|
2
2
|
const metersInOneKilometer = 1000;
|
|
3
3
|
const secondsInOneHour = 3600;
|
|
4
4
|
// according to https://en.wikipedia.org/wiki/Mile
|
|
@@ -28,119 +28,9 @@ const options = {
|
|
|
28
28
|
psi: { multiplier: psiInOneBar, offset: 0 },
|
|
29
29
|
},
|
|
30
30
|
};
|
|
31
|
-
/**
|
|
32
|
-
* Garmin fields observed in the external FIT corpus but absent from the pinned
|
|
33
|
-
* public SDK profile. These additions may not replace standard SDK fields.
|
|
34
|
-
*/
|
|
35
|
-
export const FIT_VENDOR_MESSAGE_EXTENSIONS = {
|
|
36
|
-
18: {
|
|
37
|
-
name: 'session',
|
|
38
|
-
178: field('est_sweat_loss', 'uint16', 1, 'ml'),
|
|
39
|
-
188: field('primary_benefit', 'uint8'),
|
|
40
|
-
205: field('beginning_potential_stamina', 'uint8', 1, 'percent'),
|
|
41
|
-
206: field('ending_potential_stamina', 'uint8', 1, 'percent'),
|
|
42
|
-
207: field('min_stamina', 'uint8', 1, 'percent'),
|
|
43
|
-
},
|
|
44
|
-
20: {
|
|
45
|
-
name: 'record',
|
|
46
|
-
90: field('garmin_performance_condition', 'sint8'),
|
|
47
|
-
137: field('potential_stamina', 'uint8', 1, 'percent'),
|
|
48
|
-
138: field('stamina', 'uint8', 1, 'percent'),
|
|
49
|
-
},
|
|
50
|
-
23: {
|
|
51
|
-
name: 'device_info',
|
|
52
|
-
24: field('ant_id', 'uint32z'),
|
|
53
|
-
},
|
|
54
|
-
// Undocumented Garmin user metrics message observed in activity FIT files.
|
|
55
|
-
79: {
|
|
56
|
-
name: 'user_metrics',
|
|
57
|
-
0: field('vo2_max', 'uint16', 1024 / 3.5, 'ml/kg/min'),
|
|
58
|
-
1: field('age', 'uint8', 1, 'years'),
|
|
59
|
-
2: field('height', 'uint8', 100, 'm'),
|
|
60
|
-
3: field('weight', 'uint16', 10, 'kg'),
|
|
61
|
-
4: field('gender', 'gender'),
|
|
62
|
-
6: field('max_heart_rate', 'uint8', 1, 'bpm'),
|
|
63
|
-
8: field('remaining_recovery_time', 'uint16'),
|
|
64
|
-
11: field('lthr', 'uint16', 1, 'bpm'),
|
|
65
|
-
12: field('ltpower', 'uint16', 1, 'watts'),
|
|
66
|
-
13: field('ltspeed', 'uint16', 1000, 'm/s'),
|
|
67
|
-
16: field('start_of_activity', 'date_time'),
|
|
68
|
-
19: field('first_vo2_max', 'uint32', 65536 / 3.5, 'ml/kg/min'),
|
|
69
|
-
35: field('end_of_previous_activity', 'date_time'),
|
|
70
|
-
253: field('timestamp', 'date_time'),
|
|
71
|
-
},
|
|
72
|
-
// Undocumented Garmin activity metrics message observed in activity FIT files.
|
|
73
|
-
140: {
|
|
74
|
-
name: 'activity_metrics',
|
|
75
|
-
1: field('new_max_heart_rate', 'uint8', 1, 'bpm'),
|
|
76
|
-
4: field('aerobic_training_effect', 'uint8', 10),
|
|
77
|
-
7: field('vo2_max', 'uint32', 65536 / 3.5, 'ml/kg/min'),
|
|
78
|
-
9: field('recovery_time', 'uint16', 1, 'min'),
|
|
79
|
-
11: field('sport', 'sport'),
|
|
80
|
-
20: field('anaerobic_training_effect', 'uint8', 10),
|
|
81
|
-
29: field('first_vo2_max', 'uint32', 65536 / 3.5, 'ml/kg/min'),
|
|
82
|
-
41: field('primary_benefit', 'uint8'),
|
|
83
|
-
60: field('total_ascent', 'uint16', 1, 'm'),
|
|
84
|
-
61: field('total_descent', 'uint16', 1, 'm'),
|
|
85
|
-
62: field('avg_power', 'uint16', 1, 'watts'),
|
|
86
|
-
63: field('avg_heart_rate', 'uint8', 1, 'bpm'),
|
|
87
|
-
},
|
|
88
|
-
312: {
|
|
89
|
-
name: 'split',
|
|
90
|
-
107: field('beginning_potential_stamina', 'uint8', 1, 'percent'),
|
|
91
|
-
108: field('ending_potential_stamina', 'uint8', 1, 'percent'),
|
|
92
|
-
109: field('min_stamina', 'uint8', 1, 'percent'),
|
|
93
|
-
},
|
|
94
|
-
};
|
|
95
|
-
export const FIT_VENDOR_TYPE_EXTENSIONS = {
|
|
96
|
-
mesg_num: {
|
|
97
|
-
79: 'user_metrics',
|
|
98
|
-
140: 'activity_metrics',
|
|
99
|
-
},
|
|
100
|
-
};
|
|
101
|
-
function field(name, type, scale = 1, units = '', baseType) {
|
|
102
|
-
return Object.assign(Object.assign({ field: name, type }, (baseType ? { baseType } : {})), { scale, offset: 0, units });
|
|
103
|
-
}
|
|
104
|
-
function mergeVendorMessages() {
|
|
105
|
-
const messages = Object.assign({}, GARMIN_MESSAGES);
|
|
106
|
-
Object.entries(FIT_VENDOR_MESSAGE_EXTENSIONS).forEach(([messageIdText, extension]) => {
|
|
107
|
-
const messageId = Number(messageIdText);
|
|
108
|
-
const standardMessage = messages[messageId];
|
|
109
|
-
if (!standardMessage) {
|
|
110
|
-
messages[messageId] = extension;
|
|
111
|
-
return;
|
|
112
|
-
}
|
|
113
|
-
if (standardMessage.name !== extension.name) {
|
|
114
|
-
throw new Error(`Vendor message ${messageId} conflicts with the Garmin SDK name`);
|
|
115
|
-
}
|
|
116
|
-
Object.keys(extension)
|
|
117
|
-
.filter(key => key !== 'name')
|
|
118
|
-
.forEach((fieldId) => {
|
|
119
|
-
if (standardMessage[Number(fieldId)]) {
|
|
120
|
-
throw new Error(`Vendor message ${messageId}, field ${fieldId} conflicts with the Garmin SDK profile`);
|
|
121
|
-
}
|
|
122
|
-
});
|
|
123
|
-
messages[messageId] = Object.assign(Object.assign({}, standardMessage), extension);
|
|
124
|
-
});
|
|
125
|
-
return messages;
|
|
126
|
-
}
|
|
127
|
-
function mergeVendorTypes() {
|
|
128
|
-
const types = Object.fromEntries(Object.entries(GARMIN_TYPES).map(([name, values]) => [name, Object.assign({}, values)]));
|
|
129
|
-
Object.entries(FIT_VENDOR_TYPE_EXTENSIONS).forEach(([name, extension]) => {
|
|
130
|
-
var _a;
|
|
131
|
-
const standardValues = (_a = types[name]) !== null && _a !== void 0 ? _a : {};
|
|
132
|
-
Object.keys(extension).forEach((valueId) => {
|
|
133
|
-
if (standardValues[Number(valueId)] !== undefined) {
|
|
134
|
-
throw new Error(`Vendor type ${name}, value ${valueId} conflicts with the Garmin SDK profile`);
|
|
135
|
-
}
|
|
136
|
-
});
|
|
137
|
-
types[name] = Object.assign(Object.assign({}, standardValues), extension);
|
|
138
|
-
});
|
|
139
|
-
return types;
|
|
140
|
-
}
|
|
141
31
|
export const FIT = {
|
|
142
32
|
scConst: 180 / Math.pow(2, 31),
|
|
143
33
|
options,
|
|
144
|
-
messages:
|
|
145
|
-
types:
|
|
34
|
+
messages: PROFILE_MESSAGES,
|
|
35
|
+
types: PROFILE_TYPES,
|
|
146
36
|
};
|
package/dist/fit_types.d.ts
CHANGED
|
@@ -2097,6 +2097,7 @@ export interface ParsedFit {
|
|
|
2097
2097
|
messages?: ParsedMessages;
|
|
2098
2098
|
raw_developer_fields?: ParsedRawDeveloperField[];
|
|
2099
2099
|
raw_messages?: ParsedRawFitMessage[];
|
|
2100
|
+
unmapped_messages?: ParsedRawFitMessage[];
|
|
2100
2101
|
file_creator: ParsedFileCreator;
|
|
2101
2102
|
device_settings: ParsedDeviceSettings;
|
|
2102
2103
|
dive_summary?: ParsedDiveSummary;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Message } from './fit.js';
|
|
2
|
+
/**
|
|
3
|
+
* Static, community-maintained FIT interoperability profile.
|
|
4
|
+
*
|
|
5
|
+
* This table is ordinary project source maintained under the repository's MIT
|
|
6
|
+
* license. See PROFILE.md for the maintenance and verification policy.
|
|
7
|
+
*/
|
|
8
|
+
export declare const PROFILE_MESSAGES: Record<number, Message>;
|
|
9
|
+
export declare const PROFILE_TYPES: Record<string, Record<number, string | number>>;
|