fit-file-parser 6.1.2 → 6.2.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/CHANGELOG.md +56 -0
- package/PROFILE.md +23 -0
- package/README.md +72 -5
- package/dist/binary.js +30 -17
- package/dist/cjs/binary.js +30 -17
- package/dist/cjs/fit-parser.d.ts +11 -0
- package/dist/cjs/fit-parser.js +112 -6
- package/dist/cjs/fit_types.d.ts +23 -1
- package/dist/cjs/profile.js +166 -0
- package/dist/cjs/type_generator.js +1 -0
- package/dist/fit-parser.d.ts +11 -0
- package/dist/fit-parser.js +112 -6
- package/dist/fit_types.d.ts +23 -1
- package/dist/profile.js +166 -0
- package/dist/type_generator.js +1 -0
- package/package.json +14 -5
package/dist/fit-parser.js
CHANGED
|
@@ -1,23 +1,42 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
1
10
|
import { calculateCRC, readRecord } from './binary.js';
|
|
2
11
|
import { mapDataIntoLap, mapDataIntoSession } from './helper.js';
|
|
3
12
|
export { FitBaseType, FitEncoder } from './fit-encoder.js';
|
|
4
13
|
export { getFitCoursePointId, getFitGarminProductDisplayName, getFitGarminProductName, getFitManufacturerName, getFitSportId, getFitSportName, getFitSubSportId, getFitSubSportName, } from './profile-lookup.js';
|
|
5
14
|
export { FitMessageReaderError, fitTimestampToUnixMilliseconds, getFitBaseTypeId, readFitMessages, readFitStringField, readFitUnsignedField, } from './raw-message-reader.js';
|
|
15
|
+
function hasFitHeader(blob, start) {
|
|
16
|
+
const headerLength = blob[start];
|
|
17
|
+
return blob.length - start >= headerLength
|
|
18
|
+
&& (headerLength === 12 || headerLength === 14)
|
|
19
|
+
&& blob[start + 8] === 0x2E
|
|
20
|
+
&& blob[start + 9] === 0x46
|
|
21
|
+
&& blob[start + 10] === 0x49
|
|
22
|
+
&& blob[start + 11] === 0x54;
|
|
23
|
+
}
|
|
6
24
|
export default class FitParser {
|
|
7
25
|
constructor(options = {}) {
|
|
8
|
-
var _a, _b, _c, _d;
|
|
26
|
+
var _a, _b, _c, _d, _e;
|
|
9
27
|
this.options = {
|
|
10
28
|
force: options.force != null ? options.force : true,
|
|
29
|
+
strict: (_a = options.strict) !== null && _a !== void 0 ? _a : false,
|
|
11
30
|
speedUnit: options.speedUnit || 'm/s',
|
|
12
31
|
lengthUnit: options.lengthUnit || 'm',
|
|
13
32
|
temperatureUnit: options.temperatureUnit || 'celsius',
|
|
14
33
|
elapsedRecordField: options.elapsedRecordField || false,
|
|
15
34
|
pressureUnit: options.pressureUnit || 'bar',
|
|
16
35
|
mode: options.mode || 'list',
|
|
17
|
-
includeRawDeveloperFields: (
|
|
18
|
-
includeRawMessages: (
|
|
19
|
-
includeUnmappedMessages: (
|
|
20
|
-
rawMessagesOnly: (
|
|
36
|
+
includeRawDeveloperFields: (_b = options.includeRawDeveloperFields) !== null && _b !== void 0 ? _b : false,
|
|
37
|
+
includeRawMessages: (_c = options.includeRawMessages) !== null && _c !== void 0 ? _c : false,
|
|
38
|
+
includeUnmappedMessages: (_d = options.includeUnmappedMessages) !== null && _d !== void 0 ? _d : false,
|
|
39
|
+
rawMessagesOnly: (_e = options.rawMessagesOnly) !== null && _e !== void 0 ? _e : false,
|
|
21
40
|
};
|
|
22
41
|
}
|
|
23
42
|
parseAsync(content) {
|
|
@@ -32,7 +51,81 @@ export default class FitParser {
|
|
|
32
51
|
});
|
|
33
52
|
});
|
|
34
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* Parses FIT files in input order with independent decoder state. Uses the
|
|
56
|
+
* same force and strict policies as parseAsync; strict mode rejects trailing
|
|
57
|
+
* bytes, while the default ignores a non-FIT suffix after parsed files.
|
|
58
|
+
* Rejects with an Error when any file cannot be parsed.
|
|
59
|
+
*/
|
|
60
|
+
parseFilesAsync(content) {
|
|
61
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
62
|
+
const blob = content instanceof ArrayBuffer
|
|
63
|
+
? new Uint8Array(content)
|
|
64
|
+
: new Uint8Array(content.buffer, content.byteOffset, content.byteLength);
|
|
65
|
+
const results = [];
|
|
66
|
+
let start = 0;
|
|
67
|
+
do {
|
|
68
|
+
const remaining = blob.length - start;
|
|
69
|
+
const headerLength = blob[start];
|
|
70
|
+
if (results.length > 0 && !this.options.strict && !hasFitHeader(blob, start)) {
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
if (remaining < 12) {
|
|
74
|
+
throw new Error('File to small to be a FIT file');
|
|
75
|
+
}
|
|
76
|
+
if (headerLength !== 12 && headerLength !== 14) {
|
|
77
|
+
throw new Error('Incorrect header size');
|
|
78
|
+
}
|
|
79
|
+
if (remaining < headerLength) {
|
|
80
|
+
throw new Error('File to small to be a FIT file');
|
|
81
|
+
}
|
|
82
|
+
if (blob[start + 8] !== 0x2E
|
|
83
|
+
|| blob[start + 9] !== 0x46
|
|
84
|
+
|| blob[start + 10] !== 0x49
|
|
85
|
+
|| blob[start + 11] !== 0x54) {
|
|
86
|
+
throw new Error('Missing \'.FIT\' in header');
|
|
87
|
+
}
|
|
88
|
+
const dataLength = new DataView(blob.buffer, blob.byteOffset + start, remaining)
|
|
89
|
+
.getUint32(4, true);
|
|
90
|
+
const crcStart = start + headerLength + dataLength;
|
|
91
|
+
// File completeness and CRC checks belong to the shared parser below,
|
|
92
|
+
// preserving the same validation policy and error order in every API.
|
|
93
|
+
let end = Math.min(crcStart + 2, blob.length);
|
|
94
|
+
// Missing CRC bytes can also precede the next file. Check only the
|
|
95
|
+
// declared boundary and its one-byte CRC variant; never scan activity
|
|
96
|
+
// payloads for a guessed file boundary.
|
|
97
|
+
if (this.options.force && !this.options.strict) {
|
|
98
|
+
if (hasFitHeader(blob, crcStart)) {
|
|
99
|
+
end = crcStart;
|
|
100
|
+
}
|
|
101
|
+
else if (hasFitHeader(blob, crcStart + 1)) {
|
|
102
|
+
end = crcStart + 1;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
try {
|
|
106
|
+
results.push(yield new Promise((resolve, reject) => {
|
|
107
|
+
this.parseFile(blob.slice(start, end).buffer, (error, data) => {
|
|
108
|
+
if (error) {
|
|
109
|
+
reject(error);
|
|
110
|
+
}
|
|
111
|
+
else if (data) {
|
|
112
|
+
resolve(data);
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
}));
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
throw error instanceof Error ? error : new Error(String(error));
|
|
119
|
+
}
|
|
120
|
+
start = end;
|
|
121
|
+
} while (start < blob.length);
|
|
122
|
+
return results;
|
|
123
|
+
});
|
|
124
|
+
}
|
|
35
125
|
parse(content, callback) {
|
|
126
|
+
this.parseFile(content, callback);
|
|
127
|
+
}
|
|
128
|
+
parseFile(content, callback) {
|
|
36
129
|
var _a, _b, _c;
|
|
37
130
|
const blob = content instanceof ArrayBuffer
|
|
38
131
|
? new Uint8Array(content)
|
|
@@ -75,10 +168,14 @@ export default class FitParser {
|
|
|
75
168
|
callback('File data exceeds input length', undefined);
|
|
76
169
|
return;
|
|
77
170
|
}
|
|
78
|
-
if (!this.options.force && crcStart + 2 > blob.length) {
|
|
171
|
+
if ((!this.options.force || this.options.strict) && crcStart + 2 > blob.length) {
|
|
79
172
|
callback('File CRC missing', undefined);
|
|
80
173
|
return;
|
|
81
174
|
}
|
|
175
|
+
if (this.options.strict && crcStart + 2 < blob.length) {
|
|
176
|
+
callback('Unexpected bytes after FIT file', undefined);
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
82
179
|
if (!this.options.force) {
|
|
83
180
|
const crcFile = blob[crcStart] + (blob[crcStart + 1] << 8);
|
|
84
181
|
const crcFileCalc = calculateCRC(blob, 0, crcStart);
|
|
@@ -92,6 +189,7 @@ export default class FitParser {
|
|
|
92
189
|
protocolVersion,
|
|
93
190
|
};
|
|
94
191
|
const messages = {};
|
|
192
|
+
const batteries = [];
|
|
95
193
|
let sessions = [];
|
|
96
194
|
let laps = [];
|
|
97
195
|
const records = [];
|
|
@@ -141,6 +239,10 @@ export default class FitParser {
|
|
|
141
239
|
let pausedTime = 0;
|
|
142
240
|
while (loopIndex < crcStart) {
|
|
143
241
|
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);
|
|
242
|
+
if (this.options.strict
|
|
243
|
+
&& (!Number.isInteger(nextIndex) || nextIndex <= loopIndex || nextIndex > crcStart)) {
|
|
244
|
+
throw new Error('Invalid FIT record bounds');
|
|
245
|
+
}
|
|
144
246
|
loopIndex = nextIndex;
|
|
145
247
|
if (globalMessageNumber !== undefined) {
|
|
146
248
|
const messageIndex = (_a = messageCountsByGlobalNumber.get(globalMessageNumber)) !== null && _a !== void 0 ? _a : 0;
|
|
@@ -191,6 +293,9 @@ export default class FitParser {
|
|
|
191
293
|
((_b = messages[messageType]) !== null && _b !== void 0 ? _b : (messages[messageType] = [])).push(message);
|
|
192
294
|
}
|
|
193
295
|
switch (messageType) {
|
|
296
|
+
case 'battery':
|
|
297
|
+
batteries.push(message);
|
|
298
|
+
break;
|
|
194
299
|
case 'lap':
|
|
195
300
|
laps.push(message);
|
|
196
301
|
break;
|
|
@@ -335,6 +440,7 @@ export default class FitParser {
|
|
|
335
440
|
fitObj.time_in_zone = time_in_zone;
|
|
336
441
|
fitObj.activity_metrics = activity_metrics;
|
|
337
442
|
fitObj.user_metrics = user_metrics;
|
|
443
|
+
fitObj.batteries = batteries;
|
|
338
444
|
fitObj.messages = messages;
|
|
339
445
|
if (rawDeveloperFields) {
|
|
340
446
|
fitObj.raw_developer_fields = rawDeveloperFields;
|
package/dist/fit_types.d.ts
CHANGED
|
@@ -156,7 +156,7 @@ export type MaxMetCategory = 'generic' | 'cycling' | number;
|
|
|
156
156
|
export type MaxMetHeartRateSource = 'whr' | 'hrm' | number;
|
|
157
157
|
export type MaxMetSpeedSource = 'onboard_gps' | 'connected_gps' | 'cadence' | number;
|
|
158
158
|
export type MesgCount = 'num_per_file' | 'max_per_file' | 'max_per_file_type' | number;
|
|
159
|
-
export type MesgNum = 'file_id' | 'capabilities' | 'device_settings' | 'user_profile' | 'hrm_profile' | 'sdm_profile' | 'bike_profile' | 'zones_target' | 'hr_zone' | 'power_zone' | 'met_zone' | 'sport' | 'training_settings' | 'goal' | 'session' | 'lap' | 'record' | 'event' | 'device_info' | 'workout' | 'workout_step' | 'schedule' | 'weight_scale' | 'course' | 'course_point' | 'totals' | 'activity' | 'software' | 'file_capabilities' | 'mesg_capabilities' | 'field_capabilities' | 'file_creator' | 'blood_pressure' | 'speed_zone' | 'monitoring' | 'training_file' | 'hrv' | 'user_metrics' | 'ant_rx' | 'ant_tx' | 'ant_channel_id' | 'length' | 'monitoring_info' | 'pad' | 'slave_device' | 'connectivity' | 'weather_conditions' | 'weather_alert' | 'cadence_zone' | 'hr' | 'activity_metrics' | 'segment_lap' | 'memo_glob' | 'segment_id' | 'segment_leaderboard_entry' | 'segment_point' | 'segment_file' | 'workout_session' | 'watchface_settings' | 'gps_metadata' | 'camera_event' | 'timestamp_correlation' | 'gyroscope_data' | 'accelerometer_data' | 'three_d_sensor_calibration' | 'video_frame' | 'obdii_data' | 'nmea_sentence' | 'aviation_attitude' | 'video' | 'video_title' | 'video_description' | 'video_clip' | 'ohr_settings' | 'exd_screen_configuration' | 'exd_data_field_configuration' | 'exd_data_concept_configuration' | 'field_description' | 'developer_data_id' | 'magnetometer_data' | 'barometer_data' | 'one_d_sensor_calibration' | 'monitoring_hr_data' | 'time_in_zone' | 'set' | 'stress_level' | 'max_met_data' | 'dive_settings' | 'dive_gas' | 'dive_alarm' | 'exercise_title' | 'dive_summary' | 'spo2_data' | 'sleep_level' | 'jump' | 'aad_accel_features' | 'beat_intervals' | 'respiration_rate' | 'hsa_accelerometer_data' | 'hsa_step_data' | 'hsa_spo2_data' | 'hsa_stress_data' | 'hsa_respiration_data' | 'hsa_heart_rate_data' | 'split' | 'split_summary' | 'hsa_body_battery_data' | 'hsa_event' | 'climb_pro' | 'tank_update' | 'tank_summary' | 'sleep_assessment' | 'hrv_status_summary' | 'hrv_value' | 'raw_bbi' | 'device_aux_battery_info' | 'hsa_gyroscope_data' | 'chrono_shot_session' | 'chrono_shot_data' | 'hsa_configuration_data' | 'dive_apnea_alarm' | 'skin_temp_overnight' | 'hsa_wrist_temperature_data' | 'nap_event' | 'sleep_disruption_severity_period' | 'sleep_disruption_overnight_severity' | 'mfg_range_min' | 'mfg_range_max' | 'definition' | number;
|
|
159
|
+
export type MesgNum = 'file_id' | 'capabilities' | 'device_settings' | 'user_profile' | 'hrm_profile' | 'sdm_profile' | 'bike_profile' | 'zones_target' | 'hr_zone' | 'power_zone' | 'met_zone' | 'sport' | 'training_settings' | 'goal' | 'session' | 'lap' | 'record' | 'event' | 'device_info' | 'workout' | 'workout_step' | 'schedule' | 'weight_scale' | 'course' | 'course_point' | 'totals' | 'activity' | 'software' | 'file_capabilities' | 'mesg_capabilities' | 'field_capabilities' | 'file_creator' | 'blood_pressure' | 'speed_zone' | 'monitoring' | 'training_file' | 'hrv' | 'user_metrics' | 'ant_rx' | 'ant_tx' | 'ant_channel_id' | 'length' | 'monitoring_info' | 'battery' | 'pad' | 'slave_device' | 'connectivity' | 'weather_conditions' | 'weather_alert' | 'cadence_zone' | 'hr' | 'activity_metrics' | 'segment_lap' | 'memo_glob' | 'segment_id' | 'segment_leaderboard_entry' | 'segment_point' | 'segment_file' | 'workout_session' | 'watchface_settings' | 'gps_metadata' | 'camera_event' | 'timestamp_correlation' | 'gyroscope_data' | 'accelerometer_data' | 'three_d_sensor_calibration' | 'video_frame' | 'obdii_data' | 'nmea_sentence' | 'aviation_attitude' | 'video' | 'video_title' | 'video_description' | 'video_clip' | 'ohr_settings' | 'exd_screen_configuration' | 'exd_data_field_configuration' | 'exd_data_concept_configuration' | 'field_description' | 'developer_data_id' | 'magnetometer_data' | 'barometer_data' | 'one_d_sensor_calibration' | 'monitoring_hr_data' | 'time_in_zone' | 'set' | 'stress_level' | 'max_met_data' | 'dive_settings' | 'dive_gas' | 'dive_alarm' | 'exercise_title' | 'dive_summary' | 'spo2_data' | 'sleep_level' | 'jump' | 'aad_accel_features' | 'beat_intervals' | 'respiration_rate' | 'hsa_accelerometer_data' | 'hsa_step_data' | 'hsa_spo2_data' | 'hsa_stress_data' | 'hsa_respiration_data' | 'hsa_heart_rate_data' | 'split' | 'split_summary' | 'hsa_body_battery_data' | 'hsa_event' | 'climb_pro' | 'tank_update' | 'tank_summary' | 'sleep_assessment' | 'hrv_status_summary' | 'hrv_value' | 'raw_bbi' | 'device_aux_battery_info' | 'hsa_gyroscope_data' | 'chrono_shot_session' | 'chrono_shot_data' | 'hsa_configuration_data' | 'dive_apnea_alarm' | 'skin_temp_overnight' | 'hsa_wrist_temperature_data' | 'nap_event' | 'sleep_disruption_severity_period' | 'sleep_disruption_overnight_severity' | 'mfg_range_min' | 'mfg_range_max' | 'definition' | number;
|
|
160
160
|
export interface MessageIndex {
|
|
161
161
|
value: number;
|
|
162
162
|
reserved: boolean;
|
|
@@ -498,6 +498,8 @@ export interface ParsedSession {
|
|
|
498
498
|
best_lap_index?: number;
|
|
499
499
|
min_altitude?: number;
|
|
500
500
|
active_time?: number;
|
|
501
|
+
avg_strokes_per_length?: number;
|
|
502
|
+
avg_swolf?: number;
|
|
501
503
|
player_score?: number;
|
|
502
504
|
opponent_score?: number;
|
|
503
505
|
opponent_name?: string;
|
|
@@ -522,6 +524,9 @@ export interface ParsedSession {
|
|
|
522
524
|
avg_left_pedal_smoothness?: number;
|
|
523
525
|
avg_right_pedal_smoothness?: number;
|
|
524
526
|
avg_combined_pedal_smoothness?: number;
|
|
527
|
+
num_segment_laps?: number;
|
|
528
|
+
front_gear_shift_count?: number;
|
|
529
|
+
rear_gear_shift_count?: number;
|
|
525
530
|
sport_profile_name?: string;
|
|
526
531
|
sport_index?: number;
|
|
527
532
|
time_standing?: number;
|
|
@@ -588,6 +593,7 @@ export interface ParsedSession {
|
|
|
588
593
|
avg_core_temperature?: number;
|
|
589
594
|
min_core_temperature?: number;
|
|
590
595
|
max_core_temperature?: number;
|
|
596
|
+
avg_grade_adjusted_speed?: number;
|
|
591
597
|
timestamp?: Date;
|
|
592
598
|
message_index?: MessageIndex;
|
|
593
599
|
laps?: ParsedLap[];
|
|
@@ -620,6 +626,10 @@ export interface ParsedLap {
|
|
|
620
626
|
lap_trigger?: LapTrigger;
|
|
621
627
|
sport?: Sport;
|
|
622
628
|
event_group?: number;
|
|
629
|
+
nec_lat?: number;
|
|
630
|
+
nec_long?: number;
|
|
631
|
+
swc_lat?: number;
|
|
632
|
+
swc_long?: number;
|
|
623
633
|
num_lengths?: number;
|
|
624
634
|
normalized_power?: number;
|
|
625
635
|
left_right_balance?: LeftRightBalance100;
|
|
@@ -653,6 +663,7 @@ export interface ParsedLap {
|
|
|
653
663
|
min_heart_rate?: number;
|
|
654
664
|
active_time?: number;
|
|
655
665
|
wkt_step_index?: MessageIndex;
|
|
666
|
+
avg_swolf?: number;
|
|
656
667
|
opponent_score?: number;
|
|
657
668
|
stroke_count?: (number | null)[];
|
|
658
669
|
zone_count?: (number | null)[];
|
|
@@ -669,11 +680,14 @@ export interface ParsedLap {
|
|
|
669
680
|
avg_saturated_hemoglobin_percent?: (number | null)[];
|
|
670
681
|
min_saturated_hemoglobin_percent?: (number | null)[];
|
|
671
682
|
max_saturated_hemoglobin_percent?: (number | null)[];
|
|
683
|
+
avg_strokes_per_length?: number;
|
|
672
684
|
avg_left_torque_effectiveness?: number;
|
|
673
685
|
avg_right_torque_effectiveness?: number;
|
|
674
686
|
avg_left_pedal_smoothness?: number;
|
|
675
687
|
avg_right_pedal_smoothness?: number;
|
|
676
688
|
avg_combined_pedal_smoothness?: number;
|
|
689
|
+
front_gear_shift_count?: number;
|
|
690
|
+
rear_gear_shift_count?: number;
|
|
677
691
|
time_standing?: number;
|
|
678
692
|
stand_count?: number;
|
|
679
693
|
avg_left_pco?: number;
|
|
@@ -710,11 +724,13 @@ export interface ParsedLap {
|
|
|
710
724
|
jump_count?: number;
|
|
711
725
|
avg_grit?: number;
|
|
712
726
|
avg_flow?: number;
|
|
727
|
+
metabolic_calories?: number;
|
|
713
728
|
total_fractional_ascent?: number;
|
|
714
729
|
total_fractional_descent?: number;
|
|
715
730
|
avg_core_temperature?: number;
|
|
716
731
|
min_core_temperature?: number;
|
|
717
732
|
max_core_temperature?: number;
|
|
733
|
+
avg_grade_adjusted_speed?: number;
|
|
718
734
|
timestamp?: Date;
|
|
719
735
|
message_index?: MessageIndex;
|
|
720
736
|
records?: ParsedRecord[];
|
|
@@ -1119,6 +1135,10 @@ export interface ParsedMonitoringInfo {
|
|
|
1119
1135
|
resting_metabolic_rate?: number;
|
|
1120
1136
|
timestamp?: Date;
|
|
1121
1137
|
}
|
|
1138
|
+
export interface ParsedBattery {
|
|
1139
|
+
capacity?: number;
|
|
1140
|
+
timestamp?: Date;
|
|
1141
|
+
}
|
|
1122
1142
|
export interface ParsedPad {
|
|
1123
1143
|
}
|
|
1124
1144
|
export interface ParsedSlaveDevice {
|
|
@@ -2007,6 +2027,7 @@ export interface ParsedMessages {
|
|
|
2007
2027
|
ant_channel_id?: ParsedAntChannelId[];
|
|
2008
2028
|
length?: ParsedLength[];
|
|
2009
2029
|
monitoring_info?: ParsedMonitoringInfo[];
|
|
2030
|
+
battery?: ParsedBattery[];
|
|
2010
2031
|
pad?: ParsedPad[];
|
|
2011
2032
|
slave_device?: ParsedSlaveDevice[];
|
|
2012
2033
|
connectivity?: ParsedConnectivity[];
|
|
@@ -2134,6 +2155,7 @@ export interface ParsedFit {
|
|
|
2134
2155
|
time_in_zone?: ParsedTimeInZone[];
|
|
2135
2156
|
activity_metrics?: ParsedActivityMetrics[];
|
|
2136
2157
|
user_metrics?: ParsedUserMetrics[];
|
|
2158
|
+
batteries?: ParsedBattery[];
|
|
2137
2159
|
capabilities?: ParsedCapabilities;
|
|
2138
2160
|
hrm_profile?: ParsedHrmProfile;
|
|
2139
2161
|
sdm_profile?: ParsedSdmProfile;
|
package/dist/profile.js
CHANGED
|
@@ -1345,6 +1345,60 @@ export const PROFILE_MESSAGES = {
|
|
|
1345
1345
|
name: 'goal',
|
|
1346
1346
|
},
|
|
1347
1347
|
18: {
|
|
1348
|
+
79: {
|
|
1349
|
+
field: 'avg_strokes_per_length',
|
|
1350
|
+
type: 'uint16',
|
|
1351
|
+
baseType: 'uint16',
|
|
1352
|
+
array: false,
|
|
1353
|
+
scale: 10,
|
|
1354
|
+
offset: 0,
|
|
1355
|
+
units: 'strokes/length',
|
|
1356
|
+
},
|
|
1357
|
+
80: {
|
|
1358
|
+
field: 'avg_swolf',
|
|
1359
|
+
type: 'uint16',
|
|
1360
|
+
baseType: 'uint16',
|
|
1361
|
+
array: false,
|
|
1362
|
+
scale: 1,
|
|
1363
|
+
offset: 0,
|
|
1364
|
+
units: '',
|
|
1365
|
+
},
|
|
1366
|
+
106: {
|
|
1367
|
+
field: 'num_segment_laps',
|
|
1368
|
+
type: 'uint16',
|
|
1369
|
+
baseType: 'uint16',
|
|
1370
|
+
array: false,
|
|
1371
|
+
scale: 1,
|
|
1372
|
+
offset: 0,
|
|
1373
|
+
units: '',
|
|
1374
|
+
},
|
|
1375
|
+
107: {
|
|
1376
|
+
field: 'front_gear_shift_count',
|
|
1377
|
+
type: 'uint16',
|
|
1378
|
+
baseType: 'uint16',
|
|
1379
|
+
array: false,
|
|
1380
|
+
scale: 1,
|
|
1381
|
+
offset: 0,
|
|
1382
|
+
units: '',
|
|
1383
|
+
},
|
|
1384
|
+
108: {
|
|
1385
|
+
field: 'rear_gear_shift_count',
|
|
1386
|
+
type: 'uint16',
|
|
1387
|
+
baseType: 'uint16',
|
|
1388
|
+
array: false,
|
|
1389
|
+
scale: 1,
|
|
1390
|
+
offset: 0,
|
|
1391
|
+
units: '',
|
|
1392
|
+
},
|
|
1393
|
+
211: {
|
|
1394
|
+
field: 'avg_grade_adjusted_speed',
|
|
1395
|
+
type: 'uint32',
|
|
1396
|
+
baseType: 'uint32',
|
|
1397
|
+
array: false,
|
|
1398
|
+
scale: 1000,
|
|
1399
|
+
offset: 0,
|
|
1400
|
+
units: 'm/s',
|
|
1401
|
+
},
|
|
1348
1402
|
0: {
|
|
1349
1403
|
field: 'event',
|
|
1350
1404
|
type: 'event',
|
|
@@ -2805,6 +2859,96 @@ export const PROFILE_MESSAGES = {
|
|
|
2805
2859
|
name: 'session',
|
|
2806
2860
|
},
|
|
2807
2861
|
19: {
|
|
2862
|
+
27: {
|
|
2863
|
+
field: 'nec_lat',
|
|
2864
|
+
type: 'sint32',
|
|
2865
|
+
baseType: 'sint32',
|
|
2866
|
+
array: false,
|
|
2867
|
+
scale: 1,
|
|
2868
|
+
offset: 0,
|
|
2869
|
+
units: 'semicircles',
|
|
2870
|
+
},
|
|
2871
|
+
28: {
|
|
2872
|
+
field: 'nec_long',
|
|
2873
|
+
type: 'sint32',
|
|
2874
|
+
baseType: 'sint32',
|
|
2875
|
+
array: false,
|
|
2876
|
+
scale: 1,
|
|
2877
|
+
offset: 0,
|
|
2878
|
+
units: 'semicircles',
|
|
2879
|
+
},
|
|
2880
|
+
29: {
|
|
2881
|
+
field: 'swc_lat',
|
|
2882
|
+
type: 'sint32',
|
|
2883
|
+
baseType: 'sint32',
|
|
2884
|
+
array: false,
|
|
2885
|
+
scale: 1,
|
|
2886
|
+
offset: 0,
|
|
2887
|
+
units: 'semicircles',
|
|
2888
|
+
},
|
|
2889
|
+
30: {
|
|
2890
|
+
field: 'swc_long',
|
|
2891
|
+
type: 'sint32',
|
|
2892
|
+
baseType: 'sint32',
|
|
2893
|
+
array: false,
|
|
2894
|
+
scale: 1,
|
|
2895
|
+
offset: 0,
|
|
2896
|
+
units: 'semicircles',
|
|
2897
|
+
},
|
|
2898
|
+
73: {
|
|
2899
|
+
field: 'avg_swolf',
|
|
2900
|
+
type: 'uint16',
|
|
2901
|
+
baseType: 'uint16',
|
|
2902
|
+
array: false,
|
|
2903
|
+
scale: 1,
|
|
2904
|
+
offset: 0,
|
|
2905
|
+
units: '',
|
|
2906
|
+
},
|
|
2907
|
+
90: {
|
|
2908
|
+
field: 'avg_strokes_per_length',
|
|
2909
|
+
type: 'uint16',
|
|
2910
|
+
baseType: 'uint16',
|
|
2911
|
+
array: false,
|
|
2912
|
+
scale: 10,
|
|
2913
|
+
offset: 0,
|
|
2914
|
+
units: 'strokes / length',
|
|
2915
|
+
},
|
|
2916
|
+
96: {
|
|
2917
|
+
field: 'front_gear_shift_count',
|
|
2918
|
+
type: 'uint16',
|
|
2919
|
+
baseType: 'uint16',
|
|
2920
|
+
array: false,
|
|
2921
|
+
scale: 1,
|
|
2922
|
+
offset: 0,
|
|
2923
|
+
units: '',
|
|
2924
|
+
},
|
|
2925
|
+
97: {
|
|
2926
|
+
field: 'rear_gear_shift_count',
|
|
2927
|
+
type: 'uint16',
|
|
2928
|
+
baseType: 'uint16',
|
|
2929
|
+
array: false,
|
|
2930
|
+
scale: 1,
|
|
2931
|
+
offset: 0,
|
|
2932
|
+
units: '',
|
|
2933
|
+
},
|
|
2934
|
+
155: {
|
|
2935
|
+
field: 'metabolic_calories',
|
|
2936
|
+
type: 'uint16',
|
|
2937
|
+
baseType: 'uint16',
|
|
2938
|
+
array: false,
|
|
2939
|
+
scale: 1,
|
|
2940
|
+
offset: 0,
|
|
2941
|
+
units: 'kcal',
|
|
2942
|
+
},
|
|
2943
|
+
161: {
|
|
2944
|
+
field: 'avg_grade_adjusted_speed',
|
|
2945
|
+
type: 'uint32',
|
|
2946
|
+
baseType: 'uint32',
|
|
2947
|
+
array: false,
|
|
2948
|
+
scale: 1000,
|
|
2949
|
+
offset: 0,
|
|
2950
|
+
units: 'm/s',
|
|
2951
|
+
},
|
|
2808
2952
|
0: {
|
|
2809
2953
|
field: 'event',
|
|
2810
2954
|
type: 'event',
|
|
@@ -6983,6 +7127,27 @@ export const PROFILE_MESSAGES = {
|
|
|
6983
7127
|
},
|
|
6984
7128
|
name: 'monitoring_info',
|
|
6985
7129
|
},
|
|
7130
|
+
104: {
|
|
7131
|
+
2: {
|
|
7132
|
+
field: 'capacity',
|
|
7133
|
+
type: 'uint8',
|
|
7134
|
+
baseType: 'uint8',
|
|
7135
|
+
array: false,
|
|
7136
|
+
scale: 1,
|
|
7137
|
+
offset: 0,
|
|
7138
|
+
units: '%',
|
|
7139
|
+
},
|
|
7140
|
+
253: {
|
|
7141
|
+
field: 'timestamp',
|
|
7142
|
+
type: 'date_time',
|
|
7143
|
+
baseType: 'uint32',
|
|
7144
|
+
array: false,
|
|
7145
|
+
scale: 1,
|
|
7146
|
+
offset: 0,
|
|
7147
|
+
units: '',
|
|
7148
|
+
},
|
|
7149
|
+
name: 'battery',
|
|
7150
|
+
},
|
|
6986
7151
|
105: {
|
|
6987
7152
|
name: 'pad',
|
|
6988
7153
|
},
|
|
@@ -15263,6 +15428,7 @@ export const PROFILE_TYPES = {
|
|
|
15263
15428
|
82: 'ant_channel_id',
|
|
15264
15429
|
101: 'length',
|
|
15265
15430
|
103: 'monitoring_info',
|
|
15431
|
+
104: 'battery',
|
|
15266
15432
|
105: 'pad',
|
|
15267
15433
|
106: 'slave_device',
|
|
15268
15434
|
127: 'connectivity',
|
package/dist/type_generator.js
CHANGED
|
@@ -240,6 +240,7 @@ export function generateFitType() {
|
|
|
240
240
|
time_in_zone: 'parsed_time_in_zone',
|
|
241
241
|
activity_metrics: 'parsed_activity_metrics',
|
|
242
242
|
user_metrics: 'parsed_user_metrics',
|
|
243
|
+
batteries: 'parsed_battery',
|
|
243
244
|
};
|
|
244
245
|
const referenceProperties = {
|
|
245
246
|
file_creator: 'parsed_file_creator',
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fit-file-parser",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "6.1
|
|
4
|
+
"version": "6.2.1",
|
|
5
5
|
"private": false,
|
|
6
|
-
"description": "
|
|
6
|
+
"description": "JavaScript and TypeScript library for parsing and encoding FIT files, with developer-field support, raw message access, and ESM/CommonJS builds.",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "jimmykane"
|
|
9
9
|
},
|
|
@@ -24,13 +24,22 @@
|
|
|
24
24
|
"url": "git+ssh://git@github.com/jimmykane/fit-parser.git"
|
|
25
25
|
},
|
|
26
26
|
"bugs": {
|
|
27
|
-
"url": "https://github.com/jimmykane/fit-parser"
|
|
27
|
+
"url": "https://github.com/jimmykane/fit-parser/issues"
|
|
28
28
|
},
|
|
29
29
|
"keywords": [
|
|
30
30
|
"fit",
|
|
31
|
-
"
|
|
31
|
+
"fit-file",
|
|
32
|
+
"fit-parser",
|
|
33
|
+
"fit-file-parsing",
|
|
34
|
+
"fit-encoder",
|
|
35
|
+
"javascript",
|
|
36
|
+
"typescript",
|
|
37
|
+
"nodejs",
|
|
38
|
+
"fitness",
|
|
32
39
|
"garmin",
|
|
33
|
-
"
|
|
40
|
+
"polar",
|
|
41
|
+
"suunto",
|
|
42
|
+
"binary-parser"
|
|
34
43
|
],
|
|
35
44
|
"exports": {
|
|
36
45
|
".": {
|